#define _POSIX_C_SOURCE 200809L
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static int
touch(const char *name, int nocreate, const struct timespec *times)
{
    int fd, status = 0;
    if (utimensat(AT_FDCWD, name, times, 0) == 0) return 0;
    if (errno != ENOENT) { perror(name); return 1; }
    if (nocreate) return 0;
    fd = open(name, O_WRONLY | O_CREAT, 0666);
    if (fd < 0) { perror(name); return 1; }
    if (futimens(fd, times) < 0) { perror(name); status = 1; }
    if (close(fd) < 0) { perror(name); status = 1; }
    return status;
}

int
main(int argc, char **argv)
{
    struct timespec times[2];
    const struct timespec *when = NULL;
    int option, nocreate = 0, status = 0;
    while ((option = getopt(argc, argv, "ct:")) != -1) {
        if (option == 'c') nocreate = 1;
        else if (option == 't') {
            char *end;
            long long seconds;
            errno = 0;
            seconds = strtoll(optarg, &end, 0);
            if (errno || !*optarg || *end || (long long)(time_t)seconds != seconds) goto usage;
            times[0].tv_sec = times[1].tv_sec = (time_t)seconds;
            times[0].tv_nsec = times[1].tv_nsec = 0;
            when = times;
        } else goto usage;
    }
    if (optind == argc) goto usage;
    for (; optind < argc; ++optind) status |= touch(argv[optind], nocreate, when);
    return status;
usage:
    fprintf(stderr, "usage: %s [-c] [-t seconds] file...\n", argv[0]);
    return 1;
}
