164aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley/* touch.c : change timestamp of a file 2ea52189f6d88673c7d380d4808f8f78063ad5042Rob Landley * 3f6261b3a80a29da78d8b6976ceeb71dcb30f3745Rob Landley * Copyright 2012 Choubey Ji <warior.linux@gmail.com> 4ea52189f6d88673c7d380d4808f8f78063ad5042Rob Landley * 5f033f8607f156464747abe57487c1f6226f94001Rob Landley * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/touch.html 6f033f8607f156464747abe57487c1f6226f94001Rob Landley * 7f033f8607f156464747abe57487c1f6226f94001Rob Landley * TODO: have another go at merging the -t and -d stanzas 8ea52189f6d88673c7d380d4808f8f78063ad5042Rob Landley 99628107532c705b69a211e0f595815a33d390724Rob LandleyUSE_TOUCH(NEWTOY(touch, "acd:mr:t:h[!dtr]", TOYFLAG_BIN)) 10ea52189f6d88673c7d380d4808f8f78063ad5042Rob Landley 11ea52189f6d88673c7d380d4808f8f78063ad5042Rob Landleyconfig TOUCH 12471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley bool "touch" 13ea52189f6d88673c7d380d4808f8f78063ad5042Rob Landley default y 14ea52189f6d88673c7d380d4808f8f78063ad5042Rob Landley help 159628107532c705b69a211e0f595815a33d390724Rob Landley usage: touch [-amch] [-d DATE] [-t TIME] [-r FILE] FILE... 16471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley 17ea52189f6d88673c7d380d4808f8f78063ad5042Rob Landley Update the access and modification times of each FILE to the current time. 18471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley 19471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley -a change access time 20471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley -m change modification time 21471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley -c don't create file 229628107532c705b69a211e0f595815a33d390724Rob Landley -h change symlink 2364aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley -d set time to DATE (in YYYY-MM-DDThh:mm:SS[.frac][tz] format) 249628107532c705b69a211e0f595815a33d390724Rob Landley -t set time to TIME (in [[CC]YY]MMDDhhmm[.ss][frac] format) 2564aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley -r set time same as reference FILE 26ea52189f6d88673c7d380d4808f8f78063ad5042Rob Landley*/ 27ea52189f6d88673c7d380d4808f8f78063ad5042Rob Landley 28bbda4efd9d7cda269d71ae99054e1ad2590d1b02Rob Landley#define FOR_touch 29ea52189f6d88673c7d380d4808f8f78063ad5042Rob Landley#include "toys.h" 30ea52189f6d88673c7d380d4808f8f78063ad5042Rob Landley 31bbda4efd9d7cda269d71ae99054e1ad2590d1b02Rob LandleyGLOBALS( 32471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley char *time; 33bbda4efd9d7cda269d71ae99054e1ad2590d1b02Rob Landley char *file; 34471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley char *date; 35bbda4efd9d7cda269d71ae99054e1ad2590d1b02Rob Landley) 36f6261b3a80a29da78d8b6976ceeb71dcb30f3745Rob Landley 37471ce1b29933702bdd63bf27e4470898cb37b451Rob Landleyvoid touch_main(void) 38471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley{ 399628107532c705b69a211e0f595815a33d390724Rob Landley struct timespec ts[2]; 401b7e562a286b528a440e56b48a4afe3823b2d86bRob Landley char **ss; 419628107532c705b69a211e0f595815a33d390724Rob Landley int fd, i; 42471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley 439628107532c705b69a211e0f595815a33d390724Rob Landley // use current time if no -t or -d 449628107532c705b69a211e0f595815a33d390724Rob Landley ts[0].tv_nsec = UTIME_NOW; 4564aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley if (toys.optflags & (FLAG_t|FLAG_d)) { 461b7e562a286b528a440e56b48a4afe3823b2d86bRob Landley char *s, *date; 471b7e562a286b528a440e56b48a4afe3823b2d86bRob Landley struct tm tm; 489628107532c705b69a211e0f595815a33d390724Rob Landley int len = 0; 491b7e562a286b528a440e56b48a4afe3823b2d86bRob Landley 509628107532c705b69a211e0f595815a33d390724Rob Landley localtime_r(&(ts->tv_sec), &tm); 511b7e562a286b528a440e56b48a4afe3823b2d86bRob Landley 521b7e562a286b528a440e56b48a4afe3823b2d86bRob Landley // Set time from -d? 531b7e562a286b528a440e56b48a4afe3823b2d86bRob Landley 54471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley if (toys.optflags & FLAG_d) { 55471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley date = TT.date; 5664aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley i = strlen(date); 571b7e562a286b528a440e56b48a4afe3823b2d86bRob Landley if (i) { 5876678fa5730dfced54c95696e77fdbc6c9c9e839Rob Landley // Trailing Z means UTC timezone, don't expect libc to know this. 5976678fa5730dfced54c95696e77fdbc6c9c9e839Rob Landley if (toupper(date[i-1])=='Z') { 6076678fa5730dfced54c95696e77fdbc6c9c9e839Rob Landley date[i-1] = 0; 6176678fa5730dfced54c95696e77fdbc6c9c9e839Rob Landley setenv("TZ", "UTC0", 1); 629628107532c705b69a211e0f595815a33d390724Rob Landley localtime_r(&(ts->tv_sec), &tm); 6376678fa5730dfced54c95696e77fdbc6c9c9e839Rob Landley } 6464aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley s = strptime(date, "%Y-%m-%dT%T", &tm); 65671146c3b41460ec3ad25f64f1269be0f3924b27Rob Landley ts->tv_nsec = 0; 669628107532c705b69a211e0f595815a33d390724Rob Landley if (s && *s=='.' && isdigit(s[1])) 679628107532c705b69a211e0f595815a33d390724Rob Landley sscanf(s, ".%lu%n", &ts->tv_nsec, &len); 689628107532c705b69a211e0f595815a33d390724Rob Landley else len = 0; 6964aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley } else s = 0; 7064aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley 7164aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley // Set time from -t? 7264aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley 73471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley } else { 74471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley strcpy(toybuf, "%Y%m%d%H%M"); 75471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley date = TT.time; 76a2fd3cedb28394bea7c84e4c785a61df8ccc92a9Rob Landley i = ((s = strchr(date, '.'))) ? s-date : strlen(date); 77a2fd3cedb28394bea7c84e4c785a61df8ccc92a9Rob Landley if (i < 8 || i%2) error_exit("bad '%s'", date); 78471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley for (i=0;i<3;i++) { 79471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley s = strptime(date, toybuf+(i&2), &tm); 80471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley if (s) break; 81471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley toybuf[1]='y'; 82471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley } 83671146c3b41460ec3ad25f64f1269be0f3924b27Rob Landley ts->tv_nsec = 0; 849628107532c705b69a211e0f595815a33d390724Rob Landley if (s && *s=='.' && sscanf(s, ".%2u%n", &(tm.tm_sec), &len) == 1) { 859628107532c705b69a211e0f595815a33d390724Rob Landley sscanf(s += len, "%lu%n", &ts->tv_nsec, &len); 869628107532c705b69a211e0f595815a33d390724Rob Landley len++; 879628107532c705b69a211e0f595815a33d390724Rob Landley } else len = 0; 889628107532c705b69a211e0f595815a33d390724Rob Landley } 899628107532c705b69a211e0f595815a33d390724Rob Landley if (len) { 909628107532c705b69a211e0f595815a33d390724Rob Landley s += len; 919628107532c705b69a211e0f595815a33d390724Rob Landley if (ts->tv_nsec > 999999999) s = 0; 929628107532c705b69a211e0f595815a33d390724Rob Landley else while (len++ < 10) ts->tv_nsec *= 10; 93f6261b3a80a29da78d8b6976ceeb71dcb30f3745Rob Landley } 94471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley 95471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley errno = 0; 969628107532c705b69a211e0f595815a33d390724Rob Landley ts->tv_sec = mktime(&tm); 971b7e562a286b528a440e56b48a4afe3823b2d86bRob Landley if (!s || *s || errno == EOVERFLOW) perror_exit("bad '%s'", date); 98f6261b3a80a29da78d8b6976ceeb71dcb30f3745Rob Landley } 999628107532c705b69a211e0f595815a33d390724Rob Landley ts[1]=ts[0]; 100471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley 10164aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley // Set time from -r? 10264aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley 1039628107532c705b69a211e0f595815a33d390724Rob Landley if (TT.file) { 1049628107532c705b69a211e0f595815a33d390724Rob Landley struct stat st; 105471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley 1069628107532c705b69a211e0f595815a33d390724Rob Landley xstat(TT.file, &st); 1079628107532c705b69a211e0f595815a33d390724Rob Landley ts[0] = st.st_atim; 1089628107532c705b69a211e0f595815a33d390724Rob Landley ts[1] = st.st_mtim; 1099628107532c705b69a211e0f595815a33d390724Rob Landley } 11064aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley 1119628107532c705b69a211e0f595815a33d390724Rob Landley // Which time(s) should we actually change? 1129628107532c705b69a211e0f595815a33d390724Rob Landley i = toys.optflags & (FLAG_a|FLAG_m); 1139628107532c705b69a211e0f595815a33d390724Rob Landley if (i && i!=(FLAG_a|FLAG_m)) ts[i==FLAG_m].tv_nsec = UTIME_OMIT; 114471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley 11564aae2b41f10704acad3bfb8e37e1a5b8a4c2155Rob Landley // Loop through files on command line 1169628107532c705b69a211e0f595815a33d390724Rob Landley for (ss = toys.optargs; *ss;) { 1179628107532c705b69a211e0f595815a33d390724Rob Landley 1189628107532c705b69a211e0f595815a33d390724Rob Landley // cheat: FLAG_h is rightmost flag, so its value is 1 1199628107532c705b69a211e0f595815a33d390724Rob Landley if (!utimensat(AT_FDCWD, *ss, ts, 1209628107532c705b69a211e0f595815a33d390724Rob Landley (toys.optflags & FLAG_h)*AT_SYMLINK_NOFOLLOW)) ss++; 121471ce1b29933702bdd63bf27e4470898cb37b451Rob Landley else if (toys.optflags & FLAG_c) ss++; 1229628107532c705b69a211e0f595815a33d390724Rob Landley else if (access(*ss, F_OK) && (-1!=(fd = open(*ss, O_CREAT, 0666)))) 1239628107532c705b69a211e0f595815a33d390724Rob Landley close(fd); 124662a267c9b52f256b027d0f176a846b1d973ab99Rob Landley else perror_msg("'%s'", *ss++); 125f6261b3a80a29da78d8b6976ceeb71dcb30f3745Rob Landley } 126f6261b3a80a29da78d8b6976ceeb71dcb30f3745Rob Landley} 127