10f66f451Sopenharmony_ci/* touch.c : change timestamp of a file 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2012 Choubey Ji <warior.linux@gmail.com> 40f66f451Sopenharmony_ci * 50f66f451Sopenharmony_ci * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/touch.html 60f66f451Sopenharmony_ci * 70f66f451Sopenharmony_ci * -f is ignored for BSD/macOS compatibility. busybox/coreutils also support 80f66f451Sopenharmony_ci * this, but only coreutils documents it in --help output. 90f66f451Sopenharmony_ci 100f66f451Sopenharmony_ciUSE_TOUCH(NEWTOY(touch, "<1acd:fmr:t:h[!dtr]", TOYFLAG_BIN)) 110f66f451Sopenharmony_ci 120f66f451Sopenharmony_ciconfig TOUCH 130f66f451Sopenharmony_ci bool "touch" 140f66f451Sopenharmony_ci default y 150f66f451Sopenharmony_ci help 160f66f451Sopenharmony_ci usage: touch [-amch] [-d DATE] [-t TIME] [-r FILE] FILE... 170f66f451Sopenharmony_ci 180f66f451Sopenharmony_ci Update the access and modification times of each FILE to the current time. 190f66f451Sopenharmony_ci 200f66f451Sopenharmony_ci -a Change access time 210f66f451Sopenharmony_ci -m Change modification time 220f66f451Sopenharmony_ci -c Don't create file 230f66f451Sopenharmony_ci -h Change symlink 240f66f451Sopenharmony_ci -d Set time to DATE (in YYYY-MM-DDThh:mm:SS[.frac][tz] format) 250f66f451Sopenharmony_ci -t Set time to TIME (in [[CC]YY]MMDDhhmm[.ss][frac] format) 260f66f451Sopenharmony_ci -r Set time same as reference FILE 270f66f451Sopenharmony_ci*/ 280f66f451Sopenharmony_ci 290f66f451Sopenharmony_ci#define FOR_touch 300f66f451Sopenharmony_ci#include "toys.h" 310f66f451Sopenharmony_ci 320f66f451Sopenharmony_ciGLOBALS( 330f66f451Sopenharmony_ci char *t, *r, *d; 340f66f451Sopenharmony_ci) 350f66f451Sopenharmony_ci 360f66f451Sopenharmony_civoid touch_main(void) 370f66f451Sopenharmony_ci{ 380f66f451Sopenharmony_ci struct timespec ts[2]; 390f66f451Sopenharmony_ci char **ss; 400f66f451Sopenharmony_ci int fd, i; 410f66f451Sopenharmony_ci 420f66f451Sopenharmony_ci // use current time if no -t or -d 430f66f451Sopenharmony_ci ts[0].tv_nsec = UTIME_NOW; 440f66f451Sopenharmony_ci 450f66f451Sopenharmony_ci if (FLAG(t) || FLAG(d)) { 460f66f451Sopenharmony_ci time_t t = time(0); 470f66f451Sopenharmony_ci unsigned nano; 480f66f451Sopenharmony_ci 490f66f451Sopenharmony_ci xparsedate(TT.t ? TT.t : TT.d, &t, &nano, 0); 500f66f451Sopenharmony_ci ts->tv_sec = t; 510f66f451Sopenharmony_ci ts->tv_nsec = nano; 520f66f451Sopenharmony_ci } 530f66f451Sopenharmony_ci ts[1]=ts[0]; 540f66f451Sopenharmony_ci 550f66f451Sopenharmony_ci if (TT.r) { 560f66f451Sopenharmony_ci struct stat st; 570f66f451Sopenharmony_ci 580f66f451Sopenharmony_ci xstat(TT.r, &st); 590f66f451Sopenharmony_ci ts[0] = st.st_atim; 600f66f451Sopenharmony_ci ts[1] = st.st_mtim; 610f66f451Sopenharmony_ci } 620f66f451Sopenharmony_ci 630f66f451Sopenharmony_ci // Which time(s) should we actually change? 640f66f451Sopenharmony_ci i = toys.optflags & (FLAG_a|FLAG_m); 650f66f451Sopenharmony_ci if (i && i!=(FLAG_a|FLAG_m)) ts[i!=FLAG_m].tv_nsec = UTIME_OMIT; 660f66f451Sopenharmony_ci 670f66f451Sopenharmony_ci // Loop through files on command line 680f66f451Sopenharmony_ci for (ss = toys.optargs; *ss;) { 690f66f451Sopenharmony_ci char *s = *ss++; 700f66f451Sopenharmony_ci 710f66f451Sopenharmony_ci if (!strcmp(s, "-")) { 720f66f451Sopenharmony_ci if (!futimens(1, ts)) continue; 730f66f451Sopenharmony_ci } else { 740f66f451Sopenharmony_ci // cheat: FLAG_h is rightmost flag, so its value is 1 750f66f451Sopenharmony_ci if (!utimensat(AT_FDCWD, s, ts, FLAG(h)*AT_SYMLINK_NOFOLLOW)) continue; 760f66f451Sopenharmony_ci if (FLAG(c)) continue; 770f66f451Sopenharmony_ci if (access(s, F_OK) && (-1!=(fd = open(s, O_CREAT, 0666)))) { 780f66f451Sopenharmony_ci close(fd); 790f66f451Sopenharmony_ci if (toys.optflags) ss--; 800f66f451Sopenharmony_ci continue; 810f66f451Sopenharmony_ci } 820f66f451Sopenharmony_ci } 830f66f451Sopenharmony_ci perror_msg("'%s'", s); 840f66f451Sopenharmony_ci } 850f66f451Sopenharmony_ci} 86