mbm75@leah.Albany.EDU (Michael B Meyer) (09/26/88)
Reply-to: mbm75@leah.Albany.EDU (Michael B Meyer) Does anyone know of an easy way (perhaps an existing utility?) for the owner of a file to change the time (date) of last modification to that file? Thanks for any insights. Reply directly to: mbm@halfog.albany.edu
avolio@decuac.dec.com (Frederick M. Avolio) (11/05/88)
Reply-to: avolio@decuac.dec.com (Frederick M. Avolio) No guarantees. Don't call me if you have questions. You get what you pay for, etc. Fred --------------------- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: chtim.c chtim.1 # Wrapped by avolio@gildor.dec.com on Tue Sep 27 13:28:06 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f chtim.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"chtim.c\" else echo shar: Extracting \"chtim.c\" \(6985 characters\) sed "s/^X//" >chtim.c <<'END_OF_chtim.c' X#ifndef lint Xstatic char *sccsid = "@(#)chtim.c 1.2 (Don Gworek) 8/10/85"; X#endif X X/* X * chtim [-sR] [-p proto-file] [-am "date" or seconds] files ... X * X * Change or report file time stamps X * X * -s report in shell script/archive format X * -R recursive for directories X * -p put the proto-file's time stamps on the following files X * -a set access time stamp X * -m set modification time stamp X * X * Default: report time stamps for the files X * X * unctime() routines borrowed from Berkeley dump(8) X * Recusion based on Berkeley 4.3 chmod(1) and ls(1) X * X */ X X#include <stdio.h> X#include <sys/types.h> X#include <sys/time.h> X#include <ctype.h> X#include <sys/stat.h> X#include <sys/dir.h> X X#define TRUE 1 X#define FALSE 0 X#define ARGVAL() (*++(*argv) || (--argc && *++argv)) X Xint scriptf = FALSE; Xint Recursf = FALSE; Xint protof = FALSE; Xint accessf = FALSE; Xint modif = FALSE; X Xint status = 0; Xint argc; Xchar **argv; Xlong now; Xchar nowyear[5]; Xchar command[1024]; X Xstruct tm *localtime (); Xstruct timeval newtime[2]; Xstruct stat stbuf; X Xstatic char months[12][4] = { X "jan", "feb", "mar", "apr", "may", "jun", X "jul", "aug", "sep", "oct", "nov", "dec" X}; X Xmain (ARGC, ARGV) Xint ARGC; Xchar *ARGV[]; X{ X char *s; X argc = ARGC; X argv = ARGV; X (void) strcpy (command, *argv); X (void) time (&now); X s = (char *) ctime (&now); X (void) sprintf (nowyear, "%.4s", (s + 20)); X newtime[0].tv_sec = newtime[1].tv_sec = 0; X getoptions (); X if (argc <= 0) X usage (); X for (; --argc >= 0; argv++) X chtim (*argv); X exit (status); X} X Xgetoptions () { X while (--argc > 0) X if (**(++argv) != '-') X return; X else X switch (*++(*argv)) { X case '\0': X return; X case 'p': X if (!ARGVAL ()) X usage (); X if (stat (*argv, &stbuf) == -1) { X perror (*argv); X exit (1); X } X newtime[0].tv_sec = stbuf.st_atime; X newtime[1].tv_sec = stbuf.st_mtime; X protof = TRUE; X break; X case 'a': X extract_time (0); X break; X case 'm': X extract_time (1); X break; X default: X for (; **argv != '\0'; *(*argv)++) X switch (**argv) { X case 's': X scriptf = TRUE; X break; X case 'R': X Recursf = TRUE; X break; X default: X usage (); X } X } X} X Xextract_time (option) Xint option; X{ X int a, m; X a = m = FALSE; X for (;; *++(*argv)) X switch (**argv) { X case '\0': X if (--argc && *++argv) X goto set; X else X usage (); X break; X case 'a': X a = accessf = TRUE; X break; X case 'm': X m = modif = TRUE; X break; X default: X goto set; X } Xset: X if (!isdigit (**argv)) { X if ((newtime[option].tv_sec = unctime (*argv)) < 0) X usage (); X } X else X newtime[option].tv_sec = atol (*argv); X if (a) X newtime[0].tv_sec = newtime[option].tv_sec; X if (m) X newtime[1].tv_sec = newtime[option].tv_sec; X} X Xchtim (fname) Xchar *fname; X{ X struct stat stb; X if (stat (fname, &stb) == -1) { X perror (fname); X status++; X return; X } X if (Recursf && stb.st_mode & S_IFDIR) X status += chtimr (fname); X if (newtime[0].tv_sec || newtime[1].tv_sec) { X if (accessf && !modif) X newtime[1].tv_sec = stb.st_mtime;/* preserve m value */ X else X if (modif && !accessf) X newtime[0].tv_sec = stb.st_atime;/* preserve a value */ X X if (utimes (fname, newtime) != 0) { X status++; X perror (fname); X } X } X else X if (scriptf) { X if (stb.st_atime == stb.st_mtime) X printf ("%s -am %d", command, stb.st_atime); X else X printf ("%s -a %d -m %d", command, stb.st_atime, stb.st_mtime); X printf (" %s\n", fname); X } X else { X printf ("%s\n", fname); X print_time ("a", stb.st_atime); X print_time ("m", stb.st_mtime); X print_time ("c", stb.st_ctime); X } X} X Xchtimr (dir) Xchar *dir; X{ X register DIR * dirp; X register struct direct *dp; X char dirfile[1024]; X if ((dirp = opendir (dir)) == NULL) { X perror (dir); X return (1); X } X dp = readdir (dirp); X dp = readdir (dirp); /* read "." and ".." */ X for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp)) { X (void) sprintf (dirfile, "%s/%s", dir, dp -> d_name); X chtim (dirfile); X } X closedir (dirp); X return (0); X} X Xprint_time (label, t) Xchar *label; Xlong t; X{ X char *s; X s = (char *) ctime (&t); X if (strncmp ((s + 20), nowyear, 4)) X printf ("\t%s %-13.12s%-5.4s(%d)\n", label, (s + 4), (s + 20), t); X else X printf ("\t%s %-18.15s(%d)\n", label, (s + 4), t); X} X Xchar * X substring (str, substr) Xchar *str, *substr; X{ X while (isspace (*str) && (*str != '\0')) X str++; X while (!isspace (*str) && (*str != '\0')) X *substr++ = *str++; X *substr = '\0'; X return (str); X} X X/* X * Convert a date to seconds since Jan 1, 1970. If an error, return -1. X */ Xtime_t Xunctime (str) Xchar *str; X{ X struct tm tm; X time_t emitl (); X char *s, word[30], *substring (); X if (strlen (str) >= 30) X return (-1); X X str = substring (str, word);/* extract month number */ X if ((tm.tm_mon = get_month (word)) < 0) X return (-1); X X str = substring (str, word);/* extract day */ X tm.tm_mday = atoi (word); X X str = substring (str, word);/* extract time */ X tm.tm_hour = atoi (word); X for (s = word; (*s != '\0') && (*s != ':'); s++); X if (*s == ':') X tm.tm_min = atoi (++s); X else X return (-1); /* mistake in format */ X for (; (*s != '\0') && (*s != ':'); s++); X if (*s == ':') X tm.tm_sec = atoi (++s); X else X tm.tm_sec = 0; /* assume zero */ X X str = substring (str, word);/* if no year given, */ X if (*word) /* assume this year. */ X tm.tm_year = atoi (word) - 1900; X else X tm.tm_year = atoi (nowyear) - 1900; X X return (emitl (&tm)); X} X Xget_month (str) Xchar *str; X{ X int i; X char *strp; X int uclc_diff = 'a' - 'A'; X for (strp = str; !isspace (*strp) && *strp != '\0'; strp++) X if (isupper (*strp)) X *strp += uclc_diff; X for (i = 0; i < 12; i++) X if (!strncmp (months[i], str, 3)) X return (i); X return (-1); X} X X/* X * Routine to convert a localtime(3) format date back into X * a system format date. X * X * Use a binary search. X */ Xtime_t Xemitl (dp) Xstruct tm *dp; X{ X time_t conv; X register int i, bit; X struct tm dcopy; X X dcopy = *dp; X dp = &dcopy; X conv = 0; X for (i = 30; i >= 0; i--) { X bit = 1 << i; X conv |= bit; X if (dcmp (localtime (&conv), dp) > 0) X conv &= ~bit; X } X return (conv); X} X X/* X * Compare two localtime dates, return result. X */ X#define DECIDE(a) \ Xif (dp -> a > dp2 -> a) \ X return (1); \ Xif (dp -> a < dp2 -> a) \ X return (-1) X Xstatic Xdcmp (dp, dp2) Xregister struct tm *dp, *dp2; X{ X DECIDE (tm_year); X DECIDE (tm_mon); X DECIDE (tm_mday); X DECIDE (tm_hour); X DECIDE (tm_min); X DECIDE (tm_sec); X return (0); X} X Xusage () { X fprintf (stderr, "Usage: %s [-sR] [-p proto-file]", command); X fprintf (stderr, " [-am \"date\" or seconds] files ...\n"); X exit (1); X} END_OF_chtim.c if test 6985 -ne `wc -c <chtim.c`; then echo shar: \"chtim.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f chtim.1 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"chtim.1\" else echo shar: Extracting \"chtim.1\" \(1685 characters\) sed "s/^X//" >chtim.1 <<'END_OF_chtim.1' X X X X CHTIM(l) X X X XNAME X chtim - change time stamps X XSYNOPSIS X chtim [ -sR ] [ -p proto-file ] [ -am time ] files ... X XDESCRIPTION X The -a and -m flags mean to reset the access and modifica- X tion times, respectively, to the following time. The time X can be in seconds since Jan 1, 1970; or in a conventional X month, day, time, year, format (Example: "Aug 10 14:34:12 X 1985"). The user must use quotes for the date form. If the X user leaves out the year, chtim will assume the user means X the current year. If the user leaves out the seconds field, X chtim assumes 00 seconds. The month may be in lower-case, X upper-case, or capitalized. X X The -p flag means that the time stamps on the proto-file are X to be used to reset the access and modification times on the X files. X X With a -s flag chtim makes a report in shell script format. X If the user redirects this output to a file, and later X sources that file, the original access and modification X times of the files will be restored. X X The -R flag says chtim should change or report time stamps X recursively on subdirectories. Parent directories are X changed after the child files so that the new access and X modification times on the parent are not immediately reset X to the current time. X X By default, chtim only reports the time stamps of the files. X XBUG X Utimes sets the creation time to the current time. X XSEE ALSO X utimes(2), stat(2), ls(1) X XAUTHOR X Don Gworek (3 functions borrowed from Berkeley dump(8)) X X X X X X X X X X X X X X X X X END_OF_chtim.1 if test 1685 -ne `wc -c <chtim.1`; then echo shar: \"chtim.1\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of shell archive. exit 0