1: /*
   2:  * Write (copy) a Unix file to MSDOS
   3:  *
   4:  * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
   5:  * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
   6:  * fthood!egray@uxc.cso.uiuc.edu	Directorate of Engineering & Housing
   7:  * 					Environmental Management Office
   8:  * 					Fort Hood, TX 76544-5057
   9:  */
  10: 
  11: #include <stdio.h>
  12: #include <signal.h>
  13: #include <sys/types.h>
  14: #include <sys/stat.h>
  15: #include "msdos.h"
  16: #include "patchlevel.h"
  17: 
  18: int fd = -1;                /* the file descriptor for the device */
  19: int dir_start;              /* starting sector for directory */
  20: int dir_len;                /* length of directory (in sectors) */
  21: int dir_entries;            /* number of directory entries */
  22: int clus_size;              /* cluster size (in sectors) */
  23: char *mcwd;             /* the Current Working Directory */
  24: int fat_error;              /* FAT error detected? */
  25: 
  26: int full = 0;
  27: int textmode = 0;
  28: int nowarn = 0;
  29: static int got_signal();
  30: static struct directory *writeit();
  31: static long free_space();
  32: 
  33: main(argc, argv)
  34: int argc;
  35: char *argv[];
  36: {
  37:     extern int optind;
  38:     extern char *optarg;
  39:     int i, entry, ismatch, nogo, slot, single;
  40:     int c, oops, verbose, first, mod_time;
  41:     unsigned int dot, start;
  42:     char *filename, *newfile, *get_name(), get_drive();
  43:     char *unix_name(), ans[10], *pathname, *get_path(), *fix_mcwd();
  44:     char tmp[MAX_PATH], target[13], *strcat(), *strcpy(), drive;
  45:     unsigned char *fixed, *dos_name();
  46:     void exit(), fat_write(), dir_write(), disk_flush(), dir_flush();
  47:     struct directory *dir, *dir_read();
  48:                     /* catch signals */
  49:     signal(SIGINT, (SIG_TYPE(*) ()) got_signal);
  50:     signal(SIGTERM, (SIG_TYPE(*) ()) got_signal);
  51:     signal(SIGQUIT, (SIG_TYPE(*) ()) got_signal);
  52:                     /* get command line options */
  53:     oops = 0;
  54:     verbose = 0;
  55:     mod_time = 0;
  56:     while ((c = getopt(argc, argv, "tnvm")) != EOF) {
  57:         switch (c) {
  58:             case 't':
  59:                 textmode = 1;
  60:                 break;
  61:             case 'n':
  62:                 nowarn = 1;
  63:                 break;
  64:             case 'v':
  65:                 verbose = 1;
  66:                 break;
  67:             case 'm':
  68:                 mod_time = 1;
  69:                 break;
  70:             default:
  71:                 oops = 1;
  72:                 break;
  73:         }
  74:     }
  75: 
  76:     if (oops || (argc - optind) < 2) {
  77:         fprintf(stderr, "Mtools version %s, dated %s\n", VERSION, DATE);
  78:         fprintf(stderr, "Usage: %s [-tnvm] unixfile msdosfile\n", argv[0]);
  79:         fprintf(stderr, "       %s [-tnvm] unixfile [unixfiles...] msdosdirectory\n", argv[0]);
  80:         exit(1);
  81:     }
  82:     mcwd = fix_mcwd();
  83: 
  84:     drive = get_drive(argv[argc - 1]);
  85:     if (init(drive, 2)) {
  86:         fprintf(stderr, "%s: Cannot initialize '%c:'\n", argv[0], drive);
  87:         exit(1);
  88:     }
  89: 
  90:     filename = get_name(argv[argc - 1]);
  91:     pathname = get_path(argv[argc - 1]);
  92: 
  93:     /*
  94: 	 * Move to "first guess" directory so we can see if filename is also
  95: 	 * a directory.
  96: 	 */
  97:     if (subdir(drive, pathname))
  98:         exit(1);
  99:                     /* test if last argv is a dir */
 100:     if (is_dir(filename) || *filename == '\0') {
 101:         if (*filename) {
 102:             strcpy(tmp, pathname);
 103:             if (tmp[strlen(tmp) -1] != '/')
 104:                 strcat(tmp, "/");
 105:             strcat(tmp, filename);
 106: 
 107:             if (subdir(drive, tmp))
 108:                 exit(1);
 109:         }
 110:         single = 0;
 111:     }
 112:     else {
 113:         single = 1;
 114:                     /* too many arguments */
 115:         if ((argc - optind) != 2) {
 116:             fprintf(stderr, "%s: Too many arguments or destination directory omitted\n", argv[0]);
 117:             exit(1);
 118:         }
 119:     }
 120: 
 121:     for (i = optind; i < argc - 1; i++) {
 122:         if (single)
 123:             fixed = dos_name(argv[argc - 1], verbose);
 124:         else
 125:             fixed = dos_name(argv[i], verbose);
 126: 
 127:         strcpy(target, unix_name(fixed, fixed + 8));
 128:                     /* see if exists and get slot */
 129:         ismatch = 0;
 130:         slot = -1;
 131:         dot = 0;
 132:         nogo = 0;
 133:         first = 1;
 134:         for (entry = 0; entry < dir_entries; entry++) {
 135:             dir = dir_read(entry);
 136:                     /* save the '.' entry info */
 137:             if (first) {
 138:                 first = 0;
 139:                 if ((dir->attr & 0x10) && dir->name[0] == '.') {
 140:                     dot = dir->start[1] * 0x100 + dir->start[0];
 141:                     continue;
 142:                 }
 143:             }
 144:                     /* is empty */
 145:             if (dir->name[0] == 0x0) {
 146:                 if (slot < 0)
 147:                     slot = entry;
 148:                 break;
 149:             }
 150:                     /* is erased */
 151:             if (dir->name[0] == 0xe5) {
 152:                 if (slot < 0)
 153:                     slot = entry;
 154:                 continue;
 155:             }
 156:                     /* is dir or volume label */
 157:             if ((dir->attr & 0x10) || (dir->attr & 0x08))
 158:                 continue;
 159: 
 160:             newfile = unix_name(dir->name, dir->ext);
 161: 
 162:                     /* if file exists, delete it first */
 163:             if (!strcmp(target, newfile)) {
 164:                 ismatch = 1;
 165:                 start = dir->start[1] * 0x100 + dir->start[0];
 166:                 if (nowarn) {
 167:                     if (fat_free(start))
 168:                         break;
 169:                     dir->name[0] = 0xe5;
 170:                     dir_write(entry, dir);
 171:                     if (slot < 0)
 172:                         slot = entry;
 173:                 }
 174:                 else {
 175:                     /* CONSTCOND */
 176:                     while (1) {
 177:                         printf("File \"%s\" exists, overwrite (y/n) ? ", target);
 178:                         gets(ans);
 179:                         if (ans[0] == 'n' || ans[0] == 'N') {
 180:                             nogo = 1;
 181:                             break;
 182:                         }
 183:                         if (ans[0] == 'y' || ans[0] == 'Y') {
 184:                             if (fat_free(start))
 185:                                 break;
 186:                             dir->name[0] = 0xe5;
 187:                             dir_write(entry, dir);
 188:                             if (slot < 0)
 189:                                 slot = entry;
 190:                             break;
 191:                         }
 192:                     }
 193:                 }
 194:             }
 195:             if (ismatch)
 196:                 break;
 197:         }
 198:         if (fat_error)
 199:             break;
 200: 
 201:         if (nogo)       /* chickened out... */
 202:             continue;
 203:                     /* no '.' entry means root directory */
 204:         if (dot == 0 && slot < 0) {
 205:             fprintf(stderr, "%s: No directory slots\n", argv[0]);
 206:             break;
 207:         }
 208:                     /* make the directory grow */
 209:         if (dot && slot < 0) {
 210:             if (dir_grow(dot)) {
 211:                 fprintf(stderr, "%s: Disk full\n", argv[0]);
 212:                 break;
 213:             }
 214:                     /* first entry in 'new' directory */
 215:             slot = entry;
 216:         }
 217:                     /* write the file */
 218:         if (dir = writeit(fixed, argv[i], verbose, mod_time, single, target))
 219:             dir_write(slot, dir);
 220: 
 221:         if (full) {
 222:             fprintf(stderr, "%s: Disk full\n", argv[0]);
 223:             break;
 224:         }
 225:         if (single)
 226:             break;
 227:     }
 228:                     /* write the FAT, flush the buffers */
 229:     fat_write();
 230:     dir_flush();
 231:     disk_flush();
 232:     close(fd);
 233:     exit(0);
 234: }
 235: 
 236: /*
 237:  * Open the named file for read, create the cluster chain, return the
 238:  * directory structure or NULL on error.
 239:  */
 240: 
 241: static struct directory *
 242: writeit(fixed, path, verbose, mod_time, single, target)
 243: unsigned char *fixed;
 244: char *path;
 245: int verbose, mod_time, single;
 246: char *target;
 247: {
 248:     FILE *fp;
 249:     unsigned int fat, next_fat();
 250:     long filesize, file_write(), size, time(), now;
 251:     struct directory *dir, *mk_entry();
 252:     struct stat stbuf;
 253: 
 254:     if (stat(path, &stbuf) < 0) {
 255:         fprintf(stderr, "Can't stat \"%s\"\n", path);
 256:         return(NULL);
 257:     }
 258: 
 259:     if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
 260:         if (verbose)
 261:             fprintf(stderr, "\"%s\" is a directory\n", path);
 262:         return(NULL);
 263:     }
 264: 
 265:     if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
 266:         if (verbose)
 267:             fprintf(stderr, "\"%s\" is not a regular file\n", path);
 268:         return(NULL);
 269:     }
 270: 
 271:     if (!(fp = fopen(path, "r"))) {
 272:         fprintf(stderr, "Can't open \"%s\" for read\n", path);
 273:         return(NULL);
 274:     }
 275: 
 276:     if (!single)
 277:         printf("Copying %s\n", target);
 278: 
 279:                     /* will it fit? */
 280:     filesize = stbuf.st_size;
 281:     if (filesize > free_space()) {
 282:         full = 1;
 283:         return(NULL);
 284:     }
 285:                     /* preserve mod time? */
 286:     if (mod_time)
 287:         now = stbuf.st_mtime;
 288:     else
 289:         time(&now);
 290: 
 291:                     /* if a zero length file */
 292:     if (filesize == 0L) {
 293:         dir = mk_entry(fixed, 0x20, 0, 0L, now);
 294:         return(dir);
 295:     }
 296: 
 297:     if ((fat = next_fat(0)) == 1) {
 298:         full = 1;
 299:         fclose(fp);
 300:         return(NULL);
 301:     }
 302:     if ((size = file_write(fp, fat, filesize, textmode)) < 0) {
 303:         fclose(fp);
 304:         return(NULL);
 305:     }
 306:     fclose(fp);
 307: 
 308:     dir = mk_entry(fixed, 0x20, fat, size, now);
 309:     return(dir);
 310: }
 311: 
 312: /*
 313:  * Do a graceful exit if the program is interrupted.  This will reduce
 314:  * (but not eliminate) the risk of generating a corrupted disk on
 315:  * a user abort.
 316:  */
 317: 
 318: static int
 319: got_signal()
 320: {
 321:     void exit(), disk_flush(), fat_write(), dir_flush();
 322: 
 323:     if (fd < 0)
 324:         exit(1);
 325:     fat_write();
 326:     dir_flush();
 327:     disk_flush();
 328:     close(fd);
 329:     exit(1);
 330: }
 331: 
 332: 
 333: /*
 334:  * Get the amount of remaining free space
 335:  */
 336: 
 337: static long
 338: free_space()
 339: {
 340:     register unsigned int i;
 341:     long total;
 342:     extern unsigned int num_clus;
 343:     unsigned int fat_decode();
 344: 
 345:     total = 0L;
 346:     for (i = 2; i < num_clus + 2; i++) {
 347:                     /* if fat_decode returns zero */
 348:         if (!fat_decode(i))
 349:             total += clus_size;
 350:     }
 351:     total *= MSECTOR_SIZE;
 352:     return(total);
 353: }

Defined functions

free_space defined in line 337; used 2 times
got_signal defined in line 318; used 4 times
main defined in line 33; never used
writeit defined in line 241; used 2 times

Defined variables

clus_size defined in line 22; used 1 times
dir_entries defined in line 21; used 1 times
dir_len defined in line 20; never used
dir_start defined in line 19; never used
fat_error defined in line 24; used 1 times
fd defined in line 18; used 3 times
full defined in line 26; used 5 times
mcwd defined in line 23; used 1 times
  • in line 82
nowarn defined in line 28; used 2 times
textmode defined in line 27; used 2 times
Last modified: 1992-06-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2875
Valid CSS Valid XHTML 1.0 Strict