Implement mknod and mknodat

This commit is contained in:
Abdullah Emad
2024-01-03 16:43:28 +00:00
committed by Jeremy Soller
parent 0f9aca12dd
commit 0caf011122
14 changed files with 184 additions and 16 deletions
+15 -3
View File
@@ -117,9 +117,21 @@ pub unsafe extern "C" fn mkfifo(path: *const c_char, mode: mode_t) -> c_int {
Sys::mkfifo(path, mode)
}
// #[no_mangle]
pub extern "C" fn mknod(path: *const c_char, mode: mode_t, dev: dev_t) -> c_int {
unimplemented!();
#[no_mangle]
pub unsafe extern "C" fn mknod(path: *const c_char, mode: mode_t, dev: dev_t) -> c_int {
let path = CStr::from_ptr(path);
Sys::mknod(path, mode, dev)
}
#[no_mangle]
pub unsafe extern "C" fn mknodat(
dirfd: c_int,
path: *const c_char,
mode: mode_t,
dev: dev_t,
) -> c_int {
let path = CStr::from_ptr(path);
Sys::mknodat(dirfd, path, mode, dev)
}
#[no_mangle]
+17 -2
View File
@@ -4,7 +4,7 @@ use core_io::Write;
use super::{errno, types::*, Pal};
use crate::{
c_str::CStr,
header::{dirent::dirent, signal::SIGCHLD, sys_stat::S_IFIFO},
header::{dirent::dirent, errno::EINVAL, signal::SIGCHLD, sys_stat::S_IFIFO},
};
// use header::sys_resource::rusage;
use crate::header::{
@@ -357,8 +357,23 @@ impl Pal for Sys {
e(unsafe { syscall!(MKDIRAT, AT_FDCWD, path.as_ptr(), mode) }) as c_int
}
fn mknodat(dir_fildes: c_int, path: CStr, mode: mode_t, dev: dev_t) -> c_int {
// Note: dev_t is c_long (i64) and __kernel_dev_t is u32; So we need to cast it
// and check for overflow
let k_dev: c_uint = dev as c_uint;
if k_dev as dev_t != dev {
return e(EINVAL as usize) as c_int;
}
e(unsafe { syscall!(MKNODAT, dir_fildes, path.as_ptr(), mode, k_dev) }) as c_int
}
fn mknod(path: CStr, mode: mode_t, dev: dev_t) -> c_int {
Sys::mknodat(AT_FDCWD, path, mode, dev)
}
fn mkfifo(path: CStr, mode: mode_t) -> c_int {
e(unsafe { syscall!(MKNODAT, AT_FDCWD, path.as_ptr(), mode | S_IFIFO, 0) }) as c_int
Sys::mknod(path, mode | S_IFIFO, 0)
}
unsafe fn mlock(addr: *const c_void, len: usize) -> c_int {
+4
View File
@@ -138,6 +138,10 @@ pub trait Pal {
fn mkfifo(path: CStr, mode: mode_t) -> c_int;
fn mknodat(fildes: c_int, path: CStr, mode: mode_t, dev: dev_t) -> c_int;
fn mknod(path: CStr, mode: mode_t, dev: dev_t) -> c_int;
unsafe fn mlock(addr: *const c_void, len: usize) -> c_int;
fn mlockall(flags: c_int) -> c_int;
+40 -7
View File
@@ -10,7 +10,7 @@ use crate::{
fs::File,
header::{
dirent::dirent,
errno::{EINVAL, EIO, ENOMEM, ENOSYS, EPERM, ERANGE},
errno::{EBADR, EINVAL, EIO, ENOENT, ENOMEM, ENOSYS, EPERM, ERANGE},
fcntl,
sys_mman::{MAP_ANONYMOUS, MAP_FAILED, PROT_READ, PROT_WRITE},
sys_random,
@@ -187,7 +187,7 @@ impl Pal for Sys {
fn clock_getres(clk_id: clockid_t, tp: *mut timespec) -> c_int {
// TODO
eprintln!("relibc clock_getres({}, {:p}): not implemented", clk_id, tp);
unsafe { errno = ENOSYS };
unsafe { errno = ENOSYS }
-1
}
@@ -616,11 +616,44 @@ impl Pal for Sys {
}
fn mkfifo(path: CStr, mode: mode_t) -> c_int {
match File::create(
path,
fcntl::O_CREAT | fcntl::O_CLOEXEC,
syscall::MODE_FIFO as mode_t | (mode & 0o777),
) {
Sys::mknod(path, syscall::MODE_FIFO as mode_t | (mode & 0o777), 0)
}
fn mknodat(dir_fd: c_int, path_name: CStr, mode: mode_t, dev: dev_t) -> c_int {
let mut dir_path_buf = [0; 4096];
let res = Sys::fpath(dir_fd, &mut dir_path_buf);
if res < 0 {
return !0;
}
let dir_path = match str::from_utf8(&dir_path_buf[..res as usize]) {
Ok(path) => path,
Err(_) => {
unsafe { errno = EBADR };
return !0;
}
};
let resource_path =
match path::canonicalize_using_cwd(Some(&dir_path), &path_name.to_string_lossy()) {
Some(path) => path,
None => {
// Since parent_dir_path is resolved by fpath, it is more likely that
// the problem was with path.
unsafe { errno = ENOENT };
return !0;
}
};
Sys::mknod(
CStr::borrow(&CString::new(resource_path.as_bytes()).unwrap()),
mode,
dev,
)
}
fn mknod(path: CStr, mode: mode_t, dev: dev_t) -> c_int {
match File::create(path, fcntl::O_CREAT | fcntl::O_CLOEXEC, mode) {
Ok(fd) => 0,
Err(_) => -1,
}
+5 -3
View File
@@ -33,7 +33,7 @@ EXPECT_NAMES=\
stdio/fseek \
stdio/fwrite \
stdio/getc_unget \
stdio/getline \
stdio/getline \
stdio/mutex \
stdio/popen \
stdio/printf \
@@ -131,9 +131,11 @@ EXPECT_NAMES=\
wchar/wcsnrtombs \
wchar/wcswidth \
wctype/towlower \
wctype/towupper
wctype/towupper \
mkfifo \
mknod \
mknodat \
# TODO: Fix these
# mkfifo
# netdb/netdb \
BUILD?=.
+1 -1
View File
@@ -7,7 +7,7 @@
#include <errno.h>
#include <stdio.h>
int main(int argc, char** argv) {
int main(void) {
char temp[] = "/tmp/stattest-XXXXXX";
const char file[] = "/mkfifo_fifo";
int len = sizeof(temp) + sizeof(file);
+45
View File
@@ -0,0 +1,45 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
int main(void) {
char temp[] = "/tmp/stattest-XXXXXX";
const char file[] = "/mknod";
int len = sizeof(temp) + sizeof(file);
char* path = malloc(len * sizeof(char));
if (path == NULL) {
fprintf(stderr, "Could not allocate: %s\n", strerror(errno));
exit(1);
}
if(!mktemp(temp)) {
fprintf(stderr, "Unable to create a unique dir name %s: %s\n", temp, strerror(errno));
exit(1);
}
path = strncat(path, temp, strlen(temp));
path = strncat(path, file, strlen(file));
if (mkdir(temp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) {
fprintf(stderr, "mkdir %s: %s\n", temp, strerror(errno));
exit(1);
}
if (mknod(path, S_IFREG, S_IRUSR) == -1) {
fprintf(stderr, "mknod %s: %s\n", path, strerror(errno));
exit(1);
}
struct stat sb;
if (stat(path, &sb) != 0) {
fprintf(stderr, "stat: %s\n", strerror(errno));
exit(1);
}
if (!(sb.st_mode & S_IFREG)) {
fprintf(stderr, "Expected S_IFREG flag to be set, got mode: %d\n", sb.st_mode);
exit(1);
}
}
+57
View File
@@ -0,0 +1,57 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
int main(void) {
char temp[] = "/tmp/stattest-XXXXXX";
const char separator[] = "/";
const char file[] = "mknod"; // relative
int len = sizeof(temp) + sizeof(file) + sizeof(separator);
char* path = malloc(len * sizeof(char));
if (path == NULL) {
fprintf(stderr, "Could not allocate: %s\n", strerror(errno));
exit(1);
}
if(!mktemp(temp)) {
fprintf(stderr, "Unable to create a unique dir name %s: %s\n", temp, strerror(errno));
exit(1);
}
if (mkdir(temp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) {
fprintf(stderr, "mkdir %s: %s\n", temp, strerror(errno));
exit(1);
}
int dir_fd = open(temp, O_RDONLY);
if(dir_fd == -1) {
fprintf(stderr, "unable to open temp directory: %s with error: %s\n", temp, strerror(errno));
exit(1);
}
if (mknodat(dir_fd, file, S_IFREG, S_IRUSR) == -1) {
fprintf(stderr, "mknod %s: %s\n", path, strerror(errno));
exit(1);
}
path = strncat(path, temp, strlen(temp));
path = strncat(path, separator, strlen(temp));
path = strncat(path, file, strlen(file));
struct stat sb;
if (stat(path, &sb) != 0) {
fprintf(stderr, "stat for %s: %s\n", path, strerror(errno));
exit(1);
}
if (!(sb.st_mode & S_IFREG)) {
fprintf(stderr, "Expected S_IFREG flag to be set, got mode: %d\n", sb.st_mode);
exit(1);
}
}