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