gio/
unix_fd_list.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3#[cfg(unix)]
4use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
5use std::{mem, ptr};
6
7use glib::{prelude::*, translate::*};
8#[cfg(all(not(unix), docsrs))]
9use socket::{AsFd, AsRawFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
10
11use crate::{ffi, UnixFDList};
12
13impl UnixFDList {
14    /// Creates a new #GUnixFDList containing the file descriptors given in
15    /// @fds.  The file descriptors become the property of the new list and
16    /// may no longer be used by the caller.  The array itself is owned by
17    /// the caller.
18    ///
19    /// Each file descriptor in the array should be set to close-on-exec.
20    ///
21    /// If @n_fds is -1 then @fds must be terminated with -1.
22    /// ## `fds`
23    /// the initial list of file descriptors
24    ///
25    /// # Returns
26    ///
27    /// a new #GUnixFDList
28    #[doc(alias = "g_unix_fd_list_new_from_array")]
29    pub fn from_array(fds: impl IntoIterator<Item = impl IntoRawFd>) -> UnixFDList {
30        let fds = fds.into_iter().map(|t| t.into_raw_fd()).collect::<Vec<_>>();
31        unsafe {
32            from_glib_full(ffi::g_unix_fd_list_new_from_array(
33                fds.to_glib_none().0,
34                fds.len() as i32,
35            ))
36        }
37    }
38}
39
40pub trait UnixFDListExtManual: IsA<UnixFDList> + Sized {
41    /// Adds a file descriptor to @self.
42    ///
43    /// The file descriptor is duplicated using dup(). You keep your copy
44    /// of the descriptor and the copy contained in @self will be closed
45    /// when @self is finalized.
46    ///
47    /// A possible cause of failure is exceeding the per-process or
48    /// system-wide file descriptor limit.
49    ///
50    /// The index of the file descriptor in the list is returned.  If you use
51    /// this index with g_unix_fd_list_get() then you will receive back a
52    /// duplicated copy of the same file descriptor.
53    /// ## `fd`
54    /// a valid open file descriptor
55    ///
56    /// # Returns
57    ///
58    /// the index of the appended fd in case of success, else -1
59    ///          (and @error is set)
60    #[doc(alias = "g_unix_fd_list_append")]
61    fn append(&self, fd: impl AsFd) -> Result<i32, glib::Error> {
62        unsafe {
63            let mut error = ptr::null_mut();
64            let ret = ffi::g_unix_fd_list_append(
65                self.as_ref().to_glib_none().0,
66                fd.as_fd().as_raw_fd(),
67                &mut error,
68            );
69            if error.is_null() {
70                Ok(ret)
71            } else {
72                Err(from_glib_full(error))
73            }
74        }
75    }
76
77    /// Gets a file descriptor out of @self.
78    ///
79    /// @index_ specifies the index of the file descriptor to get.  It is a
80    /// programmer error for @index_ to be out of range; see
81    /// g_unix_fd_list_get_length().
82    ///
83    /// The file descriptor is duplicated using dup() and set as
84    /// close-on-exec before being returned.  You must call close() on it
85    /// when you are done.
86    ///
87    /// A possible cause of failure is exceeding the per-process or
88    /// system-wide file descriptor limit.
89    /// ## `index_`
90    /// the index into the list
91    ///
92    /// # Returns
93    ///
94    /// the file descriptor, or -1 in case of error
95    #[doc(alias = "g_unix_fd_list_get")]
96    fn get(&self, index_: i32) -> Result<OwnedFd, glib::Error> {
97        unsafe {
98            let mut error = ptr::null_mut();
99            let raw_fd =
100                ffi::g_unix_fd_list_get(self.as_ref().to_glib_none().0, index_, &mut error);
101            if error.is_null() {
102                let fd = OwnedFd::from_raw_fd(raw_fd);
103                Ok(fd)
104            } else {
105                Err(from_glib_full(error))
106            }
107        }
108    }
109
110    /// Returns the array of file descriptors that is contained in this
111    /// object.
112    ///
113    /// After this call, the descriptors remain the property of @self.  The
114    /// caller must not close them and must not free the array.  The array is
115    /// valid only until @self is changed in any way.
116    ///
117    /// If @length is non-[`None`] then it is set to the number of file
118    /// descriptors in the returned array. The returned array is also
119    /// terminated with -1.
120    ///
121    /// This function never returns [`None`]. In case there are no file
122    /// descriptors contained in @self, an empty array is returned.
123    ///
124    /// # Returns
125    ///
126    /// an array of file
127    ///     descriptors
128    #[doc(alias = "g_unix_fd_list_peek_fds")]
129    fn peek_fds(&self) -> Vec<RawFd> {
130        unsafe {
131            let mut length = mem::MaybeUninit::uninit();
132            let ret = FromGlibContainer::from_glib_none_num(
133                ffi::g_unix_fd_list_peek_fds(self.as_ref().to_glib_none().0, length.as_mut_ptr()),
134                length.assume_init() as usize,
135            );
136            ret
137        }
138    }
139
140    /// Returns the array of file descriptors that is contained in this
141    /// object.
142    ///
143    /// After this call, the descriptors are no longer contained in
144    /// @self. Further calls will return an empty list (unless more
145    /// descriptors have been added).
146    ///
147    /// The return result of this function must be freed with g_free().
148    /// The caller is also responsible for closing all of the file
149    /// descriptors.  The file descriptors in the array are set to
150    /// close-on-exec.
151    ///
152    /// If @length is non-[`None`] then it is set to the number of file
153    /// descriptors in the returned array. The returned array is also
154    /// terminated with -1.
155    ///
156    /// This function never returns [`None`]. In case there are no file
157    /// descriptors contained in @self, an empty array is returned.
158    ///
159    /// # Returns
160    ///
161    /// an array of file
162    ///     descriptors
163    #[doc(alias = "g_unix_fd_list_steal_fds")]
164    fn steal_fds(&self) -> Vec<RawFd> {
165        unsafe {
166            let mut length = mem::MaybeUninit::uninit();
167            let ret = FromGlibContainer::from_glib_full_num(
168                ffi::g_unix_fd_list_steal_fds(self.as_ref().to_glib_none().0, length.as_mut_ptr()),
169                length.assume_init() as usize,
170            );
171            ret
172        }
173    }
174}
175
176impl<O: IsA<UnixFDList>> UnixFDListExtManual for O {}