home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / PACKER / GTAK258 / RMT / rmt_tape.c < prev    next >
C/C++ Source or Header  |  1996-06-12  |  9KB  |  470 lines

  1. /*****************************************************************************
  2.  * $Id: rmt_tape.c,v 1.20 1996/06/12 16:44:38 ak Exp $
  3.  *****************************************************************************
  4.  * $Log: rmt_tape.c,v $
  5.  * Revision 1.20  1996/06/12 16:44:38  ak
  6.  * Must not flush in rmtseek(tell).
  7.  *
  8.  * Revision 1.19  1996/06/03 01:52:42  ak
  9.  * Use QFA to rewind to beginning of volume.
  10.  * Fixed seek mode=1 and relative blocks.
  11.  *
  12.  * Revision 1.18  1996/06/03 00:33:48  ak
  13.  * Fix seek(,,0).
  14.  *
  15.  * Revision 1.17  1995/07/20 22:58:48  ak
  16.  * VACPP 3.0.
  17.  *
  18.  * Revision 1.16  1994/11/11  22:16:05  ak
  19.  * *** empty log message ***
  20.  *
  21.  * Revision 1.15  1994/08/12  10:26:34  ak
  22.  * .
  23.  *
  24.  * Revision 1.14  1994/08/12 10:15:43  ak
  25.  * Handle RecoveredData sense codes produced by Cipher devices.
  26.  *
  27.  * Revision 1.13  1994/08/03 10:27:40  ak
  28.  * Added option for retry, as undocumented hidden magic.
  29.  *
  30.  * Revision 1.12  1994/07/06 21:19:34  ak
  31.  * Bugfix.
  32.  *
  33.  * Revision 1.11  1994/06/02 13:40:31  ak
  34.  * Stop reading when a filemark is encountered.
  35.  *
  36.  * Revision 1.10  1994/02/16 15:29:20  edvkai
  37.  * Dummy checkin for CVS 1.3 crlf.
  38.  *
  39.  * Revision 1.9  1993/12/14 21:55:34  ak
  40.  * Bugfix. Partition number must be -1 (no change).
  41.  *
  42.  * Revision 1.8  1993/11/29  16:59:25  edvkai
  43.  * *** empty log message ***
  44.  *
  45.  * Revision 1.7  1993/11/26  21:59:37  edvkai
  46.  * Added "rewind" for relative multi-volume QFA.
  47.  *
  48.  * Revision 1.6  1993/11/25  18:54:01  edvkai
  49.  * Removed DLL import by number.
  50.  * Changed return codes to avoid ambiguities.
  51.  * Changed lseek into seek, parameter changes.
  52.  *
  53.  * Revision 1.3  1993/04/26  14:49:29  AK
  54.  * AIX.
  55.  *
  56.  * Revision 1.2  1993/02/10  13:41:56  AK
  57.  * Check for write-protected tapes.
  58.  * Flag '+' for append to EOT.
  59.  *
  60.  * Revision 1.1.1.1  1993/02/08  21:32:17  AK
  61.  * TAR device interface DLLs.
  62.  *
  63.  * Revision 1.1  1993/02/08  21:32:15  AK
  64.  * Initial revision
  65.  *
  66.  *****************************************************************************/
  67.  
  68. static char *rcsid = "$Id: rmt_tape.c,v 1.20 1996/06/12 16:44:38 ak Exp $";
  69.  
  70. /*
  71.  *    rmt_tape.c
  72.  *
  73.  * Tape interface for GNU tar.
  74.  */
  75.  
  76. #include <stdio.h>
  77. #include <stdlib.h>
  78. #include <fcntl.h>
  79. #include <errno.h>
  80.  
  81. #include "scsi.h"
  82. #include "tape.h"
  83. #include "errtab.h"
  84.  
  85. #ifndef __IBMC__
  86. # define _System
  87. #endif
  88.  
  89. extern FILE *msg_file;
  90.  
  91. static int    tape_no        = 0;
  92. static long    tapeblock    = -1;
  93. static long    last_error    = 0;
  94.  
  95. static int    retry;
  96. static int    wrflag;
  97. static int    filemark;
  98. static long    initial;
  99.  
  100. #define Retries    5
  101. #define Trace    0
  102.  
  103. int _System
  104. rmt_open(char *name, int mode, int prot)
  105. {
  106.     long r;
  107.     int eot = 0;
  108.  
  109. #if Trace
  110.     printf("rmt_open(\"%s\", 0x%X, 0%o)\n", name, mode, prot);
  111. #endif
  112.  
  113.     filemark = wrflag = retry = 0;
  114.  
  115.     if (*name == '+') {
  116.         ++name;
  117.         eot = 1;
  118.     }
  119.     if (*name == '!') {
  120.         ++name;
  121.         retry = 1;
  122.     }
  123.  
  124.     if ((r = tape_open(name)) != 0) {
  125.         last_error = r;
  126.         return -2;
  127.     }
  128.  
  129.     tape_ready();        /* skip "Cartridge Changed" */
  130.     r = tape_ready();
  131.     if (!r)
  132.         r = tape_get_blocksize(&tapeblock);
  133.     if (r) {
  134.         last_error = r;
  135.         return -2;
  136.     }
  137.  
  138.     if (++tape_no == 1)
  139.         switch (mode & 3) {
  140.         case O_RDWR:
  141.             /* remember current position */
  142.             tape_tell(&initial, NULL);
  143.         case O_WRONLY:
  144.             r = tape_writable();
  145.             if (r) {
  146.                 last_error = r;
  147.                 return -2;
  148.             }
  149.             if (eot)
  150.                 tape_space(TapeSpace_LogEndOfMedia, 0L, NULL);
  151.         }
  152.     else
  153.         tape_rewind(0);
  154.  
  155.     return 0;
  156. }
  157.  
  158. long
  159. repeat(long _System fcn (void _far *, long, long *), long *actual, long r,
  160.     char *p, unsigned len)
  161. {
  162.     int n;
  163.     long actual2 = *actual, r2 = r;
  164.  
  165.     if (actual2 == TapeUndefLength) {
  166.         printf(">>> RETRY NOT POSSIBLE\n");
  167.         return r;
  168.     }
  169.  
  170.     for (n = 1; n <= Retries; ++n) {
  171.         p += actual2;
  172.         len -= actual2;
  173.         if (len == 0)
  174.             return *actual;
  175.  
  176.         printf(">>> RETRY #%d: %s\n", n, tape_status(r2));
  177.  
  178.         r2 = fcn(p, len, &actual2);
  179.         if (actual2 == TapeUndefLength)
  180.             return r2;
  181.         *actual += actual2;
  182.     }
  183.     return r;
  184. }
  185.  
  186. int _System
  187. rmt_read(int fd, void *p, unsigned len)
  188. {
  189.     long actual = TapeUndefLength, r = 0;
  190.  
  191. #if Trace
  192.     printf("rmt_read(, %p, %u)\n", p, len);
  193. #endif
  194.  
  195.     if (filemark)
  196.         return 0;
  197.  
  198.     r = tape_read(p, len, &actual);
  199.     if (ErrorClass(r) == ErrclDeviceError
  200.      && ErrorType(r) == ErrtySenseByte
  201.      && (ErrorCode(r) & 0x0F) == RecoveredData) {
  202.          /* Cipher */
  203.         if (actual == TapeUndefLength)
  204.             actual = len;
  205.         if (r & 0xF0)
  206.             r &= ~0x0F;
  207.         else
  208.             r = 0;
  209.     }
  210.     if (r && retry)
  211.         r = repeat(tape_read, &actual, r, p, len);
  212.     if (actual == TapeUndefLength)
  213.         actual = 0;
  214.  
  215.     if (r) {
  216.         last_error = r;
  217.         if (ErrorClass(r) == ErrclDeviceError
  218.          && ErrorType(r) == ErrtySenseByte) {
  219.             if (r & FM)
  220.                 filemark = 1;
  221.             if (ErrorCode(r) == MediaOverflow)
  222.                 return -3;
  223.             if (ErrorCode(r) == FM+NoSense)
  224.                 return actual;
  225.         }
  226.         if (actual == 0)
  227.             return -2;
  228.     }
  229.     return actual;
  230. }
  231.  
  232. int _System
  233. rmt_write(int fd, void *p, unsigned len)
  234. {
  235.     long actual = TapeUndefLength, r = 0;
  236.  
  237. #if Trace
  238.     printf("rmt_write(, %p, %u)\n", p, len);
  239. #endif
  240.  
  241.     wrflag = 1;
  242.  
  243.     r = tape_write(p, len, &actual);
  244.     if (ErrorClass(r) == ErrclDeviceError
  245.      && ErrorType(r) == ErrtySenseByte
  246.      && (ErrorCode(r) & 0x0F) == RecoveredData) {
  247.          /* Cipher */
  248.         if (actual == TapeUndefLength)
  249.             actual = len;
  250.         if (r & 0xF0)
  251.             r &= ~0x0F;
  252.         else
  253.             r = 0;
  254.     }
  255.     if (r && retry)
  256.         r = repeat(tape_write, &actual, r, p, len);
  257.     if (actual == TapeUndefLength)
  258.         actual = 0;
  259.     if (r) {
  260.         last_error = r;
  261.         if (r == ErrclDeviceError+ErrtySenseByte+MediaOverflow)
  262.             return -3;
  263.         if (actual == 0)
  264.             return -2;
  265.     }
  266.     return actual;
  267. }
  268.  
  269. static long
  270. flush(void)
  271. {
  272.     if (wrflag) {
  273.     long r;
  274.  
  275.     wrflag = 0;
  276.     r = tape_filemark(0, 1L, NULL);
  277.     if (r) {
  278.         last_error = r;
  279.         return -2;
  280.     }
  281.     filemark = 1;
  282.     }
  283.     return 0;
  284. }
  285.  
  286. long _System
  287. rmt_seek(int fd, long block, long blocksz, int mode)
  288. {
  289.     /* used:    0/1/2    -> standard lseek, return code 0
  290.             3    -> physical block, return code 0
  291.             4    -> return current phys block
  292.             5    -> rewind tape
  293.             logical block is TAR block, not tape block
  294.     */
  295.     long r, actual;
  296.  
  297. #if Trace
  298.     printf("rmt_seek(, %ld, %ld, %d)\n", block, blocksz, mode);
  299. #endif
  300.  
  301.     switch (mode) {
  302.     case 5:
  303.         if (flush())
  304.             return -2;
  305.         filemark = 0;
  306.         r = tape_rewind(0);
  307.         if (r) {
  308.             last_error = r;
  309.             return -2;
  310.         }
  311.         return 0;
  312.     case 4:
  313.         r = tape_tell(&actual, NULL);
  314.         if (r) {
  315.             last_error = r;
  316.             return -2;
  317.         }
  318.         return actual;
  319.     case 3:
  320.         if (flush())
  321.             return -2;
  322.         filemark = 0;
  323.         /* physical block, direct seek required */
  324.         r = tape_seek(0, block, -1);
  325.         if (r) {
  326.             last_error = r;
  327.             return -2;
  328.         }
  329.         return 0;
  330.     case 2:
  331.         if (flush())
  332.             return -2;
  333.         if (!filemark)
  334.             r = tape_space(TapeSpace_Filemarks, 1L, &actual);
  335.         filemark = 0;
  336.         break;
  337.     case 1:
  338.         if (flush())
  339.             return -2;
  340.         if (filemark) {
  341.             /* beyond filemark at end of volume, skip reverse */
  342.             r = tape_space(TapeSpace_Filemarks, -1L, &actual);
  343.             if (r && actual != -1)
  344.             break;
  345.             filemark = 0;
  346.         } else
  347.             r = 0;
  348.         break;
  349.     case 0:
  350.         if (flush())
  351.             return -2;
  352.         if (initial != TapeUndefLength) {
  353.             /* QFA position of beginning of volume available */
  354.             r = tape_seek(0, initial, -1);
  355.             filemark = 0;
  356.         } else {
  357.             /* no QFA available, use filemark skips */
  358.             if (filemark) {
  359.             /* beyond filemark at end of volume, skip reverse */
  360.             r = tape_space(TapeSpace_Filemarks, -1L, &actual);
  361.             if (r && actual != -1)
  362.                 break;
  363.             filemark = 0;
  364.             }
  365.  
  366.             /* find the filemark at beginning of volume */
  367.             r = tape_space(TapeSpace_Filemarks, -1L, &actual);
  368.  
  369.             if (actual == -1) {
  370.             /* really found a filemark, skip forward */
  371.             r = tape_space(TapeSpace_Filemarks, 1L, &actual);
  372.             } else if (r == ErrclDeviceError+ErrtySenseByte+EOM+NoSense) {
  373.             /* we hit BOT instead, accept */
  374.             r = 0;
  375.             }
  376.         }
  377.         break;
  378.     default:
  379.         return -4;
  380.     }
  381.     if (block && !r) {
  382.         if (tapeblock)
  383.             block *= blocksz / tapeblock;
  384.         r = tape_space(TapeSpace_Blocks, block, &actual);
  385.         if (r == ErrclDeviceError+ErrtySenseByte+EOM+NoSense
  386.          || r == ErrclDeviceError+ErrtySenseByte+FM+NoSense)
  387.             r = 0;
  388.     }
  389.  
  390. #if Trace
  391.     if (tape_tell(&actual, NULL) == 0)
  392.         printf("    result position is %ld\n", actual);
  393. #endif
  394.  
  395.     if (!r)
  396.         return 0;
  397.     last_error = r;
  398.     return -2;
  399. }
  400.  
  401. int _System
  402. rmt_close(int fd)
  403. {
  404.     long r = 0;
  405.  
  406. #if Trace
  407.     printf("rmt_close(,)\n");
  408. #endif
  409.  
  410.     if (flush()) {
  411.         r = last_error;
  412.         tape_close();
  413.     } else
  414.         r = tape_close();
  415.     if (!r)
  416.         return 0;
  417.     last_error = r;
  418.     return -2;
  419. }
  420.  
  421. int _System
  422. rmt_ioctl(int fd, int code, void *arg)
  423. {
  424.     return -4;
  425. }
  426.  
  427. int _System
  428. rmt_block(int fd)
  429. {
  430.     return tapeblock;
  431. }
  432.  
  433. long _System
  434. rmt_error(void)
  435. {
  436.     return last_error;
  437. }
  438.  
  439. char * _System
  440. rmt_status(long rcode)
  441. {
  442.     return tape_status(rcode);
  443. }
  444.  
  445. #if defined(__EMX__)
  446.  
  447. unsigned long
  448. _DLL_InitTerm(unsigned long mod_handle, unsigned long flag)
  449. {
  450.     if (!flag) {
  451.         _CRT_init();
  452.     } else {
  453.         _CRT_term();
  454.     }
  455.     return 1;
  456. }
  457.  
  458. #elif defined(unix)
  459.  
  460. int
  461. rmt_startup(void)
  462. {
  463.     tape_no = 0;
  464.     tapeblock = 512;
  465.     last_error;
  466.     return 0;
  467. }
  468.  
  469. #endif
  470.