<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::ffi::OsString;
use std::fs::remove_file;
use std::io;
use std::mem;
use std::ops::Deref;
use std::os::unix::{
    ffi::{OsStrExt, OsStringExt},
    io::{AsRawFd, FromRawFd, RawFd},
};
use std::path::Path;
use std::path::PathBuf;
use std::ptr::null_mut;
use std::time::Duration;

// Offset of sun_path in structure sockaddr_un.
fn sun_path_offset() -> usize {
    // Safe block since we only use the created structure to calculate the offset
    unsafe {
        let addr: libc::sockaddr_un = mem::uninitialized();
        let base = &addr as *const _ as usize;
        let path = &addr.sun_path as *const _ as usize;
        path - base
    }
}

// Return `sockaddr_un` for a given `path`
fn sockaddr_un<P: AsRef<Path>>(path: P) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
    let mut addr = libc::sockaddr_un {
        sun_family: libc::AF_UNIX as libc::sa_family_t,
        sun_path: [0; 108],
    };

    // Check if the input path is valid. Since
    // * The pathname in sun_path should be null-terminated.
    // * The length of the pathname, including the terminating null byte,
    //   should not exceed the size of sun_path.
    //
    // and our input is a `Path`, we only need to check
    // * If the string size of `Path` should less than sizeof(sun_path)
    // and make sure `sun_path` ends with '\0' by initialized the sun_path with zeros.
    //
    // Empty path name is valid since abstract socket address has sun_paht[0] = '\0'
    let bytes = path.as_ref().as_os_str().as_bytes();
    if bytes.len() >= addr.sun_path.len() {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "Input path size should be less than the length of sun_path.",
        ));
    };

    // Copy data from `path` to `addr.sun_path`
    for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
        *dst = *src as libc::c_char;
    }

    // The addrlen argument that describes the enclosing sockaddr_un structure
    // should have a value of at least:
    //
    //     offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1
    //
    // or, more simply, addrlen can be specified as sizeof(struct sockaddr_un).
    let len = sun_path_offset() + bytes.len() + 1;
    Ok((addr, len as libc::socklen_t))
}

/// A Unix `SOCK_SEQPACKET` socket point to given `path`
pub struct UnixSeqpacket {
    fd: RawFd,
}

impl UnixSeqpacket {
    /// Open a `SOCK_SEQPACKET` connection to socket named by `path`.
    ///
    /// # Arguments
    /// * `path` - Path to `SOCK_SEQPACKET` socket
    ///
    /// # Returns
    /// A `UnixSeqpacket` structure point to the socket
    ///
    /// # Errors
    /// Return `io::Error` when error occurs.
    pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        // Safe socket initialization since we handle the returned error.
        let fd = unsafe {
            match libc::socket(libc::AF_UNIX, libc::SOCK_SEQPACKET, 0) {
                -1 => return Err(io::Error::last_os_error()),
                fd => fd,
            }
        };

