Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 6 additions & 37 deletions libc-bottom-half/cloudlibc/src/libc/sys/stat/futimens.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,8 @@

#include "stat_impl.h"

#ifdef __wasilibc_use_wasip2
static void set_atim_tag_from_flags(__wasi_fstflags_t flags, filesystem_new_timestamp_t* timestamp) {
if (flags & __WASI_FSTFLAGS_ATIM) {
timestamp->tag = FILESYSTEM_NEW_TIMESTAMP_TIMESTAMP;
} else if (flags & __WASI_FSTFLAGS_ATIM_NOW) {
timestamp->tag = FILESYSTEM_NEW_TIMESTAMP_NOW;
} else {
timestamp->tag = FILESYSTEM_NEW_TIMESTAMP_NO_CHANGE;
}
}

static void set_mtim_tag_from_flags(__wasi_fstflags_t flags, filesystem_new_timestamp_t* timestamp) {
if (flags & __WASI_FSTFLAGS_MTIM) {
timestamp->tag = FILESYSTEM_NEW_TIMESTAMP_TIMESTAMP;
} else if (flags & __WASI_FSTFLAGS_MTIM_NOW) {
timestamp->tag = FILESYSTEM_NEW_TIMESTAMP_NOW;
} else {
timestamp->tag = FILESYSTEM_NEW_TIMESTAMP_NO_CHANGE;
}
}

