From ac96b236166f8ac2ecd3cd82b494036fbea13644 Mon Sep 17 00:00:00 2001 From: Philip Guenther Date: Thu, 19 Mar 2015 05:14:25 +0000 Subject: Use struct timespec internally. This gives nanosecond precision to pax -rw and a basis for support of mtime and atime values in pax-format extended header records. ok millert@ --- bin/pax/ar_subs.c | 86 ++++++++++++++++++++--------------------------------- bin/pax/buf_subs.c | 6 ++-- bin/pax/cpio.c | 11 ++++--- bin/pax/extern.h | 11 ++++--- bin/pax/file_subs.c | 45 +++++++++++++++------------- bin/pax/ftree.c | 6 ++-- bin/pax/pax.h | 12 ++++---- bin/pax/tables.c | 21 ++++++------- bin/pax/tables.h | 4 +-- 9 files changed, 96 insertions(+), 106 deletions(-) (limited to 'bin/pax') diff --git a/bin/pax/ar_subs.c b/bin/pax/ar_subs.c index 8f0a28c4717..b95b1c2d317 100644 --- a/bin/pax/ar_subs.c +++ b/bin/pax/ar_subs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar_subs.c,v 1.44 2015/03/17 03:23:17 guenther Exp $ */ +/* $OpenBSD: ar_subs.c,v 1.45 2015/03/19 05:14:24 guenther Exp $ */ /* $NetBSD: ar_subs.c,v 1.5 1995/03/21 09:07:06 cgd Exp $ */ /*- @@ -148,6 +148,26 @@ list(void) pat_chk(); } +static int +cmp_file_times(int mtime_flag, int ctime_flag, ARCHD *arcn, struct stat *sbp) +{ + struct stat sb; + + if (sbp == NULL) { + if (lstat(arcn->name, &sb) != 0) + return (0); + sbp = &sb; + } + + if (ctime_flag && mtime_flag) + return (timespeccmp(&arcn->sb.st_mtim, &sbp->st_mtim, <=) && + timespeccmp(&arcn->sb.st_ctim, &sbp->st_ctim, <=)); + else if (ctime_flag) + return (timespeccmp(&arcn->sb.st_ctim, &sbp->st_ctim, <=)); + else + return (timespeccmp(&arcn->sb.st_mtim, &sbp->st_mtim, <=)); +} + /* * extract() * extract the member(s) of an archive as specified by user supplied @@ -161,7 +181,6 @@ extract(void) int res; off_t cnt; ARCHD archd; - struct stat sb; int fd; time_t now; @@ -227,22 +246,10 @@ extract(void) * file AFTER the name mod. In honesty the pax spec is probably * flawed in this respect. */ - if ((uflag || Dflag) && ((lstat(arcn->name, &sb) == 0))) { - if (uflag && Dflag) { - if ((arcn->sb.st_mtime <= sb.st_mtime) && - (arcn->sb.st_ctime <= sb.st_ctime)) { - (void)rd_skip(arcn->skip + arcn->pad); - continue; - } - } else if (Dflag) { - if (arcn->sb.st_ctime <= sb.st_ctime) { - (void)rd_skip(arcn->skip + arcn->pad); - continue; - } - } else if (arcn->sb.st_mtime <= sb.st_mtime) { - (void)rd_skip(arcn->skip + arcn->pad); - continue; - } + if ((uflag || Dflag) && + cmp_file_times(uflag, Dflag, arcn, NULL)) { + (void)rd_skip(arcn->skip + arcn->pad); + continue; } /* @@ -263,22 +270,10 @@ extract(void) * Non standard -Y and -Z flag. When the existing file is * same age or newer skip */ - if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) { - if (Yflag && Zflag) { - if ((arcn->sb.st_mtime <= sb.st_mtime) && - (arcn->sb.st_ctime <= sb.st_ctime)) { - (void)rd_skip(arcn->skip + arcn->pad); - continue; - } - } else if (Yflag) { - if (arcn->sb.st_ctime <= sb.st_ctime) { - (void)rd_skip(arcn->skip + arcn->pad); - continue; - } - } else if (arcn->sb.st_mtime <= sb.st_mtime) { - (void)rd_skip(arcn->skip + arcn->pad); - continue; - } + if ((Yflag || Zflag) && + cmp_file_times(Yflag, Zflag, arcn, NULL)) { + (void)rd_skip(arcn->skip + arcn->pad); + continue; } if (vflag) { @@ -851,14 +846,7 @@ copy(void) if (res == 0) { ftree_skipped_newer(arcn); - if (uflag && Dflag) { - if ((arcn->sb.st_mtime<=sb.st_mtime) && - (arcn->sb.st_ctime<=sb.st_ctime)) - continue; - } else if (Dflag) { - if (arcn->sb.st_ctime <= sb.st_ctime) - continue; - } else if (arcn->sb.st_mtime <= sb.st_mtime) + if (cmp_file_times(uflag, Dflag, arcn, &sb)) continue; } } @@ -883,17 +871,9 @@ copy(void) * Non standard -Y and -Z flag. When the existing file is * same age or newer skip */ - if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) { - if (Yflag && Zflag) { - if ((arcn->sb.st_mtime <= sb.st_mtime) && - (arcn->sb.st_ctime <= sb.st_ctime)) - continue; - } else if (Yflag) { - if (arcn->sb.st_ctime <= sb.st_ctime) - continue; - } else if (arcn->sb.st_mtime <= sb.st_mtime) - continue; - } + if ((Yflag || Zflag) && + cmp_file_times(Yflag, Zflag, arcn, NULL)) + continue; if (vflag) { (void)safe_print(arcn->name, listf); diff --git a/bin/pax/buf_subs.c b/bin/pax/buf_subs.c index 36fcce445bf..cac45294436 100644 --- a/bin/pax/buf_subs.c +++ b/bin/pax/buf_subs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: buf_subs.c,v 1.26 2015/01/16 06:39:32 deraadt Exp $ */ +/* $OpenBSD: buf_subs.c,v 1.27 2015/03/19 05:14:24 guenther Exp $ */ /* $NetBSD: buf_subs.c,v 1.5 1995/03/21 09:07:08 cgd Exp $ */ /*- @@ -629,7 +629,7 @@ wr_rdfile(ARCHD *arcn, int ifd, off_t *left) paxwarn(1, "File changed size during read %s", arcn->org_name); else if (fstat(ifd, &sb) < 0) syswarn(1, errno, "Failed stat on %s", arcn->org_name); - else if (arcn->sb.st_mtime != sb.st_mtime) + else if (timespeccmp(&arcn->sb.st_mtim, &sb.st_mtim, !=)) paxwarn(1, "File %s was modified during copy to archive", arcn->org_name); *left = size; @@ -803,7 +803,7 @@ cp_file(ARCHD *arcn, int fd1, int fd2) arcn->org_name, arcn->name); else if (fstat(fd1, &sb) < 0) syswarn(1, errno, "Failed stat of %s", arcn->org_name); - else if (arcn->sb.st_mtime != sb.st_mtime) + else if (timespeccmp(&arcn->sb.st_mtim, &sb.st_mtim, !=)) paxwarn(1, "File %s was modified during copy to %s", arcn->org_name, arcn->name); diff --git a/bin/pax/cpio.c b/bin/pax/cpio.c index 55950c144ad..8ff8836b80f 100644 --- a/bin/pax/cpio.c +++ b/bin/pax/cpio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpio.c,v 1.26 2015/03/17 03:23:17 guenther Exp $ */ +/* $OpenBSD: cpio.c,v 1.27 2015/03/19 05:14:24 guenther Exp $ */ /* $NetBSD: cpio.c,v 1.5 1995/03/21 09:07:13 cgd Exp $ */ /*- @@ -298,7 +298,8 @@ cpio_rd(ARCHD *arcn, char *buf) arcn->sb.st_mtime = INT_MAX; /* XXX 2038 */ else arcn->sb.st_mtime = val; - arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; + arcn->sb.st_mtim.tv_nsec = 0; + arcn->sb.st_ctim = arcn->sb.st_atim = arcn->sb.st_mtim; arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize), OCT); @@ -572,7 +573,8 @@ vcpio_rd(ARCHD *arcn, char *buf) arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX); arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX); arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX); - arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; + arcn->sb.st_mtim.tv_nsec = 0; + arcn->sb.st_ctim = arcn->sb.st_atim = arcn->sb.st_mtim; arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize, sizeof(hd->c_filesize), HEX); arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), @@ -892,7 +894,8 @@ bcpio_rd(ARCHD *arcn, char *buf) ((off_t)(SHRT_EXT(hd->h_filesize_2))); nsz = (int)(SHRT_EXT(hd->h_namesize)); } - arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; + arcn->sb.st_mtim.tv_nsec = 0; + arcn->sb.st_ctim = arcn->sb.st_atim = arcn->sb.st_mtim; /* * check the file name size, if bogus give up. otherwise read the file diff --git a/bin/pax/extern.h b/bin/pax/extern.h index 866e119a03e..12a939157cb 100644 --- a/bin/pax/extern.h +++ b/bin/pax/extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: extern.h,v 1.52 2015/03/15 21:53:09 guenther Exp $ */ +/* $OpenBSD: extern.h,v 1.53 2015/03/19 05:14:24 guenther Exp $ */ /* $NetBSD: extern.h,v 1.5 1996/03/26 23:54:16 mrg Exp $ */ /*- @@ -141,8 +141,10 @@ int chk_same(ARCHD *); int node_creat(ARCHD *); int unlnk_exist(char *, int); int chk_path(char *, uid_t, gid_t); -void set_ftime(char *fnm, time_t mtime, time_t atime, int frc); -void fset_ftime(char *fnm, int, time_t mtime, time_t atime, int frc); +void set_ftime(const char *, const struct timespec *, + const struct timespec *, int); +void fset_ftime(const char *, int, const struct timespec *, + const struct timespec *, int); int set_ids(char *, uid_t, gid_t); int fset_ids(char *, int, uid_t, gid_t); void set_pmode(char *, mode_t); @@ -282,7 +284,8 @@ int map_dev(ARCHD *, u_long, u_long); #endif /* NOCPIO */ int atdir_start(void); void atdir_end(void); -void add_atdir(char *, dev_t, ino_t, time_t, time_t); +void add_atdir(char *, dev_t, ino_t, const struct timespec *, + const struct timespec *); int do_atdir(const char *, dev_t, ino_t); int dir_start(void); void add_dir(char *, struct stat *, int); diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c index 4bfc2eb6907..fe14c598361 100644 --- a/bin/pax/file_subs.c +++ b/bin/pax/file_subs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: file_subs.c,v 1.46 2015/03/15 06:05:59 guenther Exp $ */ +/* $OpenBSD: file_subs.c,v 1.47 2015/03/19 05:14:24 guenther Exp $ */ /* $NetBSD: file_subs.c,v 1.4 1995/03/21 09:07:18 cgd Exp $ */ /*- @@ -147,8 +147,8 @@ file_close(ARCHD *arcn, int fd) if (pmode) fset_pmode(arcn->name, fd, arcn->sb.st_mode); if (patime || pmtime) - fset_ftime(arcn->name, fd, arcn->sb.st_mtime, - arcn->sb.st_atime, 0); + fset_ftime(arcn->name, fd, &arcn->sb.st_mtim, + &arcn->sb.st_atim, 0); if (close(fd) < 0) syswarn(0, errno, "Unable to close file descriptor on %s", arcn->name); @@ -525,7 +525,7 @@ badlink: } if (patime || pmtime) - set_ftime(nm, arcn->sb.st_mtime, arcn->sb.st_atime, 0); + set_ftime(nm, &arcn->sb.st_mtim, &arcn->sb.st_atim, 0); return(0); } @@ -676,14 +676,14 @@ chk_path(char *name, uid_t st_uid, gid_t st_gid) */ void -set_ftime(char *fnm, time_t mtime, time_t atime, int frc) +set_ftime(const char *fnm, const struct timespec *mtimp, + const struct timespec *atimp, 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; + tv[0] = *atimp; + tv[1] = *mtimp; + if (!frc) { /* * if we are not forcing, only set those times the user wants @@ -704,14 +704,15 @@ set_ftime(char *fnm, time_t mtime, time_t atime, int frc) } void -fset_ftime(char *fnm, int fd, time_t mtime, time_t atime, int frc) +fset_ftime(const char *fnm, int fd, const struct timespec *mtimp, + const struct timespec *atimp, 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; + + tv[0] = *atimp; + tv[1] = *mtimp; + if (!frc) { /* * if we are not forcing, only set those times the user wants @@ -834,10 +835,12 @@ set_attr(const struct file_times *ft, int force_times, mode_t mode, /* Whew, it's a match! Is there anything to change? */ if (do_mode && (mode & ABITS) != (sb.st_mode & ABITS)) fset_pmode(ft->ft_name, fd, mode); - if (((force_times || patime) && ft->ft_atime != sb.st_atime) || - ((force_times || pmtime) && ft->ft_mtime != sb.st_mtime)) - fset_ftime(ft->ft_name, fd, ft->ft_mtime, - ft->ft_atime, force_times); + if (((force_times || patime) && + timespeccmp(&ft->ft_atim, &sb.st_atim, !=)) || + ((force_times || pmtime) && + timespeccmp(&ft->ft_mtim, &sb.st_mtim, !=))) + fset_ftime(ft->ft_name, fd, &ft->ft_mtim, + &ft->ft_atim, force_times); r = 0; } close(fd); @@ -1042,8 +1045,8 @@ rdfile_close(ARCHD *arcn, int *fd) * user wants last access time reset */ if (tflag) - fset_ftime(arcn->org_name, *fd, arcn->sb.st_mtime, - arcn->sb.st_atime, 1); + fset_ftime(arcn->org_name, *fd, &arcn->sb.st_mtim, + &arcn->sb.st_atim, 1); (void)close(*fd); *fd = -1; @@ -1100,7 +1103,7 @@ set_crc(ARCHD *arcn, int fd) paxwarn(1, "File changed size %s", arcn->org_name); else if (fstat(fd, &sb) < 0) syswarn(1, errno, "Failed stat on %s", arcn->org_name); - else if (arcn->sb.st_mtime != sb.st_mtime) + else if (timespeccmp(&arcn->sb.st_mtim, &sb.st_mtim, !=)) paxwarn(1, "File %s was modified during read", arcn->org_name); else if (lseek(fd, (off_t)0L, SEEK_SET) < 0) syswarn(1, errno, "File rewind failed on: %s", arcn->org_name); diff --git a/bin/pax/ftree.c b/bin/pax/ftree.c index e6319838245..93de8b711d7 100644 --- a/bin/pax/ftree.c +++ b/bin/pax/ftree.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ftree.c,v 1.37 2015/03/09 04:23:29 guenther Exp $ */ +/* $OpenBSD: ftree.c,v 1.38 2015/03/19 05:14:24 guenther Exp $ */ /* $NetBSD: ftree.c,v 1.4 1995/03/21 09:07:21 cgd Exp $ */ /*- @@ -443,8 +443,8 @@ next_file(ARCHD *arcn) if (!tflag) break; add_atdir(ftent->fts_path, arcn->sb.st_dev, - arcn->sb.st_ino, arcn->sb.st_mtime, - arcn->sb.st_atime); + arcn->sb.st_ino, &arcn->sb.st_mtim, + &arcn->sb.st_atim); break; case S_IFCHR: arcn->type = PAX_CHR; diff --git a/bin/pax/pax.h b/bin/pax/pax.h index f06ad38be69..3aebf68ed4b 100644 --- a/bin/pax/pax.h +++ b/bin/pax/pax.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pax.h,v 1.26 2015/03/17 03:23:17 guenther Exp $ */ +/* $OpenBSD: pax.h,v 1.27 2015/03/19 05:14:24 guenther Exp $ */ /* $NetBSD: pax.h,v 1.3 1995/03/21 09:07:41 cgd Exp $ */ /*- @@ -221,11 +221,11 @@ typedef struct { * at the given name has the indicated dev+ino. */ struct file_times { - ino_t ft_ino; /* inode number to verify */ - time_t ft_mtime; /* times to set */ - time_t ft_atime; - char *ft_name; /* name of file to set the times on */ - dev_t ft_dev; /* device number to verify */ + ino_t ft_ino; /* inode number to verify */ + struct timespec ft_mtim; /* times to set */ + struct timespec ft_atim; + char *ft_name; /* name of file to set the times on */ + dev_t ft_dev; /* device number to verify */ }; /* diff --git a/bin/pax/tables.c b/bin/pax/tables.c index 308e05b1b58..220f594a5f3 100644 --- a/bin/pax/tables.c +++ b/bin/pax/tables.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tables.c,v 1.46 2015/03/17 03:23:17 guenther Exp $ */ +/* $OpenBSD: tables.c,v 1.47 2015/03/19 05:14:24 guenther Exp $ */ /* $NetBSD: tables.c,v 1.4 1995/03/21 09:07:45 cgd Exp $ */ /*- @@ -420,11 +420,11 @@ chk_ftime(ARCHD *arcn) /* * found the file, compare the times, save the newer */ - if (arcn->sb.st_mtime > pt->mtime) { + if (timespeccmp(&arcn->sb.st_mtim, &pt->mtim, >)) { /* * file is newer */ - pt->mtime = arcn->sb.st_mtime; + pt->mtim = arcn->sb.st_mtim; return(0); } /* @@ -444,7 +444,7 @@ chk_ftime(ARCHD *arcn) */ if ((pt->seek = lseek(ffd, (off_t)0, SEEK_END)) >= 0) { if (write(ffd, arcn->name, namelen) == namelen) { - pt->mtime = arcn->sb.st_mtime; + pt->mtim = arcn->sb.st_mtim; pt->namelen = namelen; pt->fow = ftab[indx]; ftab[indx] = pt; @@ -734,7 +734,7 @@ sltab_process_one(struct slinode *s, struct slpath *p, const char *first, set_pmode(path, mode); if (patime || pmtime) - set_ftime(path, sb.st_mtime, sb.st_atime, 0); + set_ftime(path, &sb.st_mtim, &sb.st_atim, 0); /* * If we tried to link to first but failed, then this new symlink @@ -1289,7 +1289,8 @@ atdir_end(void) */ void -add_atdir(char *fname, dev_t dev, ino_t ino, time_t mtime, time_t atime) +add_atdir(char *fname, dev_t dev, ino_t ino, const struct timespec *mtimp, + const struct timespec *atimp) { ATDIR *pt; sigset_t allsigs, savedsigs; @@ -1329,8 +1330,8 @@ add_atdir(char *fname, dev_t dev, ino_t ino, time_t mtime, time_t atime) if ((pt->ft.ft_name = strdup(fname)) != NULL) { pt->ft.ft_dev = dev; pt->ft.ft_ino = ino; - pt->ft.ft_mtime = mtime; - pt->ft.ft_atime = atime; + pt->ft.ft_mtim = *mtimp; + pt->ft.ft_atim = *atimp; pt->fow = atab[indx]; atab[indx] = pt; sigprocmask(SIG_SETMASK, &savedsigs, NULL); @@ -1491,8 +1492,8 @@ add_dir(char *name, struct stat *psb, int frc_mode) " directory: %s", name); return; } - dblk->ft.ft_mtime = psb->st_mtime; - dblk->ft.ft_atime = psb->st_atime; + dblk->ft.ft_mtim = psb->st_mtim; + dblk->ft.ft_atim = psb->st_atim; dblk->ft.ft_ino = psb->st_ino; dblk->ft.ft_dev = psb->st_dev; dblk->mode = psb->st_mode & ABITS; diff --git a/bin/pax/tables.h b/bin/pax/tables.h index 238986f5bb8..55eeb959284 100644 --- a/bin/pax/tables.h +++ b/bin/pax/tables.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tables.h,v 1.15 2015/03/09 04:23:29 guenther Exp $ */ +/* $OpenBSD: tables.h,v 1.16 2015/03/19 05:14:24 guenther Exp $ */ /* $NetBSD: tables.h,v 1.3 1995/03/21 09:07:47 cgd Exp $ */ /*- @@ -79,7 +79,7 @@ typedef struct hrdlnk { */ typedef struct ftm { off_t seek; /* location in scratch file */ - time_t mtime; /* files last modification time */ + struct timespec mtim; /* files last modification time */ struct ftm *fow; int namelen; /* file name length */ } FTM; -- cgit v1.2.3