Logo Search packages:      
Sourcecode: dds2tar version File versions  Download package

dds_tape.c

/*
 * This file is part of dds2tar.
 * Copyright by J"org Weule
 *
 * Special thanks to Les.Grant@mitsuibabcock.co.uk
 * for the HP-UX patch.
 */

#include <stdlib.h>
#include <stdio.h>            /* fpirntf() */
#include <errno.h>            /* perror() */
#include <sys/mtio.h>         /* MTSEEK ... */
#include <sys/ioctl.h>        /* ioctl() */
#include <unistd.h>           /* close() exit() */
#include "dds_tape.h"

#include "dds2tar.h"
#include "dds_tape.h"

/*
 * set scsi2logical
 */
int dds_scsi2logical(void){
      struct mtop p ;
      p.mt_op = MTSETDRVBUFFER ;
      p.mt_count = MT_ST_OPTIONS|MT_ST_SCSI2LOGICAL ;
      fputs("scsi2logical\n",stderr);
      return ioctl(device,MTIOCTOP,&p);
}

/*
 * set read_ahead
 */
int dds_read_ahead(void){
      struct mtop p ;
      int r ;
      p.mt_op = MTSETDRVBUFFER ;
      p.mt_count = MT_ST_OPTIONS|MT_ST_READ_AHEAD ;
      r = ioctl(device,MTIOCTOP,&p);
#ifdef DDS_TRACE
      fputs("read_ahead\n",stderr);
      if ( r < 0 ) perror("Read_ahead");
#endif
      return r ;
}

/*
 * rewind the last block
 */
int dds_bsr(void){
      struct mtop p ;
      p.mt_op = MTBSR ;
      p.mt_count = 1 ;
      return ioctl(device,MTIOCTOP,&p);
}

#ifdef MTGETBLK
/*
 * get block size
 */
int dds_get_bs(void){
      struct mtop p ;
      int r ;
      p.mt_op = MTGETBLK ;
      p.mt_count = 0 ;
      r = ioctl(device,MTSETBLK,&p);
      if ( r >= 0 ) r = p.mt_count ;
      return r ;
}
#endif

/*
 * set block size
 */
int dds_set_bs(int n){
      struct mtop p ;
      p.mt_op = MTSETBLK ;
      p.mt_count = n ;
      tar_bs = n >> 9 ;
      tar_n = n ;
#ifdef DDS_TRACE
      fprintf(stderr,"record_size=%d\n",n);
#endif
      return ioctl(device,MTSETBLK,&p);
}

/*
 * To read one line of the device and check for errors, we use the following
 * code. If a filemark is read, we try the block again.
 *
 * Note that cur_blkno and next_blkno is changed.
 */
void
dds_read_next_block(void)
{
      int     err = 0;

#ifdef HPDAT
      if (next_blkno == -1)
#endif
            next_blkno = dds_getpos(device);
      cur_blkno = next_blkno;
      cur_n = 0;
#ifdef DDS_TRACE
      fprintf(stderr, "begin --> read_next_block()\n");
      fprintf(stderr, "vid=%d \n",vid);
#endif
      if ( vid == HP ) do {
            /* If you write a tape with 'tar -b 256' on SunOS, reading */
            /* the tape needs the following workaround. SunOS splits the */
            /* block into three tape blocks of 65534, 65534 and 4 Bytes. */
            /* dds2tar is reading the tree blocks and the number is */
            /* the one of the first block. You can not use the tar */
            /* listing block is this case, because the calculation of the */
            /* right will fail. Note that 'dds2tar --dds-dd | tar ft -' */
            /* will show the index of the archive, 'tar t' fails. */
            /* */
            /* --dds-dd is in experimental state, so may be I will change */
            /* this. */
#if ( ST_BUFFER_BLOCKS > 32 )
            do {
                  err = read(device, ((char *) cur_block) + cur_n,
                                  buf_n - cur_n);
                  if (err > 0) next_blkno++, cur_n += err;
            } while ((err > 0) && (cur_n < buf_n) && ((cur_n & 0x1ff) != 0));
#else
            err = read(device, cur_block, buf_n);
            if (err > 0) next_blkno++, cur_n += err ;
#endif
            if ((cur_n & 0x1ff) != 0) {
                  fprintf(stderr, "not a tar archive, record size is"
                        " %d bytes \n", cur_n);
                  exit(4);
            }
            /*
             * We are done, if err >= 0.
             */
            if ( err >= 0 ) break ;

            /*
             * If err < 0 ... exit or decrease the buffer ...
             */
            if ((errno != EOVERFLOW) || (buf_n == 1)) {
                  perror("dds2tar");
                  exit(4);
            }
            buf_n >>= 1;
            fprintf(stderr,"decreasing buffer to %d bytes\n",buf_n);
            if (buf_n == 1) exit(4);
      } while ( 1 );
      if ( vid != HP ) {
            err = read(device, cur_block, tar_n);
            if ( err < 0 ) {
                  fprintf(stderr,
                  "Can not read from tape with blocksize of %d.\n",
                  tar_n);
                  perror("dds2index");
                  exit(4);
            }
            next_blkno += tar_bs , cur_n = err ;
            if ((cur_n & 0x1ff) != 0) {
                  fprintf(stderr, "not a tar archive, record size is"
                        " %d bytes \n", cur_n);
                  exit(4);
            }
      }
      cur_bs = cur_n >> 9;
#ifdef DDS_TRACE
      fprintf(stderr, "end ----> read_next_block()\n");
#endif
}

