/* Copyright 1986-1992 Emmet P. Gray. * Copyright 1996-2002,2007-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 . * * mmd.c * Makes an MSDOS directory */ #include "sysincludes.h" #include "mtools.h" #include "mainloop.h" #include "plain_io.h" #include "nameclash.h" #include "file.h" #include "fs.h" /* * Preserve the file modification times after the fclose() */ typedef struct Arg_t { char *target; MainParam_t mp; Stream_t *SrcDir; int entry; ClashHandling_t ch; Stream_t *targetDir; } Arg_t; typedef struct CreateArg_t { Stream_t *Dir; Stream_t *NewDir; unsigned char attr; time_t mtime; } CreateArg_t; /* * Open the named file for read, create the cluster chain, return the * directory structure or NULL on error. */ static int makeit(dos_name_t *dosname, char *longname UNUSEDP, void *arg0, direntry_t *targetEntry) { Stream_t *Target; CreateArg_t *arg = (CreateArg_t *) arg0; uint32_t fat; direntry_t subEntry; /* will it fit? At least one cluster must be free */ if (!getfreeMinClusters(targetEntry->Dir, 1)) return -1; mk_entry(dosname, ATTR_DIR, 1, 0, arg->mtime, &targetEntry->dir); Target = OpenFileByDirentry(targetEntry); if(!Target){ fprintf(stderr,"Could not open Target\n"); return -1; } /* this allocates the first cluster for our directory */ initializeDirentry(&subEntry, Target); subEntry.entry = 1; GET_DATA(targetEntry->Dir, 0, 0, 0, &fat); if (fat == fat32RootCluster(targetEntry->Dir)) { fat = 0; } mk_entry_from_base(".. ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir); dir_write(&subEntry); FLUSH(Target); subEntry.entry = 0; GET_DATA(Target, 0, 0, 0, &fat); mk_entry_from_base(". ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir); dir_write(&subEntry); mk_entry(dosname, ATTR_DIR | arg->attr, fat, 0, arg->mtime, &targetEntry->dir); arg->NewDir = Target; return 0; } static void usage(int ret) NORETURN; static void usage(int ret) { fprintf(stderr, "Mtools version %s, dated %s\n", mversion, mdate); fprintf(stderr, "Usage: %s [-D clash_option] file targetfile\n", progname); fprintf(stderr, " %s [-D clash_option] file [files...] target_directory\n", progname); exit(ret); } Stream_t *createDir(Stream_t *Dir, const char *filename, ClashHandling_t *ch, unsigned char attr, time_t mtime) { CreateArg_t arg; int ret; arg.Dir = Dir; arg.attr = attr; arg.mtime = mtime; if (!getfreeMinClusters(Dir, 1)) return NULL; ret = mwrite_one(Dir, filename, 0, makeit, &arg, ch); if(ret < 1) return NULL; else return arg.NewDir; } static int createDirCallback(direntry_t *entry UNUSEDP, MainParam_t *mp) { Stream_t *ret; time_t now; ret = createDir(mp->File, mp->targetName, &((Arg_t *)(mp->arg))->ch, ATTR_DIR, getTimeNow(&now)); if(ret == NULL) return ERROR_ONE; else { FREE(&ret); return GOT_ONE; } } void mmd(int argc, char **argv, int type UNUSEDP) NORETURN; void mmd(int argc, char **argv, int type UNUSEDP) { Arg_t arg; int c; /* get command line options */ init_clash_handling(& arg.ch); /* get command line options */ if(helpFlag(argc, argv)) usage(0); while ((c = getopt(argc, argv, "i:D:oh")) != EOF) { switch (c) { case 'i': set_cmd_line_image(optarg); break; case '?': usage(1); case 'o': handle_clash_options(&arg.ch, c); break; case 'D': if(handle_clash_options(&arg.ch, *optarg)) usage(1); break; case 'h': usage(0); default: usage(1); } } if (argc - optind < 1) usage(1); init_mp(&arg.mp); arg.mp.arg = (void *) &arg; arg.mp.openflags = O_RDWR; arg.mp.callback = createDirCallback; arg.mp.lookupflags = OPEN_PARENT | DO_OPEN_DIRS; exit(main_loop(&arg.mp, argv + optind, argc - optind)); }