commit: cc07e9b70a5cd570c5cee1213f4f8f437ea904cf
parent 1cab789b9c76b456f011015a9dadf01ea24e1d91
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Sun, 21 Apr 2024 03:04:34 +0200
cmd/mknod: new
Diffstat:
6 files changed, 228 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
@@ -95,6 +95,10 @@ cmd/mkdir: cmd/mkdir.c lib/mode.c Makefile
rm -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno}
$(CC) -std=c99 $(CFLAGS) -o $@ cmd/mkdir.c lib/mode.c $(LDFLAGS) $(LDSTATIC)
+cmd/mknod: cmd/mknod.c lib/mode.c Makefile
+ rm -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno}
+ $(CC) -std=c99 $(CFLAGS) -o $@ cmd/mknod.c lib/mode.c $(LDFLAGS) $(LDSTATIC)
+
cmd/seq: cmd/seq.c lib/absu.h Makefile
rm -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno}
$(CC) -std=c99 $(CFLAGS) -o $@ cmd/seq.c -lm $(LDFLAGS) $(LDSTATIC)
diff --git a/cmd/mknod.1 b/cmd/mknod.1
@@ -0,0 +1,67 @@
+.\" utils-std: Collection of commonly available Unix tools
+.\" Copyright 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+.\" SPDX-License-Identifier: MPL-2.0
+.Dd 2024-04-21
+.Dt MKNOD 1
+.Os
+.Sh NAME
+.Nm mknod
+.Nd Create FIFO, block-special, character-special files
+.Sh SYNOPSIS
+.Nm
+.Op Fl m Ar mode
+.Ar path
+.Ar b Ns | Ns Ar c Ns | Ns Ar u
+.Ar major
+.Ar minor
+.Nm
+.Op Fl m Ar mode
+.Ar path
+.Ar p
+.Sh DESCRIPTION
+.Nm
+creates special file at
+.Ar path
+of the given type:
+.Bl -tag -width ___
+.It Ar b
+Create block special file
+.It Ar c Ns | Ns Ar u
+Create character special file
+.It Ar p
+Create FIFO
+.El
+.Pp
+Both
+.Ar major
+and
+.Ar minor
+must be secified when type is
+.Ar b ,
+.Ar c ,
+or
+.Ar u ,
+and they must be omitted when type is
+.Ar p .
+The numbers given in
+.Ar major
+and
+.Ar minor
+are interpreted as hexadecimal with a leading 0x or 0X,
+octal with a leading 0,
+decimal otherwise.
+.Sh OPTIONS
+.Bl -tag -width _m_mode
+.It Fl m Ar mode
+Set permission of new special file,
+relative to 0666/rw-rw-rw using the same format as
+.Xr chmod 1 .
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr mkfifo 1
+.Sh STANDARDS
+None known.
+.Sh AUTHORS
+.An Haelwenn (lanodan) Monnier Aq Mt contact+utils@hacktivis.me
diff --git a/cmd/mknod.c b/cmd/mknod.c
@@ -0,0 +1,154 @@
+// utils-std: Collection of commonly available Unix tools
+// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+// SPDX-License-Identifier: MPL-2.0
+
+#define _POSIX_C_SOURCE 200809L
+#define _XOPEN_SOURCE 700 // mknod is in XSI
+
+#include "../lib/mode.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h> // fprintf
+#include <stdlib.h> // abort, exit
+#include <string.h> // strerror, strrchr
+#include <sys/stat.h> // mknod
+#include <sys/sysmacros.h> // makedev
+#include <unistd.h> // getopt
+
+mode_t filemask;
+
+static void
+usage()
+{
+ fprintf(stderr, "Usage: mknod [-m mode] file <b|c|u|p> [major minor]\n");
+}
+
+static unsigned int
+strtodev(char *arg)
+{
+ char *endptr = NULL;
+ assert(errno == 0);
+ long dev = strtol(arg, &endptr, 0);
+ if(errno != 0)
+ {
+ fprintf(stderr, "mknod: Failed parsing '%s' into a number: %s\n", arg, strerror(errno));
+ exit(1);
+ }
+ if(endptr != NULL && endptr[0] != 0)
+ {
+ fprintf(stderr,
+ "mknod: Extraneous characters in '%s' while parsing it as a number: '%s'\n",
+ arg,
+ endptr);
+ exit(1);
+ }
+
+ return (unsigned int)dev;
+}
+
+int
+main(int argc, char *argv[])
+{
+ mode_t mode = 0666;
+
+ const char *errstr = NULL;
+
+ int c = -1;
+ while((c = getopt(argc, argv, ":m:")) != -1)
+ {
+ switch(c)
+ {
+ case 'm':
+ mode = new_mode(optarg, 0666, &errstr);
+ if(errstr != NULL)
+ {
+ fprintf(stderr, "mknod: Failed parsing '%s': %s\n", optarg, errstr);
+ return 1;
+ }
+ break;
+ case ':':
+ fprintf(stderr, "mknod: Error: Missing operand for option: '-%c'\n", optopt);
+ usage();
+ return 1;
+ case '?':
+ fprintf(stderr, "mknod: Error: Unrecognised option: '-%c'\n", optopt);
+ usage();
+ return 1;
+ default:
+ abort();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ assert(errno == 0);
+
+ if(argc < 2)
+ {
+ fprintf(stderr, "mknod: Missing operands\n");
+ usage();
+ return 1;
+ }
+
+ char *file = argv[0];
+ char *type = argv[1];
+
+ if(type[0] == 0 || type[1] != 0)
+ {
+ fprintf(stderr, "mknod: Invalid type '%s'\n", type);
+ usage();
+ return 1;
+ }
+
+ assert(errno == 0);
+ if(type[0] == 'p')
+ {
+ if(mknod(file, mode | S_IFIFO, 0) != 0)
+ {
+ fprintf(stderr, "mknod: Failed creating FIFO at '%s': %s\n", file, strerror(errno));
+ return 1;
+ }
+ }
+ else
+ {
+ if(argc != 4)
+ {
+ fprintf(stderr, "mknod: non-FIFO device types requires major minor arguments to be given\n");
+ return 1;
+ }
+
+ unsigned int maj = strtodev(argv[2]);
+ unsigned int min = strtodev(argv[3]);
+
+ char *type_name;
+ switch(type[0])
+ {
+ case 'b':
+ mode |= S_IFBLK;
+ type_name = "block-special";
+ break;
+ case 'c':
+ mode |= S_IFCHR;
+ type_name = "character-special";
+ break;
+ case 'u':
+ mode |= S_IFCHR;
+ type_name = "character-special";
+ break;
+ default:
+ fprintf(stderr, "mknod: Invalid type '%c'\n", type[0]);
+ usage();
+ return 1;
+ }
+
+ if(mknod(file, mode, makedev(maj, min)) != 0)
+ {
+ fprintf(stderr, "mknod: Failed creating %s at '%s': %s\n", type_name, file, strerror(errno));
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/coreutils.txt b/coreutils.txt
@@ -45,7 +45,7 @@ ls: ?
md5sum: No
mkdir: Done
mkfifo: ?
-mknod: Todo
+mknod: Done
mktemp: Todo
mv: Todo
nice: Done
diff --git a/lsb_commands.txt b/lsb_commands.txt
@@ -79,7 +79,7 @@ man: out of scope
md5sum: No
mkdir: Done
mkfifo: ?
-mknod: Todo
+mknod: Done
mktemp: Todo
more: No
mount: out of scope
diff --git a/makeless.sh b/makeless.sh
@@ -25,6 +25,7 @@ $CC -std=c99 $CFLAGS -o cmd/id cmd/id.c $LDFLAGS $LDSTATIC
$CC -std=c99 $CFLAGS -o cmd/link cmd/link.c $LDFLAGS $LDSTATIC
$CC -std=c99 $CFLAGS -o cmd/logname cmd/logname.c $LDFLAGS $LDSTATIC
$CC -std=c99 $CFLAGS -o cmd/mkdir cmd/mkdir.c lib/mode.c $LDFLAGS $LDSTATIC
+$CC -std=c99 $CFLAGS -o cmd/mknod cmd/mknod.c lib/mode.c $LDFLAGS $LDSTATIC
$CC -std=c99 $CFLAGS -o cmd/nice cmd/nice.c $LDFLAGS $LDSTATIC
$CC -std=c99 $CFLAGS -o cmd/nohup cmd/nohup.c $LDFLAGS $LDSTATIC
$CC -std=c99 $CFLAGS -o cmd/nproc cmd/nproc.c $LDFLAGS $LDSTATIC