"Fossies" - the Fresh Open Source Software Archive 
Member "dosfstools-4.2/src/common.c" (31 Jan 2021, 8678 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 "common.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 /* common.c - Common functions
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) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
6 Copyright (C) 2018 Pali Rohár <pali.rohar@gmail.com>
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20
21 The complete text of the GNU General Public License
22 can be found in /usr/share/common-licenses/GPL-3 file.
23 */
24
25 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
26 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <errno.h>
33 #include <wctype.h>
34 #include <termios.h>
35 #include <sys/time.h>
36 #include <unistd.h>
37
38 #include "common.h"
39 #include "charconv.h"
40
41
42 int interactive;
43 int write_immed;
44 int atari_format;
45 const char *program_name;
46
47
48 typedef struct _link {
49 void *data;
50 struct _link *next;
51 } LINK;
52
53 void die(const char *msg, ...)
54 {
55 va_list args;
56
57 if (program_name)
58 fprintf(stderr, "%s: ", program_name);
59
60 va_start(args, msg);
61 vfprintf(stderr, msg, args);
62 va_end(args);
63 fprintf(stderr, "\n");
64 exit(1);
65 }
66
67 void pdie(const char *msg, ...)
68 {
69 va_list args;
70
71 if (program_name)
72 fprintf(stderr, "%s: ", program_name);
73
74 va_start(args, msg);
75 vfprintf(stderr, msg, args);
76 va_end(args);
77 fprintf(stderr, ":%s\n", strerror(errno));
78 exit(1);
79 }
80
81 void *alloc(int size)
82 {
83 void *this;
84
85 if ((this = malloc(size)))
86 return this;
87 pdie("malloc");
88 return NULL; /* for GCC */
89 }
90
91 void *qalloc(void **root, int size)
92 {
93 LINK *link;
94
95 link = alloc(sizeof(LINK));
96 link->next = *root;
97 *root = link;
98 return link->data = alloc(size);
99 }
100
101 void qfree(void **root)
102 {
103 LINK *this;
104
105 while (*root) {
106 this = (LINK *) * root;
107 *root = this->next;
108 free(this->data);
109 free(this);
110 }
111 }
112
113 int min(int a, int b)
114 {
115 return a < b ? a : b;
116 }
117
118
119 #ifndef HAVE_VASPRINTF
120 static int vasprintf(char **strp, const char *fmt, va_list va)
121 {
122 int length;
123 va_list vacopy;
124
125 va_copy(vacopy, va);
126
127 length = vsnprintf(NULL, 0, fmt, vacopy);
128 if (length < 0)
129 return length;
130
131 *strp = malloc(length + 1);
132 if (!*strp) {
133 errno = ENOMEM;
134 return -1;
135 }
136
137 return vsnprintf(*strp, length + 1, fmt, va);
138 }
139 #endif
140
141 int xasprintf(char **strp, const char *fmt, ...)
142 {
143 va_list va;
144 int retval;
145
146 va_start(va, fmt);
147 retval = vasprintf(strp, fmt, va);
148 va_end(va);
149
150 if (retval < 0)
151 pdie("asprintf");
152
153 return retval;
154 }
155
156
157 int get_choice(int noninteractive_result, const char *noninteractive_msg,
158 int choices, ...)
159 {
160 int choice_values[9];
161 const char *choice_strings[9];
162 int choice;
163 int quit_choice;
164 int print_choices, print_full_choices;
165 va_list va;
166 int i;
167 static int inhibit_quit_choice;
168
169 if (!interactive) {
170 printf("%s\n", noninteractive_msg);
171 return noninteractive_result;
172 }
173
174 if (choices < 2 || choices > 9)
175 die("internal error: invalid number %u of choices in get_choice()",
176 choices);
177
178 va_start(va, choices);
179 for (i = 0; i < choices; i++) {
180 choice_values[i] = va_arg(va, int);
181 choice_strings[i] = va_arg(va, const char *);
182 }
183 va_end(va);
184
185 print_choices = 1;
186 print_full_choices = 0;
187 while (1) {
188 if (print_choices) {
189 print_choices = 0;
190 for (i = 0; i < choices; i++)
191 printf("%d) %s\n", i + 1, choice_strings[i]);
192
193 if (print_full_choices) {
194 printf("?) List all choices\n");
195 printf("q) Quit fsck\n");
196 }
197 }
198
199 printf("[%.*s?%s]? ", choices, "123456789", inhibit_quit_choice ? "" : "q");
200 fflush(stdout);
201
202 do {
203 choice = getchar();
204 } while (choice == '\n'); /* filter out enter presses */
205
206 if (choice == EOF)
207 exit(1);
208
209 printf("%c\n", choice);
210
211 if (choice > '0' && choice <= '0' + choices)
212 break;
213
214 if (choice == '?') {
215 print_choices = 1;
216 print_full_choices = 1;
217 }
218
219 if (!inhibit_quit_choice && (choice == 'q' || choice == 'Q')) {
220 if (!write_immed)
221 printf("No changes have been written to the filesystem yet. If you choose\n"
222 "to quit, it will be left in the same state it was in before you\n"
223 "started this program.\n");
224 else
225 printf("fsck is running in immediate write mode. All changes so far have\n"
226 "already been written and can not be undone now. If you choose to\n"
227 "quit now, these changes will stay in place.\n");
228
229 inhibit_quit_choice = 1;
230 quit_choice = get_choice(1, "This is never non-interactive.",
231 2,
232 1, "Quit now",
233 2, "Continue");
234 inhibit_quit_choice = 0;
235
236 if (quit_choice == 1)
237 exit(0);
238 }
239 }
240
241 return choice_values[choice - '1'];
242 }
243
244
245 char *get_line(const char *prompt, char *dest, size_t length)
246 {
247 struct termios tio, tio_orig;
248 int tio_fail;
249 char *retval;
250
251 tio_fail = tcgetattr(0, &tio_orig);
252 if (!tio_fail) {
253 tio = tio_orig;
254 tio.c_lflag |= ICANON | ECHO;
255 tcsetattr(0, TCSAFLUSH, &tio);
256 }
257
258 printf("%s: ", prompt);
259 fflush(stdout);
260
261 retval = fgets(dest, length, stdin);
262
263 if (!tio_fail)
264 tcsetattr(0, TCSAFLUSH, &tio_orig);
265 return retval;
266 }
267
268
269 /*
270 * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
271 * of MS-DOS filesystem by default.
272 */
273 void check_atari(void)
274 {
275 #if defined(__mc68000__) && defined(__linux__) && defined(CONF_CHECK_ATARI)
276 FILE *f;
277 char line[128], *p;
278
279 if (!(f = fopen("/proc/hardware", "r"))) {
280 perror("/proc/hardware");
281 return;
282 }
283
284 while (fgets(line, sizeof(line), f)) {
285 if (strncmp(line, "Model:", 6) == 0) {
286 p = line + 6;
287 p += strspn(p, " \t");
288 if (strncmp(p, "Atari ", 6) == 0)
289 atari_format = 1;
290 break;
291 }
292 }
293 fclose(f);
294 #endif
295 }
296
297
298 uint32_t generate_volume_id(void)
299 {
300 struct timeval now;
301
302 if (gettimeofday(&now, NULL) != 0 || now.tv_sec == (time_t)-1 || now.tv_sec < 0) {
303 srand(getpid());
304 /* rand() returns int from [0,RAND_MAX], therefore only 31 bits */
305 return (((uint32_t)(rand() & 0xFFFF)) << 16) | ((uint32_t)(rand() & 0xFFFF));
306 }
307
308 /* volume ID = current time, fudged for more uniqueness */
309 return ((uint32_t)now.tv_sec << 20) | (uint32_t)now.tv_usec;
310 }
311
312 /*
313 * Validate volume label
314 *
315 * @param[in] doslabel Label stored according to current DOS codepage
316 *
317 * @return bitmask of errors
318 * 0x01 - lowercase character
319 * 0x02 - character below 0x20
320 * 0x04 - character in disallowed set
321 * 0x08 - empty or space-only label
322 * 0x10 - space at beginning
323 */
324 int validate_volume_label(char *doslabel)
325 {
326 int i;
327 int ret = 0;
328 wchar_t wlabel[12];
329
330 if (dos_string_to_wchar_string(wlabel, doslabel, sizeof(wlabel))) {
331 for (i = 0; wlabel[i]; i++) {
332 /* FAT specification: Lower case characters are not allowed in DIR_Name
333 (what these characters are is country specific)
334 Original label is stored in DOS OEM code page, so islower() function
335 cannot be used. Therefore convert original label to locale independent
336 wchar_t* and then use iswlower() function for it.
337 */
338 if (iswlower(wlabel[i])) {
339 ret |= 0x01;
340 break;
341 }
342 }
343 }
344
345 /* According to FAT specification those bytes (after conversion to DOS OEM
346 code page) are not allowed.
347 */
348 for (i = 0; i < 11; i++) {
349 if (doslabel[i] < 0x20)
350 ret |= 0x02;
351 if (doslabel[i] == 0x22 ||
352 (doslabel[i] >= 0x2A && doslabel[i] <= 0x2C) ||
353 doslabel[i] == 0x2E ||
354 doslabel[i] == 0x2F ||
355 (doslabel[i] >= 0x3A && doslabel[i] <= 0x3F) ||
356 (doslabel[i] >= 0x5B && doslabel[i] <= 0x5D) ||
357 doslabel[i] == 0x7C)
358 ret |= 0x04;
359 }
360
361 if (memcmp(doslabel, " ", 11) == 0)
362 ret |= 0x08;
363
364 if (doslabel[0] == ' ')
365 ret |= 0x10;
366
367 return ret;
368 }