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