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
usage(void)17 static void usage(void)
18 {
19 fprintf(stderr, "Usage: tune.exfat\n");
20 fprintf(stderr, "\t-l | --print-label Print volume label\n");
21 fprintf(stderr, "\t-L | --set-label=label Set volume label\n");
22 fprintf(stderr, "\t-i | --print-serial Print volume serial\n");
23 fprintf(stderr, "\t-I | --set-serial=value Set volume serial\n");
24 fprintf(stderr, "\t-V | --version Show version\n");
25 fprintf(stderr, "\t-v | --verbose Print debug\n");
26 fprintf(stderr, "\t-h | --help Show help\n");
27
28 exit(EXIT_FAILURE);
29 }
30
31 static struct option opts[] = {
32 {"print-label", no_argument, NULL, 'l' },
33 {"set-label", required_argument, NULL, 'L' },
34 {"print-serial", no_argument, NULL, 'i' },
35 {"set-serial", required_argument, NULL, 'I' },
36 {"version", no_argument, NULL, 'V' },
37 {"verbose", no_argument, NULL, 'v' },
38 {"help", no_argument, NULL, 'h' },
39 {"?", no_argument, NULL, '?' },
40 {NULL, 0, NULL, 0 }
41 };
42
main(int argc,char * argv[])43 int main(int argc, char *argv[])
44 {
45 int c;
46 int ret = EXIT_FAILURE;
47 struct exfat_blk_dev bd;
48 struct exfat_user_input ui;
49 bool version_only = false;
50 int flags = 0;
51 char label_input[VOLUME_LABEL_BUFFER_SIZE];
52 off_t root_clu_off;
53
54 init_user_input(&ui);
55
56 if (!setlocale(LC_CTYPE, ""))
57 exfat_err("failed to init locale/codeset\n");
58
59 opterr = 0;
60 while ((c = getopt_long(argc, argv, "I:iL:lVvh", opts, NULL)) != EOF)
61 switch (c) {
62 case 'l':
63 flags = EXFAT_GET_VOLUME_LABEL;
64 break;
65 case 'L':
66 snprintf(label_input, sizeof(label_input), "%s",
67 optarg);
68 flags = EXFAT_SET_VOLUME_LABEL;
69 break;
70 case 'i':
71 flags = EXFAT_GET_VOLUME_SERIAL;
72 break;
73 case 'I':
74 ui.volume_serial = strtoul(optarg, NULL, 0);
75 flags = EXFAT_SET_VOLUME_SERIAL;
76 break;
77 case 'V':
78 version_only = true;
79 break;
80 case 'v':
81 print_level = EXFAT_DEBUG;
82 break;
83 case '?':
84 case 'h':
85 default:
86 usage();
87 }
88
89 show_version();
90 if (version_only)
91 exit(EXIT_FAILURE);
92
93 if (argc < 3)
94 usage();
95
96 memset(ui.dev_name, 0, sizeof(ui.dev_name));
97 snprintf(ui.dev_name, sizeof(ui.dev_name), "%s", argv[argc - 1]);
98
99 ret = exfat_get_blk_dev_info(&ui, &bd);
100 if (ret < 0)
101 goto out;
102
103 /* Mode to change or display volume serial */
104 if (flags == EXFAT_GET_VOLUME_SERIAL) {
105 ret = exfat_show_volume_serial(bd.dev_fd);
106 goto close_fd_out;
107 } else if (flags == EXFAT_SET_VOLUME_SERIAL) {
108 ret = exfat_set_volume_serial(&bd, &ui);
109 goto close_fd_out;
110 }
111
112 root_clu_off = exfat_get_root_entry_offset(&bd);
113 if (root_clu_off < 0)
114 goto close_fd_out;
115
116 if (flags == EXFAT_GET_VOLUME_LABEL)
117 ret = exfat_show_volume_label(&bd, root_clu_off);
118 else if (flags == EXFAT_SET_VOLUME_LABEL)
119 ret = exfat_set_volume_label(&bd, label_input, root_clu_off);
120 close_fd_out:
121 close(bd.dev_fd);
122 out:
123 return ret;
124 }
125