/*--------------------------------------------------------------------------- fdate.c Greg Roelofs This program prints the modification time for a file in "YYYYMMDDhhmmss" or "YYYYMMDDhhmm.ss" (touch(1)) or Unix (seconds since 1970) format, with options to print the access time, status-change time or system time (clock) instead. To compile: cc -O -o fdate fdate.c or: gcc -Wall -O -o fdate fdate.c Revision History: 1.00 15 Mar 1993 created 1.10 15 Apr 1993 added -s option for system date 1.20 9 Feb 1999 modified default output format for Y2K 1.30 2 Jan 2000 added -t option for touch(1) output format 1.31 24 Jan 2000 merged missing 1.20 changes; updated comments 1.40 23 Sep 2002 added macro(s) for large file support 1.41 23 Sep 2004 fixed some compiler warnings 1.50 23 Jan 2005 added support for new-style touch(1) output 1.60 29 Aug 2005 added -C option to convert Unix integer timestamp ---------------------------------------------------------------------------*/ /* GRR 20020923: see http://www.suse.de/~aj/linux_lfs.html for details */ #define _FILE_OFFSET_BITS 64 /* required */ /* #define _LARGEFILE_SOURCE */ /* not required for stat() */ #include #include #include /* time_t, dev_t, etc. */ //#include /* gmtime(), localtime(), strftime(), */ #include /* gmtime(), localtime(), strftime(), */ #include /* stat(), struct stat */ #define VERSION "1.60 of 29 August 2005 (Y2K, large file support)" /* could change this to enum block... */ #define MODIFICATION 0 #define ACCESS 1 #define STATUS 2 #define SYSTEM 3 #define CONVERT 4 int main(argc, argv) int argc; char *argv[]; { char ascnumtime[32], *outfmt; int c, error=0, lflag=0, gflag=0, tflag=0, Tflag=0, uflag=0; int timetype=MODIFICATION; time_t numtime; /*--------------------------------------------------------------------------- Parse command line for '-' options. ---------------------------------------------------------------------------*/ outfmt = "%Y%m%d%H%M%S"; /* default: monotonic, integer format */ if (argc <= 1) --argc; else while (--argc > 0 && (*++argv)[0] == '-') while ((c = *++(argv[0]))) /* argv[0] not program name any more */ switch (c) { case 'a': timetype = ACCESS; break; case 'c': timetype = STATUS; break; case 'C': timetype = CONVERT; break; case 'g': ++gflag; break; case 'l': ++lflag; break; case 's': timetype = SYSTEM; break; case 't': ++tflag; outfmt = "%Y%m%d%H%M.%S"; /* new-style touch(1) */ break; case 'T': ++Tflag; outfmt = "%m%d%H%M%Y.%S"; /* old-style touch(1) */ break; case 'u': ++uflag; break; default: ++error; break; } /* end switch, while, while, if */ /*--------------------------------------------------------------------------- Print usage and exit if any errors encountered. ---------------------------------------------------------------------------*/ if (error || ((argc == 0) && (timetype != SYSTEM))) { fprintf(stderr, "\ fdate %s, by Greg Roelofs.\n\n\ Print file date(s) or system date in YYYYMMDDhhmmss (default), YYYYMMDDhhmm.ss,\n\ MMDDhhmmYYYY.ss, or Unix integer format.\n\n\ usage: fdate [ -acgltu ] file [ file ... ]\n\ fdate -s [ -gtu ]\n\ fdate -C [ -gt ] unixtime\n\ -a print time of last access\n\ -c print time of last status change\n\ -C convert Unix integer format to human-readable form\n\ -g use GMT (UTC) instead of local time for non-Unix output formats\n\ -l long format: print filename(s) as well\n\ -s print system time\n\ -t use new-style \"touch\" output format (YYYYMMDDhhmm.ss)\n\ -T use old-style \"touch\" output format (MMDDhhmmYYYY.ss)\n\ -u use Unix integer time format (always GMT/UTC)\n", VERSION); exit(1); } /*--------------------------------------------------------------------------- Get and print system time. ---------------------------------------------------------------------------*/ if (timetype == SYSTEM || timetype == CONVERT) { if (lflag) { fprintf(stderr, "fdate: -l option ignored with -%c\n", (timetype == SYSTEM)? 's' : 'C'); lflag = 0; ++error; } if (timetype == SYSTEM) numtime = time((time_t *)NULL); else numtime = atol(argv[0]); if (uflag) sprintf(ascnumtime, "%lu", (unsigned long)numtime); else { strftime(ascnumtime, 32, outfmt, gflag? gmtime(&numtime) : localtime(&numtime)); } printf("%s\n", ascnumtime); return error? 1 : 0; } /*--------------------------------------------------------------------------- Loop through files on command line, printing timestamps for each. ---------------------------------------------------------------------------*/ while (argc-- > 0) { struct stat statbuf; if (stat(*argv, &statbuf)) { fprintf(stderr, "fdate: file not found: %s\n", *argv++); ++error; continue; } switch (timetype) { case ACCESS: numtime = statbuf.st_atime; break; case STATUS: numtime = statbuf.st_ctime; break; default: numtime = statbuf.st_mtime; break; } /* convert time to string, one way or other */ if (uflag) sprintf(ascnumtime, "%lu", (unsigned long)numtime); else { strftime(ascnumtime, 32, outfmt, gflag? gmtime(&numtime) : localtime(&numtime)); } /* FIXME: do we want to include "touch -t"/"touch" for -t/-T, resp.? */ printf("%s %s\n", ascnumtime, lflag? *argv : ""); ++argv; } return error? 1 : 0; } /* end main() */