New upstream version 1.1.1
[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
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
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, &ui);
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 }