]> git.sven.stormbind.net Git - sven/exfatprogs.git/blob - label/label.c
New upstream version 1.2.1
[sven/exfatprogs.git] / label / label.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *   Copyright (C) 2020 Namjae Jeon <linkinjeon@kernel.org>
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <getopt.h>
11 #include <errno.h>
12 #include <locale.h>
13
14 #include "exfat_ondisk.h"
15 #include "libexfat.h"
16 #include "exfat_fs.h"
17
18 static void usage(void)
19 {
20         fprintf(stderr, "Usage: exfatlabel\n");
21         fprintf(stderr, "\t-i | --volume-serial                  Switch to volume serial mode\n");
22         fprintf(stderr, "\t-V | --version                        Show version\n");
23         fprintf(stderr, "\t-h | --help                           Show help\n");
24
25         exit(EXIT_FAILURE);
26 }
27
28 static struct option opts[] = {
29         {"volume-serial",       no_argument,            NULL,   'i' },
30         {"version",             no_argument,            NULL,   'V' },
31         {"help",                no_argument,            NULL,   'h' },
32         {"?",                   no_argument,            NULL,   '?' },
33         {NULL,                  0,                      NULL,    0  }
34 };
35
36 int main(int argc, char *argv[])
37 {
38         int c;
39         int ret = EXIT_FAILURE;
40         struct exfat_blk_dev bd;
41         struct exfat_user_input ui;
42         bool version_only = false;
43         int serial_mode = 0;
44         int flags = 0;
45
46         init_user_input(&ui);
47
48         if (!setlocale(LC_CTYPE, ""))
49                 exfat_err("failed to init locale/codeset\n");
50
51         if (argc == 2)
52                 flags = EXFAT_GET_VOLUME_LABEL;
53         else if (argc == 3)
54                 flags = EXFAT_SET_VOLUME_LABEL;
55
56         opterr = 0;
57         while ((c = getopt_long(argc, argv, "iVh", opts, NULL)) != EOF)
58                 switch (c) {
59                 case 'i':
60                         serial_mode = true;
61                         if (argc == 3)
62                                 flags = EXFAT_GET_VOLUME_SERIAL;
63                         else if (argc == 4)
64                                 flags = EXFAT_SET_VOLUME_SERIAL;
65
66                         break;
67                 case 'V':
68                         version_only = true;
69                         break;
70                 case '?':
71                 case 'h':
72                 default:
73                         usage();
74         }
75
76         show_version();
77         if (version_only)
78                 exit(EXIT_FAILURE);
79
80         if (argc < 2)
81                 usage();
82
83         memset(ui.dev_name, 0, sizeof(ui.dev_name));
84         snprintf(ui.dev_name, sizeof(ui.dev_name), "%s", argv[serial_mode + 1]);
85
86         ret = exfat_get_blk_dev_info(&ui, &bd);
87         if (ret < 0)
88                 goto out;
89
90         if (serial_mode) {
91                 /* Mode to change or display volume serial */
92                 if (flags == EXFAT_GET_VOLUME_SERIAL) {
93                         ret = exfat_show_volume_serial(bd.dev_fd);
94                 } else if (flags == EXFAT_SET_VOLUME_SERIAL) {
95                         ui.volume_serial = strtoul(argv[3], NULL, 0);
96                         ret = exfat_set_volume_serial(&bd, &ui);
97                 }
98         } else {
99                 struct exfat *exfat;
100                 struct pbr *bs;
101
102                 ret = read_boot_sect(&bd, &bs);
103                 if (ret)
104                         goto close_fd_out;
105
106                 exfat = exfat_alloc_exfat(&bd, bs);
107                 if (!exfat) {
108                         free(bs);
109                         ret = -ENOMEM;
110                         goto close_fd_out;
111                 }
112
113                 exfat->root = exfat_alloc_inode(ATTR_SUBDIR);
114                 if (!exfat->root) {
115                         ret = -ENOMEM;
116                         goto free_exfat;
117                 }
118
119                 exfat->root->first_clus = le32_to_cpu(exfat->bs->bsx.root_cluster);
120                 if (exfat_root_clus_count(exfat)) {
121                         exfat_err("failed to follow the cluster chain of root\n");
122                         exfat_free_inode(exfat->root);
123                         ret = -EINVAL;
124                         goto free_exfat;
125                 }
126
127                 /* Mode to change or display volume label */
128                 if (flags == EXFAT_GET_VOLUME_LABEL)
129                         ret = exfat_read_volume_label(exfat);
130                 else if (flags == EXFAT_SET_VOLUME_LABEL)
131                         ret = exfat_set_volume_label(exfat, argv[2]);
132
133 free_exfat:
134                 if (exfat)
135                         exfat_free_exfat(exfat);
136         }
137
138 close_fd_out:
139         close(bd.dev_fd);
140 out:
141         return ret;
142 }