summaryrefslogtreecommitdiff
path: root/src/commands/mkdir.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/commands/mkdir.c')
-rw-r--r--src/commands/mkdir.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/commands/mkdir.c b/src/commands/mkdir.c
new file mode 100644
index 0000000..3ff1afd
--- /dev/null
+++ b/src/commands/mkdir.c
@@ -0,0 +1,60 @@
+#include "../command.h"
+
+static struct {
+ bool make_parent;
+ mode_t mode;
+} flags;
+
+static int short_arg(char c, char* next) {
+ switch (c) {
+ case 'p':
+ flags.make_parent = true;
+ break;
+ case 'm':
+ check_arg(next);
+ flags.mode = get_mode(next);
+ return ARG_USED;
+ default:
+ return ARG_INVALID;
+ }
+ return ARG_UNUSED;
+}
+
+static void help(void) {
+ printf("Usage: mkdir [-m MODE] [-p] DIRECTORY...\n\n");
+ printf("Create DIRECTORY\n\n");
+ printf("\t-m\tMODE\n");
+ printf("\t-p\tNo error if exists; make parent directories as needed\n");
+}
+
+static bool mkdir_parents(char* path) {
+ for (size_t i = 1; i < strlen(path); i++) {
+ if (path[i] != '/') continue;
+ path[i] = '\0';
+ if (mkdir(path, flags.mode) < 0 && errno != EEXIST) {
+ error_s("failed to create directory '%s': %s", path, strerror(errno));
+ return false;
+ };
+ path[i] = '/';
+ }
+ return true;
+}
+
+COMMAND(makedir) {
+ if (argc < 1) global_help(help);
+
+ flags.make_parent = false;
+ flags.mode = 0755;
+ int start = parse_args(argc, argv, help, short_arg, NULL);
+
+ for (int i = start; i < argc; i++) {
+ if (flags.make_parent && !mkdir_parents(argv[i])) {
+ continue;
+ }
+ if (mkdir(argv[i], flags.mode) < 0) {
+ error_s("failed to create directory '%s': %s", argv[i], strerror(errno));
+ }
+ }
+
+ return EXIT_SUCCESS;
+}