home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / diskutil / mtools / mread.c < prev    next >
C/C++ Source or Header  |  1993-08-05  |  8KB  |  346 lines

  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. }
  346.