Skip to content

Commit 13d0c07

Browse files
authored
Merge pull request RustPython#1191 from mpajkowski/os_module
Implement several methods - os module
2 parents c2ec66f + 364ddeb commit 13d0c07

5 files changed

Lines changed: 208 additions & 0 deletions

File tree

Cargo.lock

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/snippets/stdlib_os.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import time
33
import stat
4+
import sys
45

56
from testutils import assert_raises
67

@@ -251,3 +252,25 @@ def __exit__(self, exc_type, exc_val, exc_tb):
251252
assert isinstance(os.supports_fd, set)
252253
assert isinstance(os.supports_dir_fd, set)
253254
assert isinstance(os.supports_follow_symlinks, set)
255+
256+
# get pid
257+
assert isinstance(os.getpid(), int)
258+
259+
# unix
260+
if "win" not in sys.platform:
261+
assert isinstance(os.getegid(), int)
262+
assert isinstance(os.getgid(), int)
263+
assert isinstance(os.getsid(os.getpid()), int)
264+
assert isinstance(os.getuid(), int)
265+
assert isinstance(os.geteuid(), int)
266+
assert isinstance(os.getppid(), int)
267+
assert isinstance(os.getpgid(os.getpid()), int)
268+
269+
assert os.getppid() < os.getpid()
270+
271+
if os.getuid() != 0:
272+
assert_raises(PermissionError, lambda: os.setgid(42))
273+
assert_raises(PermissionError, lambda: os.setegid(42))
274+
assert_raises(PermissionError, lambda: os.setpgid(os.getpid(), 42))
275+
assert_raises(PermissionError, lambda: os.setuid(42))
276+
assert_raises(PermissionError, lambda: os.seteuid(42))

vm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ maplit = "1.0"
6161
proc-macro-hack = { version = "0.5", optional = true }
6262
bitflags = "1.1"
6363
libc = "0.2"
64+
nix = "0.14.1"
6465

6566
flame = { version = "0.2", optional = true }
6667
flamer = { version = "0.3", optional = true }

