# 2.11BSD#431 - /usr/src/local/mtools/mwrite.c

##### Functions

    main              X

##### Variables

    clus_size         X
    dir_entries       X
    dir_len           X
    dir_start         X
    fat_error         X
    fd                X
    full              X
    mcwd              X
    nowarn            X
    textmode          X

       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

- in line 31, 281

got_signal defined in line 318; used 4 times

- in line 29, 49-51(3)

main defined in line 33; never used
writeit defined in line 241; used 2 times

- in line 30, 218

#### Defined variables

clus_size defined in line 22; used 1 times

- in line 349

dir_entries defined in line 21; used 1 times

- in line 134

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

- in line 198

fd defined in line 18; used 3 times

- in line 232, 323-328(2)

full defined in line 26; used 5 times

- in line 221, 282, 298
- in /usr/src/local/mtools/file_write.c line 37, 55

mcwd defined in line 23; used 1 times

- in line 82

nowarn defined in line 28; used 2 times

- in line 62, 166

textmode defined in line 27; used 2 times

- in line 59, 302

Last modified: 1992-06-24 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 921 |