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 {}