diff options
Diffstat (limited to 'mdoctorfat.c')
-rw-r--r-- | mdoctorfat.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/mdoctorfat.c b/mdoctorfat.c new file mode 100644 index 0000000..668fc19 --- /dev/null +++ b/mdoctorfat.c @@ -0,0 +1,183 @@ +/* Copyright 1999,2001,2002,2009 Alain Knaff. + * This file is part of mtools. + * + * Mtools is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Mtools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mtools. If not, see <http://www.gnu.org/licenses/>. + * + * Test program for doctoring the fat + */ + + +#define LOWERCASE + +#include "sysincludes.h" +#include "msdos.h" +#include "mtools.h" +#include "vfat.h" +#include "mainloop.h" +#include "plain_io.h" +#include "nameclash.h" +#include "file.h" +#include "fs.h" +#include "fsP.h" + +typedef struct Arg_t { + char *target; + MainParam_t mp; + ClashHandling_t ch; + Stream_t *sourcefile; + unsigned long fat; + int markbad; + int setsize; + unsigned long size; + Fs_t *Fs; +} Arg_t; + +static int dos_doctorfat(direntry_t *entry, MainParam_t *mp) +{ + Fs_t *Fs = getFs(mp->File); + Arg_t *arg=(Arg_t *) mp->arg; + + if(!arg->markbad && entry->entry != -3) { + /* if not root directory, change it */ + set_word(entry->dir.start, arg->fat & 0xffff); + set_word(entry->dir.startHi, arg->fat >> 16); + if(arg->setsize) + set_dword(entry->dir.size, arg->size); + dir_write(entry); + } + arg->Fs = Fs; + return GOT_ONE; +} + +static int unix_doctorfat(MainParam_t *mp UNUSEDP) +{ + fprintf(stderr,"File does not reside on a Dos fs\n"); + return ERROR_ONE; +} + +static void usage(int ret) NORETURN; +static void usage(int ret) +{ + fprintf(stderr, + "Mtools version %s, dated %s\n", mversion, mdate); + fprintf(stderr, + "Usage: [-b] %s file fat\n", progname); + exit(ret); +} + +void mdoctorfat(int argc, char **argv, int mtype UNUSEDP) +{ + Arg_t arg; + int c, ret; + long address, begin, end; + char *number, *eptr; + int i, j; + long offset; + + /* get command line options */ + + init_clash_handling(& arg.ch); + + offset = 0; + + arg.markbad = 0; + arg.setsize = 0; + + /* get command line options */ + if(helpFlag(argc, argv)) + usage(0); + while ((c = getopt(argc, argv, "i:bo:s:h")) != EOF) { + switch (c) { + case 'i': + set_cmd_line_image(optarg); + break; + case 'b': + arg.markbad = 1; + break; + case 'o': + offset = strtoul(optarg,0,0); + break; + case 's': + arg.setsize=1; + arg.size = strtoul(optarg,0,0); + break; + case 'h': + usage(0); + case '?': + usage(1); + break; + } + } + + if (argc - optind < 2) + usage(1); + + + /* only 1 file to copy... */ + init_mp(&arg.mp); + arg.mp.arg = (void *) &arg; + + arg.mp.callback = dos_doctorfat; + arg.mp.unixcallback = unix_doctorfat; + + arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN; + arg.mp.openflags = O_RDWR; + arg.fat = strtoul(argv[optind+1], 0, 0) + offset; + ret=main_loop(&arg.mp, argv + optind, 1); + if(ret) + exit(ret); + address = 0; + for(i=optind+1; i < argc; i++) { + number = argv[i]; + if (*number == '<') { + number++; + } + begin = strtoul(number, &eptr, 0); + if (eptr && *eptr == '-') { + number = eptr+1; + end = strtoul(number, &eptr, 0); + } else { + end = begin; + } + if (eptr == number) { + fprintf(stderr, "Not a number: %s\n", number); + exit(-1); + } + + if (eptr && *eptr == '>') { + eptr++; + } + if (eptr && *eptr) { + fprintf(stderr, "Not a number: %s\n", eptr); + exit(-1); + } + + for (j=begin; j <= end; j++) { + if(arg.markbad) { + arg.Fs->fat_encode(arg.Fs, j+offset, arg.Fs->last_fat ^ 6 ^ 8); + } else { + if(address) { + arg.Fs->fat_encode(arg.Fs, address, j+offset); + } + address = j+offset; + } + } + } + + if (address && !arg.markbad) { + arg.Fs->fat_encode(arg.Fs, address, arg.Fs->end_fat); + } + + exit(ret); +} |