diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs index f417e5bb8bea721d2a0ebfcae8838fc6cdacae9c..3b15fd7e310f754d3014c1c5946cc5adcb97c558 100644 --- a/src/header/unistd/mod.rs +++ b/src/header/unistd/mod.rs @@ -5,7 +5,7 @@ use core::{convert::TryFrom, mem, ptr, slice}; use crate::{ c_str::CStr, header::{ - errno, limits, stdlib::getenv, sys_ioctl, sys_time, sys_utsname, termios, time::timespec, + errno, fcntl, limits, stdlib::getenv, sys_ioctl, sys_time, sys_utsname, termios, time::timespec, }, platform::{self, types::*, Pal, Sys}, }; @@ -649,9 +649,19 @@ pub extern "C" fn tcsetpgrp(fd: c_int, pgrp: pid_t) -> c_int { pgrp } -// #[no_mangle] +#[no_mangle] pub extern "C" fn truncate(path: *const c_char, length: off_t) -> c_int { - unimplemented!(); + let file = unsafe { CStr::from_ptr(path) }; + let fd = Sys::open(file, fcntl::O_WRONLY, 0); + if fd < 0 { + return -1; + } + + let res = ftruncate(fd, length); + + Sys::close(fd); + + res } #[no_mangle] diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index fe149a2b02f5eba677395c75c1533872d2f118c4..19b908ffed6727f5a746cdb291c2871e68765245 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -4,7 +4,7 @@ use core_io::Write; use super::{errno, types::*, Pal}; use crate::{ c_str::CStr, - header::{dirent::dirent, signal::SIGCHLD}, + header::{dirent::dirent, signal::SIGCHLD, sys_stat::S_IFIFO}, }; // use header::sys_resource::rusage; use crate::header::{ @@ -292,7 +292,7 @@ impl Pal for Sys { } fn mkfifo(path: &CStr, mode: mode_t) -> c_int { - e(unsafe { syscall!(MKNODAT, AT_FDCWD, path.as_ptr(), mode, 0) }) as c_int + e(unsafe { syscall!(MKNODAT, AT_FDCWD, path.as_ptr(), mode | S_IFIFO, 0) }) as c_int } unsafe fn mmap( diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index e9be21afc5d3ba13e6bf58c1d540efdeeec3f10e..b77cf63d1354421441d19c8fb2a6bb95bea5550a 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -319,31 +319,29 @@ impl Pal for Sys { let mut redox_buf: redox_stat = redox_stat::default(); match e(syscall::fstat(fildes as usize, &mut redox_buf)) { 0 => { - unsafe { - if !buf.is_null() { - (*buf).st_dev = redox_buf.st_dev as dev_t; - (*buf).st_ino = redox_buf.st_ino as ino_t; - (*buf).st_nlink = redox_buf.st_nlink as nlink_t; - (*buf).st_mode = redox_buf.st_mode as mode_t; - (*buf).st_uid = redox_buf.st_uid as uid_t; - (*buf).st_gid = redox_buf.st_gid as gid_t; - // TODO st_rdev - (*buf).st_rdev = 0; - (*buf).st_size = redox_buf.st_size as off_t; - (*buf).st_blksize = redox_buf.st_blksize as blksize_t; - (*buf).st_atim = timespec { - tv_sec: redox_buf.st_atime as time_t, - tv_nsec: redox_buf.st_atime_nsec as c_long, - }; - (*buf).st_mtim = timespec { - tv_sec: redox_buf.st_mtime as time_t, - tv_nsec: redox_buf.st_mtime_nsec as c_long, - }; - (*buf).st_ctim = timespec { - tv_sec: redox_buf.st_ctime as time_t, - tv_nsec: redox_buf.st_ctime_nsec as c_long, - }; - } + if let Some(buf) = unsafe { buf.as_mut() } { + buf.st_dev = redox_buf.st_dev as dev_t; + buf.st_ino = redox_buf.st_ino as ino_t; + buf.st_nlink = redox_buf.st_nlink as nlink_t; + buf.st_mode = redox_buf.st_mode as mode_t; + buf.st_uid = redox_buf.st_uid as uid_t; + buf.st_gid = redox_buf.st_gid as gid_t; + // TODO st_rdev + buf.st_rdev = 0; + buf.st_size = redox_buf.st_size as off_t; + buf.st_blksize = redox_buf.st_blksize as blksize_t; + buf.st_atim = timespec { + tv_sec: redox_buf.st_atime as time_t, + tv_nsec: redox_buf.st_atime_nsec as c_long, + }; + buf.st_mtim = timespec { + tv_sec: redox_buf.st_mtime as time_t, + tv_nsec: redox_buf.st_mtime_nsec as c_long, + }; + buf.st_ctim = timespec { + tv_sec: redox_buf.st_ctime as time_t, + tv_nsec: redox_buf.st_ctime_nsec as c_long, + }; } 0 } diff --git a/tests/Makefile b/tests/Makefile index 530aa93724d4306683b356c05d60bf19f91515b7..9a25da5920be297eb81f4ca97daa6258a47f35fa 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -13,6 +13,7 @@ EXPECT_NAMES=\ fcntl/create \ fcntl/fcntl \ fnmatch \ + futimens \ libgen \ locale \ math \ @@ -102,6 +103,8 @@ EXPECT_NAMES=\ wchar/wcstod \ wchar/wcstok \ wchar/wcstol + # TODO: Fix these + # mkfifo # Binaries that may generate varied output NAMES=\ diff --git a/tests/expected/futimens.stderr b/tests/expected/futimens.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/futimens.stdout b/tests/expected/futimens.stdout new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/mkfifo.stderr b/tests/expected/mkfifo.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/mkfifo.stdout b/tests/expected/mkfifo.stdout new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/futimens.c b/tests/futimens.c new file mode 100644 index 0000000000000000000000000000000000000000..78e7f4c96b123555cbc21ebf2c50eafb489b4ea3 --- /dev/null +++ b/tests/futimens.c @@ -0,0 +1,67 @@ +#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> +#include <unistd.h> + +int main(int argc, char** argv) { + char temp[] = "/tmp/stattest-XXXXXX"; + const char file[] = "/mkfifo_fifo"; + int len = sizeof(temp) + sizeof(int); + char* path = malloc(len * sizeof(char)); + + if (path == NULL) { + fprintf(stderr, "Could not allocate: %s\n", strerror(errno)); + exit(1); + } + + strncat(path, mktemp(temp), sizeof(temp)); + strncat(path, file, sizeof(file)); + if (mkdir(temp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) { + fprintf(stderr, "mkdir %s: %s\n", temp, strerror(errno)); + exit(1); + } + + int tmp = open(path, O_CREAT | O_CLOEXEC | O_RDONLY | S_IRWXU | S_IRWXG | S_IRWXO); + if (tmp == -1) { + fprintf(stderr, "touch %s: %s\n", path, strerror(errno)); + exit(1); + } + if (close(tmp) == -1) { + fprintf(stderr, "close %s: %s\n", path, strerror(errno)); + exit(1); + } + + int fd = open(path, 0, 0); + if (fd == -1) { + fprintf(stderr, "open %s: %s\n", path, strerror(errno)); + exit(1); + } + + const struct timespec times[] = { { .tv_sec = 10 }, { .tv_sec = 20 } }; + if (futimens(fd, times) == -1) { + fprintf(stderr, "futimens: %s\n", strerror(errno)); + exit(1); + } + + struct stat sb; + if (stat(path, &sb) != 0) { + fprintf(stderr, "stat: %s\n", strerror(errno)); + exit(1); + } + if (sb.st_mtim.tv_sec != 20 || sb.st_mtim.tv_nsec != 0) { + fprintf(stderr, "Wrong modified time: %d.%d\n", sb.st_mtim.tv_sec, sb.st_mtim.tv_nsec); + exit(1); + } + // Access times are not flushed to disk, so this check can't be (currently) performed + /* + * if (sb.st_atim.tv_sec != 10 || sb.st_atim.tv_nsec != 0) { + * fprintf(stderr, "Wrong accessed time: %d.%d\n", sb.st_atim.tv_sec, sb.st_atim.tv_nsec); + * exit(1); + * } + */ +} diff --git a/tests/mkfifo.c b/tests/mkfifo.c new file mode 100644 index 0000000000000000000000000000000000000000..6fb40ceef37e68f0cf26e811940fa4549eb4a17b --- /dev/null +++ b/tests/mkfifo.c @@ -0,0 +1,40 @@ +#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(int argc, char** argv) { + char temp[] = "/tmp/stattest-XXXXXX"; + const char file[] = "/mkfifo_fifo"; + 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); + } + + path = strncat(path, mktemp(temp), sizeof(temp)); + path = strncat(path, file, sizeof(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 (mkfifo(path, S_IRUSR) == -1) { + fprintf(stderr, "mkfifo %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_IFIFO)) { + fprintf(stderr, "Not a FIFO: %d\n", sb.st_mode); + exit(1); + } +} diff --git a/tests/unistd/ftruncate.c b/tests/unistd/ftruncate.c index 63b159abb6f5a2428c6c65f8f7f2071c4173d0c9..c1b35cefa593c56031815fc6c983d649c45b8351 100644 --- a/tests/unistd/ftruncate.c +++ b/tests/unistd/ftruncate.c @@ -17,4 +17,8 @@ int main(void) { int c = close(fd); ERROR_IF(close, c, == -1); UNEXP_IF(close, c, != 0); + + status = truncate("ftruncate.out", 100); + ERROR_IF(truncate, status, == -1); + UNEXP_IF(truncate, status, != 0); }