summaryrefslogtreecommitdiff
path: root/Userland/mknod.cpp
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-05-03 22:59:58 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-05-03 22:59:58 +0200
commit8b249bd09bc63ad3a9aa99cc268299f0239b2f7d (patch)
tree345d460dd10fdbb34bc6e6cc283fe51a33095391 /Userland/mknod.cpp
parentabb5c890e0960fa00cb566a9905e13cba078972b (diff)
downloadserenity-8b249bd09bc63ad3a9aa99cc268299f0239b2f7d.zip
Kernel+Userland: Implement mknod() syscall and add a /bin/mknod program.
Diffstat (limited to 'Userland/mknod.cpp')
-rw-r--r--Userland/mknod.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/Userland/mknod.cpp b/Userland/mknod.cpp
new file mode 100644
index 0000000000..dc1221b51d
--- /dev/null
+++ b/Userland/mknod.cpp
@@ -0,0 +1,50 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+inline constexpr unsigned encoded_device(unsigned major, unsigned minor)
+{
+ return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);
+}
+
+static int usage()
+{
+ printf("usage: mknod <name> <c|b|p> <major> <minor>\n");
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ // FIXME: When invoked with type "p", no need for major/minor numbers.
+ // FIXME: Add some kind of option for specifying the file permissions.
+ if (argc != 5)
+ return usage();
+
+ const char* name = argv[1];
+ mode_t mode = 0666;
+ switch (argv[2][0]) {
+ case 'c':
+ case 'u':
+ mode |= S_IFCHR;
+ break;
+ case 'b':
+ mode |= S_IFBLK;
+ break;
+ case 'p':
+ mode |= S_IFIFO;
+ break;
+ default:
+ return usage();
+ }
+
+ int major = atoi(argv[3]);
+ int minor = atoi(argv[4]);
+
+ int rc = mknod(name, mode, encoded_device(major, minor));
+ if (rc < 0) {
+ perror("mknod");
+ return 1;
+ }
+ return 0;
+}