move gbp.conf to debian/
[debian/dds2tar] / dds_tape.c
1
2 /*
3  * This file is part of dds2tar.
4  * Copyright by J"org Weule
5  *
6  * Special thanks to Les.Grant@mitsuibabcock.co.uk
7  * for the HP-UX patch.
8  */
9
10 #include <stdlib.h>
11 #include <stdio.h>              /* fpirntf() */
12 #include <errno.h>              /* perror() */
13 #include <sys/mtio.h>           /* MTSEEK ... */
14 #include <sys/ioctl.h>          /* ioctl() */
15 #include <unistd.h>             /* close() exit() */
16 #include "dds_tape.h"
17
18 #include "dds2tar.h"
19 #include "dds_tape.h"
20
21 /*
22  * set scsi2logical
23  */
24 int dds_scsi2logical(void){
25         struct mtop p ;
26         p.mt_op = MTSETDRVBUFFER ;
27         p.mt_count = MT_ST_OPTIONS|MT_ST_SCSI2LOGICAL ;
28         fputs("scsi2logical\n",stderr);
29         return ioctl(device,MTIOCTOP,&p);
30 }
31
32 /*
33  * set read_ahead
34  */
35 int dds_read_ahead(void){
36         struct mtop p ;
37         int r ;
38         p.mt_op = MTSETDRVBUFFER ;
39         p.mt_count = MT_ST_OPTIONS|MT_ST_READ_AHEAD ;
40         r = ioctl(device,MTIOCTOP,&p);
41 #ifdef DDS_TRACE
42         fputs("read_ahead\n",stderr);
43         if ( r < 0 ) perror("Read_ahead");
44 #endif
45         return r ;
46 }
47
48 /*
49  * rewind the last block
50  */
51 int dds_bsr(void){
52         struct mtop p ;
53         p.mt_op = MTBSR ;
54         p.mt_count = 1 ;
55         return ioctl(device,MTIOCTOP,&p);
56 }
57
58 #ifdef MTGETBLK
59 /*
60  * get block size
61  */
62 int dds_get_bs(void){
63         struct mtop p ;
64         int r ;
65         p.mt_op = MTGETBLK ;
66         p.mt_count = 0 ;
67         r = ioctl(device,MTSETBLK,&p);
68         if ( r >= 0 ) r = p.mt_count ;
69         return r ;
70 }
71 #endif
72
73 /*
74  * set block size
75  */
76 int dds_set_bs(int n){
77         struct mtop p ;
78         p.mt_op = MTSETBLK ;
79         p.mt_count = n ;
80         tar_bs = n >> 9 ;
81         tar_n = n ;
82 #ifdef DDS_TRACE
83         fprintf(stderr,"record_size=%d\n",n);
84 #endif
85         return ioctl(device,MTSETBLK,&p);
86 }
87
88 /*
89  * To read one line of the device and check for errors, we use the following
90  * code. If a filemark is read, we try the block again.
91  *
92  * Note that cur_blkno and next_blkno is changed.
93  */
94 void
95 dds_read_next_block(void)
96 {
97         int     err = 0;
98
99 #ifdef HPDAT
100         if (next_blkno == -1)
101 #endif
102                 next_blkno = dds_getpos(device);
103         cur_blkno = next_blkno;
104         cur_n = 0;
105 #ifdef DDS_TRACE
106         fprintf(stderr, "begin --> read_next_block()\n");
107         fprintf(stderr, "vid=%d \n",vid);
108 #endif
109         if ( vid == HP ) do {
110                 /* If you write a tape with 'tar -b 256' on SunOS, reading */
111                 /* the tape needs the following workaround. SunOS splits the */
112                 /* block into three tape blocks of 65534, 65534 and 4 Bytes. */
113                 /* dds2tar is reading the tree blocks and the number is */
114                 /* the one of the first block. You can not use the tar */
115                 /* listing block is this case, because the calculation of the */
116                 /* right will fail. Note that 'dds2tar --dds-dd | tar ft -' */
117                 /* will show the index of the archive, 'tar t' fails. */
118                 /* */
119                 /* --dds-dd is in experimental state, so may be I will change */
120                 /* this. */
121 #if ( ST_BUFFER_BLOCKS > 32 )
122                 do {
123                         err = read(device, ((char *) cur_block) + cur_n,
124                                             buf_n - cur_n);
125                         if (err > 0) next_blkno++, cur_n += err;
126                 } while ((err > 0) && (cur_n < buf_n) && ((cur_n & 0x1ff) != 0));
127 #else
128                 err = read(device, cur_block, buf_n);
129                 if (err > 0) next_blkno++, cur_n += err ;
130 #endif
131                 if ((cur_n & 0x1ff) != 0) {
132                         fprintf(stderr, "not a tar archive, record size is"
133                                 " %d bytes \n", cur_n);
134                         exit(4);
135                 }
136                 /*
137                  * We are done, if err >= 0.
138                  */
139                 if ( err >= 0 ) break ;
140
141                 /*
142                  * If err < 0 ... exit or decrease the buffer ...
143                  */
144                 if ((errno != EOVERFLOW) || (buf_n == 1)) {
145                         perror("dds2tar");
146                         exit(4);
147                 }
148                 buf_n >>= 1;
149                 fprintf(stderr,"decreasing buffer to %d bytes\n",buf_n);
150                 if (buf_n == 1) exit(4);
151         } while ( 1 );
152         if ( vid != HP ) {
153                 err = read(device, cur_block, tar_n);
154                 if ( err < 0 ) {
155                         fprintf(stderr,
156                         "Can not read from tape with blocksize of %d.\n",
157                         tar_n);
158                         perror("dds2index");
159                         exit(4);
160                 }
161                 next_blkno += tar_bs , cur_n = err ;
162                 if ((cur_n & 0x1ff) != 0) {
163                         fprintf(stderr, "not a tar archive, record size is"
164                                 " %d bytes \n", cur_n);
165                         exit(4);
166                 }
167         }
168         cur_bs = cur_n >> 9;
169 #ifdef DDS_TRACE
170         fprintf(stderr, "end ----> read_next_block()\n");
171 #endif
172 }
173
174 void
175 dds_read_block(void)
176 {
177         do
178                 dds_read_next_block();
179         while (cur_n == 0);
180 }
181
182 int
183 dds_getpos(int const dev)
184 {
185         int     i,n;
186
187 #ifdef MTIOCPOS
188         struct mtpos pos;
189         i = ioctl(dev, MTIOCPOS, &pos);
190         if (i != 0) {
191                 perror("dds2tar: ioctl MTIOCPOS");
192 #else
193         i = ioctl(dev, SIOC_GET_POSITION, &n); /* HP-UX */
194         if (i != 0) {
195                 perror("dds2tar: ioctl SIOC_GET_POSITION");
196 #endif
197                 close(dev);
198                 exit(11);
199         }
200         n = pos.mt_blkno;
201         if (n < 0) {
202                 fprintf(stderr, "dds2tar: eom detected ? blkno = %d \n", n);
203                 close(dev);
204                 exit(12);
205         }
206         return n;
207 }
208
209 #ifdef MTIOCLOC
210 int
211 dds_getloc(int const dev)
212 {
213         struct mtpos pos;
214         int     i,n;
215
216         i = ioctl(dev, MTIOCPOS, &pos);
217         if (i != 0) {
218                 perror("dds2tar: ioctl MTIOCLOC");
219                 close(dev);
220                 exit(11);
221         }
222         n = pos.mt_blkno;
223         if (n < 0) {
224                 fprintf(stderr, "dds2tar: eom detected ? blkno = %d \n", n);
225                 close(dev);
226                 exit(12);
227         }
228         return n ;
229 }
230 #endif
231
232 int
233 dds_has_partitions(int const dev){
234 #ifdef MT_ISDDS1
235         struct mtget p ;
236         int i;
237         i = ioctl(dev, MTIOCGET, &p );
238         if ( i >= 0 ) {
239                 i = p.mt_type ;
240         } else perror("dds2tar");
241         /*
242         if(i==MT_ISDDS1)fprintf(stderr, "DDS2TAR: drive without partitions\n");
243         if(i==MT_ISDDS2)fprintf(stderr, "DDS2TAR: drive with partitions\n");
244         fprintf(stderr, "DDS2TAR: type = %x\n",i);
245         */
246         return i ;
247 #else
248         return -1 ;
249 #endif
250 }
251
252 int
253 dds_seek(int const dev, int const blkno)
254 {
255         struct mtop op;
256         int     i;
257
258 #ifdef SIOC_SET_POSITION
259         i = ioctl(dev, SIOC_SET_POSITION, &blkno);
260 #else
261         op.mt_op = MTSEEK;
262         op.mt_count = blkno;
263         i = ioctl(dev, MTIOCTOP, &op);
264 #endif
265         if (i != 0) {
266                 perror("ioctl SEEK");
267                 close(dev);
268                 exit(13);
269         }
270         return 0;
271 }
272
273 /*
274  * This file is part of dds2tar.
275  * Copyright by J"org Weule
276  */
277
278 #ifdef HPDAT
279 #include <stdlib.h>             /* malloc() */
280 #include <stdio.h>              /* printf() */
281 #include <sys/ioctl.h>          /* ioctl() */
282 #include <string.h>             /* memset() bcopy() */
283 #include <unistd.h>             /* exit() */
284 #include "dds_tape.h"
285
286 typedef unsigned char byte;
287
288 typedef struct {
289         int     inlen;
290         int     outlen;
291         byte    buf[1024];
292 }
293
294 ioctl_arg;
295
296 static void
297 copy_page(ioctl_arg * const arg, int const i)
298 {
299
300         static struct {
301                 char const *const text;
302                 int const inlen;
303                 int const outlen;
304                 byte const buf[32];
305         }
306         const   comp_page[7] =
307         {
308                 {
309                         "set_comp_off", 26, 128,
310                         {
311                                 0x15, 0x10, 0x00, 0x00,
312                                 0x14, 0x00, 0x00, 0x00,
313                                 0x10, 0x00, 0x0f, 0x0e,
314                                 0x40, 0x80, 0x00, 0x00,
315                                 0x00, 0x20, 0x00, 0x00,
316                                 0x00, 0x00, 0x00, 0x00,
317                                 0x00, 0x00, 0x00, 0x00,
318                                 0x00, 0x00, 0x00, 0x00
319                         }
320                 }
321                 ,
322                 {
323                         "set_cpmp_on", 26, 128,
324                         {
325                                 0x15, 0x10, 0x00, 0x00,
326                                 0x14, 0x00, 0x00, 0x00,
327                                 0x10, 0x00, 0x0f, 0x0e,
328                                 0xc0, 0x80, 0x00, 0x00,
329                                 0x00, 0x20, 0x00, 0x00,
330                                 0x00, 0x00, 0x00, 0x00,
331                                 0x00, 0x00, 0x00, 0x00,
332                                 0x00, 0x00, 0x00, 0x00
333                         }
334                 }
335                 ,
336                 {
337                         "get_comp", 6, 128,
338                         {
339                                 0x1a, 0x00, 0x0f, 0x00, 0x40, 0x00
340                         }
341                 }
342                 ,
343                 {
344                         "log_comp", 10, 128,
345                         {
346                                 0x4d, 0x00, 0x79, 0x00,
347                                 0x00, 0x00, 0x00, 0x00,
348                                 0x80, 0x00
349                         }
350                 }
351                 ,
352                 {
353                         "load_tape", 6, 128,
354                         {
355                                 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00
356                         }
357                 }
358                 ,
359                 {
360                         "unload_tape", 6, 128,
361                         {
362                                 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00
363                         }
364                 }
365                 ,
366                 {
367                         "mode_sense", 6, 128,
368                         {
369                                 0x1a, 0x00, 0x00, 0x00, 0x0C, 0x00
370                         }
371                 }
372         };
373
374         arg->inlen = comp_page[i].inlen;
375         arg->outlen = comp_page[i].outlen;
376         memset(arg->buf, 0, 1024);
377         bcopy(comp_page[i].buf, arg->buf, arg->inlen);
378 }
379
380 static int
381 print_error(byte const *const b, int len)
382 {
383
384         static char const *const sense_key[] =
385         {
386                 "no sense", "recovered error", "not ready", "medium error",
387                 "hardware error", "illegal request", "unit attention",
388                 "data protect", "blank check", "vendor specific",
389                 "copy aborted", "aborted command", "equal",
390                 "volume overflow", "miscompare", "reserved"
391         };
392
393         int     i;
394
395         if (len > 32)
396                 len = 8 + b[7];
397         printf(" err:                ");
398         for (i = 0; i < len; i++)
399                 printf(" %2X", b[i]);
400         printf("\n");
401         printf("error sense: %s\n", sense_key[b[2] & 0xf]);
402         printf("asc + ascq = %2x %2x\n", b[12], b[13]);
403         return 0;
404 }
405
406 void
407 set_compression_mode(int dev, int const comp_mode)
408 {
409         ioctl_arg *arg;
410
411         if (comp_mode < 0 || comp_mode > 5)
412                 return;
413         /*
414          * Allocate memory.
415          */
416         arg = malloc(sizeof (ioctl_arg));
417         if (arg == NULL) {
418                 fprintf(stderr, "dds2tar: not enough memory\n");
419                 exit(15);
420         }
421         /*
422          * do ioctl
423          */
424         copy_page(arg, comp_mode);
425         /*      arg->buf[12] = (comp_mode << 7) | 0x40; */
426         if (ioctl(dev, 1, arg) != 0) {
427                 close(dev);
428                 print_error(arg->buf, arg->inlen);
429                 exit(16);
430         }
431         if (comp_mode == DDSCM_QUERY) {
432                 byte   *b;
433
434                 b = arg->buf + 12;
435                 fprintf(stderr, "data compression enable %d\n", b[2] >> 7);
436         } else if (comp_mode == DDSCM_LOG) {
437                 int     i, j;
438                 byte   *b;
439
440                 b = arg->buf + 0;
441                 for (i = 0; i < b[3];) {
442
443                         static char const *const tab39[] =
444                         {
445                                 NULL,
446                                 NULL,
447                                 NULL,
448                                 NULL,
449                                 NULL,
450                                 "kilobytes to data compression",
451                                 "kilobytes from data compression",
452                                 "kilobytes to tape",
453                                 "kilobytes from tape",
454                                 NULL,
455                                 NULL,
456                                 NULL};
457
458                         byte   *p = b + i + 4;
459                         int     n, k, c;
460
461                         c = (p[0] << 8) + p[1];
462                         n = p[3];
463                         i += 4 + n;
464                         p += 4;
465                         j = 0;
466                         for (k = 0; k < n; k++)
467                                 j = (j << 8) + p[k];
468
469                         if ((c < 12) && (tab39[c] != NULL))
470                                 printf("%s: %d\n", tab39[c], j);
471                 }
472         }
473 }
474
475 #endif