changeset 702:9fb5fe6eb13f

More touch cleanup to use generic infrastructure: use getdate() from libc, use flag macros, option parsing can collect argument strings in global block, use existing perror_* macros.
author Rob Landley <rob@landley.net>
date Fri, 16 Nov 2012 18:01:35 -0600
parents 7b316e3c0e11
children 8eb26e828756
files lib/portability.h toys/posix/touch.c
diffstat 2 files changed, 26 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/lib/portability.h	Fri Nov 16 15:44:45 2012 -0600
+++ b/lib/portability.h	Fri Nov 16 18:01:35 2012 -0600
@@ -27,6 +27,8 @@
 // Another one. "Function prototypes shall be provided." but aren't.
 // http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html
 char *crypt(const char *key, const char *salt);
+// And again, from all the way back in posix-2001
+struct tm *getdate(const char *string);
 
 // When building under obsolete glibc, hold its hand a bit.
 
--- a/toys/posix/touch.c	Fri Nov 16 15:44:45 2012 -0600
+++ b/toys/posix/touch.c	Fri Nov 16 18:01:35 2012 -0600
@@ -5,7 +5,7 @@
  *
  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/touch.html 
 
-USE_TOUCH(NEWTOY(touch, "mrt", TOYFLAG_BIN))
+USE_TOUCH(NEWTOY(touch, "mr:t:", TOYFLAG_BIN))
 
 config TOUCH
   bool "th"
@@ -18,119 +18,43 @@
     -t STAMP               use [[CC]YY]MMDDhhmm[.ss] instead of current time
 */
 
+#define FOR_touch
 #include "toys.h"
 
-int check_date_format(char *date_input)
-{
-  int count_date_digit = 0;
-  unsigned long long flag_b4_sec;
-  int  flag_af_sec;
-  char *date_store = (char *)malloc(12 * sizeof(char));
-
-  while(date_input[count_date_digit] != '.') {
-    date_store[count_date_digit] = date_input[count_date_digit];
-    count_date_digit++;
-  }
-  date_store[count_date_digit++] = '\0';
-  flag_b4_sec = atoll(date_store);
-  date_store[0] = date_input[count_date_digit++];
-  date_store[1] = date_input[count_date_digit];
-  date_store[2] = '\0';
-  flag_af_sec = atoi(date_store);
-  if(date_store[0] == '0' && date_store[1] == '0') flag_af_sec = 1;
-  if(flag_b4_sec && flag_af_sec) return 0;
-  else return -1;
-}
-
-/* function to return number of seconds since epoch till the given date */
-time_t get_time_sec(char *date_input)
-{
-  int count_date_digit = 0;
-  char mm[3];
-  char year[5];
-  time_t time_of_modify;
-  struct tm t_yyyymmddhhss;
-
-  while(date_input[count_date_digit] != '.') {
-    if(count_date_digit < 4) 
-      year[count_date_digit] = date_input[count_date_digit];
-    count_date_digit++;
-    if(count_date_digit == 4) {
-      year[count_date_digit] = '\0';
-      t_yyyymmddhhss.tm_year = atoi(year)-1900;
-      break;
-    }
-  }
-  mm[0] = date_input[4];
-  mm[1] = date_input[5];
-  mm[2] = '\0';
-  t_yyyymmddhhss.tm_mon = (atoi(mm) - 1);
-  mm[0] = date_input[6];
-  mm[1] = date_input[7];
-  mm[2] = '\0';
-  t_yyyymmddhhss.tm_mday = atoi(mm);
-  mm[0] = date_input[8];
-  mm[1] = date_input[9];
-  mm[2] = '\0';
-  t_yyyymmddhhss.tm_hour = atoi(mm);
-  mm[0] = date_input[10];
-  mm[1] = date_input[11];
-  mm[2] = '\0';
-  t_yyyymmddhhss.tm_min = atoi(mm);
-  mm[0] = date_input[13];
-  mm[1] = date_input[14];
-  mm[2] = '\0';
-  t_yyyymmddhhss.tm_sec = atoi(mm);
-  time_of_modify = mktime(&t_yyyymmddhhss);
-  return time_of_modify;
-}
+GLOBALS(
+  char *date;
+  char *file;
+)
 
 void touch_main(void)
 {
-  int fd, touch_flag_t = 0, touch_flag_m = 0, touch_flag_r = 0;
+  int fd;
   time_t now;
   struct utimbuf modinfo;
-  struct stat filestat;
+  struct stat st;
 
-  if (!toys.optflags) {
-    time(&now);
-    modinfo.modtime = now;
-    modinfo.actime = now;
-  } else {
-    if (toys.optflags & 1) {
-      touch_flag_t = 1;
-      if ((toys.optflags >> 2) & 1) touch_flag_m = 1;
-    }
+  if (TT.date) {
+    struct tm *tm = getdate(TT.date);
 
-    if ((toys.optflags >> 1) & 1) touch_flag_r = 1;
+    if (!tm) perror_exit("bad date '%s'", TT.date);
+    now = mktime(tm);
+  } else time(&now);
+  modinfo.modtime = now;
+  modinfo.actime = now;
 
-    if (toys.optflags >> 2) touch_flag_m = 1;
+  if (TT.file) {
+    xstat(TT.file, &st);
+    modinfo.modtime = st.st_mtime;
+    modinfo.actime = st.st_atime;
   }
 
-  if (touch_flag_t) {
-    if (!check_date_format(toys.optargs[0])) {
-      modinfo.modtime = get_time_sec((char *)toys.optargs[0]);
-      modinfo.actime = get_time_sec(toys.optargs[0]);
-    } else {
-      perror_msg("Invalid date format, -t [yyyyMMddhhmm.ss]");
-      toys.exitval = EXIT_FAILURE;
-    }
-  }
-  if(touch_flag_r) {
-    if(stat(toys.optargs[0], &filestat) < 0) {
-      printf("Error : unable to get information for file %s\n", toys.optargs[0]);
-      toys.exitval = EXIT_FAILURE;
-    }
-    modinfo.modtime = filestat.st_mtime;
-    modinfo.actime = filestat.st_atime;
-  }
-  if(touch_flag_m) {
-    if(stat(toys.optargs[toys.optc - 1], &filestat) < 0) {
+  if (toys.optflags & FLAG_m) {
+    if(stat(toys.optargs[toys.optc - 1], &st) < 0) {
       toys.exitval = EXIT_FAILURE;
       return;
     }
-    modinfo.actime = filestat.st_atime;
-    if(!(touch_flag_r | touch_flag_t)) {
+    modinfo.actime = st.st_atime;
+    if(!(toys.optflags & (FLAG_r|FLAG_t))) {
       time(&now);
       modinfo.modtime = now;
     }
@@ -140,10 +64,8 @@
       close(fd);
       utime(toys.optargs[toys.optc - 1], &modinfo);
     } else {
-      perror("unable to create the file");
+      perror_msg("can't create '%s'", toys.optargs[toys.optc-1]);
       toys.exitval = EXIT_FAILURE;
     }
   }
 }
-
-