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