[BACK]Return to touch.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / touch

Diff for /src/usr.bin/touch/touch.c between version 1.17 and 1.18

version 1.17, 2007/08/06 19:16:06 version 1.18, 2011/08/20 06:44:24
Line 46 
Line 46 
 #include <tzfile.h>  #include <tzfile.h>
 #include <unistd.h>  #include <unistd.h>
   
 void            stime_arg1(char *, struct timeval *);  void            stime_arg1(char *, struct timespec *);
 void            stime_arg2(char *, int, struct timeval *);  void            stime_arg2(char *, int, struct timespec *);
 void            stime_file(char *, struct timeval *);  void            stime_argd(char *, struct timespec *);
   void            stime_file(char *, struct timespec *);
 __dead void     usage(void);  __dead void     usage(void);
   
 int  int
 main(int argc, char *argv[])  main(int argc, char *argv[])
 {  {
         struct stat      sb;          struct timespec  ts[2];
         struct timeval   tv[2];  
         int              aflag, cflag, mflag, ch, fd, len, rval, timeset;          int              aflag, cflag, mflag, ch, fd, len, rval, timeset;
         char            *p;          char            *p;
   
         (void)setlocale(LC_ALL, "");          (void)setlocale(LC_ALL, "");
   
         aflag = cflag = mflag = timeset = 0;          aflag = cflag = mflag = timeset = 0;
         if (gettimeofday(&tv[0], NULL))          while ((ch = getopt(argc, argv, "acd:fmr:t:")) != -1)
                 err(1, "gettimeofday");  
   
         while ((ch = getopt(argc, argv, "acfmr:t:")) != -1)  
                 switch (ch) {                  switch (ch) {
                 case 'a':                  case 'a':
                         aflag = 1;                          aflag = 1;
Line 73 
Line 70 
                 case 'c':                  case 'c':
                         cflag = 1;                          cflag = 1;
                         break;                          break;
                   case 'd':
                           timeset = 1;
                           stime_argd(optarg, ts);
                           break;
                 case 'f':                  case 'f':
                         break;                          break;
                 case 'm':                  case 'm':
Line 80 
Line 81 
                         break;                          break;
                 case 'r':                  case 'r':
                         timeset = 1;                          timeset = 1;
                         stime_file(optarg, tv);                          stime_file(optarg, ts);
                         break;                          break;
                 case 't':                  case 't':
                         timeset = 1;                          timeset = 1;
                         stime_arg1(optarg, tv);                          stime_arg1(optarg, ts);
                         break;                          break;
                 default:                  default:
                         usage();                          usage();
Line 105 
Line 106 
                 len = p - argv[0];                  len = p - argv[0];
                 if (*p == '\0' && (len == 8 || len == 10)) {                  if (*p == '\0' && (len == 8 || len == 10)) {
                         timeset = 1;                          timeset = 1;
                         stime_arg2(*argv++, len == 10, tv);                          stime_arg2(*argv++, len == 10, ts);
                 }                  }
         }          }
   
         /* Otherwise use the current time of day. */          /* Otherwise use the current time of day. */
         if (!timeset)          if (!timeset)
                 tv[1] = tv[0];                  ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW;
   
           if (!aflag)
                   ts[0].tv_nsec = UTIME_OMIT;
           if (!mflag)
                   ts[1].tv_nsec = UTIME_OMIT;
   
         if (*argv == NULL)          if (*argv == NULL)
                 usage();                  usage();
   
         for (rval = 0; *argv; ++argv) {          for (rval = 0; *argv; ++argv) {
                 /* See if the file exists. */                  /* Update the file's timestamp if it exists. */
                 if (stat(*argv, &sb)) {                  if (! utimensat(AT_FDCWD, *argv, ts, 0))
                         if (!cflag) {  
                                 /* Create the file. */  
                                 fd = open(*argv,  
                                     O_WRONLY | O_CREAT, DEFFILEMODE);  
                                 if (fd == -1 || fstat(fd, &sb) || close(fd)) {  
                                         rval = 1;  
                                         warn("%s", *argv);  
                                         continue;  
                                 }  
   
                                 /* If using the current time, we're done. */  
                                 if (!timeset)  
                                         continue;  
                         } else  
                                 continue;  
                 }  
   
                 if (!aflag)  
                         TIMESPEC_TO_TIMEVAL(&tv[0], &sb.st_atimespec);  
                 if (!mflag)  
                         TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtimespec);  
   
                 /* Try utimes(2). */  
                 if (!utimes(*argv, tv))  
                         continue;                          continue;
                   if (errno != ENOENT) {
                 /* If the user specified a time, nothing else we can do. */  
                 if (timeset) {  
                         rval = 1;                          rval = 1;
                         warn("%s", *argv);                          warn("%s", *argv);
                           continue;
                 }                  }
   
                 /*                  /* Didn't exist; should we create it? */
                  * System V and POSIX 1003.1 require that a NULL argument                  if (cflag)
                  * set the access/modification times to the current time.  
                  * The permission checks are different, too, in that the  
                  * ability to write the file is sufficient.  Take a shot.  
                  */  
                  if (!utimes(*argv, NULL))  
                         continue;                          continue;
   
                 rval = 1;                  /* Create the file. */
                 warn("%s", *argv);                  fd = open(*argv, O_WRONLY | O_CREAT, DEFFILEMODE);
                   if (fd == -1 || futimens(fd, ts) || close(fd)) {
                           rval = 1;
                           warn("%s", *argv);
                   }
         }          }
         exit(rval);          exit(rval);
 }  }
