blob: 137433d24c30dc5445c367d9840c4a92f8e3c5ce [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <utime.h>
int main(int argc, char** argv) {
bool verbose = false;
bool use_null_default = false;
bool write_data = false;
bool trunc_data = false;
bool trunc_append = false;
while (argc > 1 && argv[1][0] == '-') {
if (strcmp(argv[1], "-v") == 0) {
verbose = true;
} else if (strcmp(argv[1], "-T") == 0) {
trunc_append = true;
} else if (strcmp(argv[1], "-d") == 0) {
use_null_default = true;
} else if (strcmp(argv[1], "-w") == 0) {
// write some data, make sure that updates
write_data = true;
} else if (strcmp(argv[1], "-t") == 0) {
// truncate, make sure that updates
trunc_data = true;
} else {
break;
}
argc--;
argv++;
}
if (argc <= 1 || argv[1][0] == '-') {
printf("usage: touch [-w] [-t] [-T] [-d] [-v] f1 [f2...]\n");
exit(-1);
}
int rc = 0;
for (int i=1; i<argc; i++) {
char * fname = argv[i];
printf("touch %s\n", fname);
// open, maybe create a new file
int fd = open(fname, O_RDWR|O_CREAT, 0666);
if (fd < 0) {
perror("touch open");
continue;
}
if (trunc_append) {
// indirectly update change time by
// making a change to file contents
// (which you then reverse
// append a byte
int seekpos = lseek(fd, 0L, SEEK_END);
if (seekpos < 0) {
perror("touch seek");
close(fd);
rc = -1;
continue;
}
int count = write(fd, " ", 1);
if (count < 1) {
perror("touch write");
close(fd);
rc = -1;
continue;
}
// get rid of the extra byte
int err = ftruncate(fd, seekpos);
if (err < 0) {
perror("touch ftruncate");
rc = -1;
}
} else if (write_data) {
// write 1024 bytes of zero
char buf[1024] = {};
int len = write(fd, buf, sizeof(buf));
if (len < 0) {
perror("touch write data");
rc = -1;
}
} else if (trunc_data) {
int err = ftruncate(fd, 0L);
if (err < 0) {
perror("touch trunc data ftruncate");
rc = -1;
}
} else {
// default: set the time directly via utime
// access time not currently implemented
if (use_null_default) {
int err = utime(fname, NULL);
if (err < 0) {
perror("touch utime default");
rc = -1;
}
} else {
struct utimbuf ut;
ut.modtime = 1234567;
int err = utime(fname, &ut);
if (err < 0) {
perror("touch utime");
rc = -1;
}
}
}
if (verbose) {
struct stat statb;
fprintf(stderr, "%s: \n", fname);
if (fstat(fd, &statb) < 0) {
perror("fstat");
} else {
fprintf(stderr, "create: %#lx(%ld)\n", statb.st_ctime, statb.st_ctime);
fprintf(stderr, "modify: %#lx(%ld)\n", statb.st_mtime, statb.st_mtime);
}
}
close(fd);
}
return rc;
}