]> git.sven.stormbind.net Git - sven/exfatprogs.git/blobdiff - label/label.c
Update upstream source from tag 'upstream/1.1.0'
[sven/exfatprogs.git] / label / label.c
diff --git a/label/label.c b/label/label.c
new file mode 100644 (file)
index 0000000..fd77a54
--- /dev/null
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *   Copyright (C) 2020 Namjae Jeon <linkinjeon@kernel.org>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <locale.h>
+
+#include "exfat_ondisk.h"
+#include "libexfat.h"
+
+static void usage(void)
+{
+       fprintf(stderr, "Usage: exfatlabel\n");
+       fprintf(stderr, "\t-i | --volume-serial                  Switch to volume serial mode\n");
+       fprintf(stderr, "\t-V | --version                        Show version\n");
+       fprintf(stderr, "\t-h | --help                           Show help\n");
+
+       exit(EXIT_FAILURE);
+}
+
+static struct option opts[] = {
+       {"volume-serial",       no_argument,            NULL,   'i' },
+       {"version",             no_argument,            NULL,   'V' },
+       {"help",                no_argument,            NULL,   'h' },
+       {"?",                   no_argument,            NULL,   '?' },
+       {NULL,                  0,                      NULL,    0  }
+};
+
+int main(int argc, char *argv[])
+{
+       int c;
+       int ret = EXIT_FAILURE;
+       struct exfat_blk_dev bd;
+       struct exfat_user_input ui;
+       bool version_only = false;
+       off_t root_clu_off;
+       int serial_mode = 0;
+       int flags = 0;
+
+       init_user_input(&ui);
+
+       if (!setlocale(LC_CTYPE, ""))
+               exfat_err("failed to init locale/codeset\n");
+
+       if (argc == 2)
+               flags = EXFAT_GET_VOLUME_LABEL;
+       else if (argc == 3)
+               flags = EXFAT_SET_VOLUME_LABEL;
+
+       opterr = 0;
+       while ((c = getopt_long(argc, argv, "iVh", opts, NULL)) != EOF)
+               switch (c) {
+               case 'i':
+                       serial_mode = true;
+                       if (argc == 3)
+                               flags = EXFAT_GET_VOLUME_SERIAL;
+                       else if (argc == 4)
+                               flags = EXFAT_SET_VOLUME_SERIAL;
+
+                       break;
+               case 'V':
+                       version_only = true;
+                       break;
+               case '?':
+               case 'h':
+               default:
+                       usage();
+       }
+
+       show_version();
+       if (version_only)
+               exit(EXIT_FAILURE);
+
+       if (argc < 2)
+               usage();
+
+       memset(ui.dev_name, 0, sizeof(ui.dev_name));
+       snprintf(ui.dev_name, sizeof(ui.dev_name), "%s", argv[serial_mode + 1]);
+
+       ret = exfat_get_blk_dev_info(&ui, &bd);
+       if (ret < 0)
+               goto out;
+
+       if (serial_mode) {
+               /* Mode to change or display volume serial */
+               if (flags == EXFAT_GET_VOLUME_SERIAL) {
+                       ret = exfat_show_volume_serial(&bd, &ui);
+               } else if (flags == EXFAT_SET_VOLUME_SERIAL) {
+                       ui.volume_serial = strtoul(argv[3], NULL, 0);
+                       ret = exfat_set_volume_serial(&bd, &ui);
+               }
+       } else {
+               /* Mode to change or display volume label */
+               root_clu_off = exfat_get_root_entry_offset(&bd);
+               if (root_clu_off < 0)
+                       goto close_fd_out;
+
+               if (flags == EXFAT_GET_VOLUME_LABEL)
+                       ret = exfat_show_volume_label(&bd, root_clu_off);
+               else if (flags == EXFAT_SET_VOLUME_LABEL)
+                       ret = exfat_set_volume_label(&bd, argv[2], root_clu_off);
+       }
+
+close_fd_out:
+       close(bd.dev_fd);
+out:
+       return ret;
+}