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::{UnixFDList, ffi};
12
13impl UnixFDList {
14 /// Creates a new [`UnixFDList`][crate::UnixFDList] containing the file descriptors given
15 /// in @fds. The file descriptors become the property of the new list and may no
16 /// longer be used by the caller. The array itself is owned by the caller.
17 ///
18 /// Each file descriptor in the array should be set to close-on-exec.
19 ///
20 /// If @n_fds is -1 then @fds must be terminated with -1.
21 /// ## `fds`
22 /// the initial list of file descriptors
23 ///
24 /// # Returns
25 ///
26 /// a new [`UnixFDList`][crate::UnixFDList]
27 #[doc(alias = "g_unix_fd_list_new_from_array")]
28 pub fn from_array(fds: impl IntoIterator<Item = impl IntoRawFd>) -> UnixFDList {
29 let fds = fds.into_iter().map(|t| t.into_raw_fd()).collect::<Vec<_>>();
30 unsafe {
31 from_glib_full(ffi::g_unix_fd_list_new_from_array(
32 fds.to_glib_none().0,
33 fds.len() as i32,
34 ))
35 }
36 }
37}
38
39pub trait UnixFDListExtManual: IsA<UnixFDList> + Sized {
40 /// Adds a file descriptor to @self.
41 ///
42 /// The file descriptor is duplicated using `dup()`. You keep your copy
43 /// of the descriptor and the copy contained in @self will be closed
44 /// when @self is finalized.
45 ///
46 /// A possible cause of failure is exceeding the per-process or
47 /// system-wide file descriptor limit.
48 ///
49 /// The index of the file descriptor in the list is returned. If you use
50 /// this index with [`UnixFDListExtManual::get()`][crate::prelude::UnixFDListExtManual::get()] then you will receive back a
51 /// duplicated copy of the same file descriptor.
52 /// ## `fd`
53 /// a valid open file descriptor
54 ///
55 /// # Returns
56 ///
57 /// the index of the appended fd in case of success, else `-1`
58 /// (and @error is set)
59 #[doc(alias = "g_unix_fd_list_append")]
60 fn append(&self, fd: impl AsFd) -> Result<i32, glib::Error> {
61 unsafe {
62 let mut error = ptr::null_mut();
63 let ret = ffi::g_unix_fd_list_append(
64 self.as_ref().to_glib_none().0,
65 fd.as_fd().as_raw_fd(),
66 &mut error,
67 );
68 if error.is_null() {
69 Ok(ret)
70 } else {
71 Err(from_glib_full(error))
72 }
73 }
74 }
75
76 /// Gets a file descriptor out of @self.
77 ///
78 /// @index_ specifies the index of the file descriptor to get. It is a
79 /// programmer error for @index_ to be out of range. Either use
80 /// [`UnixFDListExtManual::lookup()`][crate::prelude::UnixFDListExtManual::lookup()] to do a checked lookup, or check the index
81 /// against the list length using [`UnixFDListExt::length()`][crate::prelude::UnixFDListExt::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-`NULL` 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 `NULL`. 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
133 FromGlibContainer::from_glib_none_num(
134 ffi::g_unix_fd_list_peek_fds(self.as_ref().to_glib_none().0, length.as_mut_ptr()),
135 length.assume_init() as usize,
136 )
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-`NULL` 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 `NULL`. 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
168 FromGlibContainer::from_glib_full_num(
169 ffi::g_unix_fd_list_steal_fds(self.as_ref().to_glib_none().0, length.as_mut_ptr()),
170 length.assume_init() as usize,
171 )
172 }
173 }
174
175 /// Adds a file descriptor to @self.
176 ///
177 /// After this call, @fd belongs to the @self and may no longer be closed by the
178 /// caller.
179 ///
180 /// The file descriptor @fd should be set to close-on-exec.
181 ///
182 /// The index of the file descriptor in the list is returned. If you use this
183 /// index with [`UnixFDListExtManual::get()`][crate::prelude::UnixFDListExtManual::get()] then you will receive back a
184 /// duplicated copy of the same file descriptor.
185 /// ## `fd`
186 /// a valid open file descriptor
187 ///
188 /// # Returns
189 ///
190 /// the index of the appended @fd
191 #[cfg(feature = "v2_90")]
192 #[cfg_attr(docsrs, doc(cfg(feature = "v2_90")))]
193 #[doc(alias = "g_unix_fd_list_append_take")]
194 fn append_take(&self, fd: impl IntoRawFd) -> usize {
195 unsafe { ffi::g_unix_fd_list_append_take(self.as_ref().to_glib_none().0, fd.into_raw_fd()) }
196 }
197
198 /// Looks up a file descriptor in @self at position @index_.
199 ///
200 /// @index_ specifies the index of the file descriptor to get. If no file
201 /// descriptor exists at this index, `-1` is returned.
202 ///
203 /// After this call, the descriptor remains the property of @self. The caller
204 /// must not close it. The descriptor is valid only until @self is changed in any
205 /// way.
206 /// ## `index_`
207 /// the file descriptor index
208 ///
209 /// # Returns
210 ///
211 /// the file descriptor, or `-1` if not found
212 #[cfg(feature = "v2_90")]
213 #[cfg_attr(docsrs, doc(cfg(feature = "v2_90")))]
214 #[doc(alias = "g_unix_fd_list_lookup")]
215 fn lookup(&self, index_: usize) -> RawFd {
216 unsafe { ffi::g_unix_fd_list_lookup(self.as_ref().to_glib_none().0, index_) }
217 }
218
219 /// Gets a file descriptor out of @self.
220 ///
221 /// @index_ specifies the index of the file descriptor to get. It is a programmer
222 /// error for @index_ to be out of range; see [`UnixFDListExt::length()`][crate::prelude::UnixFDListExt::length()].
223 ///
224 /// This will always return a valid (non-negative) file descriptor.
225 ///
226 /// After this call, the descriptor remains the property of @self. The caller
227 /// must not close it. The descriptor is valid only until @self is changed in any
228 /// way.
229 /// ## `index_`
230 /// the index into the list
231 ///
232 /// # Returns
233 ///
234 /// the file descriptor
235 #[cfg(feature = "v2_90")]
236 #[cfg_attr(docsrs, doc(cfg(feature = "v2_90")))]
237 #[doc(alias = "g_unix_fd_list_peek")]
238 fn peek(&self, index_: usize) -> RawFd {
239 unsafe { ffi::g_unix_fd_list_peek(self.as_ref().to_glib_none().0, index_) }
240 }
241}
242
243impl<O: IsA<UnixFDList>> UnixFDListExtManual for O {}