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