commit: 0c0a6d40e26ff63dbd1d3410e485d21bc2ec3a83
parent ef38ed2082a808feca4448acb8c32fbe161cdd77
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sat,  3 Jun 2023 05:00:37 +0200
cmd/touch: Remove usage of access(3)
Diffstat:
2 files changed, 31 insertions(+), 46 deletions(-)
diff --git a/cmd/touch.1 b/cmd/touch.1
@@ -76,6 +76,8 @@ is mostly compliant with the
 .St -p1003.1-2008
 specification (
 .Fl t
-is intentionally missing)
+is intentionally missing and
+.Xr futimens 3
+is always used)
 .Sh AUTHORS
 .An Haelwenn (lanodan) Monnier Aq Mt contact@hacktivis.me
diff --git a/cmd/touch.c b/cmd/touch.c
@@ -2,16 +2,17 @@
 // SPDX-FileCopyrightText: 2023 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
 
-#define _DEFAULT_SOURCE   // tm_gmtoff/tm_zone
-#define _XOPEN_SOURCE // strptime
-#include <fcntl.h>    /* open */
-#include <stdbool.h>  /* bool */
-#include <stdio.h>    /* perror, sscanf */
-#include <stdlib.h>   /* exit */
-#include <string.h>   /* memset */
-#include <sys/stat.h> /* futimens, stat */
-#include <time.h>     /* strptime, tm */
-#include <unistd.h>   /* access */
+#define _DEFAULT_SOURCE // tm_gmtoff/tm_zone
+#define _XOPEN_SOURCE   // strptime
+#include <errno.h>      /* errno */
+#include <fcntl.h>      /* open */
+#include <stdbool.h>    /* bool */
+#include <stdio.h>      /* perror, sscanf */
+#include <stdlib.h>     /* exit */
+#include <string.h>     /* memset */
+#include <sys/stat.h>   /* futimens, stat */
+#include <time.h>       /* strptime, tm */
+#include <unistd.h>     /* access */
 
 // Calls exit() on failure
 struct timespec
@@ -63,13 +64,14 @@ iso_parse(char *arg)
 int
 main(int argc, char *argv[])
 {
-	bool ch_atime = false, ch_mtime = false, no_create = false;
+	bool ch_atime = false, ch_mtime = false;
 	char *ref_file           = NULL;
 	struct timespec times[2] = {
 	    {.tv_sec = 0, .tv_nsec = UTIME_OMIT}, // access
 	    {.tv_sec = 0, .tv_nsec = UTIME_OMIT}  // modification
 	};
 	struct timespec target = {0, UTIME_NOW};
+	int open_flags         = O_WRONLY | O_CREAT | O_NOCTTY;
 
 	int c = 0;
 	while((c = getopt(argc, argv, ":acmr:t:d:")) != -1)
@@ -80,7 +82,7 @@ main(int argc, char *argv[])
 			ch_atime = true;
 			break;
 		case 'c':
-			no_create = true;
+			open_flags ^= O_CREAT;
 			break;
 		case 'm':
 			ch_mtime = true;
@@ -136,42 +138,23 @@ main(int argc, char *argv[])
 
 	for(int i = 0; i < argc; i++)
 	{
-		if(access(argv[i], F_OK) != 0)
+		int fd = open(argv[i], open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+		if(fd == -1)
 		{
-			if(no_create)
-			{
-				// Undefined return value in POSIX
-				return 1;
-			}
-
-			// File doesn't exists
-			int fd = creat(argv[i], S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
-
-			if(fd == -1)
-			{
-				perror("touch: open");
-				return 1;
-			}
-
-			if(futimens(fd, times) != 0)
-			{
-				perror("touch: futimens");
-				return 1;
-			}
-
-			if(close(fd) != 0)
-			{
-				perror("touch: close");
-				return 1;
-			}
+			if(errno != ENOENT) perror("touch: open");
+			return 1;
 		}
-		else
+
+		if(futimens(fd, times) != 0)
 		{
-			if(utimensat(AT_FDCWD, argv[i], times, 0) != 0)
-			{
-				perror("touch: utimensat");
-				return 1;
-			}
+			perror("touch: futimens");
+			return 1;
+		}
+
+		if(close(fd) != 0)
+		{
+			perror("touch: close");
+			return 1;
 		}
 	}