void
dds_read_block(void)
{
      do
            dds_read_next_block();
      while (cur_n == 0);
}

int
dds_getpos(int const dev)
{
      int     i,n;

#ifdef MTIOCPOS
      struct mtpos pos;
      i = ioctl(dev, MTIOCPOS, &pos);
      if (i != 0) {
            perror("dds2tar: ioctl MTIOCPOS");
#else
      i = ioctl(dev, SIOC_GET_POSITION, &n); /* HP-UX */
      if (i != 0) {
            perror("dds2tar: ioctl SIOC_GET_POSITION");
#endif
            close(dev);
            exit(11);
      }
      n = pos.mt_blkno;
      if (n < 0) {
            fprintf(stderr, "dds2tar: eom detected ? blkno = %d \n", n);
            close(dev);
            exit(12);
      }
      return n;
}

#ifdef MTIOCLOC
int
dds_getloc(int const dev)
{
      struct mtpos pos;
      int     i,n;

      i = ioctl(dev, MTIOCPOS, &pos);
      if (i != 0) {
            perror("dds2tar: ioctl MTIOCLOC");
            close(dev);
            exit(11);
      }
      n = pos.mt_blkno;
      if (n < 0) {
            fprintf(stderr, "dds2tar: eom detected ? blkno = %d \n", n);
            close(dev);
            exit(12);
      }
      return n ;
}
#endif

int
dds_has_partitions(int const dev){
#ifdef MT_ISDDS1
      struct mtget p ;
      int i;
      i = ioctl(dev, MTIOCGET, &p );
      if ( i >= 0 ) {
            i = p.mt_type ;
      } else perror("dds2tar");
      /*
      if(i==MT_ISDDS1)fprintf(stderr, "DDS2TAR: drive without partitions\n");
      if(i==MT_ISDDS2)fprintf(stderr, "DDS2TAR: drive with partitions\n");
      fprintf(stderr, "DDS2TAR: type = %x\n",i);
      */
      return i ;
#else
      return -1 ;
#endif
}

int
dds_seek(int const dev, int const blkno)
{
      struct mtop op;
      int     i;

#ifdef SIOC_SET_POSITION
      i = ioctl(dev, SIOC_SET_POSITION, &blkno);
#else
      op.mt_op = MTSEEK;
      op.mt_count = blkno;
      i = ioctl(dev, MTIOCTOP, &op);
#endif
      if (i != 0) {
            perror("ioctl SEEK");
            close(dev);
            exit(13);
      }
      return 0;
}

/*
 * This file is part of dds2tar.
 * Copyright by J"org Weule
 */

#ifdef HPDAT
#include <stdlib.h>           /* malloc() */
#include <stdio.h>            /* printf() */
#include <sys/ioctl.h>        /* ioctl() */
#include <string.h>           /* memset() bcopy() */
#include <unistd.h>           /* exit() */
#include "dds_tape.h"

typedef unsigned char byte;

typedef struct {
      int     inlen;
      int     outlen;
      byte    buf[1024];
}

ioctl_arg;

static void
copy_page(ioctl_arg * const arg, int const i)
{

      static struct {
            char const *const text;
            int const inlen;
            int const outlen;
            byte const buf[32];
      }
      const   comp_page[7] =
      {
            {
                  "set_comp_off", 26, 128,
                  {
                        0x15, 0x10, 0x00, 0x00,
                        0x14, 0x00, 0x00, 0x00,
                        0x10, 0x00, 0x0f, 0x0e,
                        0x40, 0x80, 0x00, 0x00,
                        0x00, 0x20, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00
                  }
            }
            ,
            {
                  "set_cpmp_on", 26, 128,
                  {
                        0x15, 0x10, 0x00, 0x00,
                        0x14, 0x00, 0x00, 0x00,
                        0x10, 0x00, 0x0f, 0x0e,
                        0xc0, 0x80, 0x00, 0x00,
                        0x00, 0x20, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00
                  }
            }
            ,
            {
                  "get_comp", 6, 128,
                  {
                        0x1a, 0x00, 0x0f, 0x00, 0x40, 0x00
                  }
            }
            ,
            {
                  "log_comp", 10, 128,
                  {
                        0x4d, 0x00, 0x79, 0x00,
                        0x00, 0x00, 0x00, 0x00,
                        0x80, 0x00
                  }
            }
            ,
            {
                  "load_tape", 6, 128,
                  {
                        0x1b, 0x00, 0x00, 0x00, 0x01, 0x00
                  }
            }
            ,
            {
                  "unload_tape", 6, 128,
                  {
                        0x1b, 0x00, 0x00, 0x00, 0x00, 0x00
                  }
            }
            ,
            {
                  "mode_sense", 6, 128,
                  {
                        0x1a, 0x00, 0x00, 0x00, 0x0C, 0x00
                  }
            }
      };

      arg->inlen = comp_page[i].inlen;
      arg->outlen = comp_page[i].outlen;
      memset(arg->buf, 0, 1024);
      bcopy(comp_page[i].buf, arg->buf, arg->inlen);
}

static int
print_error(byte const *const b, int len)
{

      static char const *const sense_key[] =
      {
            "no sense", "recovered error", "not ready", "medium error",
            "hardware error", "illegal request", "unit attention",
            "data protect", "blank check", "vendor specific",
            "copy aborted", "aborted command", "equal",
            "volume overflow", "miscompare", "reserved"
      };

      int     i;

      if (len > 32)
            len = 8 + b[7];
      printf(" err:                ");
      for (i = 0; i < len; i++)
            printf(" %2X", b[i]);
      printf("\n");
      printf("error sense: %s\n", sense_key[b[2] & 0xf]);
      printf("asc + ascq = %2x %2x\n", b[12], b[13]);
      return 0;
}

void
set_compression_mode(int dev, int const comp_mode)
{
      ioctl_arg *arg;

      if (comp_mode < 0 || comp_mode > 5)
            return;
      /*
       * Allocate memory.
       */
      arg = malloc(sizeof (ioctl_arg));
      if (arg == NULL) {
            fprintf(stderr, "dds2tar: not enough memory\n");
            exit(15);
      }
      /*
       * do ioctl
       */
      copy_page(arg, comp_mode);
      /*    arg->buf[12] = (comp_mode << 7) | 0x40; */
      if (ioctl(dev, 1, arg) != 0) {
            close(dev);
            print_error(arg->buf, arg->inlen);
            exit(16);
      }
      if (comp_mode == DDSCM_QUERY) {
            byte   *b;

            b = arg->buf + 12;
            fprintf(stderr, "data compression enable %d\n", b[2] >> 7);
      } else if (comp_mode == DDSCM_LOG) {
            int     i, j;
            byte   *b;

            b = arg->buf + 0;
            for (i = 0; i < b[3];) {

                  static char const *const tab39[] =
                  {
                        NULL,
                        NULL,
                        NULL,
                        NULL,
                        NULL,
                        "kilobytes to data compression",
                        "kilobytes from data compression",
                        "kilobytes to tape",
                        "kilobytes from tape",
                        NULL,
                        NULL,
                        NULL};

                  byte   *p = b + i + 4;
                  int     n, k, c;

                  c = (p[0] << 8) + p[1];
                  n = p[3];
                  i += 4 + n;
                  p += 4;
                  j = 0;
                  for (k = 0; k < n; k++)
                        j = (j << 8) + p[k];

                  if ((c < 12) && (tab39[c] != NULL))
                        printf("%s: %d\n", tab39[c], j);
            }
      }
}

#endif

Generated by  Doxygen 1.6.0   Back to index