home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / SRC / msdos_diskaccess.lzh / MS_DISK_ACCESS / mread.c < prev    next >
C/C++ Source or Header  |  1991-08-04  |  7KB  |  316 lines

  1. /*
  2.  * Read (copy) a 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.  *                     Directorate of Engineering & Housing
  7.  *                     Environmental Management Office
  8.  *                     Fort Hood, TX 76544-5057
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <ctype.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include "msdos.h"
  16.  
  17. #define LOWERCASE
  18.  
  19. int fd;                /* the file descriptor for the floppy */
  20. int dir_start;            /* starting sector for directory */
  21. int dir_len;            /* length of directory (in sectors) */
  22. int dir_entries;        /* number of directory entries */
  23. int dir_chain[25];        /* chain of sectors in directory */
  24. int clus_size;            /* cluster size (in sectors) */
  25. int fat_len;            /* length of FAT table (in sectors) */
  26. int num_clus;            /* number of available clusters */
  27. unsigned char *fatbuf;        /* the File Allocation Table */
  28. char *buf;            /* The input buffer */
  29. long bufsiz;            /* It's size */
  30. int maxcontig;            /* In clusters */
  31. char *mcwd;            /* the Current Working Directory */
  32.  
  33. extern union bootblock bb;
  34. long size;
  35. long current;
  36. int textmode = 0;
  37. int nowarn = 0;
  38.  
  39. main(argc, argv)
  40. int argc;
  41. char *argv[];
  42. {
  43.     extern int optind;
  44.     extern char *optarg;
  45.     int fat, i, ismatch, entry, single, c, oops, mod_time;
  46.     long mod_date, convstamp();
  47.     char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
  48.     char *strncpy(), *pathname, *getpath(), *target, tmp[MAX_PATH];
  49.     char *strcat(), *strcpy();
  50.     void perror(), exit(), free();
  51.     struct directory *dir, *search();
  52.     struct stat stbuf;
  53.  
  54.     if (init(0)) {
  55.         fprintf(stderr, "mread: Cannot initialize diskette\n");
  56.         exit(1);
  57.     }
  58.                     /* get command line options */
  59.     oops = 0;
  60.     mod_time = 0;
  61.     while ((c = getopt(argc, argv, "tnm")) != EOF) {
  62.         switch(c) {
  63.             case 't':
  64.                 textmode = 1;
  65.                 break;
  66.             case 'n':
  67.                 nowarn = 1;
  68.                 break;
  69.             case 'm':
  70.                 mod_time = 1;
  71.                 break;
  72.             default:
  73.                 oops = 1;
  74.                 break;
  75.         }
  76.     }
  77.  
  78.     if (oops || (argc - optind) < 2) {
  79.         fprintf(stderr, "Usage: mread [-tn] msdosfile unixfile\n");
  80.         fprintf(stderr, "    or mread [-tn] msdosfile [msdosfiles...] unixdirectory\n");
  81.         exit(1);
  82.     }
  83.                     /* only 1 file to copy... */
  84.     single = 1;
  85.     target = argv[argc-1];
  86.                     /* ...unless last arg is a directory */
  87.     if (!stat(target, &stbuf)) {
  88.         if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
  89.             single = 0;    
  90.     }
  91.                     /* too many arguments */
  92.     if (single && (argc - optind) != 2) {
  93.         fprintf(stderr,
  94.             "mread: too many arguments or target dir omitted\n");
  95.         exit(1);
  96.     }
  97.  
  98.     bufsiz = NSECT(bb.sb) * NTRACK(bb.sb) ;
  99.     maxcontig = (bufsiz += clus_size - (--bufsiz) % clus_size)/clus_size;
  100.  
  101.     if ( (buf = (char *)malloc(bufsiz *= MSECSIZ)) == NULL ) {
  102.         fprintf(stderr,"Could not allocate input buffer\n");
  103.         exit(1) ;
  104.     }
  105.  
  106.     for (i=optind; i<argc-1; i++) {
  107.         filename = getname(argv[i]);
  108.         pathname = getpath(argv[i]);
  109.         if (subdir(pathname)) {
  110.             free(filename);
  111.             free(pathname);
  112.             continue;
  113.         }
  114.  
  115.         ismatch = 0;
  116.         for (entry=0; entry<dir_entries; entry++) {
  117.             dir = search(entry);
  118.                     /* if empty */
  119.             if (dir->name[0] == 0x0)
  120.                 break;
  121.                     /* if erased */
  122.             if (dir->name[0] == 0xe5)
  123.                 continue;
  124.                     /* if dir or volume lable */
  125.             if ((dir->attr & 0x10) || (dir->attr & 0x08))
  126.                 continue;
  127.  
  128.             strncpy(tname, (char *) dir->name, 8);
  129.             strncpy(text, (char *) dir->ext, 3);
  130.             tname[8] = '\0';
  131.             text[3] = '\0';
  132.  
  133.             newfile = unixname(tname, text);
  134.             fat = dir->start[1]*0x100 + dir->start[0];
  135.             size = dir->size[2]*0x10000L + dir->size[1]*0x100 + dir->size[0];
  136.             if (mod_time)
  137.                 mod_date = convstamp(dir->time, dir->date);
  138.             else
  139.                 mod_date = 0L;
  140.  
  141.                     /* if single file */
  142.             if (single) {
  143.                 if (!strcmp(newfile, filename)) {
  144.                     readit(fat, target, mod_date);
  145.                     ismatch = 1;
  146.                     break;
  147.                 }
  148.             }
  149.                     /* if multiple files */
  150.             else {
  151.                 if (match(newfile, filename)) {
  152.                     printf("Copying %s\n", newfile);
  153.                     strcpy(tmp, target);
  154.                     strcat(tmp, "/");
  155.                     strcat(tmp, newfile);
  156.                     readit(fat, tmp, mod_date);
  157.                     ismatch = 1;
  158.                 }
  159.             }
  160.             free(newfile);
  161.         }
  162.         if (!ismatch)
  163.             fprintf(stderr, "mread: File \"%s\" not found\n", filename);
  164.         free(filename);
  165.         free(pathname);
  166.     }
  167.     close(fd);
  168.     exit(0);
  169. }
  170.  
  171. /*
  172.  * Decode the FAT chain given the begining FAT entry, open the named Unix
  173.  * file for write.
  174.  */
  175.  
  176. static int readpos;
  177.  
  178. int
  179. readit(fat, target, mod_date)
  180. int fat;
  181. char *target;
  182. long mod_date;
  183. {
  184.     void getclusters() ;
  185.     char ans[10];
  186.     void exit();
  187.     int curfat;
  188.     FILE *fp;
  189.     struct stat stbuf;
  190.     struct utimbuf {
  191.         time_t actime;
  192.         time_t modtime;
  193.     } utbuf;
  194.  
  195. #ifdef LOWERCASE
  196.     char *c;
  197.     c = target;
  198.     while(*c) {
  199.         if (isupper(*c))
  200.             *c = tolower(*c);
  201.         c++;
  202.     }
  203. #endif /* LOWERCASE */
  204.  
  205.     if (!nowarn) {
  206.         if (!access(target, 0)) {
  207.             while (1) {
  208.                 printf("File \"%s\" exists, overwrite (y/n) ? ", target);
  209.                 gets(ans);
  210.                 if (ans[0] == 'n' || ans[0] == 'N')
  211.                     return;
  212.                 if (ans[0] == 'y' || ans[0] == 'Y')
  213.                     break;
  214.             }
  215.                     /* sanity checking */
  216.             if (!stat(target, &stbuf)) {
  217.                 if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
  218.                     fprintf(stderr, "mread: \"%s\" is not a regular file\n", target);
  219.                     return;
  220.                 }
  221.             }
  222.         }
  223.     }
  224.  
  225.     if (!(fp = fopen(target, "w"))) {
  226.         fprintf(stderr, "mread: Can't open \"%s\" for write\n", target);
  227.         return;
  228.     }
  229. #ifdef OSK
  230.     fp->_bufsiz = 20480;
  231. #endif
  232.  
  233.     current = 0L;
  234.     readpos = -1;
  235.     for(;;) {
  236.         /*
  237.          * Find chain of contiguous clusters
  238.          * curfat -> last in chain + 1
  239.          */
  240.         for(curfat=fat;
  241.             ++curfat < fat + maxcontig &&
  242.             getfat(curfat-1)==curfat;) ;
  243.  
  244.         getclusters(fat, curfat, fp);
  245.                     /* get next cluster number */
  246.         fat = getfat(--curfat);
  247.         if (fat == -1) {
  248.             fprintf(stderr, "mread: FAT problem\n");
  249.             exit(1);
  250.         }
  251.                     /* end of cluster chain */
  252.         if (fat >= 0xff8)
  253.             break;
  254.     }
  255.     if (fclose(fp)) {
  256.         fprintf(stderr,"Error closing %s\n",target) ;
  257.         perror("close?") ;
  258.         exit(1) ;
  259.     }
  260.                     /* preserve mod times ? */
  261.     if (mod_date != 0L) {
  262.         utbuf.actime = mod_date;
  263.         utbuf.modtime = mod_date;
  264.         utime(target, &utbuf);
  265.     }
  266.     return;
  267. }
  268.  
  269. /*
  270.  * Read the named cluster, write to the Unix file descriptor.
  271.  */
  272.  
  273. void
  274. getclusters(start, end, fp)
  275. FILE *fp;
  276. {
  277.     register int i;
  278.     int buflen, blk;
  279.     void exit(), perror(), move();
  280.  
  281.     blk = (start - 2)*clus_size + dir_start + dir_len;
  282.     if (blk != readpos)
  283.         move(blk);
  284.  
  285.     buflen = (end-start) * clus_size * MSECSIZ;
  286.  
  287.     if (read(fd, (char *) buf, buflen) != buflen) {
  288.         perror("getcluster: read");
  289.         exit(1);
  290.     }
  291.     readpos = blk + (end-start)*clus_size;
  292.                     /* stop at size not EOF marker */
  293.     if (textmode) {
  294.         for (i=0; i<buflen; i++) {
  295.             current++;
  296.             if (current > size) 
  297.                 break;
  298.             if ( buf[i] == '\l')
  299.                 continue;
  300.             if ( current == size && buf[i] == 0x1a)
  301.                 continue;
  302.             putc((char) buf[i], fp);
  303.         }
  304.     }
  305.     else {
  306.         buflen = (size > buflen) ? buflen : size;
  307.         if (fwrite(buf,buflen,1,fp)!=1) {
  308.             perror("getclusters: fwrite") ;
  309.             exit(1) ;
  310.         }
  311.         size -= buflen ;
  312.     }
  313.         
  314.     return;
  315. }
  316.