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