aboutsummaryrefslogtreecommitdiff
path: root/toys/touch.c
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2007-10-31 01:13:36 -0500
committerRob Landley <rob@landley.net>2007-10-31 01:13:36 -0500
commit8ae467cdd0d90bed82ee7561e9be5bfbbc9952e1 (patch)
treee404fe0cb7727d2487df95f2b888388ae768046a /toys/touch.c
parent503d0f5b52fe2eafd6523ce785d6c9f73b46329b (diff)
downloadtoybox-8ae467cdd0d90bed82ee7561e9be5bfbbc9952e1.tar.gz
Patch from Charlie Shepherd: Implement touch, set the default in Config.in to
y, and remove the length argument (and all talk of changing the length of files).
Diffstat (limited to 'toys/touch.c')
-rw-r--r--toys/touch.c91
1 files changed, 88 insertions, 3 deletions
diff --git a/toys/touch.c b/toys/touch.c
index 51fd53f2..6771877b 100644
--- a/toys/touch.c
+++ b/toys/touch.c
@@ -1,14 +1,99 @@
/* vi: set sw=4 ts=4: */
/*
- * touch.c - Modify a file's timestamps (or length).
+ * touch.c - Modify a file's timestamps.
+ *
+ * Copyright (C) 2007 Charlie Shepherd <masterdriverz@gentoo.org>
*/
+#define _XOPEN_SOURCE
+#include <sys/stat.h>
+#include <utime.h>
+#include <time.h>
#include "toys.h"
-# warning touch unimplemented
+#define MTIME 0x01
+#define NO_CREATE 0x02
+#define ATIME 0x04
+#define REFERENCE 0x08
+#define TIME 0x10
int touch_main(void)
{
- printf("Hello world\n");
+ char *arg;
+ int i, set_a, set_m, create;
+ time_t curr_a, curr_m;
+
+ set_a = !!(toys.optflags & ATIME);
+ set_m = !!(toys.optflags & MTIME);
+ create = !(toys.optflags & NO_CREATE);
+
+ if (toys.optflags & REFERENCE) {
+ struct stat sb;
+ if (toys.optflags & TIME) {
+ fprintf(stderr,
+ "Cannot specify times from more than one source\n");
+ return 1;
+ }
+ if (stat(toy.touch.ref_file, &sb) == -1) {
+ perror(toy.touch.ref_file);
+ return 1;
+ }
+ curr_m = sb.st_mtime;
+ curr_a = sb.st_atime;
+ } else if (toys.optflags & TIME) {
+ struct tm t;
+ time_t curr;
+ char *c;
+ curr = time(NULL);
+ if (!localtime_r(&curr, &t))
+ goto err;
+ c = strptime(toy.touch.time, "%m%d%H%M", &t);
+ if (!c || *c)
+ goto err;
+ curr_a = curr_m = mktime(&t);
+ if (curr_a == -1) {
+err:
+ fprintf(stderr, "Error converting time %s to internal format",
+ toy.touch.time);
+ return 1;
+ }
+ } else {
+ curr_m = curr_a = time(NULL);
+ }
+
+ for (i = 0; (arg = toys.optargs[i]); i++) {
+ struct utimbuf buf;
+ struct stat sb;
+
+ buf.modtime = curr_m;
+ buf.actime = curr_a;
+
+ if (stat(arg, &sb) == -1) {
+ if (create && errno == ENOENT) {
+ if (creat(arg, O_RDWR))
+ goto error;
+ if (stat(arg, &sb))
+ goto error;
+ }
+ } else {
+error:
+ perror(arg);
+ return 1;
+ }
+
+ if ((set_a+set_m) == 1) {
+ /* We've been asked to only change one */
+ if (set_a)
+ buf.modtime = sb.st_mtime;
+ else if (set_m)
+ buf.actime = sb.st_atime;
+ }
+
+ if (utime(arg, &buf)) {
+ perror(arg);
+ return 1;
+ }
+ }
+
return 0;
}