int futimens(int fd, const struct timespec *times) {
// Translate the file descriptor to an internal handle
#ifdef __wasilibc_use_wasip2
// Translate the file descriptor to an internal handle
filesystem_borrow_descriptor_t file_handle;
if (!fd_to_file_handle_allow_open(fd, &file_handle)) {
Expand All @@ -46,22 +25,14 @@ int futimens(int fd, const struct timespec *times) {
}

// Convert timestamps and extract NOW/OMIT flags.
filesystem_datetime_t st_atim;
filesystem_datetime_t st_mtim;
filesystem_new_timestamp_t new_timestamp_atim;
filesystem_new_timestamp_t new_timestamp_mtim;
__wasi_fstflags_t flags;
if (!utimens_get_timestamps(times, &st_atim, &st_mtim, &flags)) {
if (!utimens_get_timestamps(times, &new_timestamp_atim, &new_timestamp_mtim)) {
errno = EINVAL;
return -1;
}

// Set up filesystem_new_timestamps
filesystem_new_timestamp_t new_timestamp_atim;
set_atim_tag_from_flags(flags, &new_timestamp_atim);
new_timestamp_atim.val.timestamp = st_atim;
filesystem_new_timestamp_t new_timestamp_mtim;
set_mtim_tag_from_flags(flags, &new_timestamp_mtim);
new_timestamp_mtim.val.timestamp = st_mtim;

// Perform system call.
filesystem_error_code_t error;
if (!filesystem_method_descriptor_set_times(file_handle,
Expand All @@ -72,10 +43,7 @@ int futimens(int fd, const struct timespec *times) {
return -1;
}

return 0;
}
#else
int futimens(int fd, const struct timespec *times) {
// Convert timestamps and extract NOW/OMIT flags.
__wasi_timestamp_t st_atim;
__wasi_timestamp_t st_mtim;
Expand All @@ -91,6 +59,7 @@ int futimens(int fd, const struct timespec *times) {
errno = error;
return -1;
}
#endif

return 0;
}
#endif
69 changes: 26 additions & 43 deletions libc-bottom-half/cloudlibc/src/libc/sys/stat/stat_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,53 +127,36 @@ static inline void to_public_stat(const __wasi_filestat_t *in,
#endif

#ifdef __wasilibc_use_wasip2
static inline bool utimens_get_timestamp(const struct timespec *time,
filesystem_new_timestamp_t *out) {
switch (time->tv_nsec) {
case UTIME_NOW:
out->tag = FILESYSTEM_NEW_TIMESTAMP_NOW;
break;
case UTIME_OMIT:
out->tag = FILESYSTEM_NEW_TIMESTAMP_NO_CHANGE;
break;
default:
out->tag = FILESYSTEM_NEW_TIMESTAMP_TIMESTAMP;
if (!timespec_to_timestamp_exact(time, &out->val.timestamp))
return false;
break;
}
return true;
}

static inline bool utimens_get_timestamps(const struct timespec *times,
filesystem_datetime_t *st_atim,
filesystem_datetime_t *st_mtim,
__wasi_fstflags_t *flags) {
filesystem_new_timestamp_t *st_atim,
filesystem_new_timestamp_t *st_mtim) {
if (times == NULL) {
// Update both timestamps.
*flags = __WASI_FSTFLAGS_ATIM_NOW | __WASI_FSTFLAGS_MTIM_NOW;
st_atim->seconds = 0;
st_atim->nanoseconds = 0;
st_mtim->seconds = 0;
st_mtim->nanoseconds = 0;
st_atim->tag = FILESYSTEM_NEW_TIMESTAMP_NOW;
st_mtim->tag = FILESYSTEM_NEW_TIMESTAMP_NOW;
} else {
// Set individual timestamps.
*flags = 0;
switch (times[0].tv_nsec) {
case UTIME_NOW:
*flags |= __WASI_FSTFLAGS_ATIM_NOW;
st_atim->seconds = 0;
st_atim->nanoseconds = 0;
break;
case UTIME_OMIT:
st_atim->seconds = 0;
st_atim->nanoseconds = 0;
break;
default:
*flags |= __WASI_FSTFLAGS_ATIM;
if (!timespec_to_timestamp_exact(&times[0], st_atim))
return false;
break;
}

switch (times[1].tv_nsec) {
case UTIME_NOW:
*flags |= __WASI_FSTFLAGS_MTIM_NOW;
st_mtim->seconds = 0;
st_mtim->nanoseconds = 0;
break;
case UTIME_OMIT:
st_mtim->seconds = 0;
st_mtim->nanoseconds = 0;
break;
default:
*flags |= __WASI_FSTFLAGS_MTIM;
if (!timespec_to_timestamp_exact(&times[1], st_mtim))
return false;
break;
}
if (!utimens_get_timestamp(&times[0], st_atim))
return false;
if (!utimens_get_timestamp(&times[1], st_mtim))
return false;
}
return true;
}
Expand Down
25 changes: 6 additions & 19 deletions libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@

#include "stat_impl.h"

#ifdef __wasilibc_use_wasip2
int __wasilibc_nocwd_utimensat(int fd, const char *path, const struct timespec times[2],
int flag) {
// Translate the file descriptor to an internal handle
#ifdef __wasilibc_use_wasip2
// Translate the file descriptor to an internal handle
filesystem_borrow_descriptor_t file_handle;
if (!fd_to_file_handle_allow_open(fd, &file_handle)) {
Expand All @@ -29,22 +28,13 @@ int __wasilibc_nocwd_utimensat(int fd, const char *path, const struct timespec t
}

// Convert timestamps and extract NOW/OMIT flags.
filesystem_datetime_t st_atim;
filesystem_datetime_t st_mtim;
__wasi_fstflags_t flags;
if (!utimens_get_timestamps(times, &st_atim, &st_mtim, &flags)) {
filesystem_new_timestamp_t new_timestamp_atim;
filesystem_new_timestamp_t new_timestamp_mtim;
if (!utimens_get_timestamps(times, &new_timestamp_atim, &new_timestamp_mtim)) {
errno = EINVAL;
return -1;
}

// Set up filesystem_new_timestamps
filesystem_new_timestamp_t new_timestamp_atim;
new_timestamp_atim.tag = FILESYSTEM_NEW_TIMESTAMP_TIMESTAMP;
new_timestamp_atim.val.timestamp = st_atim;
filesystem_new_timestamp_t new_timestamp_mtim;
new_timestamp_mtim.tag = FILESYSTEM_NEW_TIMESTAMP_TIMESTAMP;
new_timestamp_mtim.val.timestamp = st_mtim;

// Create lookup properties.
__wasi_lookupflags_t lookup_flags = 0;
if ((flag & AT_SYMLINK_NOFOLLOW) == 0)
Expand All @@ -68,11 +58,8 @@ int __wasilibc_nocwd_utimensat(int fd, const char *path, const struct timespec t
return -1;
}

return 0;
}
#else
int __wasilibc_nocwd_utimensat(int fd, const char *path, const struct timespec times[2],
int flag) {

// Convert timestamps and extract NOW/OMIT flags.
__wasi_timestamp_t st_atim;
__wasi_timestamp_t st_mtim;
Expand All @@ -94,6 +81,6 @@ int __wasilibc_nocwd_utimensat(int fd, const char *path, const struct timespec t
errno = error;
return -1;
}
#endif
return 0;
}
#endif
40 changes: 28 additions & 12 deletions test/src/utime.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include "test.h"

#define TEST(c, ...) ((c) ? 1 : (t_error(#c" failed: " __VA_ARGS__),0))
Expand All @@ -24,27 +25,32 @@ static FILE *make_temp_file() {
return f;
}

int main(void)
static int doit_futimens(int fd, const struct timespec times[2]) {
return futimens(fd, times);
}

static int doit_utimensat(int fd, const struct timespec times[2]) {
return utimensat(AT_FDCWD, "temp_file", times, 0);
}

void run(int (*set_times)(int, const struct timespec[2]))
{
struct stat st;
FILE *f;
int fd;
time_t t;

TEST(futimens(-1, ((struct timespec[2]){{.tv_nsec=UTIME_OMIT},{.tv_nsec=UTIME_OMIT}}))==0 || errno==EBADF,
"%s\n", strerror(errno));

if (!TEST(f = make_temp_file())) return t_status;
if (!TEST(f = make_temp_file())) return;
fd = fileno(f);

TEST(futimens(fd, (struct timespec[2]){0}) == 0, "\n");
TEST(set_times(fd, (struct timespec[2]){0}) == 0, "\n");
TEST(fstat(fd, &st) == 0, "\n");
TESTVAL(st.st_atim.tv_sec,==,0);
TESTVAL(st.st_atim.tv_nsec,==,0);
TESTVAL(st.st_mtim.tv_sec,==,0);
TESTVAL(st.st_mtim.tv_nsec,==,0);

TEST(futimens(fd, ((struct timespec[2]){{.tv_sec=1,.tv_nsec=UTIME_OMIT},{.tv_sec=1,.tv_nsec=UTIME_OMIT}})) == 0, "\n");
TEST(set_times(fd, ((struct timespec[2]){{.tv_sec=1,.tv_nsec=UTIME_OMIT},{.tv_sec=1,.tv_nsec=UTIME_OMIT}})) == 0, "\n");
TEST(fstat(fd, &st) == 0, "\n");
TESTVAL(st.st_atim.tv_sec,==,0);
TESTVAL(st.st_atim.tv_nsec,==,0);
Expand All @@ -53,32 +59,42 @@ int main(void)

t = time(0);

TEST(futimens(fd, ((struct timespec[2]){{.tv_nsec=UTIME_NOW},{.tv_nsec=UTIME_OMIT}})) == 0, "\n");
TEST(set_times(fd, ((struct timespec[2]){{.tv_nsec=UTIME_NOW},{.tv_nsec=UTIME_OMIT}})) == 0, "\n");
TEST(fstat(fd, &st) == 0, "\n");
TESTVAL(st.st_atim.tv_sec,>=,t);
TESTVAL(st.st_mtim.tv_sec,==,0);
TESTVAL(st.st_mtim.tv_nsec,==,0);

TEST(futimens(fd, (struct timespec[2]){0}) == 0, "\n");
TEST(futimens(fd, ((struct timespec[2]){{.tv_nsec=UTIME_OMIT},{.tv_nsec=UTIME_NOW}})) == 0, "\n");
TEST(set_times(fd, (struct timespec[2]){0}) == 0, "\n");
TEST(set_times(fd, ((struct timespec[2]){{.tv_nsec=UTIME_OMIT},{.tv_nsec=UTIME_NOW}})) == 0, "\n");
TEST(fstat(fd, &st) == 0, "\n");
TESTVAL(st.st_atim.tv_sec,==,0);
TESTVAL(st.st_mtim.tv_sec,>=,t);

TEST(futimens(fd, ((struct timespec[2]){{.tv_nsec=UTIME_NOW},{.tv_nsec=UTIME_OMIT}})) == 0, "\n");
TEST(set_times(fd, ((struct timespec[2]){{.tv_nsec=UTIME_NOW},{.tv_nsec=UTIME_OMIT}})) == 0, "\n");
TEST(fstat(fd, &st) == 0, "\n");
TESTVAL(st.st_atim.tv_sec,>=,t);
TESTVAL(st.st_mtim.tv_sec,>=,t);

if (TEST((time_t)(1LL<<32) == (1LL<<32), "implementation has Y2038 EOL\n")) {
if (TEST(futimens(fd, ((struct timespec[2]){{.tv_sec=1LL<<32},{.tv_sec=1LL<<32}})) == 0, "%s\n", strerror(errno))) {
if (TEST(set_times(fd, ((struct timespec[2]){{.tv_sec=1LL<<32},{.tv_sec=1LL<<32}})) == 0, "%s\n", strerror(errno))) {
TEST(fstat(fd, &st) == 0, "\n");
TESTVAL(st.st_atim.tv_sec, ==, 1LL<<32);
TESTVAL(st.st_mtim.tv_sec, ==, 1LL<<32);
}
}

fclose(f);
}

int main(void)
{
TEST(futimens(-1, ((struct timespec[2]){{.tv_nsec=UTIME_OMIT},{.tv_nsec=UTIME_OMIT}}))==0 || errno==EBADF,
"%s\n", strerror(errno));
fprintf(stderr, "testing futimens...\n");
run(doit_futimens);
fprintf(stderr, "testing utimensat...\n");
run(doit_utimensat);

return t_status;
}