Line 169 
Line 149 
 #define ATOI2(s)        ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))  #define ATOI2(s)        ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))
   
 void  void
 stime_arg1(char *arg, struct timeval *tvp)  stime_arg1(char *arg, struct timespec *tsp)
 {  {
         struct tm       *lt;          struct tm       *lt;
         time_t           tmptime;          time_t           tmptime;
         int              yearset;          int              yearset;
         char            *dot, *p;          char            *dot, *p;
                                         /* Start with the current time. */                                          /* Start with the current time. */
         tmptime = tvp[0].tv_sec;          tmptime = tsp[0].tv_sec;
         if ((lt = localtime(&tmptime)) == NULL)          if ((lt = localtime(&tmptime)) == NULL)
                 err(1, "localtime");                  err(1, "localtime");
                                         /* [[CC]YY]MMDDhhmm[.SS] */                                          /* [[CC]YY]MMDDhhmm[.SS] */
Line 233 
Line 213 
         }          }
   
         lt->tm_isdst = -1;              /* Figure out DST. */          lt->tm_isdst = -1;              /* Figure out DST. */
         tvp[0].tv_sec = tvp[1].tv_sec = mktime(lt);          tsp[0].tv_sec = tsp[1].tv_sec = mktime(lt);
         if (tvp[0].tv_sec == -1)          if (tsp[0].tv_sec == -1)
 terr:           errx(1,  terr:           errx(1,
         "out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]");          "out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]");
   
         tvp[0].tv_usec = tvp[1].tv_usec = 0;          tsp[0].tv_nsec = tsp[1].tv_nsec = 0;
 }  }
   
 void  void
 stime_arg2(char *arg, int year, struct timeval *tvp)  stime_arg2(char *arg, int year, struct timespec *tsp)
 {  {
         struct tm       *lt;          struct tm       *lt;
         time_t           tmptime;          time_t           tmptime;
                                         /* Start with the current time. */                                          /* Start with the current time. */
         tmptime = tvp[0].tv_sec;          tmptime = tsp[0].tv_sec;
         if ((lt = localtime(&tmptime)) == NULL)          if ((lt = localtime(&tmptime)) == NULL)
                 err(1, "localtime");                  err(1, "localtime");
   
Line 271 
Line 251 
         lt->tm_sec = 0;          lt->tm_sec = 0;
   
         lt->tm_isdst = -1;              /* Figure out DST. */          lt->tm_isdst = -1;              /* Figure out DST. */
         tvp[0].tv_sec = tvp[1].tv_sec = mktime(lt);          tsp[0].tv_sec = tsp[1].tv_sec = mktime(lt);
         if (tvp[0].tv_sec == -1)          if (tsp[0].tv_sec == -1)
 terr:           errx(1,  terr:           errx(1,
         "out of range or illegal time specification: MMDDhhmm[YY]");          "out of range or illegal time specification: MMDDhhmm[YY]");
   
         tvp[0].tv_usec = tvp[1].tv_usec = 0;          tsp[0].tv_nsec = tsp[1].tv_nsec = 0;
 }  }
   
 void  void
 stime_file(char *fname, struct timeval *tvp)  stime_file(char *fname, struct timespec *tsp)
 {  {
         struct stat     sb;          struct stat     sb;
   
         if (stat(fname, &sb))          if (stat(fname, &sb))
                 err(1, "%s", fname);                  err(1, "%s", fname);
         TIMESPEC_TO_TIMEVAL(tvp, &sb.st_atimespec);          tsp[0] = sb.st_atim;
         TIMESPEC_TO_TIMEVAL(tvp + 1, &sb.st_mtimespec);          tsp[1] = sb.st_mtim;
 }  }
   
   void
   stime_argd(char *arg, struct timespec *tsp)
   {
           struct tm       tm;
           char            *frac, *p;
           int             utc = 0;
   
           /* accept YYYY-MM-DD(T| )hh:mm:ss[(.|,)frac][Z] */
           memset(&tm, 0, sizeof(tm));
           p = strptime(arg, "%F", &tm);
           if (p == NULL || (*p != 'T' && *p != ' '))
                   goto terr;
           p = strptime(p + 1, "%T", &tm);
           if (p == NULL)
                   goto terr;
           tsp[0].tv_nsec = 0;
           if (*p == '.' || *p == ',') {
                   frac = ++p;
                   while (isdigit((unsigned char)*p)) {
                           if (p - frac < 9) {
                                   tsp[0].tv_nsec = tsp[0].tv_nsec * 10 +
                                       *p - '0';
                           }
                           p++;
                   }
                   if (p == frac)
                           goto terr;
   
                   /* fill in the trailing zeros */
                   while (p - frac-- < 9)
                           tsp[0].tv_nsec *= 10;
           }
           if (*p == 'Z') {
                   utc = 1;
                   p++;
           }
           if (*p != '\0')
                   goto terr;
   
           tm.tm_isdst = -1;
           tsp[0].tv_sec = utc ? timegm(&tm) : mktime(&tm);
           if (tsp[0].tv_sec == -1)
   terr:           errx(1,
     "out of range or illegal time specification: YYYY-MM-DDThh:mm:ss[.frac][Z]");
           tsp[1] = tsp[0];
   }
   
 __dead void  __dead void
 usage(void)  usage(void)
 {  {
         extern char     *__progname;  
   
         (void)fprintf(stderr,          (void)fprintf(stderr,
             "usage: %s [-acm] [-r file] [-t [[CC]YY]MMDDhhmm[.SS]] file ...\n",  "usage: touch [-acm] [-d YYYY-MM-DDThh:mm:SS[.frac][Z]] [-r file]\n"
             __progname);  "             [-t [[CC]YY]MMDDhhmm[.SS]] file ...\n");
         exit(1);          exit(1);
 }  }

Legend:
Removed from v.1.17  
changed lines
  Added in v.1.18