changeset 147:ec6e13b2495d

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).
author Rob Landley <rob@landley.net>
date Wed, 31 Oct 2007 01:13:36 -0500
parents 99e651512aa4
children 88dd003ccdf4
files toys/Config.in toys/touch.c toys/toylist.h
diffstat 3 files changed, 96 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/toys/Config.in	Fri Oct 19 19:12:48 2007 -0500
+++ b/toys/Config.in	Wed Oct 31 01:13:36 2007 -0500
@@ -248,17 +248,17 @@
 
 config TOUCH
 	bool "touch"
-	default n
+	default y
 	help
 	  usage: touch [-acmrt] FILE...
 
-	  Change file timestamps/length.  Create empty or sparse files.
+	  Change file timestamps and ensure file existance.
 
-	  -a
-	  -c
-	  -m
-	  -r
-	  -t
+	  -a	Only change the access time.
+	  -c	Do not create the file if it doesn't exist.
+	  -m	Only change the modification time.
+	  -r	Reference file to take timestamps from.
+	  -t	Time to change {a,m}time to, in the format MMDDhhmm.
 
 config TOYSH
 	bool "sh (toysh)"
--- a/toys/touch.c	Fri Oct 19 19:12:48 2007 -0500
+++ b/toys/touch.c	Wed Oct 31 01:13:36 2007 -0500
@@ -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;
 }
--- a/toys/toylist.h	Fri Oct 19 19:12:48 2007 -0500
+++ b/toys/toylist.h	Wed Oct 31 01:13:36 2007 -0500
@@ -55,7 +55,6 @@
 struct touch_data {
 	char *ref_file;
 	char *time;
-	long length;
 };
 
 struct toysh_data {
@@ -111,7 +110,7 @@
 USE_TOYSH(OLDTOY(sh, toysh, "c:i", TOYFLAG_BIN))
 USE_SLEEP(NEWTOY(sleep, "<1", TOYFLAG_BIN))
 USE_SYNC(NEWTOY(sync, NULL, TOYFLAG_BIN))
-USE_TOUCH(NEWTOY(touch, "l#t:r:mca", TOYFLAG_BIN))
+USE_TOUCH(NEWTOY(touch, "t:r:mca", TOYFLAG_BIN))
 USE_TOYSH(NEWTOY(toysh, "c:i", TOYFLAG_BIN))
 USE_TRUE(NEWTOY(true, NULL, TOYFLAG_BIN))
 USE_WHICH(NEWTOY(which, "a", TOYFLAG_USR|TOYFLAG_BIN))