        let (addr, len) = sockaddr_un(path.as_ref())?;
        // Safe connect since we handle the error and use the right length generated from
        // `sockaddr_un`.
        unsafe {
            let ret = libc::connect(fd, &addr as *const _ as *const _, len);
            if ret < 0 {
                return Err(io::Error::last_os_error());
            }
        }
        Ok(UnixSeqpacket { fd })
    }

    /// Creates a pair of connected `SOCK_SEQPACKET` sockets.
    ///
    /// Both returned file descriptors have the `CLOEXEC` flag set.s
    pub fn pair() -> io::Result<(UnixSeqpacket, UnixSeqpacket)> {
        let mut fds = [0, 0];
        unsafe {
            // Safe because we give enough space to store all the fds and we check the return value.
            let ret = libc::socketpair(
                libc::AF_UNIX,
                libc::SOCK_SEQPACKET | libc::SOCK_CLOEXEC,
                0,
                &mut fds[0],
            );
            if ret == 0 {
                Ok((
                    UnixSeqpacket::from_raw_fd(fds[0]),
                    UnixSeqpacket::from_raw_fd(fds[1]),
                ))
            } else {
                Err(io::Error::last_os_error())
            }
        }
    }

    /// Clone the underlying FD.
    pub fn try_clone(&self) -> io::Result<Self> {
        // Calling `dup` is safe as the kernel doesn't touch any user memory it the process.
        let new_fd = unsafe { libc::dup(self.fd) };
        if new_fd < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(UnixSeqpacket { fd: new_fd })
        }
    }

    /// Gets the number of bytes that can be read from this socket without blocking.
    pub fn get_readable_bytes(&self) -> io::Result<usize> {
        let mut byte_count = 0 as libc::c_int;
        let ret = unsafe { libc::ioctl(self.fd, libc::FIONREAD, &mut byte_count) };
        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(byte_count as usize)
        }
    }

    /// Write data from a given buffer to the socket fd
    ///
    /// # Arguments
    /// * `buf` - A reference to the data buffer.
    ///
    /// # Returns
    /// * `usize` - The size of bytes written to the buffer.
    ///
    /// # Errors
    /// Returns error when `libc::write` failed.
    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
        // Safe since we make sure the input `count` == `buf.len()` and handle the returned error.
        unsafe {
            let ret = libc::write(self.fd, buf.as_ptr() as *const _, buf.len());
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(ret as usize)
            }
        }
    }

    /// Read data from the socket fd to a given buffer
    ///
    /// # Arguments
    /// * `buf` - A mut reference to the data buffer.
    ///
    /// # Returns
    /// * `usize` - The size of bytes read to the buffer.
    ///
    /// # Errors
    /// Returns error when `libc::read` failed.
    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
        // Safe since we make sure the input `count` == `buf.len()` and handle the returned error.
        unsafe {
            let ret = libc::read(self.fd, buf.as_mut_ptr() as *mut _, buf.len());
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(ret as usize)
            }
        }
    }

    fn set_timeout(&self, timeout: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
        let timeval = match timeout {
            Some(t) => {
                if t.as_secs() == 0 && t.subsec_micros() == 0 {
                    return Err(io::Error::new(
                        io::ErrorKind::InvalidInput,
                        "zero timeout duration is invalid",
                    ));
                }
                libc::timeval {
                    tv_sec: t.as_secs() as libc::time_t,
                    tv_usec: t.subsec_micros() as libc::suseconds_t,
                }
            }
            None => libc::timeval {
                tv_sec: 0,
                tv_usec: 0,
            },
        };
        // Safe because we own the fd, and the length of the pointer's data is the same as the
        // passed in length parameter. The level argument is valid, the kind is assumed to be valid,
        // and the return value is checked.
        let ret = unsafe {
            libc::setsockopt(<commit_msg>sys_util: net: Make clippy clean<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::ffi::OsString;
use std::fs::remove_file;
use std::io;
use std::mem;
use std::ops::Deref;
use std::os::unix::{
    ffi::{OsStrExt, OsStringExt},
    io::{AsRawFd, FromRawFd, RawFd},
};
use std::path::Path;
use std::path::PathBuf;
use std::ptr::null_mut;
use std::time::Duration;

// Offset of sun_path in structure sockaddr_un.
fn sun_path_offset() -> usize {
    // Safe block since we only use the created structure to calculate the offset
    unsafe {
        let addr: libc::sockaddr_un = mem::uninitialized();
        let base = &addr as *const _ as usize;
        let path = &addr.sun_path as *const _ as usize;
        path - base
    }
}

// Return `sockaddr_un` for a given `path`
fn sockaddr_un<P: AsRef<Path>>(path: P) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
    let mut addr = libc::sockaddr_un {
        sun_family: libc::AF_UNIX as libc::sa_family_t,
        sun_path: [0; 108],
    };

    // Check if the input path is valid. Since
    // * The pathname in sun_path should be null-terminated.
    // * The length of the pathname, including the terminating null byte,
    //   should not exceed the size of sun_path.
    //
    // and our input is a `Path`, we only need to check
    // * If the string size of `Path` should less than sizeof(sun_path)
    // and make sure `sun_path` ends with '\0' by initialized the sun_path with zeros.
    //
    // Empty path name is valid since abstract socket address has sun_paht[0] = '\0'
    let bytes = path.as_ref().as_os_str().as_bytes();
    if bytes.len() >= addr.sun_path.len() {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "Input path size should be less than the length of sun_path.",
        ));
    };

    // Copy data from `path` to `addr.sun_path`
    for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
        *dst = *src as libc::c_char;
    }

    // The addrlen argument that describes the enclosing sockaddr_un structure
    // should have a value of at least:
    //
    //     offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1
    //
    // or, more simply, addrlen can be specified as sizeof(struct sockaddr_un).
    let len = sun_path_offset() + bytes.len() + 1;
    Ok((addr, len as libc::socklen_t))
}

/// A Unix `SOCK_SEQPACKET` socket point to given `path`
pub struct UnixSeqpacket {
    fd: RawFd,
}

