void fset_ftime(char *fnm, int fd, time_t mtime, time_t atime, int frc) { struct timespec tv[2]; tv[0].tv_sec = atime; tv[0].tv_nsec = 0L; tv[1].tv_sec = mtime; tv[1].tv_nsec = 0L; if (!frc) { /* * if we are not forcing, only set those times the user wants * set. */ if (!patime) tv[0].tv_nsec = UTIME_OMIT; if (!pmtime) tv[1].tv_nsec = UTIME_OMIT; } /* * set the times */ if (futimens(fd, tv) < 0) syswarn(1, errno, "Access/modification time set failed on: %s", fnm); }
int main(int argc, char *argv[]) { int i, fd; struct stat statbuf; struct timespec times[2]; for (int i = 0; i < argc; ++i) { if (stat(argv[i], &statbuf) < 0) { err_ret("%s: stat error", argv[i]); continue; } if ((fd = open(argv[i], O_RDWR | O_TRUNC)) < 0) { err_ret("%s :open error", argv[i]); continue; } times[0] = statbuf.st_atim; times[1] = statbuf.st_mtim; if (futimens(fd, times) < 0) err_ret("%s: futimens error", argv[i]); close(fd); } exit(0); }
void default_touch(const char *str) { #ifdef _MSC_VER int mode_file; #endif #ifdef __GNUC__ mode_t mode_file; #endif int handle; mode_file = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; if (access(str, F_OK) == ERROR) { if ((handle = creat(str, mode_file)) == ERROR) { warn(" creat - default_touch\n"); return; } if (futimens(handle, NULL) == ERROR) { warn(" fudimens - default_touch.\n"); return; } close(handle); } }
static void restore_timestamps(struct file_stream *out, const tchar *newpath, const struct stat *stbuf) { int ret; #if defined(HAVE_FUTIMENS) struct timespec times[2] = { stbuf->st_atim, stbuf->st_mtim, }; ret = futimens(out->fd, times); #elif defined(HAVE_FUTIMES) struct timeval times[2] = { { stbuf->st_atim.tv_sec, stbuf->st_atim.tv_nsec / 1000, }, { stbuf->st_mtim.tv_sec, stbuf->st_mtim.tv_nsec / 1000, }, }; ret = futimes(out->fd, times); #else /* HAVE_FUTIMES */ struct tutimbuf times = { stbuf->st_atime, stbuf->st_mtime, }; ret = tutime(newpath, ×); #endif /* !HAVE_FUTIMES */ if (ret != 0) msg_errno("%"TS": unable to preserve timestamps", out->name); }
/* Closes the file belonging to a flow. * Does not take tcpip out of flow database. * Does not change pos. */ void tcpip::close_file() { if (fd>=0){ struct timeval times[2]; times[0] = myflow.tstart; times[1] = myflow.tstart; DEBUG(5) ("%s: closing file in tcpip::close_file", flow_pathname.c_str()); /* close the file and remember that it's closed */ #if defined(HAVE_FUTIMES) if(futimes(fd,times)){ fprintf(stderr,"%s: futimes(fd=%d)\n",strerror(errno),fd); abort(); } #elif defined(HAVE_FUTIMENS) struct timespec tstimes[2]; for(int i=0;i<2;i++){ tstimes[i].tv_sec = times[i].tv_sec; tstimes[i].tv_nsec = times[i].tv_usec * 1000; } if(futimens(fd,tstimes)){ perror("futimens(fd=%d)",fd); } #endif close(fd); fd = -1; } demux.open_flows.erase(this); // we are no longer open }
void fset_ftime(char *fnm, int fd, time_t mtime, time_t atime, int frc) { static struct timespec tv[2] = {{0L, 0L}, {0L, 0L}}; struct stat sb; tv[0].tv_sec = (long)atime; tv[1].tv_sec = (long)mtime; if (!frc && (!patime || !pmtime)) { /* * if we are not forcing, only set those times the user wants * set. We get the current values of the times if we need them. */ if (fstat(fd, &sb) == 0) { if (!patime) tv[0].tv_sec = (long)sb.st_atime; if (!pmtime) tv[1].tv_sec = (long)sb.st_mtime; } else syswarn(0,errno,"Unable to obtain file stats %s", fnm); } /* * set the times */ if (futimens(fd, tv) < 0) syswarn(1, errno, "Access/modification time set failed on: %s", fnm); return; }
int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s file1 file2 file3 ... fileN\n", argv[0]); exit(EXIT_FAILURE); } int i; for (i = 1; i < argc; i++) { struct stat statbuf; if (stat(argv[i], &statbuf) < 0) { fprintf(stderr, "Error collecting file data for %s: %s\n", argv[i], strerror(errno)); continue; } int fd; if ((fd = open(argv[i], O_RDWR | O_CREAT | O_TRUNC)) < 0) { fprintf(stderr, "Couldn't open %s: %s\n", argv[i], strerror(errno)); continue; } struct timespec times[2]; times[0] = statbuf.st_atim; times[1] = statbuf.st_mtim; if (futimens(fd, times) < 0) { fprintf(stderr, "Error changing file access and modification times for %s: %s\n", argv[i], strerror(errno)); } close(fd); } return 0; }
void sys_stat_check_functions() { (void)chmod((const char *)1234, (mode_t)0); (void)fchmod(0, (mode_t)0); #if HAVE_XXXAT (void)fchmodat(0, (const char *)1234, (mode_t)0, 0); #endif (void)fstat(0, (struct stat *)1234); #if HAVE_XXXAT (void)fstatat(0, (const char *)1234, (struct stat *)1234, 0); #endif (void)futimens(0, (const struct timespec *)1234); (void)lstat((const char *)1234, (struct stat *)1234); (void)mkdir((const char *)1234, (mode_t)0); #if HAVE_XXXAT (void)mkdirat(0, (const char *)1234, (mode_t)0); #endif (void)mkfifo((const char *)1234, (mode_t)0); (void)mkfifoat(0, (const char *)1234, (mode_t)0); (void)mknod((const char *)1234, (mode_t)0, (dev_t)0); (void)mknodat(0, (const char *)1234, (mode_t)0, (dev_t)0); (void)stat((const char *)1234, (struct stat *)1234); (void)umask((mode_t)0); (void)utimensat(0, (const char *)1234, (const struct timespec *)1234, 0); }
/* Closes the file belonging to a flow. * Does not take tcpip out of flow database. * Does not change pos. */ void tcpip::close_file() { if (fd>=0){ struct timeval times[2]; times[0] = myflow.tstart; times[1] = myflow.tstart; DEBUG(5) ("%s: closing file in tcpip::close_file", flow_pathname.c_str()); /* close the file and remember that it's closed */ #if defined(HAVE_FUTIMES) if(futimes(fd,times)){ fprintf(stderr,"%s: futimes(fd=%d)\n",strerror(errno),fd); abort(); } #elif defined(HAVE_FUTIMENS) struct timespec tstimes[2]; for(int i=0;i<2;i++){ tstimes[i].tv_sec = times[i].tv_sec; tstimes[i].tv_nsec = times[i].tv_usec * 1000; } if(futimens(fd,tstimes)){ perror("futimens(fd=%d)",fd); } #endif close(fd); fd = -1; demux.open_flows.erase(this); // we are no longer open } // Also close the flow_index file, if flow indexing is in use --GDD if(demux.opt.output_packet_index && idx_file.is_open()){ idx_file.close(); } //std::cerr << "close_file1 " << *this << "\n"; }
static int apply_timestamp(const char *path, struct timespec *ts) { struct timespec twice[2] = { *ts, *ts }; struct stat st; assert(path); assert(ts); if (stat(path, &st) >= 0) { /* Is the timestamp file already newer than the OS? If * so, there's nothing to do. We ignore the nanosecond * component of the timestamp, since some file systems * do not support any better accuracy than 1s and we * have no way to identify the accuracy * available. Most notably ext4 on small disks (where * 128 byte inodes are used) does not support better * accuracy than 1s. */ if (st.st_mtim.tv_sec > ts->tv_sec) return 0; /* It is older? Then let's update it */ if (utimensat(AT_FDCWD, path, twice, AT_SYMLINK_NOFOLLOW) < 0) { if (errno == EROFS) return log_debug("Can't update timestamp file %s, file system is read-only.", path); return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); } } else if (errno == ENOENT) { _cleanup_close_ int fd = -1; int r; /* The timestamp file doesn't exist yet? Then let's create it. */ r = mac_selinux_create_file_prepare(path, S_IFREG); if (r < 0) return log_error_errno(r, "Failed to set SELinux context for %s: %m", path); fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); mac_selinux_create_file_clear(); if (fd < 0) { if (errno == EROFS) return log_debug("Can't create timestamp file %s, file system is read-only.", path); return log_error_errno(errno, "Failed to create timestamp file %s: %m", path); } (void) loop_write(fd, MESSAGE, strlen(MESSAGE), false); if (futimens(fd, twice) < 0) return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); } else log_error_errno(errno, "Failed to stat() timestamp file %s: %m", path); return 0; }
TEST(sys_stat, futimens) { FILE* fp = tmpfile(); ASSERT_TRUE(fp != NULL); int fd = fileno(fp); ASSERT_NE(fd, -1); // ARC MOD BEGIN // NaCl IRT does not have futimens. #if !defined(__native_client__) && !defined(BARE_METAL_BIONIC) // ARC MOD END timespec times[2]; times[0].tv_sec = 123; times[0].tv_nsec = 0; times[1].tv_sec = 456; times[1].tv_nsec = 0; ASSERT_EQ(0, futimens(fd, times)) << strerror(errno); struct stat sb; ASSERT_EQ(0, fstat(fd, &sb)); ASSERT_EQ(times[0].tv_sec, static_cast<long>(sb.st_atime)); ASSERT_EQ(times[1].tv_sec, static_cast<long>(sb.st_mtime)); // ARC MOD BEGIN #endif // ARC MOD END fclose(fp); }
int write_string_stream_ts( FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts) { assert(f); assert(line); fputs(line, f); if (!(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n")) fputc('\n', f); if (ts) { struct timespec twice[2] = {*ts, *ts}; if (futimens(fileno(f), twice) < 0) return -errno; } if (flags & WRITE_STRING_FILE_SYNC) return fflush_sync_and_check(f); else return fflush_and_check(f); }
int main(int argc, char *argv[]) { int i, fd; struct stat statbuf; struct timespec times[2]; for (i = 1; i < argc; i ++) { if (stat(argv[i], &statbuf) < 0) { fprintf(stderr, "%s: stat error\n", argv[i]); continue; } if ((fd = open(argv[i], O_RDWR | O_TRUNC)) < 0) { fprintf(stderr, "%s: open error\n", argv[i]); continue; } times[0] = statbuf.st_atim; times[1] = statbuf.st_mtim; if (futimens(fd, times) < 0) { fprintf(stderr, "%s: futimens error\n", argv[i]); } close(fd); } return 0; }
// ARC MOD END TEST(sys_stat, futimens_EBADF) { timespec times[2]; times[0].tv_sec = 123; times[0].tv_nsec = 0; times[1].tv_sec = 456; times[1].tv_nsec = 0; ASSERT_EQ(-1, futimens(-1, times)); ASSERT_EQ(EBADF, errno); }
static int apply_timestamp(const char *path, struct timespec *ts) { struct timespec twice[2]; struct stat st; assert(path); assert(ts); if (stat(path, &st) >= 0) { /* Is the timestamp file already newer than the OS? If so, there's nothing to do. */ if (st.st_mtim.tv_sec > ts->tv_sec || (st.st_mtim.tv_sec == ts->tv_sec && st.st_mtim.tv_nsec >= ts->tv_nsec)) return 0; /* It is older? Then let's update it */ twice[0] = *ts; twice[1] = *ts; if (utimensat(AT_FDCWD, path, twice, AT_SYMLINK_NOFOLLOW) < 0) { if (errno == EROFS) return log_debug("Can't update timestamp file %s, file system is read-only.", path); return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); } } else if (errno == ENOENT) { _cleanup_close_ int fd = -1; int r; /* The timestamp file doesn't exist yet? Then let's create it. */ r = mac_selinux_create_file_prepare(path, S_IFREG); if (r < 0) return log_error_errno(r, "Failed to set SELinux context for %s: %m", path); fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); mac_selinux_create_file_clear(); if (fd < 0) { if (errno == EROFS) return log_debug("Can't create timestamp file %s, file system is read-only.", path); return log_error_errno(errno, "Failed to create timestamp file %s: %m", path); } (void) loop_write(fd, MESSAGE, strlen(MESSAGE), false); twice[0] = *ts; twice[1] = *ts; if (futimens(fd, twice) < 0) return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); } else log_error_errno(errno, "Failed to stat() timestamp file %s: %m", path); return 0; }
static int copy_metadata(struct btrfs_root *root, int fd, struct btrfs_key *key) { struct btrfs_path *path; struct btrfs_inode_item *inode_item; int ret; path = btrfs_alloc_path(); if (!path) { fprintf(stderr, "ERROR: Ran out of memory\n"); return -ENOMEM; } ret = btrfs_lookup_inode(NULL, root, path, key, 0); if (ret == 0) { struct btrfs_timespec *bts; struct timespec times[2]; inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0], struct btrfs_inode_item); ret = fchown(fd, btrfs_inode_uid(path->nodes[0], inode_item), btrfs_inode_gid(path->nodes[0], inode_item)); if (ret) { fprintf(stderr, "ERROR: Failed to change owner: %s\n", strerror(errno)); goto out; } ret = fchmod(fd, btrfs_inode_mode(path->nodes[0], inode_item)); if (ret) { fprintf(stderr, "ERROR: Failed to change mode: %s\n", strerror(errno)); goto out; } bts = btrfs_inode_atime(inode_item); times[0].tv_sec = btrfs_timespec_sec(path->nodes[0], bts); times[0].tv_nsec = btrfs_timespec_nsec(path->nodes[0], bts); bts = btrfs_inode_mtime(inode_item); times[1].tv_sec = btrfs_timespec_sec(path->nodes[0], bts); times[1].tv_nsec = btrfs_timespec_nsec(path->nodes[0], bts); ret = futimens(fd, times); if (ret) { fprintf(stderr, "ERROR: Failed to set times: %s\n", strerror(errno)); goto out; } } out: btrfs_free_path(path); return ret; }
int do_touch (const char *path) { int fd; int r; struct stat buf; /* RHBZ#582484: Restrict touch to regular files. It's also OK * here if the file does not exist, since we will create it. * * XXX Coverity flags this as a time-of-check to time-of-use race * condition, particularly in the libguestfs live case. Not clear * how to fix this yet, since unconditionally opening the file can * cause a hang, so you have to somehow check it first before you * open it. */ CHROOT_IN; r = lstat (path, &buf); CHROOT_OUT; if (r == -1) { if (errno != ENOENT) { reply_with_perror ("lstat: %s", path); return -1; } } else { if (! S_ISREG (buf.st_mode)) { reply_with_error ("%s: touch can only be used on a regular files", path); return -1; } } CHROOT_IN; fd = open (path, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0666); CHROOT_OUT; if (fd == -1) { reply_with_perror ("open: %s", path); return -1; } r = futimens (fd, NULL); if (r == -1) { reply_with_perror ("futimens: %s", path); close (fd); return -1; } if (close (fd) == -1) { reply_with_perror ("close: %s", path); return -1; } return 0; }
int setfile(struct stat *fs, int fd) { struct timespec ts[2]; int rval; rval = 0; fs->st_mode &= S_ISTXT | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; ts[0] = fs->st_atim; ts[1] = fs->st_mtim; if (fd >= 0 ? futimens(fd, ts) : utimensat(AT_FDCWD, to.p_path, ts, AT_SYMLINK_NOFOLLOW)) { warn("update times: %s", to.p_path); rval = 1; } /* * Changing the ownership probably won't succeed, unless we're root * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting * the mode; current BSD behavior is to remove all setuid bits on * chown. If chown fails, lose setuid/setgid bits. */ if (fd >= 0 ? fchown(fd, fs->st_uid, fs->st_gid) : lchown(to.p_path, fs->st_uid, fs->st_gid)) { if (errno != EPERM) { warn("chown: %s", to.p_path); rval = 1; } fs->st_mode &= ~(S_ISTXT | S_ISUID | S_ISGID); } if (fd >= 0 ? fchmod(fd, fs->st_mode) : fchmodat(AT_FDCWD, to.p_path, fs->st_mode, AT_SYMLINK_NOFOLLOW)) { warn("chmod: %s", to.p_path); rval = 1; } /* * XXX * NFS doesn't support chflags; ignore errors unless there's reason * to believe we're losing bits. (Note, this still won't be right * if the server supports flags and we were trying to *remove* flags * on a file that we copied, i.e., that we didn't create.) */ errno = 0; if (fd >= 0 ? fchflags(fd, fs->st_flags) : chflagsat(AT_FDCWD, to.p_path, fs->st_flags, AT_SYMLINK_NOFOLLOW)) if (errno != EOPNOTSUPP || fs->st_flags != 0) { warn("chflags: %s", to.p_path); rval = 1; } return (rval); }
int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) { _cleanup_close_ int fd; int r; assert(path); if (parents) mkdir_parents(path, 0755); fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, (mode == 0 || mode == MODE_INVALID) ? 0644 : mode); if (fd < 0) return -errno; if (mode != MODE_INVALID) { r = fchmod(fd, mode); if (r < 0) return -errno; } if (uid != UID_INVALID || gid != GID_INVALID) { r = fchown(fd, uid, gid); if (r < 0) return -errno; } if (stamp != USEC_INFINITY) { struct timespec ts[2]; timespec_store(&ts[0], stamp); ts[1] = ts[0]; r = futimens(fd, ts); } else r = futimens(fd, NULL); if (r < 0) return -errno; return 0; }
static int apply_timestamp(const char *path, struct timespec *ts) { struct timespec twice[2] = { *ts, *ts }; int fd = -1; _cleanup_fclose_ FILE *f = NULL; int r; assert(path); assert(ts); /* * We store the timestamp both as mtime of the file and in the file itself, * to support filesystems which cannot store nanosecond-precision timestamps. * Hence, don't bother updating the file, let's just rewrite it. */ r = mac_selinux_create_file_prepare(path, S_IFREG); if (r < 0) return log_error_errno(r, "Failed to set SELinux context for %s: %m", path); fd = open(path, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); mac_selinux_create_file_clear(); if (fd < 0) { if (errno == EROFS) return log_debug("Can't create timestamp file %s, file system is read-only.", path); return log_error_errno(errno, "Failed to create/open timestamp file %s: %m", path); } f = fdopen(fd, "w"); if (!f) { safe_close(fd); return log_error_errno(errno, "Failed to fdopen() timestamp file %s: %m", path); } (void) fprintf(f, "%s" "TimestampNSec=" NSEC_FMT "\n", MESSAGE, timespec_load_nsec(ts)); fflush(f); if (futimens(fd, twice) < 0) return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); return 0; }
int utimesys(int code, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4) { switch (code) { case 0: return (futimens((int)arg1, (timespec_t *)arg2)); case 1: return (utimensat((int)arg1, (char *)arg2, (timespec_t *)arg3, (int)arg4)); default: return (set_errno(EINVAL)); } }
int do_touch (const char *path) { int fd; int r; struct stat buf; /* RHBZ#582484: Restrict touch to regular files. It's also OK * here if the file does not exist, since we will create it. */ CHROOT_IN; r = lstat (path, &buf); CHROOT_OUT; if (r == -1) { if (errno != ENOENT) { reply_with_perror ("lstat: %s", path); return -1; } } else { if (! S_ISREG (buf.st_mode)) { reply_with_error ("%s: touch can only be used on a regular files", path); return -1; } } CHROOT_IN; fd = open (path, O_WRONLY | O_CREAT | O_NOCTTY, 0666); CHROOT_OUT; if (fd == -1) { reply_with_perror ("open: %s", path); return -1; } r = futimens (fd, NULL); if (r == -1) { reply_with_perror ("futimens: %s", path); close (fd); return -1; } if (close (fd) == -1) { reply_with_perror ("close: %s", path); return -1; } return 0; }
void fallback(int f, struct stat* st) { #if HAVE_FUTIMENS struct timespec tv[2]; #else struct timeval tv[2]; #endif int ret; #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */ tv[0].tv_sec = st->st_mtime; if (STAT_NSEC(st) != STAT_NSEC_INVALID) tv[0].tv_nsec = STAT_NSEC(st); else tv[0].tv_nsec = 0; tv[1].tv_sec = tv[0].tv_sec; tv[1].tv_nsec = tv[0].tv_nsec; ret = futimens(f, tv); #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */ tv[0].tv_sec = st->st_mtime; if (STAT_NSEC(st) != STAT_NSEC_INVALID) tv[0].tv_usec = STAT_NSEC(st) / 1000; else tv[0].tv_usec = 0; tv[1].tv_sec = tv[0].tv_sec; tv[1].tv_usec = tv[0].tv_usec; ret = futimes(f, tv); #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ tv[0].tv_sec = st->st_mtime; if (STAT_NSEC(st) != STAT_NSEC_INVALID) tv[0].tv_usec = STAT_NSEC(st) / 1000; else tv[0].tv_usec = 0; tv[1].tv_sec = tv[0].tv_sec; tv[1].tv_usec = tv[0].tv_usec; ret = futimesat(f, 0, tv); #else #error No function available to set file timestamps #endif if (ret != 0) { /* LCOV_EXCL_START */ fprintf(stderr, "Error restoring time\n"); exit(EXIT_FAILURE); /* LCOV_EXCL_STOP */ } }
int write_string_stream_ts( FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts) { bool needs_nl; int r; assert(f); assert(line); if (ferror(f)) return -EIO; needs_nl = !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n"); if (needs_nl && (flags & WRITE_STRING_FILE_DISABLE_BUFFER)) { /* If STDIO buffering was disabled, then let's append the newline character to the string itself, so * that the write goes out in one go, instead of two */ line = strjoina(line, "\n"); needs_nl = false; } if (fputs(line, f) == EOF) return -errno; if (needs_nl) if (fputc('\n', f) == EOF) return -errno; if (flags & WRITE_STRING_FILE_SYNC) r = fflush_sync_and_check(f); else r = fflush_and_check(f); if (r < 0) return r; if (ts) { struct timespec twice[2] = {*ts, *ts}; if (futimens(fileno(f), twice) < 0) return -errno; } return 0; }
int main(int argc, char **argv) { int fd = creat ("file", 0600); struct stat st1, st2; struct timespec t[2] = { { 1000000000, 0 }, { 0, UTIME_OMIT } }; fstat(fd, &st1); sleep(1); futimens(fd, t); fstat(fd, &st2); if (st1.st_ctime == st2.st_ctime) printf("failed to update ctime!\n"); return 0; }
int fdutimensat (int fd, int dir, char const *file, struct timespec const ts[2], int atflag) { int result = 1; if (0 <= fd) result = futimens (fd, ts); if (file && (fd < 0 || (result == -1 && errno == ENOSYS))) result = utimensat (dir, file, ts, atflag); if (result == 1) { errno = EBADF; result = -1; } return result; }
static int copy_metadata(struct btrfs_root *root, int fd, struct btrfs_key *key) { struct btrfs_path path; struct btrfs_inode_item *inode_item; int ret; btrfs_init_path(&path); ret = btrfs_lookup_inode(NULL, root, &path, key, 0); if (ret == 0) { struct btrfs_timespec *bts; struct timespec times[2]; inode_item = btrfs_item_ptr(path.nodes[0], path.slots[0], struct btrfs_inode_item); ret = fchown(fd, btrfs_inode_uid(path.nodes[0], inode_item), btrfs_inode_gid(path.nodes[0], inode_item)); if (ret) { error("failed to change owner: %m"); goto out; } ret = fchmod(fd, btrfs_inode_mode(path.nodes[0], inode_item)); if (ret) { error("failed to change mode: %m"); goto out; } bts = btrfs_inode_atime(inode_item); times[0].tv_sec = btrfs_timespec_sec(path.nodes[0], bts); times[0].tv_nsec = btrfs_timespec_nsec(path.nodes[0], bts); bts = btrfs_inode_mtime(inode_item); times[1].tv_sec = btrfs_timespec_sec(path.nodes[0], bts); times[1].tv_nsec = btrfs_timespec_nsec(path.nodes[0], bts); ret = futimens(fd, times); if (ret) { error("failed to set times: %m"); goto out; } } out: btrfs_release_path(&path); return ret; }
int ask_the_user(const char *domain) { struct stat stat_buf; char stat_file_path[100]; int stat_file_fd; char ask_cmd[512]; time_t now; int autoaccept_time; const char *env; struct timespec times[2]; autoaccept_time = DEFAULT_AUTOACCEPT_TIME; env = getenv("QUBES_GPG_AUTOACCEPT"); if (env) autoaccept_time = atoi(env); snprintf(stat_file_path, sizeof(stat_file_path), "%s/stat.%s", RUNDIR, domain); now = time(NULL); // if user accepts at most "autoaccept_time" seconds ago if (stat(stat_file_path, &stat_buf) == 0 && stat_buf.st_mtime > now-autoaccept_time ) return 1; snprintf(ask_cmd, sizeof(ask_cmd), "zenity --question --text \"Do you allow" " VM '%s' to access your GPG keys (now and for the following %d" " seconds)?\" 2>/dev/null", domain, autoaccept_time); switch (system(ask_cmd)) { case -1: perror("system"); exit(1); case 0: // "YES" stat_file_fd = open(stat_file_path, O_WRONLY | O_CREAT, 0600); if (stat_file_fd < 0) { perror("Cannot touch stat-file"); // continue on this error } else { times[0].tv_nsec = UTIME_OMIT; times[1].tv_nsec = UTIME_NOW; futimens(stat_file_fd, times); close(stat_file_fd); } return 1; default: // "NO" or any other case return 0; } }
/* * set the owner, mode, flags & utimes using the given file descriptor. * file is only used in possible warning messages. */ static void copymodes(int fd, const struct stat *sbp, const char *file) { struct timespec times[2]; struct stat sb; /* * If we have no info on the input, give this file some * default values and return.. */ if (sbp == NULL) { mode_t mask = umask(022); (void)fchmod(fd, DEFFILEMODE & ~mask); (void)umask(mask); return; } sb = *sbp; /* if the chown fails, remove set-id bits as-per compress(1) */ if (fchown(fd, sb.st_uid, sb.st_gid) < 0) { if (errno != EPERM) maybe_warn("couldn't fchown: %s", file); sb.st_mode &= ~(S_ISUID|S_ISGID); } /* we only allow set-id and the 9 normal permission bits */ sb.st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; if (fchmod(fd, sb.st_mode) < 0) maybe_warn("couldn't fchmod: %s", file); #ifdef __APPLE__ times[0] = sb.st_atimespec; times[1] = sb.st_mtimespec; #else times[0] = sb.st_atim; times[1] = sb.st_mtim; #endif if (futimens(fd, times) < 0) maybe_warn("couldn't futimens: %s", file); /* only try flags if they exist already */ if (sb.st_flags != 0 && fchflags(fd, sb.st_flags) < 0) maybe_warn("couldn't fchflags: %s", file); }
int insecure_utimens (const char *path, const struct timespec tv[2]) { insecure_flush_tables (); gchar *backname = insecure_get_backname (path); gchar *full_backname = g_build_path ("/", FS_DATA->backend_point, backname, NULL); int fd = open (full_backname, O_RDONLY); if (fd < 0) return -errno; int ret = futimens (fd, tv); close (fd); g_free (backname); g_free (full_backname); if (ret < 0) return -errno; return 0; }