xref: /aosp_15_r20/external/mtools/mdoctorfat.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
1*d5c9a868SElliott Hughes /*  Copyright 1999,2001,2002,2009 Alain Knaff.
2*d5c9a868SElliott Hughes  *  This file is part of mtools.
3*d5c9a868SElliott Hughes  *
4*d5c9a868SElliott Hughes  *  Mtools is free software: you can redistribute it and/or modify
5*d5c9a868SElliott Hughes  *  it under the terms of the GNU General Public License as published by
6*d5c9a868SElliott Hughes  *  the Free Software Foundation, either version 3 of the License, or
7*d5c9a868SElliott Hughes  *  (at your option) any later version.
8*d5c9a868SElliott Hughes  *
9*d5c9a868SElliott Hughes  *  Mtools is distributed in the hope that it will be useful,
10*d5c9a868SElliott Hughes  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11*d5c9a868SElliott Hughes  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*d5c9a868SElliott Hughes  *  GNU General Public License for more details.
13*d5c9a868SElliott Hughes  *
14*d5c9a868SElliott Hughes  *  You should have received a copy of the GNU General Public License
15*d5c9a868SElliott Hughes  *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
16*d5c9a868SElliott Hughes  *
17*d5c9a868SElliott Hughes  * Test program for doctoring the fat
18*d5c9a868SElliott Hughes  */
19*d5c9a868SElliott Hughes 
20*d5c9a868SElliott Hughes 
21*d5c9a868SElliott Hughes #include "sysincludes.h"
22*d5c9a868SElliott Hughes #include "msdos.h"
23*d5c9a868SElliott Hughes #include "mtools.h"
24*d5c9a868SElliott Hughes #include "vfat.h"
25*d5c9a868SElliott Hughes #include "mainloop.h"
26*d5c9a868SElliott Hughes #include "plain_io.h"
27*d5c9a868SElliott Hughes #include "nameclash.h"
28*d5c9a868SElliott Hughes #include "file.h"
29*d5c9a868SElliott Hughes #include "fs.h"
30*d5c9a868SElliott Hughes #include "fsP.h"
31*d5c9a868SElliott Hughes 
32*d5c9a868SElliott Hughes typedef struct Arg_t {
33*d5c9a868SElliott Hughes 	char *target;
34*d5c9a868SElliott Hughes 	MainParam_t mp;
35*d5c9a868SElliott Hughes 	ClashHandling_t ch;
36*d5c9a868SElliott Hughes 	Stream_t *sourcefile;
37*d5c9a868SElliott Hughes 	uint32_t fat;
38*d5c9a868SElliott Hughes 	int markbad;
39*d5c9a868SElliott Hughes 	int setsize;
40*d5c9a868SElliott Hughes 	uint32_t size;
41*d5c9a868SElliott Hughes 	Fs_t *Fs;
42*d5c9a868SElliott Hughes } Arg_t;
43*d5c9a868SElliott Hughes 
dos_doctorfat(direntry_t * entry,MainParam_t * mp)44*d5c9a868SElliott Hughes static int dos_doctorfat(direntry_t *entry, MainParam_t *mp)
45*d5c9a868SElliott Hughes {
46*d5c9a868SElliott Hughes 	Fs_t *Fs = getFs(mp->File);
47*d5c9a868SElliott Hughes 	Arg_t *arg=(Arg_t *) mp->arg;
48*d5c9a868SElliott Hughes 
49*d5c9a868SElliott Hughes 	if(!arg->markbad && entry->entry != -3) {
50*d5c9a868SElliott Hughes 		/* if not root directory, change it */
51*d5c9a868SElliott Hughes 		set_word(entry->dir.start, arg->fat & 0xffff);
52*d5c9a868SElliott Hughes 		set_word(entry->dir.startHi, arg->fat >> 16);
53*d5c9a868SElliott Hughes 		if(arg->setsize)
54*d5c9a868SElliott Hughes 			set_dword(entry->dir.size, arg->size);
55*d5c9a868SElliott Hughes 		dir_write(entry);
56*d5c9a868SElliott Hughes 	}
57*d5c9a868SElliott Hughes 	arg->Fs = Fs;
58*d5c9a868SElliott Hughes 	return GOT_ONE;
59*d5c9a868SElliott Hughes }
60*d5c9a868SElliott Hughes 
unix_doctorfat(MainParam_t * mp UNUSEDP)61*d5c9a868SElliott Hughes static int unix_doctorfat(MainParam_t *mp UNUSEDP)
62*d5c9a868SElliott Hughes {
63*d5c9a868SElliott Hughes 	fprintf(stderr,"File does not reside on a Dos fs\n");
64*d5c9a868SElliott Hughes 	return ERROR_ONE;
65*d5c9a868SElliott Hughes }
66*d5c9a868SElliott Hughes 
67*d5c9a868SElliott Hughes static void usage(int ret) NORETURN;
usage(int ret)68*d5c9a868SElliott Hughes static void usage(int ret)
69*d5c9a868SElliott Hughes {
70*d5c9a868SElliott Hughes 	fprintf(stderr,
71*d5c9a868SElliott Hughes 		"Mtools version %s, dated %s\n", mversion, mdate);
72*d5c9a868SElliott Hughes 	fprintf(stderr,
73*d5c9a868SElliott Hughes 		"Usage: [-b] %s file fat\n", progname);
74*d5c9a868SElliott Hughes 	exit(ret);
75*d5c9a868SElliott Hughes }
76*d5c9a868SElliott Hughes 
77*d5c9a868SElliott Hughes void mdoctorfat(int argc, char **argv, int mtype UNUSEDP) NORETURN;
mdoctorfat(int argc,char ** argv,int mtype UNUSEDP)78*d5c9a868SElliott Hughes void mdoctorfat(int argc, char **argv, int mtype UNUSEDP)
79*d5c9a868SElliott Hughes {
80*d5c9a868SElliott Hughes 	Arg_t arg;
81*d5c9a868SElliott Hughes 	int c, ret;
82*d5c9a868SElliott Hughes 	unsigned int address;
83*d5c9a868SElliott Hughes 	unsigned int begin, end;
84*d5c9a868SElliott Hughes 	char *number, *eptr;
85*d5c9a868SElliott Hughes 	int i;
86*d5c9a868SElliott Hughes 	unsigned int offset;
87*d5c9a868SElliott Hughes 
88*d5c9a868SElliott Hughes 	/* get command line options */
89*d5c9a868SElliott Hughes 
90*d5c9a868SElliott Hughes 	init_clash_handling(& arg.ch);
91*d5c9a868SElliott Hughes 
92*d5c9a868SElliott Hughes 	offset = 0;
93*d5c9a868SElliott Hughes 
94*d5c9a868SElliott Hughes 	arg.markbad = 0;
95*d5c9a868SElliott Hughes 	arg.setsize = 0;
96*d5c9a868SElliott Hughes 
97*d5c9a868SElliott Hughes 	/* get command line options */
98*d5c9a868SElliott Hughes 	if(helpFlag(argc, argv))
99*d5c9a868SElliott Hughes 		usage(0);
100*d5c9a868SElliott Hughes 	while ((c = getopt(argc, argv, "i:bo:s:h")) != EOF) {
101*d5c9a868SElliott Hughes 		char *endptr = NULL;
102*d5c9a868SElliott Hughes 		errno=0;
103*d5c9a868SElliott Hughes 		switch (c) {
104*d5c9a868SElliott Hughes 			case 'i':
105*d5c9a868SElliott Hughes 				set_cmd_line_image(optarg);
106*d5c9a868SElliott Hughes 				break;
107*d5c9a868SElliott Hughes 			case 'b':
108*d5c9a868SElliott Hughes 				arg.markbad = 1;
109*d5c9a868SElliott Hughes 				break;
110*d5c9a868SElliott Hughes 			case 'o':
111*d5c9a868SElliott Hughes 				offset = strtoui(optarg,&endptr,0);
112*d5c9a868SElliott Hughes 				break;
113*d5c9a868SElliott Hughes 			case 's':
114*d5c9a868SElliott Hughes 				arg.setsize=1;
115*d5c9a868SElliott Hughes 				arg.size = strtou32(optarg,&endptr,0);
116*d5c9a868SElliott Hughes 				break;
117*d5c9a868SElliott Hughes 			case 'h':
118*d5c9a868SElliott Hughes 				usage(0);
119*d5c9a868SElliott Hughes 			case '?':
120*d5c9a868SElliott Hughes 				usage(1);
121*d5c9a868SElliott Hughes 		}
122*d5c9a868SElliott Hughes 		check_number_parse_errno((char)c, optarg, endptr);
123*d5c9a868SElliott Hughes 	}
124*d5c9a868SElliott Hughes 
125*d5c9a868SElliott Hughes 	if (argc - optind < 2)
126*d5c9a868SElliott Hughes 		usage(1);
127*d5c9a868SElliott Hughes 
128*d5c9a868SElliott Hughes 
129*d5c9a868SElliott Hughes 	/* only 1 file to copy... */
130*d5c9a868SElliott Hughes 	init_mp(&arg.mp);
131*d5c9a868SElliott Hughes 	arg.mp.arg = (void *) &arg;
132*d5c9a868SElliott Hughes 
133*d5c9a868SElliott Hughes 	arg.mp.callback = dos_doctorfat;
134*d5c9a868SElliott Hughes 	arg.mp.unixcallback = unix_doctorfat;
135*d5c9a868SElliott Hughes 
136*d5c9a868SElliott Hughes 	arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN;
137*d5c9a868SElliott Hughes 	arg.mp.openflags = O_RDWR;
138*d5c9a868SElliott Hughes 	arg.fat = strtoui(argv[optind+1], 0, 0) + offset;
139*d5c9a868SElliott Hughes 	ret=main_loop(&arg.mp, argv + optind, 1);
140*d5c9a868SElliott Hughes 	if(ret)
141*d5c9a868SElliott Hughes 		exit(ret);
142*d5c9a868SElliott Hughes 	address = 0;
143*d5c9a868SElliott Hughes 	for(i=optind+1; i < argc; i++) {
144*d5c9a868SElliott Hughes 		unsigned int j;
145*d5c9a868SElliott Hughes 		number = argv[i];
146*d5c9a868SElliott Hughes 		if (*number == '<') {
147*d5c9a868SElliott Hughes 			number++;
148*d5c9a868SElliott Hughes 		}
149*d5c9a868SElliott Hughes 		begin = strtoui(number, &eptr, 0);
150*d5c9a868SElliott Hughes 		if (eptr && *eptr == '-') {
151*d5c9a868SElliott Hughes 			number = eptr+1;
152*d5c9a868SElliott Hughes 			end = strtoui(number, &eptr, 0);
153*d5c9a868SElliott Hughes 		} else {
154*d5c9a868SElliott Hughes 			end = begin;
155*d5c9a868SElliott Hughes 		}
156*d5c9a868SElliott Hughes 		if (eptr == number) {
157*d5c9a868SElliott Hughes 			fprintf(stderr, "Not a number: %s\n", number);
158*d5c9a868SElliott Hughes 			exit(-1);
159*d5c9a868SElliott Hughes 		}
160*d5c9a868SElliott Hughes 
161*d5c9a868SElliott Hughes 		if (eptr && *eptr == '>') {
162*d5c9a868SElliott Hughes 			eptr++;
163*d5c9a868SElliott Hughes 		}
164*d5c9a868SElliott Hughes 		if (eptr && *eptr) {
165*d5c9a868SElliott Hughes 			fprintf(stderr, "Not a number: %s\n", eptr);
166*d5c9a868SElliott Hughes 			exit(-1);
167*d5c9a868SElliott Hughes 		}
168*d5c9a868SElliott Hughes 
169*d5c9a868SElliott Hughes 		for (j=begin; j <= end; j++) {
170*d5c9a868SElliott Hughes 			if(arg.markbad) {
171*d5c9a868SElliott Hughes 				arg.Fs->fat_encode(arg.Fs, j+offset, arg.Fs->last_fat ^ 6 ^ 8);
172*d5c9a868SElliott Hughes 			} else {
173*d5c9a868SElliott Hughes 				if(address) {
174*d5c9a868SElliott Hughes 					arg.Fs->fat_encode(arg.Fs, address, j+offset);
175*d5c9a868SElliott Hughes 				}
176*d5c9a868SElliott Hughes 				address = j+offset;
177*d5c9a868SElliott Hughes 			}
178*d5c9a868SElliott Hughes 		}
179*d5c9a868SElliott Hughes 	}
180*d5c9a868SElliott Hughes 
181*d5c9a868SElliott Hughes 	if (address && !arg.markbad) {
182*d5c9a868SElliott Hughes 		arg.Fs->fat_encode(arg.Fs, address, arg.Fs->end_fat);
183*d5c9a868SElliott Hughes 	}
184*d5c9a868SElliott Hughes 
185*d5c9a868SElliott Hughes 	exit(ret);
186*d5c9a868SElliott Hughes }
187