diff options
author | Jakob Kaivo <jkk@ung.org> | 2022-03-13 13:41:01 -0400 |
---|---|---|
committer | Jakob Kaivo <jkk@ung.org> | 2022-03-13 13:41:01 -0400 |
commit | 9af2c490ad435ddb61b9d79174ffa7c05a1399dd (patch) | |
tree | 030e346284f25dd85ddaf430199e58438e560fb1 |
initial commit
-rw-r--r-- | Makefile | 30 | ||||
-rw-r--r-- | touch.c | 154 |
2 files changed, 184 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1951f71 --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +.POSIX: + +# This Makefile was generated by maje +# See https://gitlab.com/jkaivo/maje/ for more information +# Do not edit this Makefile by hand + +CC=c99 +LD=$(CC) +CFLAGS=-Wall -Wextra -Wpedantic -Werror -g +LDFLAGS= +LDLIBS= +SRCDIR=. +OBJDIR=. +BINDIR=$(OBJDIR) +DESTDIR=/usr/local + +all: $(BINDIR)/touch + +clean: + rm -f $(BINDIR)/touch $(OBJDIR)/*.o + +install: $(BINDIR)/touch + cp $(BINDIR)/touch $(DESTDIR)/bin + +$(BINDIR)/touch: $(OBJDIR)/touch.o +$(OBJDIR)/touch.o: $(SRCDIR)/touch.c + $(CC) $(CFLAGS) -o $@ -c $(SRCDIR)/touch.c + +$(BINDIR)/touch: + $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/*.o $(LDLIBS) @@ -0,0 +1,154 @@ +/* + * UNG's Not GNU + * + * Copyright (c) 2022, Jakob Kaivo <jkk@ung.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define _POSIX_C_SOURCE 200809L +#include <errno.h> +#include <fcntl.h> +#include <locale.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <time.h> +#include <unistd.h> + +enum times { + ACCESS = (1<<0), + MODIFY = (1<<1), +}; + +static int touch(const char *path, struct timespec times[2], int create) +{ + int fd = open(path, (create ? O_CREAT : 0), 0644); + if (fd == -1) { + if (!create && errno == ENOENT) { + return 0; + } + fprintf(stderr, "touch: %s: %s\n", path, strerror(errno)); + return 1; + } + if (futimens(fd, times) != 0) { + fprintf(stderr, "touch: %s: %s\n", path, strerror(errno)); + close(fd); + return 1; + } + close(fd); + return 0; +} + +int main(int argc, char *argv[]) +{ + setlocale(LC_ALL, ""); + enum times which = 0; + int create = 1; + enum { CURRENT, TIME, DATE, FILE } how = CURRENT; + char *source = NULL; + + int c; + while ((c = getopt(argc, argv, "acmr:t:d:")) != -1) { + switch(c) { + case 'a': + which |= ACCESS; + break; + + case 'c': + create = 0; + break; + + case 'm': + which |= MODIFY; + break; + + case 'd': + if (how != CURRENT) { + fprintf(stderr, "touch: only one of -d, -r, and -t is allowed\n"); + return 1; + } + how = DATE; + source = optarg; + break; + + case 'r': + if (how != CURRENT) { + fprintf(stderr, "touch: only one of -d, -r, and -t is allowed\n"); + return 1; + } + how = FILE; + source = optarg; + break; + + case 't': + if (how != CURRENT) { + fprintf(stderr, "touch: only one of -d, -r, and -t is allowed\n"); + return 1; + } + how = TIME; + source = optarg; + break; + + default: + return 1; + } + } + + struct timespec times[2] = { { 0 } }; + struct stat st; + + switch (how) { + case CURRENT: + times[0].tv_nsec = UTIME_NOW; + times[0].tv_nsec = UTIME_NOW; + break; + case DATE: + /* TODO */ + break; + case TIME: + /* TODO */ + break; + case FILE: + if (stat(source, &st) != 0) { + fprintf(stderr, "touch: %s: %s\n", source, strerror(errno)); + return 1; + } + times[0] = st.st_atim; + times[1] = st.st_mtim; + } + + if (which == 0) { + which = ACCESS | MODIFY; + } + + if (!(which & ACCESS)) { + times[0].tv_nsec = UTIME_OMIT; + } + + if (!(which & MODIFY)) { + times[1].tv_nsec = UTIME_OMIT; + } + + int ret = 0; + do { + ret |= touch(argv[optind++], times, create); + } while (optind < argc); + return ret; +} |