vm/src/builtins.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,7 @@ pub fn make_module(vm: &VirtualMachine, module: PyObjectRef) {
892892
"FileExistsError" => ctx.exceptions.file_exists_error.clone(),
893893
"StopIteration" => ctx.exceptions.stop_iteration.clone(),
894894
"SystemError" => ctx.exceptions.system_error.clone(),
895+
"PermissionError" => ctx.exceptions.permission_error.clone(),
895896
"UnicodeError" => ctx.exceptions.unicode_error.clone(),
896897
"UnicodeDecodeError" => ctx.exceptions.unicode_decode_error.clone(),
897898
"UnicodeEncodeError" => ctx.exceptions.unicode_encode_error.clone(),

vm/src/stdlib/os.rs

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ use std::time::{Duration, SystemTime};
66
use std::{env, fs};
77

88
use bitflags::bitflags;
9+
#[cfg(unix)]
10+
use nix::errno::Errno;
11+
#[cfg(unix)]
12+
use nix::unistd::{self, Gid, Pid, Uid};
913
use num_traits::cast::ToPrimitive;
1014

1115
use crate::function::{IntoPyNativeFunc, PyFuncArgs};
@@ -174,6 +178,43 @@ fn convert_io_error(vm: &VirtualMachine, err: io::Error) -> PyObjectRef {
174178
os_error
175179
}
176180

181+
#[cfg(unix)]
182+
fn convert_nix_error(vm: &VirtualMachine, err: nix::Error) -> PyObjectRef {
183+
let nix_error = match err {
184+
nix::Error::InvalidPath => {
185+
let exc_type = vm.ctx.exceptions.file_not_found_error.clone();
186+
vm.new_exception(exc_type, err.to_string())
187+
}
188+
nix::Error::InvalidUtf8 => {
189+
let exc_type = vm.ctx.exceptions.unicode_error.clone();
190+
vm.new_exception(exc_type, err.to_string())
191+
}
192+
nix::Error::UnsupportedOperation => {
193+
let exc_type = vm.ctx.exceptions.runtime_error.clone();
194+
vm.new_exception(exc_type, err.to_string())
195+
}
196+
nix::Error::Sys(errno) => {
197+
let exc_type = convert_nix_errno(vm, errno);
198+
vm.new_exception(exc_type, err.to_string())
199+
}
200+
};
201+
202+
if let nix::Error::Sys(errno) = err {
203+
vm.set_attr(&nix_error, "errno", vm.ctx.new_int(errno as i32))
204+
.unwrap();
205+
}
206+
207+
nix_error
208+
}
209+
210+
#[cfg(unix)]
211+
fn convert_nix_errno(vm: &VirtualMachine, errno: Errno) -> PyClassRef {
212+
match errno {
213+
Errno::EPERM => vm.ctx.exceptions.permission_error.clone(),
214+
_ => vm.ctx.exceptions.os_error.clone(),
215+
}
216+
}
217+
177218
fn os_error(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
178219
arg_check!(
179220
vm,
@@ -709,6 +750,105 @@ fn os_rename(src: PyStringRef, dst: PyStringRef, vm: &VirtualMachine) -> PyResul
709750
fs::rename(&src.value, &dst.value).map_err(|err| convert_io_error(vm, err))
710751
}
711752

753+
fn os_getpid(vm: &VirtualMachine) -> PyObjectRef {
754+
let pid = std::process::id();
755+
vm.new_int(pid)
756+
}
757+
758+
#[cfg(unix)]
759+
fn os_getppid(vm: &VirtualMachine) -> PyObjectRef {
760+
let ppid = unistd::getppid().as_raw();
761+
vm.new_int(ppid)
762+
}
763+
764+
#[cfg(unix)]
765+
fn os_getgid(vm: &VirtualMachine) -> PyObjectRef {
766+
let gid = unistd::getgid().as_raw();
767+
vm.new_int(gid)
768+
}
769+
770+
#[cfg(unix)]
771+
fn os_getegid(vm: &VirtualMachine) -> PyObjectRef {
772+
let egid = unistd::getegid().as_raw();
773+
vm.new_int(egid)
774+
}
775+
776+
#[cfg(unix)]
777+
fn os_getpgid(pid: PyIntRef, vm: &VirtualMachine) -> PyObjectRef {
778+
let pid = pid.as_bigint().to_u32().unwrap();
779+
780+
match unistd::getpgid(Some(Pid::from_raw(pid as i32))) {
781+
Ok(pgid) => vm.new_int(pgid.as_raw()),
782+
Err(err) => convert_nix_error(vm, err),
783+
}
784+
}
785+
786+
#[cfg(unix)]
787+
fn os_getsid(pid: PyIntRef, vm: &VirtualMachine) -> PyObjectRef {
788+
let pid = pid.as_bigint().to_u32().unwrap();
789+
790+
match unistd::getsid(Some(Pid::from_raw(pid as i32))) {
791+
Ok(sid) => vm.new_int(sid.as_raw()),
792+
Err(err) => convert_nix_error(vm, err),
793+
}
794+
}
795+
796+
#[cfg(unix)]
797+
fn os_getuid(vm: &VirtualMachine) -> PyObjectRef {
798+
let uid = unistd::getuid().as_raw();
799+
vm.new_int(uid)
800+
}
801+
802+
#[cfg(unix)]
803+
fn os_geteuid(vm: &VirtualMachine) -> PyObjectRef {
804+
let euid = unistd::geteuid().as_raw();
805+
vm.new_int(euid)
806+
}
807+
808+
#[cfg(unix)]
809+
fn os_setgid(gid: PyIntRef, vm: &VirtualMachine) -> PyResult<()> {
810+
let gid = gid.as_bigint().to_u32().unwrap();
811+
812+
unistd::setgid(Gid::from_raw(gid)).map_err(|err| convert_nix_error(vm, err))
813+
}
814+
815+
#[cfg(unix)]
816+
fn os_setegid(egid: PyIntRef, vm: &VirtualMachine) -> PyResult<()> {
817+
let egid = egid.as_bigint().to_u32().unwrap();
818+
819+
unistd::setegid(Gid::from_raw(egid)).map_err(|err| convert_nix_error(vm, err))
820+
}
821+
822+
#[cfg(unix)]
823+
fn os_setpgid(pid: PyIntRef, pgid: PyIntRef, vm: &VirtualMachine) -> PyResult<()> {
824+
let pid = pid.as_bigint().to_u32().unwrap();
825+
let pgid = pgid.as_bigint().to_u32().unwrap();
826+
827+
unistd::setpgid(Pid::from_raw(pid as i32), Pid::from_raw(pgid as i32))
828+
.map_err(|err| convert_nix_error(vm, err))
829+
}
830+
831+
#[cfg(unix)]
832+
fn os_setsid(vm: &VirtualMachine) -> PyResult<()> {
833+
unistd::setsid()
834+
.map(|_ok| ())
835+
.map_err(|err| convert_nix_error(vm, err))
836+
}
837+
838+
#[cfg(unix)]
839+
fn os_setuid(uid: PyIntRef, vm: &VirtualMachine) -> PyResult<()> {
840+
let uid = uid.as_bigint().to_u32().unwrap();
841+
842+
unistd::setuid(Uid::from_raw(uid)).map_err(|err| convert_nix_error(vm, err))
843+
}
844+
845+
#[cfg(unix)]
846+
fn os_seteuid(euid: PyIntRef, vm: &VirtualMachine) -> PyResult<()> {
847+
let euid = euid.as_bigint().to_u32().unwrap();
848+
849+
unistd::seteuid(Uid::from_raw(euid)).map_err(|err| convert_nix_error(vm, err))
850+
}
851+
712852
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
713853
let ctx = &vm.ctx;
714854

@@ -832,6 +972,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
832972
"R_OK" => ctx.new_int(4),
833973
"W_OK" => ctx.new_int(2),
834974
"X_OK" => ctx.new_int(1),
975+
"getpid" => ctx.new_rustfunc(os_getpid)
835976
});
836977

