"Fossies" - the Fresh Open Source Software Archive 
Member "dosfstools-4.2/src/fatlabel.c" (31 Jan 2021, 7174 Bytes) of package /linux/misc/dosfstools-4.2.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "fatlabel.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
4.1_vs_4.2.
1 /* fatlabel.c - User interface
2
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>
9
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.
14
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.
19
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/>.
22
23 The complete text of the GNU General Public License
24 can be found in /usr/share/common-licenses/GPL-3 file.
25 */
26
27 #include "version.h"
28
29 #include <stdbool.h>
30 #include <errno.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <limits.h>
36 #include <unistd.h>
37 #include <getopt.h>
38 #include <ctype.h>
39
40 #include "common.h"
41 #include "fsck.fat.h"
42 #include "io.h"
43 #include "boot.h"
44 #include "fat.h"
45 #include "file.h"
46 #include "check.h"
47 #include "charconv.h"
48
49 int rw = 0, list = 0, test = 0, verbose = 0, no_spaces_in_sfns = 0;
50 long fat_table = 0;
51 unsigned n_files = 0;
52 void *mem_queue = NULL;
53
54
55 static void handle_label(bool change, bool reset, const char *device, char *newlabel)
56 {
57 DOS_FS fs = { 0 };
58 off_t offset;
59 DIR_ENT de;
60
61 char label[12] = { 0 };
62 size_t len;
63 int ret;
64 int i;
65
66 if (change) {
67 len = mbstowcs(NULL, newlabel, 0);
68 if (len != (size_t)-1 && len > 11) {
69 fprintf(stderr,
70 "fatlabel: labels can be no longer than 11 characters\n");
71 exit(1);
72 }
73
74 if (!local_string_to_dos_string(label, newlabel, 12)) {
75 fprintf(stderr,
76 "fatlabel: error when processing label\n");
77 exit(1);
78 }
79
80 for (i = strlen(label); i < 11; ++i)
81 label[i] = ' ';
82 label[11] = 0;
83
84 ret = validate_volume_label(label);
85 if (ret & 0x1) {
86 fprintf(stderr,
87 "fatlabel: warning - lowercase labels might not work properly on some systems\n");
88 }
89 if (ret & 0x2) {
90 fprintf(stderr,
91 "fatlabel: labels with characters below 0x20 are not allowed\n");
92 exit(1);
93 }
94 if (ret & 0x4) {
95 fprintf(stderr,
96 "fatlabel: labels with characters *?.,;:/\\|+=<>[]\" are not allowed\n");
97 exit(1);
98 }
99 if (ret & 0x08) {
100 fprintf(stderr,
101 "fatlabel: labels can't be empty or white space only\n");
102 exit(1);
103 }
104 if (ret & 0x10) {
105 fprintf(stderr,
106 "fatlabel: labels can't start with a space character\n");
107 exit(1);
108 }
109 }
110
111 fs_open(device, rw);
112 read_boot(&fs);
113
114 if (!change && !reset) {
115 if (fs.fat_bits == 32)
116 read_fat(&fs, 0);
117
118 offset = find_volume_de(&fs, &de);
119 if (offset != 0) {
120 if (de.name[0] == 0x05)
121 de.name[0] = 0xe5;
122 printf("%s\n", pretty_label((char *)de.name));
123 }
124
125 if (fs.fat_bits == 32)
126 release_fat(&fs);
127
128 exit(0);
129 }
130
131 if (fs.fat_bits == 32)
132 read_fat(&fs, 1);
133
134 if (!reset)
135 write_label(&fs, label);
136 else
137 remove_label(&fs);
138
139 if (fs.fat_bits == 32)
140 release_fat(&fs);
141 }
142
143
144 static void handle_volid(bool change, bool reset, const char *device, const char *newserial)
145 {
146 DOS_FS fs = { 0 };
147 char *tmp;
148 long long conversion;
149 uint32_t serial = 0;
150
151 if (change) {
152 errno = 0;
153 conversion = strtoll(newserial, &tmp, 16);
154
155 if (!*newserial || isspace(*newserial) || *tmp || conversion < 0) {
156 fprintf(stderr, "fatlabel: volume ID must be a hexadecimal number\n");
157 exit(1);
158 }
159 if (conversion > UINT32_MAX) {
160 fprintf(stderr, "fatlabel: given volume ID does not fit in 32 bit\n");
161 exit(1);
162 }
163 if (errno) {
164 fprintf(stderr, "fatlabel: parsing volume ID failed (%s)\n", strerror(errno));
165 exit(1);
166 }
167
168 serial = conversion;
169 }
170
171 if (reset)
172 serial = generate_volume_id();
173
174 fs_open(device, rw);
175 read_boot(&fs);
176 if (!change && !reset) {
177 printf("%08x\n", fs.serial);
178 exit(0);
179 }
180
181 write_serial(&fs, serial);
182 }
183
184
185 static void usage(int error, int usage_only)
186 {
187 FILE *f = error ? stderr : stdout;
188 int status = error ? 1 : 0;
189
190 fprintf(f, "Usage: fatlabel [OPTIONS] DEVICE [NEW]\n");
191 if (usage_only)
192 exit(status);
193
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");
196 fprintf(f, "\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");
203 exit(status);
204 }
205
206
207 int main(int argc, char *argv[])
208 {
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'},
215 {0,}
216 };
217 bool change;
218 bool reset = false;
219 bool volid_mode = false;
220 char *device = NULL;
221 char *new = NULL;
222 char *tmp;
223 long codepage;
224 int c;
225
226 check_atari();
227
228 while ((c = getopt_long(argc, argv, "irc:Vh", long_options, NULL)) != -1) {
229 switch (c) {
230 case 'i':
231 volid_mode = 1;
232 break;
233
234 case 'r':
235 reset = true;
236 break;
237
238 case 'c':
239 errno = 0;
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);
243 usage(1, 0);
244 }
245 if (!set_dos_codepage(codepage))
246 usage(1, 0);
247 break;
248
249 case 'V':
250 printf("fatlabel " VERSION " (" VERSION_DATE ")\n");
251 exit(0);
252 break;
253
254 case 'h':
255 usage(0, 0);
256 break;
257
258 case '?':
259 usage(1, 0);
260 exit(1);
261
262 default:
263 fprintf(stderr,
264 "Internal error: getopt_long() returned unexpected value %d\n", c);
265 exit(2);
266 }
267 }
268
269 if (!set_dos_codepage(-1)) /* set default codepage if none was given in command line */
270 exit(1);
271
272 if (optind == argc - 2) {
273 change = true;
274 } else if (optind == argc - 1) {
275 change = false;
276 } else {
277 usage(1, 1);
278 }
279
280 if (change || reset)
281 rw = 1;
282
283 if (change && reset) {
284 fprintf(stderr, "fatlabel: giving new value with --reset not allowed\n");
285 exit(1);
286 }
287
288 device = argv[optind++];
289 if (change)
290 new = argv[optind];
291
292 if (!volid_mode)
293 handle_label(change, reset, device, new);
294 else
295 handle_volid(change, reset, device, new);
296
297 fs_close(rw);
298 return 0;
299 }