Implement mknod and mknodat
This commit is contained in:
committed by
Jeremy Soller
parent
0f9aca12dd
commit
0caf011122
@@ -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]
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user