Skip to content

Commit 54331d5

Browse files
authored
Merge pull request #1687 from A6GibKm/safe-io-3
Port some functions to safe-io: pt I
2 parents 28e8994 + 16b9f87 commit 54331d5

File tree

7 files changed

+93
-58
lines changed

7 files changed

+93
-58
lines changed

gio/src/desktop_app_info.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#[cfg(all(unix, feature = "v2_58"))]
44
use std::boxed::Box as Box_;
55
#[cfg(all(unix, feature = "v2_58"))]
6-
use std::os::unix::io::AsRawFd;
6+
use std::os::unix::io::{AsFd, AsRawFd};
77
#[cfg(all(unix, feature = "v2_58"))]
88
use std::ptr;
99

@@ -48,21 +48,16 @@ impl DesktopAppInfo {
4848
pub trait DesktopAppInfoExtManual: IsA<DesktopAppInfo> {
4949
#[cfg_attr(docsrs, doc(cfg(all(feature = "v2_58", unix))))]
5050
#[doc(alias = "g_desktop_app_info_launch_uris_as_manager_with_fds")]
51-
fn launch_uris_as_manager_with_fds<
52-
P: IsA<AppLaunchContext>,
53-
T: AsRawFd,
54-
U: AsRawFd,
55-
V: AsRawFd,
56-
>(
51+
fn launch_uris_as_manager_with_fds<P: IsA<AppLaunchContext>>(
5752
&self,
5853
uris: &[&str],
5954
launch_context: Option<&P>,
6055
spawn_flags: glib::SpawnFlags,
6156
user_setup: Option<Box_<dyn FnOnce() + 'static>>,
6257
pid_callback: Option<&mut dyn (FnMut(&DesktopAppInfo, glib::Pid))>,
63-
stdin_fd: &mut T,
64-
stdout_fd: &mut U,
65-
stderr_fd: &mut V,
58+
stdin_fd: Option<impl AsFd>,
59+
stdout_fd: Option<impl AsFd>,
60+
stderr_fd: Option<impl AsFd>,
6661
) -> Result<(), Error> {
6762
let user_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(user_setup);
6863
unsafe extern "C" fn user_setup_func(user_data: glib::ffi::gpointer) {
@@ -99,6 +94,10 @@ pub trait DesktopAppInfoExtManual: IsA<DesktopAppInfo> {
9994
let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = user_setup_data;
10095
let super_callback1: &Option<&mut dyn (FnMut(&DesktopAppInfo, glib::Pid))> =
10196
&pid_callback_data;
97+
98+
let stdin_raw_fd = stdin_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
99+
let stdout_raw_fd = stdout_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
100+
let stderr_raw_fd = stderr_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
102101
unsafe {
103102
let mut error = ptr::null_mut();
104103
let _ = ffi::g_desktop_app_info_launch_uris_as_manager_with_fds(
@@ -110,9 +109,9 @@ pub trait DesktopAppInfoExtManual: IsA<DesktopAppInfo> {
110109
Box_::into_raw(super_callback0) as *mut _,
111110
pid_callback,
112111
super_callback1 as *const _ as *mut _,
113-
stdin_fd.as_raw_fd(),
114-
stdout_fd.as_raw_fd(),
115-
stderr_fd.as_raw_fd(),
112+
stdin_raw_fd,
113+
stdout_raw_fd,
114+
stderr_raw_fd,
116115
&mut error,
117116
);
118117
if error.is_null() {

gio/src/socket.rs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Take a look at the license at the top of the repository in the LICENSE file.
22

33
#[cfg(unix)]
4-
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
4+
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
55
#[cfg(windows)]
66
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
77
#[cfg(feature = "v2_60")]
@@ -18,15 +18,18 @@ use crate::{ffi, Cancellable, Socket, SocketAddress, SocketControlMessage};
1818
impl Socket {
1919
#[cfg(unix)]
2020
#[cfg_attr(docsrs, doc(cfg(unix)))]
21-
#[allow(clippy::missing_safety_doc)]
22-
pub unsafe fn from_fd(fd: impl IntoRawFd) -> Result<Socket, glib::Error> {
21+
#[doc(alias = "g_socket_new_from_fd")]
22+
pub fn from_fd(fd: OwnedFd) -> Result<Socket, glib::Error> {
2323
let fd = fd.into_raw_fd();
2424
let mut error = ptr::null_mut();
25-
let ret = ffi::g_socket_new_from_fd(fd, &mut error);
26-
if error.is_null() {
27-
Ok(from_glib_full(ret))
28-
} else {
29-
Err(from_glib_full(error))
25+
unsafe {
26+
let ret = ffi::g_socket_new_from_fd(fd, &mut error);
27+
if error.is_null() {
28+
Ok(from_glib_full(ret))
29+
} else {
30+
libc::close(fd);
31+
Err(from_glib_full(error))
32+
}
3033
}
3134
}
3235
#[cfg(windows)]
@@ -52,6 +55,17 @@ impl AsRawFd for Socket {
5255
}
5356
}
5457

58+
#[cfg(unix)]
59+
#[cfg_attr(docsrs, doc(cfg(unix)))]
60+
impl AsFd for Socket {
61+
fn as_fd(&self) -> BorrowedFd<'_> {
62+
unsafe {
63+
let raw_fd = self.as_raw_fd();
64+
BorrowedFd::borrow_raw(raw_fd)
65+
}
66+
}
67+
}
68+
5569
#[cfg(windows)]
5670
#[cfg_attr(docsrs, doc(cfg(windows)))]
5771
impl AsRawSocket for Socket {
@@ -801,7 +815,10 @@ mod tests {
801815
#[test]
802816
#[cfg(unix)]
803817
fn socket_messages() {
804-
use std::{io, os::unix::io::AsRawFd};
818+
use std::{
819+
io,
820+
os::unix::io::{AsRawFd, FromRawFd, OwnedFd},
821+
};
805822

806823
use super::Socket;
807824
use crate::{prelude::*, Cancellable, UnixFDMessage};
@@ -813,8 +830,8 @@ mod tests {
813830
panic!("{}", io::Error::last_os_error());
814831
}
815832
(
816-
Socket::from_fd(fds[0]).unwrap(),
817-
Socket::from_fd(fds[1]).unwrap(),
833+
Socket::from_fd(OwnedFd::from_raw_fd(fds[0])).unwrap(),
834+
Socket::from_fd(OwnedFd::from_raw_fd(fds[1])).unwrap(),
818835
)
819836
};
820837

gio/src/unix_input_stream.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,24 @@
11
// Take a look at the license at the top of the repository in the LICENSE file.
22

33
#[cfg(unix)]
4-
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
4+
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, IntoRawFd, OwnedFd, RawFd};
55

66
use glib::{prelude::*, translate::*};
77
#[cfg(all(not(unix), docsrs))]
8-
use socket::{AsRawFd, IntoRawFd, RawFd};
8+
use socket::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
99

1010
use crate::{ffi, InputStream, UnixInputStream};
1111

1212
impl UnixInputStream {
1313
// rustdoc-stripper-ignore-next
1414
/// Creates a new [`Self`] that takes ownership of the passed in fd.
15-
///
16-
/// # Safety
17-
/// You must not close the fd unless you've previously called [`UnixInputStreamExtManual::set_close_fd`]
18-
/// with `true` on this stream. At which point you may only do so when all references to this
19-
/// stream have been dropped.
2015
#[doc(alias = "g_unix_input_stream_new")]
21-
pub unsafe fn take_fd(fd: impl IntoRawFd) -> UnixInputStream {
16+
pub fn take_fd(fd: OwnedFd) -> UnixInputStream {
2217
let fd = fd.into_raw_fd();
2318
let close_fd = true.into_glib();
24-
InputStream::from_glib_full(ffi::g_unix_input_stream_new(fd, close_fd)).unsafe_cast()
19+
unsafe {
20+
InputStream::from_glib_full(ffi::g_unix_input_stream_new(fd, close_fd)).unsafe_cast()
21+
}
2522
}
2623

2724
// rustdoc-stripper-ignore-next
@@ -43,6 +40,15 @@ impl AsRawFd for UnixInputStream {
4340
}
4441
}
4542

43+
impl AsFd for UnixInputStream {
44+
fn as_fd(&self) -> BorrowedFd<'_> {
45+
unsafe {
46+
let raw_fd = self.as_raw_fd();
47+
BorrowedFd::borrow_raw(raw_fd)
48+
}
49+
}
50+
}
51+
4652
pub trait UnixInputStreamExtManual: IsA<UnixInputStream> + Sized {
4753
// rustdoc-stripper-ignore-next
4854
/// Sets whether the fd of this stream will be closed when the stream is closed.

gio/src/unix_output_stream.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,24 @@
11
// Take a look at the license at the top of the repository in the LICENSE file.
22

33
#[cfg(unix)]
4-
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
4+
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, IntoRawFd, OwnedFd, RawFd};
55

66
use glib::{prelude::*, translate::*};
77
#[cfg(all(not(unix), docsrs))]
8-
use socket::{AsRawFd, IntoRawFd, RawFd};
8+
use socket::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
99

1010
use crate::{ffi, OutputStream, UnixOutputStream};
1111

1212
impl UnixOutputStream {
1313
// rustdoc-stripper-ignore-next
1414
/// Creates a new [`Self`] that takes ownership of the passed in fd.
15-
///
16-
/// # Safety
17-
/// You must not close the fd unless you've previously called [`UnixOutputStreamExtManual::set_close_fd`]
18-
/// on this stream. At which point you may only do so when all references to this stream have
19-
/// been dropped.
2015
#[doc(alias = "g_unix_output_stream_new")]
21-
pub unsafe fn take_fd(fd: impl IntoRawFd) -> UnixOutputStream {
16+
pub fn take_fd(fd: OwnedFd) -> UnixOutputStream {
2217
let fd = fd.into_raw_fd();
2318
let close_fd = true.into_glib();
24-
OutputStream::from_glib_full(ffi::g_unix_output_stream_new(fd, close_fd)).unsafe_cast()
19+
unsafe {
20+
OutputStream::from_glib_full(ffi::g_unix_output_stream_new(fd, close_fd)).unsafe_cast()
21+
}
2522
}
2623

2724
// rustdoc-stripper-ignore-next
@@ -43,6 +40,15 @@ impl AsRawFd for UnixOutputStream {
4340
}
4441
}
4542

43+
impl AsFd for UnixOutputStream {
44+
fn as_fd(&self) -> BorrowedFd<'_> {
45+
unsafe {
46+
let raw_fd = self.as_raw_fd();
47+
BorrowedFd::borrow_raw(raw_fd)
48+
}
49+
}
50+
}
51+
4652
pub trait UnixOutputStreamExtManual: IsA<UnixOutputStream> + Sized {
4753
// rustdoc-stripper-ignore-next
4854
/// Sets whether the fd of this stream will be closed when the stream is closed.

gio/tests/dbus_peer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn test_gdbus_peer_connection() {
88
prelude::*,
99
DBusConnection, DBusConnectionFlags, DBusNodeInfo, Socket,
1010
};
11-
use std::os::{fd::IntoRawFd, unix::net::UnixStream};
11+
use std::os::unix::net::UnixStream;
1212

1313
const EXAMPLE_XML: &str = r#"
1414
<node>
@@ -23,7 +23,7 @@ fn test_gdbus_peer_connection() {
2323
"#;
2424

2525
pub async fn spawn_server(fd: UnixStream) -> DBusConnection {
26-
let socket = unsafe { Socket::from_fd(fd.into_raw_fd()) }.unwrap();
26+
let socket = Socket::from_fd(fd.into()).unwrap();
2727
let socket_connection = socket.connection_factory_create_connection();
2828

2929
let guid = gio::dbus_generate_guid();
@@ -112,7 +112,7 @@ fn test_gdbus_peer_connection() {
112112
}
113113

114114
pub async fn spawn_client(fd: UnixStream) -> DBusConnection {
115-
let socket_client = unsafe { Socket::from_fd(fd.into_raw_fd()) }.unwrap();
115+
let socket_client = Socket::from_fd(fd.into()).unwrap();
116116
let socket_connection_client = socket_client.connection_factory_create_connection();
117117

118118
dbg!("client connecting");

glib/src/functions.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::boxed::Box as Box_;
77
use std::mem;
88
#[cfg(not(windows))]
99
#[cfg(feature = "v2_58")]
10-
use std::os::unix::io::AsRawFd;
10+
use std::os::unix::io::{AsFd, AsRawFd};
1111
#[cfg(not(windows))]
1212
use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd};
1313
use std::ptr;
@@ -24,15 +24,15 @@ use crate::{Error, Pid, SpawnFlags};
2424
#[cfg_attr(docsrs, doc(cfg(all(feature = "v2_58", not(windows)))))]
2525
#[allow(clippy::too_many_arguments)]
2626
#[doc(alias = "g_spawn_async_with_fds")]
27-
pub fn spawn_async_with_fds<P: AsRef<std::path::Path>, T: AsRawFd, U: AsRawFd, V: AsRawFd>(
27+
pub fn spawn_async_with_fds<P: AsRef<std::path::Path>>(
2828
working_directory: P,
2929
argv: &[&str],
3030
envp: &[&str],
3131
flags: SpawnFlags,
3232
child_setup: Option<Box_<dyn FnOnce() + 'static>>,
33-
stdin_fd: T,
34-
stdout_fd: U,
35-
stderr_fd: V,
33+
stdin_fd: Option<impl AsFd>,
34+
stdout_fd: Option<impl AsFd>,
35+
stderr_fd: Option<impl AsFd>,
3636
) -> Result<Pid, Error> {
3737
let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup);
3838
unsafe extern "C" fn child_setup_func(user_data: ffi::gpointer) {
@@ -47,6 +47,9 @@ pub fn spawn_async_with_fds<P: AsRef<std::path::Path>, T: AsRawFd, U: AsRawFd, V
4747
None
4848
};
4949
let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data;
50+
let stdin_raw_fd = stdin_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
51+
let stdout_raw_fd = stdout_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
52+
let stderr_raw_fd = stderr_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
5053
unsafe {
5154
let mut child_pid = mem::MaybeUninit::uninit();
5255
let mut error = ptr::null_mut();
@@ -58,9 +61,9 @@ pub fn spawn_async_with_fds<P: AsRef<std::path::Path>, T: AsRawFd, U: AsRawFd, V
5861
child_setup,
5962
Box_::into_raw(super_callback0) as *mut _,
6063
child_pid.as_mut_ptr(),
61-
stdin_fd.as_raw_fd(),
62-
stdout_fd.as_raw_fd(),
63-
stderr_fd.as_raw_fd(),
64+
stdin_raw_fd,
65+
stdout_raw_fd,
66+
stderr_raw_fd,
6467
&mut error,
6568
);
6669
let child_pid = from_glib(child_pid.assume_init());

glib/src/log.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Take a look at the license at the top of the repository in the LICENSE file.
22

33
#[cfg(unix)]
4-
use std::os::unix::io::AsRawFd;
4+
use std::os::unix::io::{AsFd, AsRawFd};
55
use std::{
66
boxed::Box as Box_,
77
sync::{Arc, Mutex, OnceLock},
@@ -972,16 +972,20 @@ pub fn log_variant(log_domain: Option<&str>, log_level: LogLevel, fields: &crate
972972
#[cfg_attr(docsrs, doc(cfg(unix)))]
973973
#[doc(alias = "g_log_writer_supports_color")]
974974
#[inline]
975-
pub fn log_writer_supports_color<T: AsRawFd>(output_fd: T) -> bool {
976-
unsafe { from_glib(ffi::g_log_writer_supports_color(output_fd.as_raw_fd())) }
975+
pub fn log_writer_supports_color(output_fd: impl AsFd) -> bool {
976+
unsafe {
977+
from_glib(ffi::g_log_writer_supports_color(
978+
output_fd.as_fd().as_raw_fd(),
979+
))
980+
}
977981
}
978982

979983
#[cfg(unix)]
980984
#[cfg_attr(docsrs, doc(cfg(unix)))]
981985
#[doc(alias = "g_log_writer_is_journald")]
982986
#[inline]
983-
pub fn log_writer_is_journald<T: AsRawFd>(output_fd: T) -> bool {
984-
unsafe { from_glib(ffi::g_log_writer_is_journald(output_fd.as_raw_fd())) }
987+
pub fn log_writer_is_journald(output_fd: impl AsFd) -> bool {
988+
unsafe { from_glib(ffi::g_log_writer_is_journald(output_fd.as_fd().as_raw_fd())) }
985989
}
986990

987991
#[doc(alias = "g_log_writer_format_fields")]

0 commit comments

Comments
 (0)