1/* Copyright 1986-1992 Emmet P. Gray. 2 * Copyright 1996-2002,2007-2009 Alain Knaff. 3 * This file is part of mtools. 4 * 5 * Mtools is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * Mtools is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with Mtools. If not, see <http://www.gnu.org/licenses/>. 17 * 18 * mmd.c 19 * Makes an MSDOS directory 20 */ 21 22 23#define LOWERCASE 24 25#include "sysincludes.h" 26#include "msdos.h" 27#include "mtools.h" 28#include "vfat.h" 29#include "mainloop.h" 30#include "plain_io.h" 31#include "nameclash.h" 32#include "file.h" 33#include "fs.h" 34 35/* 36 * Preserve the file modification times after the fclose() 37 */ 38 39typedef struct Arg_t { 40 char *target; 41 MainParam_t mp; 42 43 Stream_t *SrcDir; 44 int entry; 45 ClashHandling_t ch; 46 Stream_t *targetDir; 47} Arg_t; 48 49 50typedef struct CreateArg_t { 51 Stream_t *Dir; 52 Stream_t *NewDir; 53 unsigned char attr; 54 time_t mtime; 55} CreateArg_t; 56 57/* 58 * Open the named file for read, create the cluster chain, return the 59 * directory structure or NULL on error. 60 */ 61static int makeit(dos_name_t *dosname, 62 char *longname, 63 void *arg0, 64 direntry_t *targetEntry) 65{ 66 Stream_t *Target; 67 CreateArg_t *arg = (CreateArg_t *) arg0; 68 int fat; 69 direntry_t subEntry; 70 71 /* will it fit? At least one cluster must be free */ 72 if (!getfreeMinClusters(targetEntry->Dir, 1)) 73 return -1; 74 75 mk_entry(dosname, ATTR_DIR, 1, 0, arg->mtime, &targetEntry->dir); 76 Target = OpenFileByDirentry(targetEntry); 77 if(!Target){ 78 fprintf(stderr,"Could not open Target\n"); 79 return -1; 80 } 81 82 /* this allocates the first cluster for our directory */ 83 84 initializeDirentry(&subEntry, Target); 85 86 subEntry.entry = 1; 87 GET_DATA(targetEntry->Dir, 0, 0, 0, &fat); 88 if (fat == fat32RootCluster(targetEntry->Dir)) { 89 fat = 0; 90 } 91 mk_entry_from_base(".. ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir); 92 dir_write(&subEntry); 93 94 FLUSH((Stream_t *) Target); 95 subEntry.entry = 0; 96 GET_DATA(Target, 0, 0, 0, &fat); 97 mk_entry_from_base(". ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir); 98 dir_write(&subEntry); 99 100 mk_entry(dosname, ATTR_DIR | arg->attr, fat, 0, arg->mtime, 101 &targetEntry->dir); 102 arg->NewDir = Target; 103 return 0; 104} 105 106 107static void usage(int ret) NORETURN; 108static void usage(int ret) 109{ 110 fprintf(stderr, 111 "Mtools version %s, dated %s\n", mversion, mdate); 112 fprintf(stderr, 113 "Usage: %s [-D clash_option] file targetfile\n", progname); 114 fprintf(stderr, 115 " %s [-D clash_option] file [files...] target_directory\n", 116 progname); 117 exit(ret); 118} 119 120Stream_t *createDir(Stream_t *Dir, const char *filename, ClashHandling_t *ch, 121 unsigned char attr, time_t mtime) 122{ 123 CreateArg_t arg; 124 int ret; 125 126 arg.Dir = Dir; 127 arg.attr = attr; 128 arg.mtime = mtime; 129 130 if (!getfreeMinClusters(Dir, 1)) 131 return NULL; 132 133 ret = mwrite_one(Dir, filename, 0, makeit, &arg, ch); 134 if(ret < 1) 135 return NULL; 136 else 137 return arg.NewDir; 138} 139 140static int createDirCallback(direntry_t *entry, MainParam_t *mp) 141{ 142 Stream_t *ret; 143 time_t now; 144 145 ret = createDir(mp->File, mp->targetName, &((Arg_t *)(mp->arg))->ch, 146 ATTR_DIR, getTimeNow(&now)); 147 if(ret == NULL) 148 return ERROR_ONE; 149 else { 150 FREE(&ret); 151 return GOT_ONE; 152 } 153 154} 155 156void mmd(int argc, char **argv, int type) 157{ 158 Arg_t arg; 159 int c; 160 161 /* get command line options */ 162 163 init_clash_handling(& arg.ch); 164 165 /* get command line options */ 166 if(helpFlag(argc, argv)) 167 usage(0); 168 while ((c = getopt(argc, argv, "i:D:oh")) != EOF) { 169 switch (c) { 170 case 'i': 171 set_cmd_line_image(optarg, 0); 172 break; 173 case '?': 174 usage(1); 175 case 'o': 176 handle_clash_options(&arg.ch, c); 177 break; 178 case 'D': 179 if(handle_clash_options(&arg.ch, *optarg)) 180 usage(1); 181 break; 182 case 'h': 183 usage(0); 184 default: 185 usage(1); 186 break; 187 } 188 } 189 190 if (argc - optind < 1) 191 usage(1); 192 193 init_mp(&arg.mp); 194 arg.mp.arg = (void *) &arg; 195 arg.mp.openflags = O_RDWR; 196 arg.mp.callback = createDirCallback; 197 arg.mp.lookupflags = OPEN_PARENT | DO_OPEN_DIRS; 198 exit(main_loop(&arg.mp, argv + optind, argc - optind)); 199} 200