blob: 173eae00878de7819848fb780a18884da42925b2 [file] [log] [blame]
Alistair Delvabeaee832021-02-24 11:27:23 -08001/* Copyright 1996-2005,2007-2009,2011 Alain Knaff.
2 * This file is part of mtools.
3 *
4 * Mtools is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * Mtools is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18#include "sysincludes.h"
19#include "mtools.h"
20#include "codepage.h"
21#include "mtoolsPaths.h"
22
23/* global variables */
24/* they are not really harmful here, because there is only one configuration
25 * file per invocations */
26
27#define MAX_LINE_LEN 256
28
29/* scanner */
30static char buffer[MAX_LINE_LEN+1]; /* buffer for the whole line */
31static char *pos; /* position in line */
32static char *token; /* last scanned token */
33static size_t token_length; /* length of the token */
34static FILE *fp; /* file pointer for configuration file */
35static int linenumber; /* current line number. Only used for printing
36 * error messages */
37static int lastTokenLinenumber; /* line numnber for last token */
38static const char *filename=NULL; /* current file name. Used for printing
39 * error messages, and for storing in
40 * the device definition (mtoolstest) */
41static int file_nr=0;
42
43
44static unsigned int flag_mask; /* mask of currently set flags */
45
46/* devices */
47static unsigned int cur_devs; /* current number of defined devices */
48static int cur_dev; /* device being filled in. If negative, none */
49static int trusted=0; /* is the currently parsed device entry trusted? */
Yi Kong39bbd962022-01-09 19:41:38 +080050static unsigned int nr_dev; /* number of devices that the current table can
Alistair Delvabeaee832021-02-24 11:27:23 -080051 hold */
52struct device *devices; /* the device table */
53static int token_nr; /* number of tokens in line */
54
55static char default_drive='\0'; /* default drive */
56
57/* "environment" variables */
58unsigned int mtools_skip_check=0;
59unsigned int mtools_fat_compatibility=0;
60unsigned int mtools_ignore_short_case=0;
61uint8_t mtools_rate_0=0;
62uint8_t mtools_rate_any=0;
63unsigned int mtools_no_vfat=0;
64unsigned int mtools_numeric_tail=1;
65unsigned int mtools_dotted_dir=0;
66unsigned int mtools_twenty_four_hour_clock=1;
67unsigned int mtools_lock_timeout=30;
68unsigned int mtools_default_codepage=850;
69const char *mtools_date_string="yyyy-mm-dd";
70char *country_string=0;
71
72typedef struct switches_l {
73 const char *name;
74 caddr_t address;
75 enum {
76 T_INT,
77 T_STRING,
78 T_UINT,
79 T_UINT8,
Yi Kong39bbd962022-01-09 19:41:38 +080080 T_UINT16,
81 T_UQSTRING
Alistair Delvabeaee832021-02-24 11:27:23 -080082 } type;
83} switches_t;
84
85static switches_t global_switches[] = {
86 { "MTOOLS_LOWER_CASE", (caddr_t) & mtools_ignore_short_case, T_UINT },
87 { "MTOOLS_FAT_COMPATIBILITY", (caddr_t) & mtools_fat_compatibility, T_UINT },
88 { "MTOOLS_SKIP_CHECK", (caddr_t) & mtools_skip_check, T_UINT },
89 { "MTOOLS_NO_VFAT", (caddr_t) & mtools_no_vfat, T_UINT },
90 { "MTOOLS_RATE_0", (caddr_t) &mtools_rate_0, T_UINT8 },
91 { "MTOOLS_RATE_ANY", (caddr_t) &mtools_rate_any, T_UINT8 },
92 { "MTOOLS_NAME_NUMERIC_TAIL", (caddr_t) &mtools_numeric_tail, T_UINT },
93 { "MTOOLS_DOTTED_DIR", (caddr_t) &mtools_dotted_dir, T_UINT },
94 { "MTOOLS_TWENTY_FOUR_HOUR_CLOCK",
95 (caddr_t) &mtools_twenty_four_hour_clock, T_UINT },
96 { "MTOOLS_DATE_STRING",
97 (caddr_t) &mtools_date_string, T_STRING },
98 { "MTOOLS_LOCK_TIMEOUT", (caddr_t) &mtools_lock_timeout, T_UINT },
99 { "DEFAULT_CODEPAGE", (caddr_t) &mtools_default_codepage, T_UINT }
100};
101
102typedef struct {
103 const char *name;
104 unsigned int flag;
105} flags_t;
106
107static flags_t openflags[] = {
108#ifdef O_SYNC
109 { "sync", O_SYNC },
110#endif
111#ifdef O_NDELAY
112 { "nodelay", O_NDELAY },
113#endif
114#ifdef O_EXCL
115 { "exclusive", O_EXCL },
116#endif
117 { "none", 0 } /* hack for those compilers that choke on commas
118 * after the last element of an array */
119};
120
121static flags_t misc_flags[] = {
122#ifdef USE_XDF
123 { "use_xdf", USE_XDF_FLAG },
124#endif
125 { "scsi", SCSI_FLAG },
126 { "nolock", NOLOCK_FLAG },
127 { "mformat_only", MFORMAT_ONLY_FLAG },
128 { "filter", FILTER_FLAG },
129 { "privileged", PRIV_FLAG },
130 { "vold", VOLD_FLAG },
131 { "remote", FLOPPYD_FLAG },
132 { "swap", SWAP_FLAG },
133};
134
135static struct {
136 const char *name;
137 signed char fat_bits;
138 unsigned int tracks;
139 unsigned short heads;
140 unsigned short sectors;
141} default_formats[] = {
142 { "hd514", 12, 80, 2, 15 },
143 { "high-density-5-1/4", 12, 80, 2, 15 },
144 { "1.2m", 12, 80, 2, 15 },
145
146 { "hd312", 12, 80, 2, 18 },
147 { "high-density-3-1/2", 12, 80, 2, 18 },
148 { "1.44m", 12, 80, 2, 18 },
149
150 { "dd312", 12, 80, 2, 9 },
151 { "double-density-3-1/2", 12, 80, 2, 9 },
152 { "720k", 12, 80, 2, 9 },
153
154 { "dd514", 12, 40, 2, 9 },
155 { "double-density-5-1/4", 12, 40, 2, 9 },
156 { "360k", 12, 40, 2, 9 },
157
158 { "320k", 12, 40, 2, 8 },
159 { "180k", 12, 40, 1, 9 },
160 { "160k", 12, 40, 1, 8 }
161};
162
163#define OFFS(x) ((caddr_t)&((struct device *)0)->x)
164
165static switches_t dswitches[]= {
166 { "FILE", OFFS(name), T_STRING },
167 { "OFFSET", OFFS(offset), T_UINT },
168 { "PARTITION", OFFS(partition), T_UINT },
169 { "FAT", OFFS(fat_bits), T_INT },
170 { "FAT_BITS", OFFS(fat_bits), T_UINT },
171 { "MODE", OFFS(mode), T_UINT },
172 { "TRACKS", OFFS(tracks), T_UINT },
173 { "CYLINDERS", OFFS(tracks), T_UINT },
174 { "HEADS", OFFS(heads), T_UINT16 },
175 { "SECTORS", OFFS(sectors), T_UINT16 },
176 { "HIDDEN", OFFS(hidden), T_UINT },
177 { "PRECMD", OFFS(precmd), T_STRING },
178 { "BLOCKSIZE", OFFS(blocksize), T_UINT },
Yi Kong39bbd962022-01-09 19:41:38 +0800179 { "CODEPAGE", OFFS(codepage), T_UINT },
180 { "DATA_MAP", OFFS(data_map), T_UQSTRING }
Alistair Delvabeaee832021-02-24 11:27:23 -0800181};
182
183#if (defined HAVE_TOUPPER_L || defined HAVE_STRNCASECMP_L)
184static locale_t C=NULL;
185
186static void init_canon(void) {
187 if(C == NULL)
188 C = newlocale(LC_CTYPE_MASK, "C", NULL);
189}
190#endif
191
192#ifdef HAVE_TOUPPER_L
193static int canon_drv(int drive) {
194 int ret;
195 init_canon();
196 ret = toupper_l(drive, C);
197 return ret;
198}
199#else
200static int canon_drv(int drive) {
201 return toupper(drive);
202}
203#endif
204
205#ifdef HAVE_STRNCASECMP_L
Yi Kong39bbd962022-01-09 19:41:38 +0800206static int cmp_tok(const char *a, const char *b, size_t len) {
Alistair Delvabeaee832021-02-24 11:27:23 -0800207 init_canon();
208 return strncasecmp_l(a, b, len, C);
209}
210#else
Yi Kong39bbd962022-01-09 19:41:38 +0800211static int cmp_tok(const char *a, const char *b, size_t len) {
Alistair Delvabeaee832021-02-24 11:27:23 -0800212 return strncasecmp(a, b, len);
213}
214#endif
215
216
217static char ch_canon_drv(char drive) {
218 return (char) canon_drv( (unsigned char) drive);
219}
220
221static void maintain_default_drive(char drive)
222{
223 if(default_drive == ':')
224 return; /* we have an image */
225 if(default_drive == '\0' ||
226 default_drive > drive)
227 default_drive = drive;
228}
229
230char get_default_drive(void)
231{
232 if(default_drive != '\0')
233 return default_drive;
234 else
235 return 'A';
236}
237
238static void syntax(const char *msg, int thisLine) NORETURN;
239static void syntax(const char *msg, int thisLine)
240{
241 char drive='\0';
242 if(thisLine)
243 lastTokenLinenumber = linenumber;
244 if(cur_dev >= 0)
245 drive = devices[cur_dev].drive;
246 fprintf(stderr,"Syntax error at line %d ", lastTokenLinenumber);
247 if(drive) fprintf(stderr, "for drive %c: ", drive);
248 if(token) fprintf(stderr, "column %ld ", (long)(token - buffer));
249 fprintf(stderr, "in file %s: %s", filename, msg);
250 if(errno != 0)
251 fprintf(stderr, " (%s)", strerror(errno));
252 fprintf(stderr, "\n");
253 exit(1);
254}
255
Yi Kong39bbd962022-01-09 19:41:38 +0800256#pragma GCC diagnostic push
257#pragma GCC diagnostic ignored "-Wcast-align"
Alistair Delvabeaee832021-02-24 11:27:23 -0800258static void get_env_conf(void)
259{
260 char *s;
261 unsigned int i;
262
263 for(i=0; i< sizeof(global_switches) / sizeof(*global_switches); i++) {
264 s = getenv(global_switches[i].name);
265 if(s) {
266 errno = 0;
267 switch(global_switches[i].type) {
268 case T_INT:
269 * ((int *)global_switches[i].address) = strtoi(s,0,0);
270 break;
271 case T_UINT:
272 * ((unsigned int *)global_switches[i].address) = strtoui(s,0,0);
273 break;
274 case T_UINT8:
275 * ((uint8_t *)global_switches[i].address) = strtou8(s,0,0);
276 break;
277 case T_UINT16:
278 * ((uint16_t *)global_switches[i].address) = strtou16(s,0,0);
279 break;
280 case T_STRING:
Yi Kong39bbd962022-01-09 19:41:38 +0800281 case T_UQSTRING:
Alistair Delvabeaee832021-02-24 11:27:23 -0800282 * ((char **)global_switches[i].address) = s;
283 break;
284 }
285 if(errno != 0) {
286 fprintf(stderr, "Bad number %s for %s (%s)\n", s,
287 global_switches[i].name,
288 strerror(errno));
289 exit(1);
290 }
291 }
292 }
293}
Yi Kong39bbd962022-01-09 19:41:38 +0800294#pragma GCC diagnostic pop
Alistair Delvabeaee832021-02-24 11:27:23 -0800295
296static int mtools_getline(void)
297{
298 if(!fp || !fgets(buffer, MAX_LINE_LEN+1, fp))
299 return -1;
300 linenumber++;
301 pos = buffer;
302 token_nr = 0;
303 buffer[MAX_LINE_LEN] = '\0';
304 if(strlen(buffer) == MAX_LINE_LEN)
305 syntax("line too long", 1);
306 return 0;
307}
Yi Kong39bbd962022-01-09 19:41:38 +0800308
Alistair Delvabeaee832021-02-24 11:27:23 -0800309static void skip_junk(int expect)
310{
311 lastTokenLinenumber = linenumber;
312 while(!pos || !*pos || strchr(" #\n\t", *pos)) {
313 if(!pos || !*pos || *pos == '#') {
314 if(mtools_getline()) {
315 pos = 0;
316 if(expect)
317 syntax("end of file unexpected", 1);
318 return;
319 }
320 } else
321 pos++;
322 }
323 token_nr++;
324}
325
326/* get the next token */
327static char *get_next_token(void)
328{
329 skip_junk(0);
330 if(!pos) {
331 token_length = 0;
332 token = 0;
333 return 0;
334 }
335 token = pos;
336 token_length = strcspn(token, " \t\n#:=");
337 pos += token_length;
338 return token;
339}
340
341static int match_token(const char *template)
342{
343 return (strlen(template) == token_length &&
344 !cmp_tok(template, token, token_length));
345}
346
347static void expect_char(char c)
348{
349 char buf[11];
350
351 skip_junk(1);
352 if(*pos != c) {
353 sprintf(buf, "expected %c", c);
354 syntax(buf, 1);
355 }
356 pos++;
357}
358
359static char *get_string(void)
360{
361 char *end, *str;
362
363 skip_junk(1);
364 if(*pos != '"')
365 syntax(" \" expected", 0);
366 str = pos+1;
367 end = strchr(str, '\"');
368 if(!end)
369 syntax("unterminated string constant", 1);
Yi Kong39bbd962022-01-09 19:41:38 +0800370 str = strndup(str, ptrdiff(end, str));
Alistair Delvabeaee832021-02-24 11:27:23 -0800371 pos = end+1;
372 return str;
373}
374
Yi Kong39bbd962022-01-09 19:41:38 +0800375static char *get_unquoted_string(void)
376{
377 if(*pos == '"')
378 return get_string();
379 else {
380 char *str=get_next_token();
381 return strndup(str, token_length);
382 }
383}
384
Alistair Delvabeaee832021-02-24 11:27:23 -0800385static unsigned long get_unumber(unsigned long max)
386{
387 char *last;
388 unsigned long n;
389
390 skip_junk(1);
391 last = pos;
392 n=strtoul(pos, &pos, 0);
393 if(errno)
394 syntax("bad number", 0);
395 if(last == pos)
396 syntax("numeral expected", 0);
397 if(n > max)
398 syntax("number too big", 0);
399 pos++;
400 token_nr++;
401 return n;
402}
403
404static int get_number(void)
405{
406 char *last;
407 int n;
408
409 skip_junk(1);
410 last = pos;
411 n=(int) strtol(pos, &pos, 0);
412 if(errno)
413 syntax("bad number", 0);
414 if(last == pos)
415 syntax("numeral expected", 0);
416 pos++;
417 token_nr++;
418 return n;
419}
420
421/* purge all entries pertaining to a given drive from the table */
422static void purge(char drive, int fn)
423{
424 unsigned int i, j;
425
426 drive = ch_canon_drv(drive);
427 for(j=0, i=0; i < cur_devs; i++) {
428 if(devices[i].drive != drive ||
429 devices[i].file_nr == fn)
430 devices[j++] = devices[i];
431 }
432 cur_devs = j;
433}
434
435static void grow(void)
436{
437 if(cur_devs >= nr_dev - 2) {
438 nr_dev = (cur_devs + 2) << 1;
439 if(!(devices=Grow(devices, nr_dev, struct device))){
440 printOom();
441 exit(1);
442 }
443 }
444}
Yi Kong39bbd962022-01-09 19:41:38 +0800445
Alistair Delvabeaee832021-02-24 11:27:23 -0800446
447static void init_drive(void)
448{
449 memset((char *)&devices[cur_dev], 0, sizeof(struct device));
450 devices[cur_dev].ssize = 2;
451}
452
453/* prepends a device to the table */
454static void prepend(void)
455{
456 unsigned int i;
457
458 grow();
459 for(i=cur_devs; i>0; i--)
460 devices[i] = devices[i-1];
461 cur_dev = 0;
462 cur_devs++;
463 init_drive();
464}
465
466
467/* appends a device to the table */
468static void append(void)
469{
470 grow();
Yi Kong39bbd962022-01-09 19:41:38 +0800471 cur_dev = (int) cur_devs;
Alistair Delvabeaee832021-02-24 11:27:23 -0800472 cur_devs++;
473 init_drive();
474}
475
476
477static void finish_drive_clause(void)
478{
479 if(cur_dev == -1) {
480 trusted = 0;
481 return;
482 }
483 if(!devices[cur_dev].name)
484 syntax("missing filename", 0);
485 if(devices[cur_dev].tracks ||
486 devices[cur_dev].heads ||
487 devices[cur_dev].sectors) {
488 if(!devices[cur_dev].tracks ||
489 !devices[cur_dev].heads ||
490 !devices[cur_dev].sectors)
491 syntax("incomplete geometry: either indicate all of track/heads/sectors or none of them", 0);
492 if(!(devices[cur_dev].misc_flags &
493 (MFORMAT_ONLY_FLAG | FILTER_FLAG)))
494 syntax("if you supply a geometry, you also must supply one of the `mformat_only' or `filter' flags", 0);
495 }
496 devices[cur_dev].file_nr = file_nr;
497 devices[cur_dev].cfg_filename = filename;
Alistair Delvabeaee832021-02-24 11:27:23 -0800498 if(!trusted && (devices[cur_dev].misc_flags & PRIV_FLAG)) {
499 fprintf(stderr,
500 "Warning: privileged flag ignored for drive %c: defined in file %s\n",
501 canon_drv(devices[cur_dev].drive), filename);
502 devices[cur_dev].misc_flags &= ~PRIV_FLAG;
503 }
504 trusted = 0;
505 cur_dev = -1;
506}
507
Yi Kong39bbd962022-01-09 19:41:38 +0800508#pragma GCC diagnostic push
509#pragma GCC diagnostic ignored "-Wcast-align"
Alistair Delvabeaee832021-02-24 11:27:23 -0800510static int set_var(struct switches_l *switches, int nr,
511 caddr_t base_address)
512{
513 int i;
514 for(i=0; i < nr; i++) {
515 if(match_token(switches[i].name)) {
516 expect_char('=');
Yi Kong39bbd962022-01-09 19:41:38 +0800517 /* All pointers cast back to pointers with alignment
518 * constraints were such pointers with alignment
519 * constraints initially, thus they do indeed fit the
520 * constraint */
521
Alistair Delvabeaee832021-02-24 11:27:23 -0800522 if(switches[i].type == T_UINT)
523 * ((unsigned int *)((long)switches[i].address+base_address)) =
524 (unsigned int) get_unumber(UINT_MAX);
525 else if(switches[i].type == T_UINT8)
526 * ((uint8_t *)((long)switches[i].address+base_address)) =
527 (uint8_t) get_unumber(UINT8_MAX);
528 else if(switches[i].type == T_UINT16)
529 * ((uint16_t *)((long)switches[i].address+base_address)) =
530 (uint16_t) get_unumber(UINT16_MAX);
531 else if(switches[i].type == T_INT)
532 * ((int *)((long)switches[i].address+base_address)) =
533 get_number();
534 else if (switches[i].type == T_STRING)
535 * ((char**)((long)switches[i].address+base_address))=
Yi Kong39bbd962022-01-09 19:41:38 +0800536 get_string();
537 else if (switches[i].type == T_UQSTRING)
538 * ((char**)((long)switches[i].address+base_address))=
539 get_unquoted_string();
Alistair Delvabeaee832021-02-24 11:27:23 -0800540 return 0;
541 }
542 }
543 return 1;
544}
Yi Kong39bbd962022-01-09 19:41:38 +0800545#pragma GCC diagnostic pop
Alistair Delvabeaee832021-02-24 11:27:23 -0800546
547static int set_openflags(struct device *dev)
548{
549 unsigned int i;
550
551 for(i=0; i < sizeof(openflags) / sizeof(*openflags); i++) {
552 if(match_token(openflags[i].name)) {
553 dev->mode |= openflags[i].flag;
554 return 0;
555 }
556 }
557 return 1;
558}
559
560static int set_misc_flags(struct device *dev)
561{
562 unsigned int i;
563 for(i=0; i < sizeof(misc_flags) / sizeof(*misc_flags); i++) {
564 if(match_token(misc_flags[i].name)) {
565 flag_mask |= misc_flags[i].flag;
566 skip_junk(0);
567 if(pos && *pos == '=') {
568 pos++;
569 switch(get_number()) {
570 case 0:
571 return 0;
572 case 1:
573 break;
574 default:
575 syntax("expected 0 or 1", 0);
576 }
577 }
578 dev->misc_flags |= misc_flags[i].flag;
579 return 0;
580 }
581 }
582 return 1;
583}
584
585static int set_def_format(struct device *dev)
586{
587 unsigned int i;
588
589 for(i=0; i < sizeof(default_formats)/sizeof(*default_formats); i++) {
590 if(match_token(default_formats[i].name)) {
591 if(!dev->ssize)
592 dev->ssize = 2;
593 if(!dev->tracks)
594 dev->tracks = default_formats[i].tracks;
595 if(!dev->heads)
596 dev->heads = default_formats[i].heads;
597 if(!dev->sectors)
598 dev->sectors = default_formats[i].sectors;
599 if(!dev->fat_bits)
600 dev->fat_bits = default_formats[i].fat_bits;
601 return 0;
602 }
603 }
604 return 1;
605}
606
607static void parse_all(int privilege);
608
609void set_cmd_line_image(char *img) {
610 char *ofsp;
611
612 prepend();
613 devices[cur_dev].drive = ':';
614 default_drive = ':';
615
616 ofsp = strstr(img, "@@");
617 if (ofsp == NULL) {
618 /* no separator => no offset */
619 devices[cur_dev].name = strdup(img);
620 devices[cur_dev].offset = 0;
621 } else {
Yi Kong39bbd962022-01-09 19:41:38 +0800622 devices[cur_dev].name = strndup(img, ptrdiff(ofsp, img));
Alistair Delvabeaee832021-02-24 11:27:23 -0800623 devices[cur_dev].offset = str_to_offset(ofsp+2);
624 }
625
626 devices[cur_dev].fat_bits = 0;
627 devices[cur_dev].tracks = 0;
628 devices[cur_dev].heads = 0;
629 devices[cur_dev].sectors = 0;
630 if (strchr(devices[cur_dev].name, '|')) {
631 char *pipechar = strchr(devices[cur_dev].name, '|');
632 *pipechar = 0;
633 strncpy(buffer, pipechar+1, MAX_LINE_LEN);
634 buffer[MAX_LINE_LEN] = '\0';
635 fp = NULL;
636 filename = "{command line}";
637 linenumber = 0;
638 lastTokenLinenumber = 0;
639 pos = buffer;
640 token = 0;
641 parse_all(0);
642 }
643}
644
645void check_number_parse_errno(char c, const char *oarg, char *endptr) {
646 if(endptr && *endptr) {
647 fprintf(stderr, "Bad number %s\n", oarg);
648 exit(1);
649 }
650 if(errno) {
651 fprintf(stderr, "Bad number %s for -%c (%s)\n", oarg,
652 c, strerror(errno));
653 exit(1);
654 }
655}
656
657static uint16_t tou16(int in, const char *comment) {
Yi Kong39bbd962022-01-09 19:41:38 +0800658 if(in > (int) UINT16_MAX) {
Alistair Delvabeaee832021-02-24 11:27:23 -0800659 fprintf(stderr, "Number of %s %d too big\n", comment, in);
660 exit(1);
661 }
662 if(in < 0) {
663 fprintf(stderr, "Number of %s %d negative\n", comment, in);
664 exit(1);
665 }
666 return (uint16_t) in;
Alistair Delvabeaee832021-02-24 11:27:23 -0800667}
668
669static void parse_old_device_line(char drive)
670{
671 char name[MAXPATHLEN];
672 int items;
673 long offset;
674
Yi Kong39bbd962022-01-09 19:41:38 +0800675 int heads, sectors, tracks;
676
Alistair Delvabeaee832021-02-24 11:27:23 -0800677 /* finish any old drive */
678 finish_drive_clause();
679
680 /* purge out data of old configuration files */
681 purge(drive, file_nr);
Yi Kong39bbd962022-01-09 19:41:38 +0800682
Alistair Delvabeaee832021-02-24 11:27:23 -0800683 /* reserve slot */
684 append();
685 items = sscanf(token,"%c %s %i %i %i %i %li",
686 &devices[cur_dev].drive,name,&devices[cur_dev].fat_bits,
Yi Kong39bbd962022-01-09 19:41:38 +0800687 &tracks,&heads,&sectors, &offset);
Alistair Delvabeaee832021-02-24 11:27:23 -0800688 devices[cur_dev].heads = tou16(heads, "heads");
689 devices[cur_dev].sectors = tou16(sectors, "sectors");
Yi Kong39bbd962022-01-09 19:41:38 +0800690 devices[cur_dev].tracks = (unsigned int) tracks;
Alistair Delvabeaee832021-02-24 11:27:23 -0800691 devices[cur_dev].offset = (off_t) offset;
692 switch(items){
693 case 2:
694 devices[cur_dev].fat_bits = 0;
695 /* fall thru */
696 case 3:
697 devices[cur_dev].sectors = 0;
698 devices[cur_dev].heads = 0;
699 devices[cur_dev].tracks = 0;
700 /* fall thru */
701 case 6:
702 devices[cur_dev].offset = 0;
703 /* fall thru */
704 default:
705 break;
706 case 0:
707 case 1:
708 case 4:
709 case 5:
710 syntax("bad number of parameters", 1);
711 }
712 if(!devices[cur_dev].tracks){
713 devices[cur_dev].sectors = 0;
714 devices[cur_dev].heads = 0;
715 }
Yi Kong39bbd962022-01-09 19:41:38 +0800716
Alistair Delvabeaee832021-02-24 11:27:23 -0800717 devices[cur_dev].drive = ch_canon_drv(devices[cur_dev].drive);
718 maintain_default_drive(devices[cur_dev].drive);
719 if (!(devices[cur_dev].name = strdup(name))) {
720 printOom();
721 exit(1);
722 }
723 devices[cur_dev].misc_flags |= MFORMAT_ONLY_FLAG;
724 finish_drive_clause();
725 pos=0;
726}
727
728static int parse_one(int privilege)
729{
730 int action=0;
731
732 get_next_token();
733 if(!token)
734 return 0;
735
736 if((match_token("drive") && ((action = 1)))||
737 (match_token("drive+") && ((action = 2))) ||
738 (match_token("+drive") && ((action = 3))) ||
739 (match_token("clear_drive") && ((action = 4))) ) {
740 /* finish off the previous drive */
741 finish_drive_clause();
742
743 get_next_token();
744 if(token_length != 1)
745 syntax("drive letter expected", 0);
746
747 if(action==1 || action==4)
Yi Kong39bbd962022-01-09 19:41:38 +0800748 /* replace existing drive */
Alistair Delvabeaee832021-02-24 11:27:23 -0800749 purge(token[0], file_nr);
750 if(action==4)
751 return 1;
752 if(action==3)
753 prepend();
754 else
755 append();
756 memset((char*)(devices+cur_dev), 0, sizeof(*devices));
757 trusted = privilege;
758 flag_mask = 0;
759 devices[cur_dev].drive = ch_canon_drv(token[0]);
760 maintain_default_drive(devices[cur_dev].drive);
761 expect_char(':');
762 return 1;
763 }
764 if(token_nr == 1 && token_length == 1) {
765 parse_old_device_line(token[0]);
766 return 1;
767 }
768
769 if((cur_dev < 0 ||
770 (set_var(dswitches,
771 sizeof(dswitches)/sizeof(*dswitches),
772 (caddr_t)&devices[cur_dev]) &&
773 set_openflags(&devices[cur_dev]) &&
774 set_misc_flags(&devices[cur_dev]) &&
775 set_def_format(&devices[cur_dev]))) &&
776 set_var(global_switches,
777 sizeof(global_switches)/sizeof(*global_switches), 0))
778 syntax("unrecognized keyword", 1);
779 return 1;
780}
781
782static void parse_all(int privilege) {
783 errno=0;
784 while (parse_one(privilege));
785}
786
787
788static int parse(const char *name, int privilege)
789{
790 if(fp) {
791 fprintf(stderr, "File descriptor already set!\n");
792 exit(1);
793 }
794 fp = fopen(name, "r");
795 if(!fp)
796 return 0;
797 file_nr++;
798 filename = name; /* no strdup needed: although lifetime of variable
799 exceeds this function (due to dev->cfg_filename),
800 we know that the name is always either
801 1. a constant
802 2. a statically allocate buffer
803 3. an environment variable that stays unchanged
804 */
805 linenumber = 0;
806 lastTokenLinenumber = 0;
807 pos = 0;
808 token = 0;
809 cur_dev = -1; /* no current device */
810
811 parse_all(privilege);
812 finish_drive_clause();
813 fclose(fp);
814 filename = NULL;
815 fp = NULL;
816 return 1;
817}
818
819void read_config(void)
820{
821 char *homedir;
822 char *envConfFile;
823 static char conf_file[MAXPATHLEN+sizeof(CFG_FILE1)];
824
Yi Kong39bbd962022-01-09 19:41:38 +0800825
Alistair Delvabeaee832021-02-24 11:27:23 -0800826 /* copy compiled-in devices */
827 file_nr = 0;
828 cur_devs = nr_const_devices;
829 nr_dev = nr_const_devices + 2;
830 devices = NewArray(nr_dev, struct device);
831 if(!devices) {
832 printOom();
833 exit(1);
834 }
835 if(nr_const_devices)
836 memcpy(devices, const_devices,
837 nr_const_devices*sizeof(struct device));
838
839 (void) ((parse(CONF_FILE,1) |
840 parse(LOCAL_CONF_FILE,1) |
841 parse(SYS_CONF_FILE,1)) ||
842 (parse(OLD_CONF_FILE,1) |
843 parse(OLD_LOCAL_CONF_FILE,1)));
844 /* the old-name configuration files only get executed if none of the
845 * new-name config files were used */
846
847 homedir = get_homedir();
848 if ( homedir ){
849 strncpy(conf_file, homedir, MAXPATHLEN );
850 conf_file[MAXPATHLEN]='\0';
851 strcat( conf_file, CFG_FILE1);
852 parse(conf_file,0);
853 }
854 memset((char *)&devices[cur_devs],0,sizeof(struct device));
855
856 envConfFile = getenv("MTOOLSRC");
857 if(envConfFile)
858 parse(envConfFile,0);
859
860 /* environmental variables */
861 get_env_conf();
862 if(mtools_skip_check)
863 mtools_fat_compatibility=1;
864}
865
866void mtoolstest(int argc, char **argv, int type UNUSEDP) NORETURN;
867void mtoolstest(int argc, char **argv, int type UNUSEDP)
868{
869 /* testing purposes only */
870 struct device *dev;
871 char drive='\0';
872
873 if(argc > 1 && argv[1][0] && argv[1][1] == ':') {
874 drive = ch_canon_drv(argv[1][0]);
875 }
876
877 for (dev=devices; dev->name; dev++) {
878 if(drive && drive != dev->drive)
879 continue;
880 printf("drive %c:\n", dev->drive);
881 printf("\t#fn=%d mode=%d ",
882 dev->file_nr, dev->mode);
883 if(dev->cfg_filename)
884 printf("defined in %s\n", dev->cfg_filename);
885 else
886 printf("builtin\n");
887 printf("\tfile=\"%s\" fat_bits=%d \n",
888 dev->name,dev->fat_bits);
889 printf("\ttracks=%d heads=%d sectors=%d hidden=%d\n",
890 dev->tracks, dev->heads, dev->sectors, dev->hidden);
891 printf("\toffset=0x%lx\n", (long) dev->offset);
892 printf("\tpartition=%d\n", dev->partition);
893
894 if(dev->misc_flags)
895 printf("\t");
896
897 if(DO_SWAP(dev))
898 printf("swap ");
899 if(IS_SCSI(dev))
900 printf("scsi ");
901 if(IS_PRIVILEGED(dev))
902 printf("privileged");
903 if(IS_MFORMAT_ONLY(dev))
904 printf("mformat_only ");
905 if(SHOULD_USE_VOLD(dev))
906 printf("vold ");
907#ifdef USE_XDF
908 if(SHOULD_USE_XDF(dev))
909 printf("use_xdf ");
910#endif
911 if(dev->misc_flags)
912 printf("\n");
913
914 if(dev->mode)
915 printf("\t");
916#ifdef O_SYNC
917 if(dev->mode & O_SYNC)
918 printf("sync ");
919#endif
920#ifdef O_NDELAY
921 if((dev->mode & O_NDELAY))
922 printf("nodelay ");
923#endif
924#ifdef O_EXCL
925 if((dev->mode & O_EXCL))
926 printf("exclusive ");
927#endif
928 if(dev->mode)
929 printf("\n");
930
931 if(dev->precmd)
932 printf("\tprecmd=%s\n", dev->precmd);
933
934 printf("\n");
935 }
936
937 printf("mtools_fat_compatibility=%d\n",mtools_fat_compatibility);
938 printf("mtools_skip_check=%d\n",mtools_skip_check);
939 printf("mtools_lower_case=%d\n",mtools_ignore_short_case);
940
941 exit(0);
942}
943
944/*
945 * Local Variables:
946 * c-basic-offset: 4
947 * End:
948 */