837978
for support in support_funcs {
@@ -863,5 +1004,33 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
8631004
"supports_follow_symlinks" => supports_follow_symlinks.into_object(),
8641005
});
8651006

1007+
extend_module_platform_specific(&vm, module)
1008+
}
1009+
1010+
#[cfg(unix)]
1011+
fn extend_module_platform_specific(vm: &VirtualMachine, module: PyObjectRef) -> PyObjectRef {
1012+
let ctx = &vm.ctx;
1013+
1014+
extend_module!(vm, module, {
1015+
"getppid" => ctx.new_rustfunc(os_getppid),
1016+
"getgid" => ctx.new_rustfunc(os_getgid),
1017+
"getegid" => ctx.new_rustfunc(os_getegid),
1018+
"getpgid" => ctx.new_rustfunc(os_getpgid),
1019+
"getsid" => ctx.new_rustfunc(os_getsid),
1020+
"getuid" => ctx.new_rustfunc(os_getuid),
1021+
"geteuid" => ctx.new_rustfunc(os_geteuid),
1022+
"setgid" => ctx.new_rustfunc(os_setgid),
1023+
"setegid" => ctx.new_rustfunc(os_setegid),
1024+
"setpgid" => ctx.new_rustfunc(os_setpgid),
1025+
"setsid" => ctx.new_rustfunc(os_setsid),
1026+
"setuid" => ctx.new_rustfunc(os_setuid),
1027+
"seteuid" => ctx.new_rustfunc(os_seteuid),
1028+
});
1029+
1030+
module
1031+
}
1032+
1033+
#[cfg(not(unix))]
1034+
fn extend_module_platform_specific(_vm: &VirtualMachine, module: PyObjectRef) -> PyObjectRef {
8661035
module
8671036
}

0 commit comments

Comments
 (0)