home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / os2 / gtak / source / 1.10 / ak_tape.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-12  |  6.7 KB  |  329 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 (!f_here
  187.                             && tape_space(SpaceLogEndOfMedia, 0L, NULL) != 0)
  188.                           fprintf(msg_file, "Seek to end of tape failed\n");
  189.             break;
  190.         case O_RDWR:
  191.             errno = EINVAL;
  192.             return -1;
  193.         }
  194.     else
  195.         tape_rewind(0);
  196.  
  197.     return bias;
  198. }
  199.  
  200. int
  201. __rmt_read(int fd, void *p, unsigned len)
  202. {
  203.       long actual = 0, chunk, real;
  204.       int r = 0;
  205.       char *cp = p;
  206.       
  207.     while (len) {
  208.         chunk = (len > 32768) ? 32768 : len;
  209.         r = tape_read(cp, chunk, &real);
  210.         if (actual != TapeUndefLength)
  211.             actual += real;
  212.         if (r < 0 || real != chunk)
  213.               break;
  214.         cp  += chunk;
  215.         len -= chunk;
  216.     }
  217.     if (r <= 0) {
  218.         if (r == SenseKey+MediaOverflow || r == MappedError+0x32) {
  219.             errcode = r;
  220.             errno = ENOSPC;
  221.             return -1;
  222.         }
  223.         if (r < 0 && r != EndOfTape)
  224.             return error(r);
  225.     }
  226.     return r ? r : actual;
  227. }
  228.  
  229. int
  230. __rmt_write(int fd, void *p, unsigned len)
  231. {
  232.     long actual = 0, chunk, real;
  233.     int r = 0;
  234.     char *cp = p;
  235.  
  236.     while (len) {
  237.         chunk = (len > 32768) ? 32768 : len;
  238.         r = tape_write(cp, chunk, &real);
  239.         if (actual != TapeUndefLength)
  240.             actual += real;
  241.         if (r < 0 || real != chunk)
  242.              break;
  243.         cp  += chunk;
  244.         len -= chunk;
  245.     }
  246.     if (r <= 0) {
  247.         if (r == SenseKey+MediaOverflow || r == MappedError+0x32) {
  248.             errcode = r;
  249.             errno = ENOSPC;
  250.             return -1;
  251.         }
  252.         if (r < 0)
  253.             return error(r);
  254.     }
  255.     return r ? r : actual;
  256. }
  257.  
  258. long
  259. __rmt_lseek(int fd, long offs, int mode)
  260. {
  261.     /* used:    offs, 0/1/2    -> standard lseek, return code 0
  262.             offs, 3        -> physical block, return code 0
  263.             0, 4        -> return current phys block
  264.     */
  265.     long r, actual;
  266.  
  267.     offs /= tapeblock;
  268.  
  269.     switch (mode) {
  270.     case 4:
  271.         r = tape_tell();
  272.         if (r < 0)
  273.             return error(r);
  274.         return r;
  275.     case 3:
  276.         /* physical block, direct seek required */
  277.         r = tape_seek(0, offs);
  278.         if (r < 0)
  279.             return error(r);
  280.         return 0;
  281.     case 2:
  282.         r = tape_space(SpaceFileMarks, 1L, &actual);
  283.         tape_space(SpaceFileMarks, -1L, &actual);
  284.         break;
  285.     case 1:
  286.         r = 0;
  287.         break;
  288.     case 0:
  289.         r = tape_space(SpaceFileMarks, -1L, &actual);
  290.         tape_space(SpaceFileMarks, 1L, &actual);
  291.         break;
  292.     default:
  293.         errno = EINVAL;
  294.         return -1;
  295.     }
  296.     if (r != 0 && r != EndOfTape)
  297.         return error(r);
  298.     if (offs) {
  299.         r = tape_space(SpaceBlocks, offs, &actual);
  300.         if (r)
  301.             return error(r);
  302.     }
  303.     return 0;
  304. }
  305.  
  306. int
  307. __rmt_close(int fd)
  308. {
  309.     int r = 0;
  310.  
  311. #ifdef OS2
  312.     if (disk > 1) {
  313.         BYTE cmd = 0;
  314.         ULONG ulParmLengthInOut = sizeof(cmd), 
  315.               ulDataLengthInOut = 0;
  316.         DosDevIOCtl(handle, IOCTL_DISK, DSK_UNLOCKDRIVE, 
  317.                 &cmd, sizeof(cmd), &ulParmLengthInOut,
  318.                 0, 0, &ulDataLengthInOut);
  319.     } else if (wrflag && !disk) {
  320.         r = tape_filemark(0, 1L, NULL);
  321.         if (r < 0)
  322.             r = error(r);
  323.     }
  324. #endif
  325.     tape_term();
  326.     wrflag = 0;
  327.     return r;
  328. }
  329.