1 /* fatlabel.c - User interface
3 Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
4 Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
5 Copyright (C) 2007 Red Hat, Inc.
6 Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
7 Copyright (C) 2015-2017 Andreas Bombe <aeb@debian.org>
8 Copyright (C) 2017-2018 Pali Rohár <pali.rohar@gmail.com>
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 The complete text of the GNU General Public License
24 can be found in /usr/share/common-licenses/GPL-3 file.
49 int rw = 0, list = 0, test = 0, verbose = 0, no_spaces_in_sfns = 0;
52 void *mem_queue = NULL;
55 static void handle_label(bool change, bool reset, const char *device, char *newlabel)
61 char label[12] = { 0 };
67 len = mbstowcs(NULL, newlabel, 0);
68 if (len != (size_t)-1 && len > 11) {
70 "fatlabel: labels can be no longer than 11 characters\n");
74 if (!local_string_to_dos_string(label, newlabel, 12)) {
76 "fatlabel: error when processing label\n");
80 for (i = strlen(label); i < 11; ++i)
84 ret = validate_volume_label(label);
87 "fatlabel: warning - lowercase labels might not work properly on some systems\n");
91 "fatlabel: labels with characters below 0x20 are not allowed\n");
96 "fatlabel: labels with characters *?.,;:/\\|+=<>[]\" are not allowed\n");
101 "fatlabel: labels can't be empty or white space only\n");
106 "fatlabel: labels can't start with a space character\n");
114 if (!change && !reset) {
115 if (fs.fat_bits == 32)
118 offset = find_volume_de(&fs, &de);
120 if (de.name[0] == 0x05)
122 printf("%s\n", pretty_label((char *)de.name));
125 if (fs.fat_bits == 32)
131 if (fs.fat_bits == 32)
135 write_label(&fs, label);
139 if (fs.fat_bits == 32)
144 static void handle_volid(bool change, bool reset, const char *device, const char *newserial)
148 long long conversion;
153 conversion = strtoll(newserial, &tmp, 16);
155 if (!*newserial || isspace(*newserial) || *tmp || conversion < 0) {
156 fprintf(stderr, "fatlabel: volume ID must be a hexadecimal number\n");
159 if (conversion > UINT32_MAX) {
160 fprintf(stderr, "fatlabel: given volume ID does not fit in 32 bit\n");
164 fprintf(stderr, "fatlabel: parsing volume ID failed (%s)\n", strerror(errno));
172 serial = generate_volume_id();
176 if (!change && !reset) {
177 printf("%08x\n", fs.serial);
181 write_serial(&fs, serial);
185 static void usage(int error, int usage_only)
187 FILE *f = error ? stderr : stdout;
188 int status = error ? 1 : 0;
190 fprintf(f, "Usage: fatlabel [OPTIONS] DEVICE [NEW]\n");
194 fprintf(f, "Change the FAT filesystem label or serial on DEVICE to NEW or display the\n");
195 fprintf(f, "existing label or serial if NEW is not given.\n");
197 fprintf(f, "Options:\n");
198 fprintf(f, " -i, --volume-id Work on serial number instead of label\n");
199 fprintf(f, " -r, --reset Remove label or generate new serial number\n");
200 fprintf(f, " -c N, --codepage=N use DOS codepage N to encode/decode label (default: %d)\n", DEFAULT_DOS_CODEPAGE);
201 fprintf(f, " -V, --version Show version number and terminate\n");
202 fprintf(f, " -h, --help Print this message and terminate\n");
207 int main(int argc, char *argv[])
209 const struct option long_options[] = {
210 {"volume-id", no_argument, NULL, 'i'},
211 {"reset", no_argument, NULL, 'r'},
212 {"codepage", required_argument, NULL, 'c'},
213 {"version", no_argument, NULL, 'V'},
214 {"help", no_argument, NULL, 'h'},
219 bool volid_mode = false;
228 while ((c = getopt_long(argc, argv, "irc:Vh", long_options, NULL)) != -1) {
240 codepage = strtol(optarg, &tmp, 10);
241 if (!*optarg || isspace(*optarg) || *tmp || errno || codepage < 0 || codepage > INT_MAX) {
242 fprintf(stderr, "Invalid codepage : %s\n", optarg);
245 if (!set_dos_codepage(codepage))
250 printf("fatlabel " VERSION " (" VERSION_DATE ")\n");
264 "Internal error: getopt_long() returned unexpected value %d\n", c);
269 if (!set_dos_codepage(-1)) /* set default codepage if none was given in command line */
272 if (optind == argc - 2) {
274 } else if (optind == argc - 1) {
283 if (change && reset) {
284 fprintf(stderr, "fatlabel: giving new value with --reset not allowed\n");
288 device = argv[optind++];
293 handle_label(change, reset, device, new);
295 handle_volid(change, reset, device, new);