home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / g / gtak212.zip / 1.10 / ak_tape.c < prev    next >
C/C++ Source or Header  |  1993-02-02  |  7KB  |  328 lines

  1. /*****************************************************************************
  2.  * $Id: ak_tape.c,v 1.4 1993/01/27 08:04:16 ak Exp $
  3.  *****************************************************************************
  4.  * $Log: ak_tape.c,v $
  5.  * Revision 1.4  1993/01/27  08:04:16  ak
  6.  * Fix for variable length tape blocks (HP DAT).
  7.  *
  8.  * Revision 1.3  1992/09/26  09:25:11  ak
  9.  * *** empty log message ***
  10.  *
  11.  * Revision 1.2  1992/09/12  15:57:11  ak
  12.  * - Usenet patches for GNU TAR 1.10
  13.  * - Bugfixes and patches of Kai Uwe Rommel:
  14.  *         filename conversion for FAT
  15.  *         EMX 0.8e
  16.  *         -0..1 alias for a: b:
  17.  *         -2..7 alias for +++TAPE$x
  18.  *
  19.  * Revision 1.1  1992/09/02  20:07:43  ak
  20.  * Initial revision
  21.  *
  22.  * Revision 1.1.1.1  1992/01/06  20:41:35  ak
  23.  * -Y = don't recurse: new.
  24.  * -X = exclude list: for extract.
  25.  * Use BUFFER for OS/2 tape compression.
  26.  * No own tape buffering for OS/2.
  27.  * Support for SYSTEM and HIDDEN files.
  28.  *
  29.  * Revision 1.1  1992/01/06  20:41:34  ak
  30.  * Initial revision
  31.  *
  32.  *****************************************************************************/
  33.  
  34. static char *rcsid = "$Id: ak_tape.c,v 1.4 1993/01/27 08:04:16 ak Exp $";
  35.  
  36. /*
  37.  *    tape_io.c
  38.  *
  39.  * Tape interface for GNU tar.
  40.  * Use "Remote Tape Interface".
  41.  */
  42.  
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <errno.h>
  46. #include <fcntl.h>
  47. #include <limits.h>
  48. #include <sys/types.h>
  49. #include <ctype.h>
  50. #if defined(OS2)
  51. # define INCL_DOSFILEMGR
  52. # define INCL_DOSDEVICES
  53. # define INCL_DOSDEVIOCTL
  54. # define _Packed
  55. # include <os2.h>
  56. #elif defined(MSDOS)
  57. # include <dos.h>
  58. #else
  59.   typedef unsigned char BYTE;
  60.   typedef unsigned long ULONG;
  61. #endif
  62.  
  63. #include "tar.h"
  64. #include "port.h"
  65. #include "rmt.h"
  66.  
  67. #define _far
  68. #include "scsi.h"
  69. #include "tape.h"
  70.  
  71. extern FILE *msg_file;
  72. char *__rmt_path;
  73.  
  74. static int    errcode;
  75. static int    wrflag;
  76. static int    tape_no = 0;
  77. long        tapeblock = 512;
  78.  
  79. #ifdef OS2
  80. static HFILE    handle;
  81. static ULONG    disk = 0;
  82. #endif
  83.  
  84. static int
  85. error(int code)
  86. {
  87.     errcode = code;
  88.     errno = EIO;
  89.     return -1;
  90. }
  91.  
  92. #undef perror
  93.  
  94. void
  95. my_perror(const char *msg)
  96. {
  97.     if (errno >= 2000) {
  98.         if (msg)
  99.             fprintf(msg_file, "%s: ", msg);
  100.         switch (errno) {
  101.         case EINVAL:
  102.             fprintf(msg_file, "invalid operation\n");
  103.             break;
  104.         case ENOSPC:
  105.             fprintf(msg_file, "reached end of tape\n");
  106.             break;
  107.         case EIO:
  108.             fprintf(msg_file, "tape error\n");
  109.             if (errcode)
  110.                 tape_print_sense(msg_file, errcode);
  111.             break;
  112.         }
  113.     } else
  114.         perror(msg);
  115. }
  116.  
  117. int
  118. __rmt_open(char *name, int mode, int prot, int bias)
  119. {
  120.     int r, unit;
  121.     char *cp;
  122.     extern int map_read;
  123.  
  124. #ifdef OS2
  125.     ULONG    action;
  126.  
  127.     if (disk = _isdisk(name)) {
  128.         disk += ((mode & 3) != O_RDONLY);
  129.     } else
  130.         while (*name == '+')
  131.             ++name;
  132.     r = DosOpen((PSZ)name, &handle, &action, 0L, 0, FILE_OPEN,
  133.         ((mode & 3) == O_RDONLY ? OPEN_SHARE_DENYNONE 
  134.                                 : OPEN_SHARE_DENYREADWRITE)
  135.         + OPEN_FLAGS_FAIL_ON_ERROR
  136.         + (disk ? OPEN_FLAGS_DASD : 0)
  137.         + (mode & 3), 0);
  138.     if (r) {
  139.         errno = EINVAL;
  140.         return -1;
  141.     }
  142.     if (disk) {
  143.             if (disk > 1) {
  144.                 BYTE cmd = 0;
  145.             ULONG ulParmLengthInOut = sizeof(cmd), 
  146.                   ulDataLengthInOut = 0;
  147.             DosDevIOCtl(handle, IOCTL_DISK, DSK_LOCKDRIVE, 
  148.                     &cmd, sizeof(cmd), &ulParmLengthInOut,
  149.                     0, 0, &ulDataLengthInOut);
  150.         }
  151.         return handle;
  152.     }
  153.     bias += handle;
  154. #endif
  155.  
  156.     unit = -1;
  157.     for (cp = name; *cp; ++cp)
  158.         if (isdigit(*cp))
  159.             unit = *cp - '0';
  160.  
  161. #ifdef unix
  162.     tape_init();
  163. #else
  164.     tape_file(handle);
  165.     if (unit >= 0)
  166.         tape_target(unit);
  167. #endif
  168.     tape_ready();        /* skip "Cartridge Changed" */
  169.     r = tape_ready();
  170.     if (r != 0) {
  171.         fprintf(msg_file, "Tape not ready\n");
  172.         tape_print_sense(msg_file, r);
  173.         exit(EX_SYSTEM);
  174.     }
  175.  
  176.     tapeblock = tape_get_blocksize();
  177.     if (tapeblock == 0)
  178.         tapeblock = blocksize;
  179.  
  180.     if (++tape_no == 1)
  181.         switch (mode & 3) {
  182.         case O_RDONLY:
  183.             break;
  184.         case O_WRONLY:
  185.             wrflag = 1;
  186.             if (tape_space(SpaceLogEndOfMedia, 0L, NULL) != 0)
  187.                 fprintf(msg_file, "Seek to end of tape failed\n");
  188.             break;
  189.         case O_RDWR:
  190.             errno = EINVAL;
  191.             return -1;
  192.         }
  193.     else
  194.         tape_rewind(0);
  195.  
  196.     return bias;
  197. }
  198.  
  199. int
  200. __rmt_read(int fd, void *p, unsigned len)
  201. {
  202.       long actual = 0, chunk, real;
  203.       int r = 0;
  204.       char *cp = p;
  205.       
  206.     while (len) {
  207.         chunk = (len > 32768) ? 32768 : len;
  208.         r = tape_read(cp, chunk, &real);
  209.         if (actual != TapeUndefLength)
  210.             actual += real;
  211.         if (r < 0 || real != chunk)
  212.               break;
  213.         cp  += chunk;
  214.         len -= chunk;
  215.     }
  216.     if (r <= 0) {
  217.         if (r == SenseKey+MediaOverflow || r == MappedError+0x32) {
  218.             errcode = r;
  219.             errno = ENOSPC;
  220.             return -1;
  221.         }
  222.         if (r < 0 && r != EndOfTape)
  223.             return error(r);
  224.     }
  225.     return r ? r : actual;
  226. }
  227.  
  228. int
  229. __rmt_write(int fd, void *p, unsigned len)
  230. {
  231.     long actual = 0, chunk, real;
  232.     int r = 0;
  233.     char *cp = p;
  234.  
  235.     while (len) {
  236.         chunk = (len > 32768) ? 32768 : len;
  237.         r = tape_write(cp, chunk, &real);
  238.         if (actual != TapeUndefLength)
  239.             actual += real;
  240.         if (r < 0 || real != chunk)
  241.              break;
  242.         cp  += chunk;
  243.         len -= chunk;
  244.     }
  245.     if (r <= 0) {
  246.         if (r == SenseKey+MediaOverflow || r == MappedError+0x32) {
  247.             errcode = r;
  248.             errno = ENOSPC;
  249.             return -1;
  250.         }
  251.         if (r < 0)
  252.             return error(r);
  253.     }
  254.     return r ? r : actual;
  255. }
  256.  
  257. long
  258. __rmt_lseek(int fd, long offs, int mode)
  259. {
  260.     /* used:    offs, 0/1/2    -> standard lseek, return code 0
  261.             offs, 3        -> physical block, return code 0
  262.             0, 4        -> return current phys block
  263.     */
  264.     long r, actual;
  265.  
  266.     offs /= tapeblock;
  267.  
  268.     switch (mode) {
  269.     case 4:
  270.         r = tape_tell();
  271.         if (r < 0)
  272.             return error(r);
  273.         return r;
  274.     case 3:
  275.         /* physical block, direct seek required */
  276.         r = tape_seek(0, offs);
  277.         if (r < 0)
  278.             return error(r);
  279.         return 0;
  280.     case 2:
  281.         r = tape_space(SpaceFileMarks, 1L, &actual);
  282.         tape_space(SpaceFileMarks, -1L, &actual);
  283.         break;
  284.     case 1:
  285.         r = 0;
  286.         break;
  287.     case 0:
  288.         r = tape_space(SpaceFileMarks, -1L, &actual);
  289.         tape_space(SpaceFileMarks, 1L, &actual);
  290.         break;
  291.     default:
  292.         errno = EINVAL;
  293.         return -1;
  294.     }
  295.     if (r != 0 && r != EndOfTape)
  296.         return error(r);
  297.     if (offs) {
  298.         r = tape_space(SpaceBlocks, offs, &actual);
  299.         if (r)
  300.             return error(r);
  301.     }
  302.     return 0;
  303. }
  304.  
  305. int
  306. __rmt_close(int fd)
  307. {
  308.     int r = 0;
  309.  
  310. #ifdef OS2
  311.     if (disk > 1) {
  312.         BYTE cmd = 0;
  313.         ULONG ulParmLengthInOut = sizeof(cmd), 
  314.               ulDataLengthInOut = 0;
  315.         DosDevIOCtl(handle, IOCTL_DISK, DSK_UNLOCKDRIVE, 
  316.                 &cmd, sizeof(cmd), &ulParmLengthInOut,
  317.                 0, 0, &ulDataLengthInOut);
  318.     } else if (wrflag && !disk) {
  319.         r = tape_filemark(0, 1L, NULL);
  320.         if (r < 0)
  321.             r = error(r);
  322.     }
  323. #endif
  324.     tape_term();
  325.     wrflag = 0;
  326.     return r;
  327. }
  328.