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 34typedef 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 46static 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 63static 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 69static void usage(int ret) NORETURN; 70static 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 79void 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} 184