Initial import package mtools: Programs for accessing MS-DOS disks without mounting...
[profile/ivi/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 #define LOWERCASE
22
23 #include "sysincludes.h"
24 #include "msdos.h"
25 #include "mtools.h"
26 #include "vfat.h"
27 #include "mainloop.h"
28 #include "plain_io.h"
29 #include "nameclash.h"
30 #include "file.h"
31 #include "fs.h"
32 #include "fsP.h"
33
34 typedef struct Arg_t {
35         char *target;
36         MainParam_t mp;
37         ClashHandling_t ch;
38         Stream_t *sourcefile;
39         unsigned long fat;
40         int markbad;
41         int setsize;
42         unsigned long size;
43         Fs_t *Fs;
44 } Arg_t;
45
46 static int dos_doctorfat(direntry_t *entry, MainParam_t *mp)
47 {
48         Fs_t *Fs = getFs(mp->File);
49         Arg_t *arg=(Arg_t *) mp->arg;
50         
51         if(!arg->markbad && entry->entry != -3) {
52                 /* if not root directory, change it */
53                 set_word(entry->dir.start, arg->fat & 0xffff);
54                 set_word(entry->dir.startHi, arg->fat >> 16);
55                 if(arg->setsize)
56                         set_dword(entry->dir.size, arg->size);
57                 dir_write(entry);               
58         }
59         arg->Fs = Fs; 
60         return GOT_ONE;
61 }
62
63 static int unix_doctorfat(MainParam_t *mp)
64 {
65         fprintf(stderr,"File does not reside on a Dos fs\n");
66         return ERROR_ONE;
67 }
68
69 static void usage(int ret) NORETURN;
70 static void usage(int ret)
71 {
72         fprintf(stderr,
73                 "Mtools version %s, dated %s\n", mversion, mdate);
74         fprintf(stderr,
75                 "Usage: [-b] %s file fat\n", progname);
76         exit(ret);
77 }
78
79 void mdoctorfat(int argc, char **argv, int mtype)
80 {
81         Arg_t arg;
82         int c, ret;
83         long address, begin, end;
84         char *number, *eptr;
85         int i, j;
86         long 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                 switch (c) {
102                         case 'i':
103                                 set_cmd_line_image(optarg, 0);
104                                 break;
105                         case 'b':
106                                 arg.markbad = 1;
107                                 break;
108                         case 'o':
109                                 offset = strtoul(optarg,0,0);
110                                 break;
111                         case 's':
112                                 arg.setsize=1;
113                                 arg.size = strtoul(optarg,0,0);
114                                 break;
115                         case 'h':
116                                 usage(0);
117                         case '?':
118                                 usage(1);
119                                 break;
120                 }
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 = strtoul(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                 number = argv[i];
143                 if (*number == '<') {
144                         number++;
145                 }
146                 begin = strtoul(number, &eptr, 0);
147                 if (eptr && *eptr == '-') {
148                         number = eptr+1;
149                         end = strtoul(number, &eptr, 0);
150                 } else {
151                         end = begin;
152                 }
153                 if (eptr == number) {
154                         fprintf(stderr, "Not a number: %s\n", number);
155                         exit(-1);
156                 }
157
158                 if (eptr && *eptr == '>') {
159                         eptr++;
160                 }
161                 if (eptr && *eptr) {
162                         fprintf(stderr, "Not a number: %s\n", eptr);
163                         exit(-1);
164                 }
165
166                 for (j=begin; j <= end; j++) {
167                         if(arg.markbad) {
168                                 arg.Fs->fat_encode(arg.Fs, j+offset, arg.Fs->last_fat ^ 6 ^ 8);
169                         } else {
170                                 if(address) {
171                                         arg.Fs->fat_encode(arg.Fs, address, j+offset);
172                                 }
173                                 address = j+offset;
174                         }
175                 }
176         }
177
178         if (address && !arg.markbad) {
179                 arg.Fs->fat_encode(arg.Fs, address, arg.Fs->end_fat);
180         }
181
182         exit(ret);
183 }