Skip to content

Commit 711c222

Browse files
authored
Merge pull request RustPython#1616 from maybe-rachel/stdlib_os_additions
add some os stdlib functions
2 parents ec011f5 + 0e7a22b commit 711c222

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed

tests/snippets/stdlib_os.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,69 @@ def __exit__(self, exc_type, exc_val, exc_tb):
290290
os.close(b)
291291
os.close(a)
292292

293+
# os.get_blocking, os.set_blocking
294+
# TODO: windows support should be added for below functions
295+
# os.pipe,
296+
# os.set_inheritable, os.get_inheritable,
297+
rfd, wfd = os.pipe()
298+
try:
299+
os.write(wfd, CONTENT2)
300+
assert os.read(rfd, len(CONTENT2)) == CONTENT2
301+
assert not os.get_inheritable(rfd)
302+
assert not os.get_inheritable(wfd)
303+
os.set_inheritable(rfd, True)
304+
os.set_inheritable(wfd, True)
305+
assert os.get_inheritable(rfd)
306+
assert os.get_inheritable(wfd)
307+
os.set_inheritable(rfd, True)
308+
os.set_inheritable(wfd, True)
309+
os.set_inheritable(rfd, True)
310+
os.set_inheritable(wfd, True)
311+
assert os.get_inheritable(rfd)
312+
assert os.get_inheritable(wfd)
313+
314+
assert os.get_blocking(rfd)
315+
assert os.get_blocking(wfd)
316+
os.set_blocking(rfd, False)
317+
os.set_blocking(wfd, False)
318+
assert not os.get_blocking(rfd)
319+
assert not os.get_blocking(wfd)
320+
os.set_blocking(rfd, True)
321+
os.set_blocking(wfd, True)
322+
os.set_blocking(rfd, True)
323+
os.set_blocking(wfd, True)
324+
assert os.get_blocking(rfd)
325+
assert os.get_blocking(wfd)
326+
finally:
327+
os.close(rfd)
328+
os.close(wfd)
329+
330+
# os.pipe2
331+
if sys.platform.startswith('linux') or sys.platform.startswith('freebsd'):
332+
rfd, wfd = os.pipe2(0)
333+
try:
334+
os.write(wfd, CONTENT2)
335+
assert os.read(rfd, len(CONTENT2)) == CONTENT2
336+
assert os.get_inheritable(rfd)
337+
assert os.get_inheritable(wfd)
338+
assert os.get_blocking(rfd)
339+
assert os.get_blocking(wfd)
340+
finally:
341+
os.close(rfd)
342+
os.close(wfd)
343+
rfd, wfd = os.pipe2(os.O_CLOEXEC | os.O_NONBLOCK)
344+
try:
345+
os.write(wfd, CONTENT2)
346+
assert os.read(rfd, len(CONTENT2)) == CONTENT2
347+
assert not os.get_inheritable(rfd)
348+
assert not os.get_inheritable(wfd)
349+
assert not os.get_blocking(rfd)
350+
assert not os.get_blocking(wfd)
351+
finally:
352+
os.close(rfd)
353+
os.close(wfd)
354+
355+
293356
with TestWithTempDir() as tmpdir:
294357
for i in range(0, 4):
295358
file_name = os.path.join(tmpdir, 'file' + str(i))

vm/src/stdlib/os.rs

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use nix::errno::Errno;
2020
use nix::pty::openpty;
2121
#[cfg(unix)]
2222
use nix::unistd::{self, Gid, Pid, Uid, Whence};
23+
#[cfg(unix)]
24+
use std::os::unix::io::RawFd;
2325

2426
use super::errno::errors;
2527
use crate::function::{IntoPyNativeFunc, OptionalArg, PyFuncArgs};
@@ -925,6 +927,96 @@ fn os_chdir(path: PyStringRef, vm: &VirtualMachine) -> PyResult<()> {
925927
env::set_current_dir(path.as_str()).map_err(|err| convert_io_error(vm, err))
926928
}
927929

