• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*  Copyright 1999,2001,2002,2009 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  * Test program for doctoring the fat
18  */
19 
20 
21 #include "sysincludes.h"
22 #include "msdos.h"
23 #include "mtools.h"
24 #include "vfat.h"
25 #include "mainloop.h"
26 #include "plain_io.h"
27 #include "nameclash.h"
28 #include "file.h"
29 #include "fs.h"
30 #include "fsP.h"
31 
32 typedef struct Arg_t {
33 	char *target;
34 	MainParam_t mp;
35 	ClashHandling_t ch;
36 	Stream_t *sourcefile;
37 	uint32_t fat;
38 	int markbad;
39 	int setsize;
40 	unsigned long size;
41 	Fs_t *Fs;
42 } Arg_t;
43 
dos_doctorfat(direntry_t * entry,MainParam_t * mp)44 static int dos_doctorfat(direntry_t *entry, MainParam_t *mp)
45 {
46 	Fs_t *Fs = getFs(mp->File);
47 	Arg_t *arg=(Arg_t *) mp->arg;
48 
49 	if(!arg->markbad && entry->entry != -3) {
50 		/* if not root directory, change it */
51 		set_word(entry->dir.start, arg->fat & 0xffff);
52 		set_word(entry->dir.startHi, arg->fat >> 16);
53 		if(arg->setsize)
54 			set_dword(entry->dir.size, arg->size);
55 		dir_write(entry);
56 	}
57 	arg->Fs = Fs;
58 	return GOT_ONE;
59 }
60 
unix_doctorfat(MainParam_t * mp UNUSEDP)61 static int unix_doctorfat(MainParam_t *mp UNUSEDP)
62 {
63 	fprintf(stderr,"File does not reside on a Dos fs\n");
64 	return ERROR_ONE;
65 }
66 
67 static void usage(int ret) NORETURN;
usage(int ret)68 static void usage(int ret)
69 {
70 	fprintf(stderr,
71 		"Mtools version %s, dated %s\n", mversion, mdate);
72 	fprintf(stderr,
73 		"Usage: [-b] %s file fat\n", progname);
74 	exit(ret);
75 }
76 
77 void mdoctorfat(int argc, char **argv, int mtype UNUSEDP) NORETURN;
mdoctorfat(int argc,char ** argv,int mtype UNUSEDP)78 void mdoctorfat(int argc, char **argv, int mtype UNUSEDP)
79 {
80 	Arg_t arg;
81 	int c, ret;
82 	unsigned int address;
83 	unsigned int begin, end;
84 	char *number, *eptr;
85 	int i;
86 	unsigned int offset;
87 
88 	/* get command line options */
89 
90 	init_clash_handling(& arg.ch);
91 
92 	offset = 0;
93 
94 	arg.markbad = 0;
95 	arg.setsize = 0;
96 
97 	/* get command line options */
98 	if(helpFlag(argc, argv))
99 		usage(0);
100 	while ((c = getopt(argc, argv, "i:bo:s:h")) != EOF) {
101 		char *endptr = NULL;
102 		errno=0;
103 		switch (c) {
104 			case 'i':
105 				set_cmd_line_image(optarg);
106 				break;
107 			case 'b':
108 				arg.markbad = 1;
109 				break;
110 			case 'o':
111 				offset = strtoui(optarg,&endptr,0);
112 				break;
113 			case 's':
114 				arg.setsize=1;
115 				arg.size = strtoul(optarg,&endptr,0);
116 				break;
117 			case 'h':
118 				usage(0);
119 			case '?':
120 				usage(1);
121 		}
122 		check_number_parse_errno(c, optarg, endptr);
123 	}
124 
125 	if (argc - optind < 2)
126 		usage(1);
127 
128 
129 	/* only 1 file to copy... */
130 	init_mp(&arg.mp);
131 	arg.mp.arg = (void *) &arg;
132 
133 	arg.mp.callback = dos_doctorfat;
134 	arg.mp.unixcallback = unix_doctorfat;
135 
136 	arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN;
137 	arg.mp.openflags = O_RDWR;
138 	arg.fat = strtoui(argv[optind+1], 0, 0) + offset;
139 	ret=main_loop(&arg.mp, argv + optind, 1);
140 	if(ret)
141 		exit(ret);
142 	address = 0;
143 	for(i=optind+1; i < argc; i++) {
144 		unsigned int j;
145 		number = argv[i];
146 		if (*number == '<') {
147 			number++;
148 		}
149 		begin = strtoui(number, &eptr, 0);
150 		if (eptr && *eptr == '-') {
151 			number = eptr+1;
152 			end = strtoui(number, &eptr, 0);
153 		} else {
154 			end = begin;
155 		}
156 		if (eptr == number) {
157 			fprintf(stderr, "Not a number: %s\n", number);
158 			exit(-1);
159 		}
160 
161 		if (eptr && *eptr == '>') {
162 			eptr++;
163 		}
164 		if (eptr && *eptr) {
165 			fprintf(stderr, "Not a number: %s\n", eptr);
166 			exit(-1);
167 		}
168 
169 		for (j=begin; j <= end; j++) {
170 			if(arg.markbad) {
171 				arg.Fs->fat_encode(arg.Fs, j+offset, arg.Fs->last_fat ^ 6 ^ 8);
172 			} else {
173 				if(address) {
174 					arg.Fs->fat_encode(arg.Fs, address, j+offset);
175 				}
176 				address = j+offset;
177 			}
178 		}
179 	}
180 
181 	if (address && !arg.markbad) {
182 		arg.Fs->fat_encode(arg.Fs, address, arg.Fs->end_fat);
183 	}
184 
185 	exit(ret);
186 }
187