static void s_save_status( screen_t *s) { /* This futimes call tries to trick the system into using st_mtime as a tampering flag. This of course only works on systems where futimes is defined, but it should make the status saving stuff failsafe. */ struct timeval t[]= { { time(0)-1, 0 } , { time(0)-1, 0 } } ; /* Don't check return value on these. We don't care if they fail, really. This is all just to make the prompt look ok, which is impossible to do 100% reliably. We try, at least. */ futimes( 1, t ); futimes( 2, t ); fstat( 1, &s->prev_buff_1 ); fstat( 2, &s->prev_buff_2 ); }
axStatus axFileSystem::touchDir ( const char* dir ) { axStatus st; DIR* p = opendir( dir ); int fd = dirfd(p); if( futimes( fd, NULL ) != 0 ) return -1; return 0; }
bool CFile::SetTimestamp(long timestamp) { #ifdef WIN32 FILETIME ftime; HANDLE h; bool close = false; if (handle==NULL) { h = CreateFile(s2ws(filename).c_str() , GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); close = true; } else { h = (HANDLE)_get_osfhandle(fileno(handle)); } if (h == NULL) { return false; } fileSystem->TimestampToFiletime(timestamp, ftime); bool ret = SetFileTime(h, NULL, NULL, &ftime); if (close) { //close opened file CloseHandle(h); } return ret; #else struct timeval tv = {0, 0}; tv.tv_sec = timestamp; if (handle==NULL) { return lutimes(filename.c_str(), &tv) == 0; } else { return futimes(fileno(handle), &tv) == 0; } #endif }
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 }
/* 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"; }
// Copy file times CAMLprim value copy_file_times(value in_h_val, value out_h_val) { CAMLparam2(in_h_val, out_h_val); int good; #if defined(WIN32) HANDLE in_h = Handle_val(in_h_val); HANDLE out_h = Handle_val(out_h_val); FILETIME create; FILETIME access; FILETIME modify; good = GetFileTime(in_h, &create, &access, &modify); if(good) { good = SetFileTime(out_h, &create, &access, &modify); } #else int in_h = Int_val(in_h_val); int out_h = Int_val(out_h_val); struct stat s; struct timeval set[2]; good = !fstat(in_h, &s); if(good) { set[0].tv_sec = s.st_atime; set[0].tv_usec = 0; set[1].tv_sec = s.st_mtime; set[1].tv_usec = 0; good = !futimes(out_h, set); } #endif CAMLreturn(Val_bool(good)); }
static ssize_t uv__fs_futime(uv_fs_t* req) { #if defined(__linux__) /* utimesat() has nanosecond resolution but we stick to microseconds * for the sake of consistency with other platforms. */ struct timespec ts[2]; ts[0].tv_sec = req->atime; ts[0].tv_nsec = (unsigned long)(req->atime * 1000000) % 1000000 * 1000; ts[1].tv_sec = req->mtime; ts[1].tv_nsec = (unsigned long)(req->mtime * 1000000) % 1000000 * 1000; return uv__utimesat(req->file, NULL, ts, 0); #elif defined(__APPLE__) \ || defined(__DragonFly__) \ || defined(__FreeBSD__) \ || defined(__sun) struct timeval tv[2]; tv[0].tv_sec = req->atime; tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000; tv[1].tv_sec = req->mtime; tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000; return futimes(req->file, tv); #else errno = ENOSYS; return -1; #endif }
void fset_ftime(char *fnm, int fd, time_t mtime, time_t atime, int frc) { static struct timeval 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 (futimes(fd, tv) < 0) syswarn(1, errno, "Access/modification time set failed on: %s", fnm); return; }
int dirfwstat(int fd, Dir *dir) { int ret; struct timeval tv[2]; ret = 0; if(~dir->mode != 0){ if(fchmod(fd, dir->mode) < 0) ret = -1; } if(~dir->mtime != 0){ tv[0].tv_sec = dir->mtime; tv[0].tv_usec = 0; tv[1].tv_sec = dir->mtime; tv[1].tv_usec = 0; if(futimes(fd, tv) < 0) ret = -1; } if(~dir->length != 0){ if(ftruncate(fd, dir->length) < 0) ret = -1; } return ret; }
/* * A limited implementation of utimensat() that only implements the * functionality used by OpenSSH, currently only AT_FDCWD and * AT_SYMLINK_NOFOLLOW. */ int utimensat(int fd, const char *path, const struct timespec times[2], int flag) { struct timeval tv[2]; int ret, oflags = O_WRONLY; tv[0].tv_sec = times[0].tv_sec; tv[0].tv_usec = times[0].tv_nsec / 1000; tv[1].tv_sec = times[1].tv_sec; tv[1].tv_usec = times[1].tv_nsec / 1000; if (fd != AT_FDCWD) { errno = ENOSYS; return -1; } # ifndef HAVE_FUTIMES return utimes(path, tv); # else # ifdef O_NOFOLLOW if (flag & AT_SYMLINK_NOFOLLOW) oflags |= O_NOFOLLOW; # endif /* O_NOFOLLOW */ if ((fd = open(path, oflags)) == -1) return -1; ret = futimes(fd, tv); close(fd); return ret; # endif }
int unco_utimes(int fd, const struct stat *st, int (*futimes)(int, const struct timeval times[2])) { struct timeval times[2]; times[0].tv_sec = st->st_atime; times[0].tv_usec = 0; times[1].tv_sec = st->st_mtime; times[1].tv_usec = 0; return futimes(fd, times); }
gint32 Mono_Posix_Syscall_futimes(int fd, struct Mono_Posix_Timeval *tv) { struct timeval _tv[2]; struct timeval *ptv; ptv = copy_utimes (_tv, tv); return futimes (fd, ptv); }
long do_futimes(uint32_t arg1, struct timeval * arg2) { DPRINTF("futimes(0x%x, %p)\n", arg1, arg2); if(arg2) { byteswap_timeval(arg2); byteswap_timeval(arg2+1); } return get_errno(futimes(arg1, arg2)); }
void ServerConnection::recvSendFile( const QString &filename, const QDateTime &mtime, const QByteArray &data, bool executable ) { qDebug() << "File " << fSourceDir << filename << " datasize " << data.size() << " date: " << mtime; QFile file( joinPath(fSourceDir,filename) ); if( !file.open(QIODevice::WriteOnly) ) { // maybe we are missing some directories QString filedir = joinPath( fSourceDir, filename ).section( '/', 0, -2 ); QDir dir(filedir); bool result = true; if(!dir.exists()) { result = dir.mkpath(filedir); } if( !result ) { qWarning() << "Could not create path \"" << filedir << "\""; } else { file.open( QIODevice::WriteOnly ); } } if( !file.isOpen() ) { sendSendFileResult( filename, mtime, false ); qWarning() << "Could not create file \"" << filename << "\""; } else { file.write( data ); if(executable) { file.setPermissions(file.permissions()|QFile::ExeOwner|QFile::ExeGroup|QFile::ExeOther); } file.flush(); // For some reason QFileInfo is lacking setLastModified() struct timeval times[2]; times[0].tv_sec = times[1].tv_sec = mtime.toTime_t(); times[0].tv_usec = times[1].tv_usec = 0; if( futimes(file.handle(), times) != 0 ) { sendSendFileResult( filename, mtime, false ); qWarning() << "Could not set times on file \"" << filename << "\""; } else { sendSendFileResult( filename, mtime, true ); } } }
static int restore_time(struct cpio *cpio, struct archive_entry *entry, const char *name, int fd) { #ifndef HAVE_UTIMES static int warned = 0; (void)cpio; /* UNUSED */ (void)entry; /* UNUSED */ (void)name; /* UNUSED */ if (!warned) lafe_warnc(0, "Can't restore access times on this platform"); warned = 1; return (fd); #else #if defined(_WIN32) && !defined(__CYGWIN__) struct __timeval times[2]; #else struct timeval times[2]; #endif if (!cpio->option_atime_restore) return (fd); times[1].tv_sec = archive_entry_mtime(entry); times[1].tv_usec = archive_entry_mtime_nsec(entry) / 1000; times[0].tv_sec = archive_entry_atime(entry); times[0].tv_usec = archive_entry_atime_nsec(entry) / 1000; #if defined(HAVE_FUTIMES) && !defined(__CYGWIN__) if (fd >= 0 && futimes(fd, times) == 0) return (fd); #endif /* * Some platform cannot restore access times if the file descriptor * is still opened. */ if (fd >= 0) { close(fd); fd = -1; } #ifdef HAVE_LUTIMES if (lutimes(name, times) != 0) #else if ((AE_IFLNK != archive_entry_filetype(entry)) && utimes(name, times) != 0) #endif lafe_warnc(errno, "Can't update time for %s", name); #endif return (fd); }
static void process_fsetstat(void) { Attrib *a; u_int32_t id; int handle, fd, ret; int status = SSH2_FX_OK; id = get_int(); handle = get_handle(); a = get_attrib(); debug("request %u: fsetstat handle %d", id, handle); fd = handle_to_fd(handle); if (fd < 0) status = SSH2_FX_FAILURE; else if (readonly) status = SSH2_FX_PERMISSION_DENIED; else { char *name = handle_to_name(handle); if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", name, (unsigned long long)a->size); ret = ftruncate(fd, a->size); if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { logit("set \"%s\" mode %04o", name, a->perm); ret = fchmod(fd, a->perm & 07777); if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { char buf[64]; time_t t = a->mtime; strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", localtime(&t)); logit("set \"%s\" modtime %s", name, buf); ret = futimes(fd, attrib_to_tv(a)); if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { logit("set \"%s\" owner %lu group %lu", name, (u_long)a->uid, (u_long)a->gid); ret = fchown(fd, a->uid, a->gid); if (ret == -1) status = errno_to_portable(errno); } } send_status(id, status); }
/* * copy_file - copy a file * * Copy a file from src to dst. * * statp, mt, uid, gid are used to set the access and modification and the * access rights. * * Return 0 on success, -1 on error. */ static int copy_file (const char *src, const char *dst, const struct stat *statp, const struct timeval mt[], long int uid, long int gid) { int err = 0; int ifd; int ofd; char buf[1024]; ssize_t cnt; ifd = open (src, O_RDONLY); if (ifd < 0) { return -1; } #ifdef WITH_SELINUX selinux_file_context (dst); #endif ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777); if ( (ofd < 0) || (fchown (ofd, (uid == -1) ? statp->st_uid : (uid_t) uid, (gid == -1) ? statp->st_gid : (gid_t) gid) != 0) || (fchmod (ofd, statp->st_mode & 07777) != 0)) { (void) close (ifd); return -1; } while ((cnt = read (ifd, buf, sizeof buf)) > 0) { if (write (ofd, buf, (size_t)cnt) != cnt) { return -1; } } (void) close (ifd); #ifdef HAVE_FUTIMES if (futimes (ofd, mt) != 0) { return -1; } #endif if (close (ofd) != 0) { return -1; } #ifndef HAVE_FUTIMES if (utimes(dst, mt) != 0) { return -1; } #endif return err; }
/// Stat stdout and stderr and save result. This should be done before calling a function that may /// cause output. static void s_save_status(screen_t *s) { // PCA Let's not do this futimes stuff, because sudo dumbly uses the tty's ctime as part of its // tty_tickets feature. Disabling this should fix issue #122. #if 0 // This futimes call tries to trick the system into using st_mtime as a tampering flag. This of // course only works on systems where futimes is defined, but it should make the status saving // stuff failsafe. struct timeval t[] = { { time(0)-1, 0 }, { time(0)-1, 0 } }; // Don't check return value on these. We don't care if they fail, really. This is all just to // make the prompt look ok, which is impossible to do 100% reliably. We try, at least. futimes(1, t); futimes(2, t); #endif fstat(1, &s->prev_buff_1); fstat(2, &s->prev_buff_2); }
static void process_fsetstat(void) { Attrib *a; u_int32_t id; int handle, fd, ret; int status = SSH2_FX_OK; char *name; id = get_int(); handle = get_handle(); a = get_attrib(); TRACE("fsetstat id %u handle %d", id, handle); fd = handle_to_fd(handle); name = handle_to_name(handle); if (fd < 0 || name == NULL) { status = SSH2_FX_FAILURE; } else { if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { ret = ftruncate(fd, a->size); if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { #ifdef HAVE_FCHMOD ret = fchmod(fd, a->perm & 0777); #else ret = chmod(name, a->perm & 0777); #endif if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { #ifdef HAVE_FUTIMES ret = futimes(fd, attrib_to_tv(a)); #else ret = utimes(name, attrib_to_tv(a)); #endif if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { #ifdef HAVE_FCHOWN ret = fchown(fd, a->uid, a->gid); #else ret = chown(name, a->uid, a->gid); #endif if (ret == -1) status = errno_to_portable(errno); } } send_status(id, status); }
static void process_fsetstat(u_int32_t id) { Attrib a; int handle, fd, r; int status = SSH2_FX_OK; if ((r = get_handle(iqueue, &handle)) != 0 || (r = decode_attrib(iqueue, &a)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: fsetstat handle %d", id, handle); fd = handle_to_fd(handle); if (fd < 0) status = SSH2_FX_FAILURE; else { char *name = handle_to_name(handle); if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", name, (unsigned long long)a.size); r = ftruncate(fd, a.size); if (r == -1) status = errno_to_portable(errno); } if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { logit("set \"%s\" mode %04o", name, a.perm); r = fchmod(fd, a.perm & 07777); if (r == -1) status = errno_to_portable(errno); } if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { char buf[64]; time_t t = a.mtime; strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", localtime(&t)); logit("set \"%s\" modtime %s", name, buf); r = futimes(fd, attrib_to_tv(&a)); if (r == -1) status = errno_to_portable(errno); } if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { logit("set \"%s\" owner %lu group %lu", name, (u_long)a.uid, (u_long)a.gid); r = fchown(fd, a.uid, a.gid); if (r == -1) status = errno_to_portable(errno); } } send_status(id, status); }
int futimens(int fd, const struct timespec ts[2]) { struct timeval tv[2]; tv[0].tv_sec = ts[0].tv_sec; tv[0].tv_usec = ts[0].tv_nsec / 1000; tv[1].tv_sec = ts[1].tv_sec; tv[1].tv_usec = ts[1].tv_nsec / 1000; return (futimes(fd, tv)); }
void DiskFile::SetLastWriteTime(time_t lastWriteTime) { #if defined(PLATFORM_WINDOWS) #if _MSC_VER && _MSC_VER <= 1300 assert(0); #else FILETIME localFILETIME; LONGLONG ll = Int32x32To64(lastWriteTime, 10000000) + 116444736000000000ULL; localFILETIME.dwLowDateTime = (DWORD) ll; localFILETIME.dwHighDateTime = (DWORD)(ll >>32); SYSTEMTIME localSystemTime; FileTimeToSystemTime(&localFILETIME, &localSystemTime); SYSTEMTIME universalSystemTime; if (CheckFor98Mill()) { CORE_ASSERT(0); } else { if (!fnTzSpecificLocalTimeToSystemTime) { HMODULE aLib = LoadLibraryA("kernel32.dll"); if (aLib == NULL) return; *(void**)&fnTzSpecificLocalTimeToSystemTime = (void*)GetProcAddress(aLib, "TzSpecificLocalTimeToSystemTime"); } fnTzSpecificLocalTimeToSystemTime(NULL, &localSystemTime, &universalSystemTime); } FILETIME lastWriteTimeFILETIME; SystemTimeToFileTime(&localSystemTime, &lastWriteTimeFILETIME); if ( !::SetFileTime(m_fileHandle, NULL, NULL, &lastWriteTimeFILETIME) ) return; #endif #else timeval tv[2]; tv[0].tv_sec = lastWriteTime; tv[0].tv_usec = 0; tv[1].tv_sec = lastWriteTime; tv[1].tv_usec = 0; if (futimes(m_fileHandle, (const timeval*)&tv) != 0) return; #endif }
/* XXX - need to check accessed and dirty bits... */ static void msync_set_modtimes(struct file *filp) { int fd; /* XXX */ return; for (fd = NR_OPEN - 1; fd >= 0; fd--) { if (__current->fd[fd] == NULL) { __current->fd[fd] = filp; assert(futimes(fd, NULL) == 0); __current->fd[fd] = NULL; return; } } assert(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 */ } }
void __do_futime(IN tt_io_ev_t *io_ev) { __futime_t *futime_ev = (__futime_t *)io_ev; struct timeval times[2]; __date2timeval(futime_ev->accessed, ×[0]); __date2timeval(futime_ev->modified, ×[1]); if (futimes(futime_ev->file->fd, times) == 0) { futime_ev->result = TT_SUCCESS; } else { futime_ev->result = TT_FAIL; TT_ERROR("futime failed"); } }
int journal::wait() { #if HAVE_FSTITCH /* {{{ */ if(!last_commit) return -EINVAL; return patchgroup_sync(last_commit); #else /* }}} */ int r; /* by changing the timestamp and calling fsync() on a file within * the target file system, we force the ext3 transaction to end */ fd_tv[0].tv_sec++; r = futimes(fs_fd, fd_tv); assert(r >= 0); r = fsync(fs_fd); assert(r >= 0); return 0; #endif }
/* * 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 timeval 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); /* only try flags if they exist already */ #ifndef __minix if (sb.st_flags != 0 && fchflags(fd, sb.st_flags) < 0) maybe_warn("couldn't fchflags: %s", file); #endif TIMESPEC_TO_TIMEVAL(×[0], &sb.st_atimespec); TIMESPEC_TO_TIMEVAL(×[1], &sb.st_mtimespec); #ifndef __minix if (futimes(fd, times) < 0) maybe_warn("couldn't utimes: %s", file); #endif }
int 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 return ret; }
int main(int argc, char const *argv[]) { int fd; struct stat buf; #ifdef __APPLE__ struct timeval times[2]; #else struct timespec times[2]; #endif for (int i = 1; i < argc; ++i) { if (stat(argv[i], &buf) < 0) { fprintf(stderr, "stat error for %s\n", argv[i]); continue; } if ((fd = open(argv[i], O_RDWR | O_TRUNC)) < 0) { fprintf(stderr, "open error for %s\n", argv[i]); continue; } #ifdef __APPLE__ times[0].tv_sec = buf.st_atimespec.tv_sec; // access time times[0].tv_usec = buf.st_atimespec.tv_nsec * 1000; times[1].tv_sec = buf.st_mtimespec.tv_sec; // modification time times[1].tv_usec = buf.st_mtimespec.tv_nsec * 1000; if (futimes(fd, times) < 0) { /* reset times */ fprintf(stderr, "futimes error for %s\n", argv[i]); } #else times[0].tv_sec = buf.st_atime; // access time times[0].tv_nsec = 0; times[1].tv_sec = buf.st_mtime; // modification time times[1].tv_nsec = 0; if (futimens(fd, times) < 0) { /* reset times */ fprintf(stderr, "futimens error for %s\n", argv[i]); } #endif close(fd); } return 0; }