]> git.sven.stormbind.net Git - sven/exfatprogs.git/blob - tune/tune.c
Add CVE ID to debian changelog
[sven/exfatprogs.git] / tune / tune.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *   Copyright (C) 2019 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: tune.exfat\n");
21         fprintf(stderr, "\t-l | --print-label                    Print volume label\n");
22         fprintf(stderr, "\t-L | --set-label=label                Set volume label\n");
23         fprintf(stderr, "\t-u | --print-guid                     Print volume GUID\n");
24         fprintf(stderr, "\t-U | --set-guid=guid                  Set volume GUID\n");
25         fprintf(stderr, "\t-i | --print-serial                   Print volume serial\n");
26         fprintf(stderr, "\t-I | --set-serial=value               Set volume serial\n");
27         fprintf(stderr, "\t-V | --version                        Show version\n");
28         fprintf(stderr, "\t-v | --verbose                        Print debug\n");
29         fprintf(stderr, "\t-h | --help                           Show help\n");
30
31         exit(EXIT_FAILURE);
32 }
33
34 static struct option opts[] = {
35         {"print-label",         no_argument,            NULL,   'l' },
36         {"set-label",           required_argument,      NULL,   'L' },
37         {"print-guid",          no_argument,            NULL,   'u' },
38         {"set-guid",            required_argument,      NULL,   'U' },
39         {"print-serial",        no_argument,            NULL,   'i' },
40         {"set-serial",          required_argument,      NULL,   'I' },
41         {"version",             no_argument,            NULL,   'V' },
42         {"verbose",             no_argument,            NULL,   'v' },
43         {"help",                no_argument,            NULL,   'h' },
44         {"?",                   no_argument,            NULL,   '?' },
45         {NULL,                  0,                      NULL,    0  }
46 };
47
48 int main(int argc, char *argv[])
49 {
50         int c;
51         int ret = EXIT_FAILURE;
52         struct exfat_blk_dev bd;
53         struct exfat_user_input ui;
54         bool version_only = false;
55         int flags = 0;
56         char label_input[VOLUME_LABEL_BUFFER_SIZE];
57         struct exfat *exfat = NULL;
58         struct pbr *bs;
59
60         init_user_input(&ui);
61
62         if (!setlocale(LC_CTYPE, ""))
63                 exfat_err("failed to init locale/codeset\n");
64
65         opterr = 0;
66         while ((c = getopt_long(argc, argv, "I:iL:lU:uVvh", opts, NULL)) != EOF)
67                 switch (c) {
68                 case 'l':
69                         flags = EXFAT_GET_VOLUME_LABEL;
70                         break;
71                 case 'L':
72                         snprintf(label_input, sizeof(label_input), "%s",
73                                         optarg);
74                         flags = EXFAT_SET_VOLUME_LABEL;
75                         break;
76                 case 'u':
77                         flags = EXFAT_GET_VOLUME_GUID;
78                         break;
79                 case 'U':
80                         if (*optarg != '\0' && *optarg != '\r')
81                                 ui.guid = optarg;
82                         flags = EXFAT_SET_VOLUME_GUID;
83                         break;
84                 case 'i':
85                         flags = EXFAT_GET_VOLUME_SERIAL;
86                         break;
87                 case 'I':
88                         ui.volume_serial = strtoul(optarg, NULL, 0);
89                         flags = EXFAT_SET_VOLUME_SERIAL;
90                         break;
91                 case 'V':
92                         version_only = true;
93                         break;
94                 case 'v':
95                         print_level = EXFAT_DEBUG;
96                         break;
97                 case '?':
98                 case 'h':
99                 default:
100                         usage();
101         }
102
103         show_version();
104         if (version_only)
105                 exit(EXIT_FAILURE);
106
107         if (argc < 3)
108                 usage();
109
110         memset(ui.dev_name, 0, sizeof(ui.dev_name));
111         snprintf(ui.dev_name, sizeof(ui.dev_name), "%s", argv[argc - 1]);
112
113         ret = exfat_get_blk_dev_info(&ui, &bd);
114         if (ret < 0)
115                 goto out;
116
117         /* Mode to change or display volume serial */
118         if (flags == EXFAT_GET_VOLUME_SERIAL) {
119                 ret = exfat_show_volume_serial(bd.dev_fd);
120                 goto close_fd_out;
121         } else if (flags == EXFAT_SET_VOLUME_SERIAL) {
122                 ret = exfat_set_volume_serial(&bd, &ui);
123                 goto close_fd_out;
124         }
125
126         ret = read_boot_sect(&bd, &bs);
127         if (ret)
128                 goto close_fd_out;
129
130         exfat = exfat_alloc_exfat(&bd, bs);
131         if (!exfat) {
132                 free(bs);
133                 ret = -ENOMEM;
134                 goto close_fd_out;
135         }
136
137         exfat->root = exfat_alloc_inode(ATTR_SUBDIR);
138         if (!exfat->root) {
139                 ret = -ENOMEM;
140                 goto close_fd_out;
141         }
142
143         exfat->root->first_clus = le32_to_cpu(exfat->bs->bsx.root_cluster);
144         if (exfat_root_clus_count(exfat)) {
145                 exfat_err("failed to follow the cluster chain of root\n");
146                 exfat_free_inode(exfat->root);
147                 ret = -EINVAL;
148                 goto close_fd_out;
149         }
150
151         if (flags == EXFAT_GET_VOLUME_LABEL)
152                 ret = exfat_read_volume_label(exfat);
153         else if (flags == EXFAT_SET_VOLUME_LABEL)
154                 ret = exfat_set_volume_label(exfat, label_input);
155         else if (flags == EXFAT_GET_VOLUME_GUID)
156                 ret = exfat_read_volume_guid(exfat);
157         else if (flags == EXFAT_SET_VOLUME_GUID)
158                 ret = exfat_set_volume_guid(exfat, ui.guid);
159
160 close_fd_out:
161         close(bd.dev_fd);
162         if (exfat)
163                 exfat_free_exfat(exfat);
164 out:
165         return ret;
166 }