home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume8 / mdcopy / part01 / mdcopy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-02  |  5.3 KB  |  252 lines

  1. /*
  2.  * mdcopy    copy a file to/from multiple diskettes.
  3.  *
  4.  * This is a sample program used to illustrate the multi-disk i/o
  5.  * (mdio) package.  The prompt routines are used to check for the
  6.  * continuation of a file.  These are guaranteed to be called
  7.  * after no more bytes can be transferred to/from a file.
  8.  *
  9.  * When writing a file, after a diskette is full, the file is closed
  10.  * and the `output' prompt routine is called.  This creates an empty
  11.  * file with an extension of .TBC (to-be-continued), and asks for the
  12.  * next diskette.
  13.  *
  14.  * When reading a file, at EOF, the `at eof' function is called.
  15.  * This looks for a file with a .TBC extension, and if found returns
  16.  * FALSE since we are not really at EOF.  If this file is NOT found
  17.  * then we are really at EOF, so TRUE is returned.
  18.  *
  19.  * After the input file is closed, the `input' prompt routine is
  20.  * called which asks the user to insert the next diskette for the file.
  21.  *
  22.  * Note:  using an extension can be ambiguous, but this is only a
  23.  *        sample program.
  24.  *
  25.  * March 1989    created by greg yachuk.  placed in the public domain.
  26.  */
  27. #include <stdio.h>
  28. #include <malloc.h>
  29. #include <string.h>
  30. #include <fcntl.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #include <dos.h>
  34.  
  35. #include "mdiskio.h"
  36.  
  37. /* these two guys are global for debugging purposes */
  38. MDFILE *ip, *op;
  39.  
  40. main(argc, argv)
  41. int    argc;
  42. char  **argv;
  43. {
  44.     char   *fname;
  45.     int    diridx;
  46.     struct find_t buffer;
  47.  
  48.     if (argc < 2 || argc > 3)
  49.         usage();
  50.  
  51.     if (_dos_findfirst(argv[1], _A_NORMAL|_A_RDONLY, &buffer))
  52.     {
  53.         fprintf(stderr, "%s: no match\n", argv[1]);
  54.         exit(1);
  55.     }
  56.  
  57.     fname = argv[1] - 1;
  58.     do
  59.     {
  60.         diridx = strcspn(fname+1, "/\\:");
  61.         fname += diridx + 1;
  62.     } while (*fname);
  63.  
  64.     fname -= diridx;
  65.     *fname = '\0';
  66.  
  67.     do
  68.     {
  69.         mdcopy(argv[1], buffer.name, argc == 3 ? argv[2] : buffer.name);
  70.     }
  71.     while (_dos_findnext(&buffer) == 0);
  72.  
  73.     exit(0);
  74. }
  75.  
  76. mdcopy(srcdir, srcfile, dstfile)
  77. char   *srcdir;
  78. char   *srcfile;
  79. char   *dstfile;
  80. {
  81.     char    buf[BUFSIZ];
  82.     int    len;
  83.     int    inprompt();
  84.     int    ateof();
  85.     int    outprompt();
  86.  
  87.     strcpy(buf, srcdir);
  88.     strcat(buf, "/");
  89.     strcat(buf, srcfile);
  90.  
  91.     if ((ip = mdopen(buf, "rb", NULL, 0)) == NULL)
  92.     {
  93.         perror(buf);
  94.         exit(2);
  95.     }
  96.  
  97.     if ((op = mdopen(dstfile, "wb", NULL, 0)) == NULL)
  98.     {
  99.         perror(dstfile);
  100.         exit(3);
  101.     }
  102.  
  103.     /* set buffer sizes to 16K each */
  104.  
  105.     mdsetbuf(ip, 16*1024);
  106.     mdsetbuf(op, 16*1024);
  107.  
  108.     /* override the default "prompt" routines */
  109.  
  110.     mdfnateof(ip, ateof);
  111.     mdfnprompt(ip, inprompt);
  112.     mdfnprompt(op, outprompt);
  113.  
  114.     /* and copy away... */
  115. #ifdef    PROFILE
  116.     PRFstart((long far *) main);
  117. #endif
  118.     while (!mdeof(ip))
  119.     {
  120.         len = mdread(buf, sizeof (char), sizeof buf, ip);
  121.         if (mdwrite(buf, sizeof (char), len, op) != len)
  122.             break;
  123.     }
  124. #ifdef    PROFILE
  125.     PRFstop();
  126. #endif
  127.     /* alternative copy... */
  128.  
  129.     while (!mdeof(ip) && !mdeof(op))
  130.         mdputc(mdgetc(ip), op);
  131.  
  132.     /* gotta make sure we close, cause this flushes the buffers */
  133.  
  134.     mdclose(ip);
  135.     mdclose(op);
  136. }
  137.  
  138. /*
  139.  * usage -    display the usage message and exit
  140.  */
  141. usage()
  142. {
  143.     puts("usage: mdcopy srcfile dstfile");
  144.     puts("       mdcopy srcfiles dstdir");
  145.     exit(1);
  146. }
  147.  
  148. /*
  149.  * contfnm -    construct the name of the `to-be-continued' marker file.
  150.  *        this is constructed from the basename with an extension
  151.  *        of `tbc' (to-be-continued).
  152.  */
  153. char   *
  154. contfnm(mdp)
  155. MDFILE *mdp;
  156. {
  157.     static char contfile[256];
  158.     char   *base;
  159.     char   *dotp;
  160.  
  161.     /* copy the basename */
  162.     strcpy(contfile, mdp->basename);
  163.  
  164.     /* strip off the drive and path from the tail */
  165.     if ((base = strrchr(contfile, '/')) == NULL)
  166.         base = contfile;
  167. #ifdef    DOS
  168.     /* this is DOS, y'know.  it allows both / and \ */
  169.     if ((dotp = strrchr(base, '\\')) == NULL)
  170.         dotp = base;
  171. #endif
  172.     /* scan for the '.' */
  173.     for (; *dotp && *dotp != '.'; ++dotp);
  174.  
  175.     /* and add the new extension */
  176.     *dotp++ = '.';
  177.     *dotp++ = 't';
  178.     *dotp++ = 'b';
  179.     *dotp++ = 'c';
  180.     *dotp = '\0';
  181.  
  182.     return (contfile);
  183. }
  184.  
  185. /*
  186.  * ateof -    this routine is called when EOF is reached while
  187.  *        reading the input file.  We check if we need to
  188.  *        ask for a new diskette, by checking for the existence
  189.  *        of a `.tbc' (to-be-continued) file.
  190.  */
  191. ateof(mdp, mode)
  192. MDFILE *mdp;
  193. int    mode;
  194. {
  195.     return (access(contfnm(mdp), 00));
  196. }
  197.  
  198. /*
  199.  * inprompt -    this routine is called when EOF of a diskette is
  200.  *        found, but there is supposed to be another diskette.
  201.  *        it prompts for the next diskette and waits for the
  202.  *        user to enter a carriage-return.
  203.  */
  204. inprompt(mdp)
  205. MDFILE *mdp;
  206. {
  207.     /* ask for another diskette, and wait for a response */
  208.     fputs("Please insert next diskette for ", stderr);
  209.     fputs(mdp->basename, stderr);
  210.     fputs(" and press ENTER...", stderr);
  211.  
  212.     while (getchar() != '\n');
  213.  
  214.     /* all ready to go with the next diskette */
  215.  
  216.     return (1);
  217. }
  218.  
  219. /*
  220.  * outprompt -    this routine is called when no more bytes can be
  221.  *        written to a file.  we create a `.tbc' (to-be-
  222.  *        continued) file on the same diskette.  Luckily,
  223.  *        DOS still has room to create a file when all the
  224.  *        disk space is gone.  Then ask for a new diskette.
  225.  */
  226. outprompt(mdp)
  227. MDFILE *mdp;
  228. {
  229.     char   *contfile;
  230.     int    fd;
  231.  
  232.     /* get the name of the to-be-continued file */
  233.     contfile = contfnm(mdp);
  234.  
  235.     /* create the to-be-continued file */
  236.     fd = open(contfile, O_CREAT|O_WRONLY, S_IREAD|S_IWRITE);
  237.     if (fd == -1)
  238.     {
  239.         perror(contfile);    /* something drastic went wrong */
  240.         return (0);        /* can't continue this file */
  241.     }
  242.  
  243.     close(fd);
  244.  
  245.     /* ask for another diskette and wait for a response */
  246.     _mdprompt(mdp);
  247.  
  248.     /* all ready to go with next diskette */
  249.  
  250.     return (1);
  251. }
  252.