Skip to content

Commit e9138e9

Browse files
authored
Fchownat, ptsname and fstatfs (#115)
* add fchownat * set errno for incorrect einval * ptsname * fstatfs and fstatfs64 * set error cval for enotty for invalid fd * return errno from ptsname_r
1 parent f5a79e5 commit e9138e9

File tree

5 files changed

+120
-20
lines changed

5 files changed

+120
-20
lines changed

c-scape/src/fs/fchown.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use crate::convert_res;
2+
use core::ffi::CStr;
3+
use libc::{c_char, c_int, c_uint};
4+
use rustix::fd::BorrowedFd;
5+
use rustix::fs::AtFlags;
6+
7+
#[no_mangle]
8+
unsafe extern "C" fn fchownat(
9+
dirfd: c_int,
10+
pathname: *const c_char,
11+
owner: libc::uid_t,
12+
group: libc::gid_t,
13+
flags: c_int,
14+
) -> c_int {
15+
libc!(libc::fchownat(dirfd, pathname, owner, group, flags));
16+
17+
let pathname = CStr::from_ptr(pathname);
18+
let owner = Some(rustix::process::Uid::from_raw(owner));
19+
let group = Some(rustix::process::Gid::from_raw(group));
20+
let flags = AtFlags::from_bits_retain(flags as c_uint);
21+
let dirfd = BorrowedFd::borrow_raw(dirfd);
22+
match convert_res(rustix::fs::chownat(dirfd, pathname, owner, group, flags)) {
23+
Some(()) => 0,
24+
None => -1,
25+
}
26+
}

c-scape/src/fs/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod chmod;
44
mod dir;
55
mod fadvise;
66
mod fallocate;
7+
mod fchown;
78
mod fcntl;
89
mod flock;
910
mod inotify;

c-scape/src/fs/stat.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,60 @@ unsafe extern "C" fn statfs(path: *const c_char, stat_: *mut libc::statfs) -> c_
208208
None => -1,
209209
}
210210
}
211+
212+
#[no_mangle]
213+
unsafe extern "C" fn fstatfs64(fd: c_int, stat_: *mut libc::statfs64) -> c_int {
214+
libc!(libc::fstatfs64(fd, stat_));
215+
let stat_: *mut rustix::fs::StatFs = checked_cast!(stat_);
216+
217+
match convert_res(rustix::fs::fstatfs(BorrowedFd::borrow_raw(fd))) {
218+
Some(r) => {
219+
*stat_ = r;
220+
0
221+
}
222+
None => -1,
223+
}
224+
}
225+
226+
#[no_mangle]
227+
unsafe extern "C" fn fstatfs(fd: c_int, stat_: *mut libc::statfs) -> c_int {
228+
libc!(libc::fstatfs(fd, stat_));
229+
230+
match convert_res(rustix::fs::fstatfs(BorrowedFd::borrow_raw(fd))) {
231+
Some(r) => {
232+
#[cfg(target_os = "linux")]
233+
{
234+
let mut converted = core::mem::zeroed::<libc::statfs>();
235+
converted.f_type = r.f_type.try_into().unwrap();
236+
converted.f_bsize = r.f_bsize.try_into().unwrap();
237+
converted.f_blocks = r.f_blocks.try_into().unwrap();
238+
converted.f_bfree = r.f_bfree.try_into().unwrap();
239+
converted.f_bavail = r.f_bavail.try_into().unwrap();
240+
converted.f_files = r.f_files.try_into().unwrap();
241+
converted.f_ffree = r.f_ffree.try_into().unwrap();
242+
converted.f_namelen = r.f_namelen.try_into().unwrap();
243+
converted.f_frsize = r.f_frsize.try_into().unwrap();
244+
245+
// The libc crate declares `f_fsid` with private fields,
246+
// perhaps because who even knows what this field means,
247+
// but understanding is not required for the job here.
248+
assert_eq!(size_of_val(&r.f_fsid), size_of_val(&converted.f_fsid));
249+
copy_nonoverlapping(
250+
addr_of!(r.f_fsid).cast::<u8>(),
251+
addr_of_mut!(converted.f_fsid).cast::<u8>(),
252+
size_of_val(&r.f_fsid),
253+
);
254+
255+
*stat_ = converted;
256+
}
257+
258+
#[cfg(not(target_os = "linux"))]
259+
{
260+
*stat_ = r;
261+
}
262+
263+
0
264+
}
265+
None => -1,
266+
}
267+
}

c-scape/src/termios_/mod.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use crate::{convert_res, set_errno, Errno};
44
use core::mem::{size_of, transmute, zeroed};
55
use core::ops::Index;
6+
use core::ptr::copy_nonoverlapping;
67
use libc::{c_char, c_int, pid_t, termios, winsize};
78
use rustix::fd::{BorrowedFd, FromRawFd, IntoRawFd, OwnedFd};
89
use rustix::process::Pid;
@@ -545,3 +546,38 @@ unsafe extern "C" fn tcflow(fd: c_int, action: c_int) -> c_int {
545546
None => -1,
546547
}
547548
}
549+
550+
#[no_mangle]
551+
unsafe extern "C" fn ptsname(fd: c_int) -> *mut c_char {
552+
static mut PTS_BUFFER: [c_char; 30] = [0; 30];
553+
if ptsname_r(fd, PTS_BUFFER.as_mut_ptr(), PTS_BUFFER.len()) != 0 {
554+
core::ptr::null_mut()
555+
} else {
556+
PTS_BUFFER.as_mut_ptr()
557+
}
558+
}
559+
560+
#[no_mangle]
561+
unsafe extern "C" fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int {
562+
libc!(libc::ptsname_r(fd, buf, buflen));
563+
if buf.is_null() {
564+
Errno(libc::EINVAL).into()
565+
} else {
566+
let fd = BorrowedFd::borrow_raw(fd);
567+
match rustix::pty::ptsname(fd, []) {
568+
Ok(name) => {
569+
let len = name.as_bytes().len() + 1; // length inc null terminator
570+
if len > buflen {
571+
Errno(libc::ERANGE).into()
572+
} else {
573+
// we have checked the string will fit in the buffer
574+
// so can use strcpy safely
575+
let s = name.as_ptr().cast();
576+
copy_nonoverlapping(s, buf, len);
577+
0
578+
}
579+
}
580+
Err(err) => err.raw_os_error(),
581+
}
582+
}
583+
}

c-scape/src/todo.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,6 @@ unsafe extern "C" fn eaccess() {
4949
todo!("eaccess")
5050
}
5151
#[no_mangle]
52-
unsafe extern "C" fn fchownat() {
53-
todo!("fchownat")
54-
}
55-
#[no_mangle]
56-
unsafe extern "C" fn fstatfs() {
57-
todo!("fstatfs")
58-
}
59-
#[no_mangle]
60-
unsafe extern "C" fn fstatfs64() {
61-
todo!("fstatfs64")
62-
}
63-
#[no_mangle]
6452
unsafe extern "C" fn timerfd_gettime() {
6553
todo!("timerfd_gettime")
6654
}
@@ -360,14 +348,6 @@ unsafe extern "C" fn ptrace() {
360348
todo!("ptrace")
361349
}
362350
#[no_mangle]
363-
unsafe extern "C" fn ptsname() {
364-
todo!("ptsname")
365-
}
366-
#[no_mangle]
367-
unsafe extern "C" fn ptsname_r() {
368-
todo!("ptsname_r")
369-
}
370-
#[no_mangle]
371351
unsafe extern "C" fn forkpty() {
372352
todo!("forkpty")
373353
}

0 commit comments

Comments
 (0)