930+
#[cfg(unix)]
931+
fn os_get_inheritable(fd: RawFd, vm: &VirtualMachine) -> PyResult<bool> {
932+
use nix::fcntl::fcntl;
933+
use nix::fcntl::FcntlArg;
934+
let flags = fcntl(fd, FcntlArg::F_GETFD);
935+
match flags {
936+
Ok(ret) => Ok((ret & libc::FD_CLOEXEC) == 0),
937+
Err(err) => Err(convert_nix_error(vm, err)),
938+
}
939+
}
940+
941+
#[cfg(unix)]
942+
fn os_set_inheritable(fd: RawFd, inheritable: bool, vm: &VirtualMachine) -> PyResult<()> {
943+
let _set_flag = || {
944+
use nix::fcntl::fcntl;
945+
use nix::fcntl::FcntlArg;
946+
use nix::fcntl::FdFlag;
947+
948+
let flags = FdFlag::from_bits_truncate(fcntl(fd, FcntlArg::F_GETFD)?);
949+
let mut new_flags = flags;
950+
new_flags.set(FdFlag::from_bits_truncate(libc::FD_CLOEXEC), !inheritable);
951+
if flags != new_flags {
952+
fcntl(fd, FcntlArg::F_SETFD(new_flags))?;
953+
}
954+
Ok(())
955+
};
956+
_set_flag().or_else(|err| Err(convert_nix_error(vm, err)))
957+
}
958+
959+
#[cfg(unix)]
960+
fn os_get_blocking(fd: RawFd, vm: &VirtualMachine) -> PyResult<bool> {
961+
use nix::fcntl::fcntl;
962+
use nix::fcntl::FcntlArg;
963+
let flags = fcntl(fd, FcntlArg::F_GETFL);
964+
match flags {
965+
Ok(ret) => Ok((ret & libc::O_NONBLOCK) == 0),
966+
Err(err) => Err(convert_nix_error(vm, err)),
967+
}
968+
}
969+
970+
#[cfg(unix)]
971+
fn os_set_blocking(fd: RawFd, blocking: bool, vm: &VirtualMachine) -> PyResult<()> {
972+
let _set_flag = || {
973+
use nix::fcntl::fcntl;
974+
use nix::fcntl::FcntlArg;
975+
use nix::fcntl::OFlag;
976+
977+
let flags = OFlag::from_bits_truncate(fcntl(fd, FcntlArg::F_GETFL)?);
978+
let mut new_flags = flags;
979+
new_flags.set(OFlag::from_bits_truncate(libc::O_NONBLOCK), !blocking);
980+
if flags != new_flags {
981+
fcntl(fd, FcntlArg::F_SETFL(new_flags))?;
982+
}
983+
Ok(())
984+
};
985+
_set_flag().or_else(|err| Err(convert_nix_error(vm, err)))
986+
}
987+
988+
#[cfg(unix)]
989+
fn os_pipe(vm: &VirtualMachine) -> PyResult<(RawFd, RawFd)> {
990+
use nix::unistd::close;
991+
use nix::unistd::pipe;
992+
let (rfd, wfd) = pipe().map_err(|err| convert_nix_error(vm, err))?;
993+
os_set_inheritable(rfd, false, vm)
994+
.and_then(|_| os_set_inheritable(wfd, false, vm))
995+
.or_else(|err| {
996+
let _ = close(rfd);
997+
let _ = close(wfd);
998+
Err(err)
999+
})?;
1000+
Ok((rfd, wfd))
1001+
}
1002+
1003+
// cfg from nix
1004+
#[cfg(any(
1005+
target_os = "android",
1006+
target_os = "dragonfly",
1007+
target_os = "emscripten",
1008+
target_os = "freebsd",
1009+
target_os = "linux",
1010+
target_os = "netbsd",
1011+
target_os = "openbsd"
1012+
))]
1013+
fn os_pipe2(flags: libc::c_int, vm: &VirtualMachine) -> PyResult<(RawFd, RawFd)> {
1014+
use nix::fcntl::OFlag;
1015+
use nix::unistd::pipe2;
1016+
let oflags = OFlag::from_bits_truncate(flags);
1017+
pipe2(oflags).map_err(|err| convert_nix_error(vm, err))
1018+
}
1019+
9281020
#[cfg(unix)]
9291021
fn os_system(command: PyStringRef, _vm: &VirtualMachine) -> PyResult<i32> {
9301022
use libc::system;
@@ -1277,12 +1369,17 @@ fn extend_module_platform_specific(vm: &VirtualMachine, module: PyObjectRef) ->
12771369
extend_module!(vm, module, {
12781370
"access" => ctx.new_rustfunc(os_access),
12791371
"chmod" => ctx.new_rustfunc(os_chmod),
1372+
"get_inheritable" => ctx.new_rustfunc(os_get_inheritable), // TODO: windows
1373+
"get_blocking" => ctx.new_rustfunc(os_get_blocking),
12801374
"getppid" => ctx.new_rustfunc(os_getppid),
12811375
"getgid" => ctx.new_rustfunc(os_getgid),
12821376
"getegid" => ctx.new_rustfunc(os_getegid),
12831377
"getpgid" => ctx.new_rustfunc(os_getpgid),
12841378
"getuid" => ctx.new_rustfunc(os_getuid),
12851379
"geteuid" => ctx.new_rustfunc(os_geteuid),
1380+
"pipe" => ctx.new_rustfunc(os_pipe), //TODO: windows
1381+
"set_inheritable" => ctx.new_rustfunc(os_set_inheritable), // TODO: windows
1382+
"set_blocking" => ctx.new_rustfunc(os_set_blocking),
12861383
"setgid" => ctx.new_rustfunc(os_setgid),
12871384
"setpgid" => ctx.new_rustfunc(os_setpgid),
12881385
"setuid" => ctx.new_rustfunc(os_setuid),
@@ -1305,6 +1402,7 @@ fn extend_module_platform_specific(vm: &VirtualMachine, module: PyObjectRef) ->
13051402
"EX_NOPERM" => ctx.new_int(exitcode::NOPERM as i8),
13061403
"EX_CONFIG" => ctx.new_int(exitcode::CONFIG as i8),
13071404
"O_DSYNC" => ctx.new_int(libc::O_DSYNC),
1405+
"O_NONBLOCK" => ctx.new_int(libc::O_NONBLOCK),
13081406
"O_NDELAY" => ctx.new_int(libc::O_NDELAY),
13091407
"O_NOCTTY" => ctx.new_int(libc::O_NOCTTY),
13101408
"O_CLOEXEC" => ctx.new_int(libc::O_CLOEXEC),
@@ -1335,6 +1433,19 @@ fn extend_module_platform_specific(vm: &VirtualMachine, module: PyObjectRef) ->
13351433
"SEEK_DATA" => ctx.new_int(Whence::SeekData as i8),
13361434
"SEEK_HOLE" => ctx.new_int(Whence::SeekHole as i8)
13371435
});
1436+
// cfg from nix
1437+
#[cfg(any(
1438+
target_os = "android",
1439+
target_os = "dragonfly",
1440+
target_os = "emscripten",
1441+
target_os = "freebsd",
1442+
target_os = "linux",
1443+
target_os = "netbsd",
1444+
target_os = "openbsd"
1445+
))]
1446+
extend_module!(vm, module, {
1447+
"pipe2" => ctx.new_rustfunc(os_pipe2),
1448+
});
13381449

13391450
module
13401451
}

0 commit comments

Comments
 (0)