1: /*
   2:  * Read (copy) an MSDOS file to Unix
   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: #define LOWERCASE
  12: 
  13: #include <stdio.h>
  14: #include <ctype.h>
  15: #include <sys/types.h>
  16: #include <sys/stat.h>
  17: #ifdef BSD
  18: #include <sys/time.h>
  19: #else /* BSD */
  20: #include <time.h>
  21: #endif /* BSD */
  22: #include "msdos.h"
  23: #include "patchlevel.h"
  24: 
  25: int fd = -1;                /* the file descriptor for the device */
  26: int dir_start;              /* starting sector for directory */
  27: int dir_len;                /* length of directory (in sectors) */
  28: int dir_entries;            /* number of directory entries */
  29: int clus_size;              /* cluster size (in sectors) */
  30: char *mcwd;             /* the Current Working Directory */
  31: int fat_error;              /* FAT error detected? */
  32: 
  33: static void set_mtime();
  34: static FILE *open_file();
  35: static long conv_stamp();
  36: 
  37: main(argc, argv)
  38: int argc;
  39: char *argv[];
  40: {
  41:     FILE *fp;
  42:     extern int optind;
  43:     extern char *optarg;
  44:     int i, ismatch, entry, single, c, oops, preserve, nowarn, textmode;
  45:     unsigned int fat;
  46:     long size, mtime;
  47:     char *filename, *newfile, *get_name(), *unix_name(), *pathname;
  48:     char *get_path(), *target, tmp[MAX_PATH], *strcat(), *strcpy(), drive;
  49:     char get_drive(), last_drive, *fix_mcwd(), *s;
  50:     void exit();
  51:     struct directory *dir, *dir_read();
  52:     struct stat stbuf;
  53: 
  54:                     /* get command line options */
  55:     oops = 0;
  56:     preserve = 0;
  57:     nowarn = 0;
  58:     textmode = 0;
  59:     while ((c = getopt(argc, argv, "tnmv")) != EOF) {
  60:         switch (c) {
  61:             case 't':
  62:                 textmode = 1;
  63:                 break;
  64:             case 'n':
  65:                 nowarn = 1;
  66:                 break;
  67:             case 'm':
  68:                 preserve = 1;
  69:                 break;
  70:             case 'v':   /* dummy option for mcopy */
  71:                 break;
  72:             default:
  73:                 oops = 1;
  74:                 break;
  75:         }
  76:     }
  77: 
  78:     if (oops || (argc - optind) < 2) {
  79:         fprintf(stderr, "Mtools version %s, dated %s\n", VERSION, DATE);
  80:         fprintf(stderr, "Usage: %s [-tnm] msdosfile unixfile\n", argv[0]);
  81:         fprintf(stderr, "       %s [-tnm] msdosfile [msdosfiles...] unixdirectory\n", argv[0]);
  82:         exit(1);
  83:     }
  84:     last_drive = 'x';
  85:     mcwd = fix_mcwd();
  86:                     /* only 1 file to copy... */
  87:     single = 1;
  88:     target = argv[argc - 1];
  89:                     /* ...unless last arg is a directory */
  90:     if (!stat(target, &stbuf)) {
  91:         if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
  92:             single = 0;
  93:     }
  94:                     /* too many arguments */
  95:     if (single && (argc - optind) != 2) {
  96:         fprintf(stderr, "%s: Too many arguments or destination directory omitted\n", argv[0]);
  97:         exit(1);
  98:     }
  99: 
 100:     for (i = optind; i < argc - 1; i++) {
 101:         drive = get_drive(argv[i]);
 102:         if (drive != last_drive) {
 103:             if (init(drive, 0)) {
 104:                 fprintf(stderr, "%s: Cannot initialize '%c:'\n", argv[0], drive);
 105:                 continue;
 106:             }
 107:             last_drive = drive;
 108:         }
 109:         filename = get_name(argv[i]);
 110:         pathname = get_path(argv[i]);
 111:         if (subdir(drive, pathname))
 112:             continue;
 113: 
 114:         ismatch = 0;
 115:         for (entry = 0; entry < dir_entries; entry++) {
 116:             dir = dir_read(entry);
 117:                     /* if empty */
 118:             if (dir->name[0] == 0x0)
 119:                 break;
 120:                     /* if erased */
 121:             if (dir->name[0] == 0xe5)
 122:                 continue;
 123:                     /* if dir or volume label */
 124:             if ((dir->attr & 0x10) || (dir->attr & 0x08))
 125:                 continue;
 126: 
 127:             newfile = unix_name(dir->name, dir->ext);
 128: 
 129:                     /* if single file */
 130:             if (single) {
 131:                 if (!strcmp(newfile, filename)) {
 132:                     fat = dir->start[1] * 0x100 + dir->start[0];
 133:                     size = dir->size[3] * 0x1000000L + dir->size[2] * 0x10000L + dir->size[1] * 0x100 + dir->size[0];
 134:                     if (preserve)
 135:                         mtime = conv_stamp(dir->time, dir->date);
 136:                     else
 137:                         mtime = 0L;
 138:                     if ((fp = open_file(target, nowarn))) {
 139:                         if (file_read(fp, fat, textmode, 0, size)) {
 140:                             fclose(fp);
 141:                             break;
 142:                         }
 143:                         fclose(fp);
 144:                         set_mtime(target, mtime);
 145:                     }
 146:                     ismatch = 1;
 147:                     break;
 148:                 }
 149:             }
 150:                     /* if multiple files */
 151:             else {
 152:                 if (match(newfile, filename)) {
 153:                     fat = dir->start[1] * 0x100 + dir->start[0];
 154:                     size = dir->size[3] * 0x1000000L + dir->size[2] * 0x10000L + dir->size[1] * 0x100 + dir->size[0];
 155:                     if (preserve)
 156:                         mtime = conv_stamp(dir->time, dir->date);
 157:                     else
 158:                         mtime = 0L;
 159:                     printf("Copying %s\n", newfile);
 160: #ifdef LOWERCASE
 161:                     s = newfile;
 162:                     while (*s) {
 163:                         if (isupper(*s))
 164:                             *s = tolower(*s);
 165:                         s++;
 166:                     }
 167: #endif /* LOWERCASE */
 168:                     strcpy(tmp, target);
 169:                     strcat(tmp, "/");
 170:                     strcat(tmp, newfile);
 171:                     if ((fp = open_file(tmp, nowarn))) {
 172:                         if (file_read(fp, fat, textmode, 0, size)) {
 173:                             fclose(fp);
 174:                             break;
 175:                         }
 176:                         fclose(fp);
 177:                         set_mtime(tmp, mtime);
 178:                     }
 179:                     ismatch = 1;
 180:                 }
 181:             }
 182:         }
 183:         if (fat_error)
 184:             break;
 185: 
 186:         if (!ismatch)
 187:             fprintf(stderr, "%s: File \"%s\" not found\n", argv[0], filename);
 188:     }
 189:     close(fd);
 190:     exit(0);
 191: }
 192: 
 193: /*
 194:  * Open the named Unix file for write.
 195:  */
 196: 
 197: static FILE *
 198: open_file(target, nowarn)
 199: char *target;
 200: int nowarn;
 201: {
 202:     static FILE *fp;
 203:     char ans[10];
 204:     struct stat stbuf;
 205: 
 206:     if (!nowarn) {
 207:         if (!access(target, 0)) {
 208:             /* CONSTCOND */
 209:             while (1) {
 210:                 printf("File \"%s\" exists, overwrite (y/n) ? ", target);
 211:                 gets(ans);
 212:                 if (ans[0] == 'n' || ans[0] == 'N')
 213:                     return(NULL);
 214:                 if (ans[0] == 'y' || ans[0] == 'Y')
 215:                     break;
 216:             }
 217:                     /* sanity checking */
 218:             if (!stat(target, &stbuf)) {
 219:                 if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
 220:                     fprintf(stderr, "\"%s\" is not a regular file\n", target);
 221:                     return(NULL);
 222:                 }
 223:             }
 224:         }
 225:     }
 226: 
 227:     if (!(fp = fopen(target, "w"))) {
 228:         fprintf(stderr, "Can't open \"%s\" for write\n", target);
 229:         return(NULL);
 230:     }
 231:     return(fp);
 232: }
 233: 
 234: /*
 235:  * Convert an MSDOS time & date stamp to the Unix time() format
 236:  */
 237: 
 238: static long
 239: conv_stamp(time_field, date_field)
 240: unsigned char *time_field, *date_field;
 241: {
 242: #ifdef BSD
 243:     struct timeval tv;
 244:     struct timezone tz;
 245: #else /* BSD */
 246:     extern long timezone;
 247:     void tzset();
 248: #endif /* BSD */
 249:     struct tm *tmbuf, *localtime();
 250:     int year, mon, mday, hour, min, sec, old_leaps;
 251:     long answer, sec_year, sec_mon, sec_mday, sec_hour, sec_min, sec_leap;
 252:     long tzone, dst;
 253:     static int month[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304,
 254:     334};
 255:                     /* dissect the parts */
 256:     year = (date_field[1] >> 1) + 1980;
 257:     mon = (((date_field[1] & 0x1) << 3) + (date_field[0] >> 5));
 258:     mday = date_field[0] & 0x1f;
 259:     hour = time_field[1] >> 3;
 260:     min = (((time_field[1] & 0x7) << 3) + (time_field[0] >> 5));
 261:     sec = (time_field[0] & 0x1f) * 2;
 262:                     /* how many previous leap years */
 263:     old_leaps = (year - 1972) / 4L;
 264:     sec_leap = old_leaps * 24L * 60L * 60L;
 265:                     /* back off 1 day if before 29 Feb */
 266:     if (!(year % 4) && mon < 3)
 267:         sec_leap -= 24L * 60L * 60L;
 268:     sec_year = (year - 1970) * 365L * 24L * 60L * 60L;
 269:     sec_mon = month[mon - 1] * 24L * 60L * 60L;
 270:     sec_mday = mday * 24L * 60L * 60L;
 271:     sec_hour = hour * 60L * 60L;
 272:     sec_min = min * 60L;
 273:                     /* correct for Time Zone */
 274: #ifdef BSD
 275:     gettimeofday(&tv, &tz);
 276:     tzone = tz.tz_minuteswest * 60L;
 277: #else /* BSD */
 278:     tzset();
 279:     tzone = timezone;
 280: #endif /* BSD */
 281: 
 282:     answer = sec_leap + sec_year + sec_mon + sec_mday + sec_hour + sec_min + sec + tzone;
 283:                     /* correct for Daylight Saving Time */
 284:     tmbuf = localtime(&answer);
 285:     dst = (tmbuf->tm_isdst) ? (-60L * 60L) : 0L;
 286:     answer += dst;
 287: 
 288:     return(answer);
 289: }
 290: 
 291: /*
 292:  * Preserve the file modification times after the fclose()
 293:  */
 294: 
 295: static void
 296: set_mtime(target, mtime)
 297: char *target;
 298: long mtime;
 299: {
 300: #ifdef BSD
 301:     struct timeval tv[2];
 302: 
 303:     if (mtime != 0L) {
 304:         tv[0].tv_sec = mtime;
 305:         tv[0].tv_usec = 0;
 306:         tv[1].tv_sec = mtime;
 307:         tv[1].tv_usec = 0;
 308:         utimes(target, tv);
 309:     }
 310: #else /* BSD */
 311:     struct {
 312:         time_t actime;
 313:         time_t modtime;
 314:     } utbuf;
 315: 
 316:     if (mtime != 0L) {
 317:         utbuf.actime = mtime;
 318:         utbuf.modtime = mtime;
 319:         utime(target, &utbuf);
 320:     }
 321: #endif /* BSD */
 322:     return;
 323: }
 324: 
 325: /*
 326:  * stubs for read-only programs
 327:  */
 328: 
 329: void
 330: disk_flush()
 331: {
 332:     extern int disk_dirty;
 333: 
 334:     disk_dirty = 0;
 335:     return;
 336: }
 337: 
 338: void
 339: dir_flush()
 340: {
 341:     extern int dir_dirty;
 342: 
 343:     dir_dirty = 0;
 344:     return;
 345: }

Defined functions

conv_stamp defined in line 238; used 3 times
dir_flush defined in line 338; never used
disk_flush defined in line 329; never used
main defined in line 37; never used
open_file defined in line 197; used 3 times
set_mtime defined in line 295; used 3 times

Defined variables

clus_size defined in line 29; never used
dir_entries defined in line 28; used 1 times
dir_len defined in line 27; never used
dir_start defined in line 26; never used
fat_error defined in line 31; used 1 times
fd defined in line 25; used 1 times
mcwd defined in line 30; used 1 times
  • in line 85

Defined macros

LOWERCASE defined in line 11; used 1 times
Last modified: 1992-06-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3197
Valid CSS Valid XHTML 1.0 Strict