impl UnixSeqpacket {
    /// Open a `SOCK_SEQPACKET` connection to socket named by `path`.
    ///
    /// # Arguments
    /// * `path` - Path to `SOCK_SEQPACKET` socket
    ///
    /// # Returns
    /// A `UnixSeqpacket` structure point to the socket
    ///
    /// # Errors
    /// Return `io::Error` when error occurs.
    pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        // Safe socket initialization since we handle the returned error.
        let fd = unsafe {
            match libc::socket(libc::AF_UNIX, libc::SOCK_SEQPACKET, 0) {
                -1 => return Err(io::Error::last_os_error()),
                fd => fd,
            }
        };

        let (addr, len) = sockaddr_un(path.as_ref())?;
        // Safe connect since we handle the error and use the right length generated from
        // `sockaddr_un`.
        unsafe {
            let ret = libc::connect(fd, &addr as *const _ as *const _, len);
            if ret < 0 {
                return Err(io::Error::last_os_error());
            }
        }
        Ok(UnixSeqpacket { fd })
    }

    /// Creates a pair of connected `SOCK_SEQPACKET` sockets.
    ///
    /// Both returned file descriptors have the `CLOEXEC` flag set.s
    pub fn pair() -> io::Result<(UnixSeqpacket, UnixSeqpacket)> {
        let mut fds = [0, 0];
        unsafe {
            // Safe because we give enough space to store all the fds and we check the return value.
            let ret = libc::socketpair(
                libc::AF_UNIX,
                libc::SOCK_SEQPACKET | libc::SOCK_CLOEXEC,
                0,
                &mut fds[0],
            );
            if ret == 0 {
                Ok((
                    UnixSeqpacket::from_raw_fd(fds[0]),
                    UnixSeqpacket::from_raw_fd(fds[1]),
                ))
            } else {
                Err(io::Error::last_os_error())
            }
        }
    }

    /// Clone the underlying FD.
    pub fn try_clone(&self) -> io::Result<Self> {
        // Calling `dup` is safe as the kernel doesn't touch any user memory it the process.
        let new_fd = unsafe { libc::dup(self.fd) };
        if new_fd < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(UnixSeqpacket { fd: new_fd })
        }
    }

    /// Gets the number of bytes that can be read from this socket without blocking.
    pub fn get_readable_bytes(&self) -> io::Result<usize> {
        let mut byte_count = 0 as libc::c_int;
        let ret = unsafe { libc::ioctl(self.fd, libc::FIONREAD, &mut byte_count) };
        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(byte_count as usize)
        }
    }

    /// Write data from a given buffer to the socket fd
    ///
    /// # Arguments
    /// * `buf` - A reference to the data buffer.
    ///
    /// # Returns
    /// * `usize` - The size of bytes written to the buffer.
    ///
    /// # Errors
    /// Returns error when `libc::write` failed.
    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
        // Safe since we make sure the input `count` == `buf.len()` and handle the returned error.
        unsafe {
            let ret = libc::write(self.fd, buf.as_ptr() as *const _, buf.len());
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(ret as usize)
            }
        }
    }

    /// Read data from the socket fd to a given buffer
    ///
    /// # Arguments
    /// * `buf` - A mut reference to the data buffer.
    ///
    /// # Returns
    /// * `usize` - The size of bytes read to the buffer.
    ///
    /// # Errors
    /// Returns error when `libc::read` failed.
    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
        // Safe since we make sure the input `count` == `buf.len()` and handle the returned error.
        unsafe {
            let ret = libc::read(self.fd, buf.as_mut_ptr() as *mut _, buf.len());
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(ret as usize)
            }
        }
    }

    fn set_timeout(&self, timeout: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
        let timeval = match timeout {
            Some(t) => {
                if t.as_secs() == 0 && t.subsec_micros() == 0 {
                    return Err(io::Error::new(
                        io::ErrorKind::InvalidInput,
                        "zero timeout duration is invalid",
                    ));
                }
                // subsec_micros fits in i32 because it is defined to be less than one million.
                let nsec = t.subsec_micros() as i32;
                libc::timeval {
                    tv_sec: t.as_secs() as libc::time_t,
                    tv_usec: libc::suseconds_t::from(nsec),
                }
            }
            None => libc::timeval {
                tv_sec: 0,
                tv_usec: 0,
            },
        };
        // Safe because we own the fd, and the length of the pointer's data is the same as the
        // passed in length parameter. The level argument is valid, the kind is assumed to be valid,
        // and the return value is checked.
        let ret = unsafe {
            libc::setsockopt(
{'fraction_non_alphanumeric': 0.12689964732285988, 'fraction_numerical': 0.004616864379608849, 'mean_word_length': 1.796485565716335, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1833541', 'n_tokens_mistral': 4893, 'n_tokens_neox': 4681, 'n_words': 1502}