Imported Upstream version 3.1.0
[debian/amanda] / ndmp-src / ndma_ctst_tape.c
1 /*
2  * Copyright (c) 1998,1999,2000
3  *      Traakan, Inc., Los Altos, CA
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice unmodified, this list of conditions, and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 /*
30  * Project:  NDMJOB
31  * Ident:    $Id: $
32  *
33  * Description:
34  *
35  *****************************************************************
36  *
37  * NDMP Elements of a test-tape session
38  *
39  *                   +-----+     ###########
40  *                   | Job |----># CONTROL #
41  *                   +-----+     #  Agent  #
42  *                               #         #
43  *                               ###########
44  *                                    |  |
45  *                                    |  +---------------------+
46  *                            control | connections            |
47  *                                    V                        V
48  *                               ############  +-------+   #########
49  *                               #  TAPE    #  |       |   # ROBOT #
50  *                               #  Agent   #  | ROBOT |<-># Agent #
51  *                               #          #  |+-----+|   #       #
52  *                               #        ======|DRIVE||   #       #
53  *                               #          #  |+-----+|   #       #
54  *                               ############  +-------+   #########
55  *
56  ****************************************************************
57  */
58
59
60 #include "ndmagents.h"
61
62
63 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
64
65
66 extern int      ndmca_tt_wrapper (struct ndm_session *sess,
67                                 int (*func)(struct ndm_session *sess));
68
69
70 extern int      ndmca_op_test_tape (struct ndm_session *sess);
71 extern int      ndmca_tt_openclose (struct ndm_session *sess);
72 extern int      ndmca_tt_basic_getstate (struct ndm_session *sess);
73 extern int      ndmca_tt_basic_write (struct ndm_session *sess);
74 extern int      ndmca_tt_basic_read (struct ndm_session *sess);
75 extern int      ndmca_tt_basic_write_and_read (struct ndm_session *sess);
76 extern int      ndmca_tt_write (struct ndm_session *sess);
77 extern int      ndmca_tt_read (struct ndm_session *sess);
78 extern int      ndmca_tt_mtio (struct ndm_session *sess);
79
80 extern int      ndmca_tt_check_fileno_recno (struct ndm_session *sess,
81                         char *what, u_long file_num, u_long blockno,
82                         char *note);
83
84 extern int      ndmca_test_tape_open (struct ndm_session *sess,
85                         ndmp9_error expect_err,
86                         char *device, int mode);
87 extern int      ndmca_test_tape_close (struct ndm_session *sess,
88                         ndmp9_error expect_err);
89 extern int      ndmca_test_tape_get_state (struct ndm_session *sess,
90                         ndmp9_error expect_err);
91 extern int      ndmca_test_tape_mtio (struct ndm_session *sess,
92                         ndmp9_error expect_err,
93                         ndmp9_tape_mtio_op op, u_long count, u_long *resid);
94 extern int      ndmca_check_tape_mtio (struct ndm_session *sess,
95                         ndmp9_error expect_err,
96                         ndmp9_tape_mtio_op op, u_long count, u_long resid);
97 extern int      ndmca_test_tape_write (struct ndm_session *sess,
98                         ndmp9_error expect_err,
99                         char *buf, unsigned count);
100 extern int      ndmca_test_tape_read (struct ndm_session *sess,
101                         ndmp9_error expect_err,
102                         char *buf, unsigned count);
103 extern int      ndmca_test_tape_read_2cnt (struct ndm_session *sess,
104                         ndmp9_error expect_err,
105                         char *buf, unsigned count, unsigned true_count);
106
107
108 struct series {
109         unsigned        n_rec;
110         unsigned        recsize;
111 };
112
113 struct series tt_series[] = {
114         { 1,    512 },
115         { 100,  1024 },
116         { 1,    512 },
117         { 100,  139 },
118         { 1,    512 },
119         { 99,   10240 },
120         { 1,    512 },
121         { 3,    32768 },
122         { 1,    512 },
123         { 0 }
124 };
125
126
127
128 int
129 ndmca_op_test_tape (struct ndm_session *sess)
130 {
131         struct ndmconn *        conn;
132         int                     (*save_call) (struct ndmconn *conn,
133                                                 struct ndmp_xa_buf *xa);
134         int                     rc;
135
136         rc = ndmca_test_load_tape (sess);
137         if (rc) return rc;
138
139         conn = sess->plumb.tape;
140         save_call = conn->call;
141         conn->call = ndma_call_no_tattle;
142
143         if (rc == 0)
144                 rc = ndmca_tt_wrapper (sess, ndmca_tt_openclose);
145         if (rc == 0)
146                 rc = ndmca_tt_wrapper (sess, ndmca_tt_basic_getstate);
147         if (rc == 0)
148                 rc = ndmca_tt_wrapper (sess, ndmca_tt_basic_write);
149         if (rc == 0)
150                 rc = ndmca_tt_wrapper (sess, ndmca_tt_basic_read);
151         if (rc == 0)
152                 rc = ndmca_tt_wrapper (sess, ndmca_tt_basic_write_and_read);
153         if (rc == 0)
154                 rc = ndmca_tt_wrapper (sess, ndmca_tt_write);
155         if (rc == 0)
156                 rc = ndmca_tt_wrapper (sess, ndmca_tt_read);
157         if (rc == 0)
158                 rc = ndmca_tt_wrapper (sess, ndmca_tt_mtio);
159
160         ndmca_test_unload_tape (sess);
161
162         ndmca_test_done_series (sess, "test-tape");
163
164         conn->call = save_call;
165
166         return 0;
167 }
168
169 int
170 ndmca_tt_wrapper (struct ndm_session *sess,
171   int (*func)(struct ndm_session *sess))
172 {
173         int             rc;
174
175         rc = (*func)(sess);
176
177         if (rc != 0) {
178                 ndmalogf (sess, "Test", 1, "Failure");
179         }
180
181         ndmca_test_done_phase (sess);
182
183         /* clean up mess */
184         ndmca_test_log_note (sess, 2, "Cleaning up...");
185
186         ndmca_tape_open (sess); /* Open the tape, OK if already opened */
187         ndmca_tape_mtio (sess, NDMP9_MTIO_REW, 1, 0);
188         rc = ndmca_tape_close (sess);   /* close, collective error */
189         if (rc != 0) {
190                 ndmca_test_log_note (sess, 0, "Cleaning up failed, quiting");
191         } else {
192                 ndmca_test_log_note (sess, 2, "Cleaning up done");
193         }
194
195         return rc;
196 }
197
198
199 int
200 ndmca_tt_openclose (struct ndm_session *sess)
201 {
202         int             rc;
203
204         ndmca_test_phase (sess, "T-OC", "Tape Open/Close");
205
206         rc = ndmca_test_tape_close (sess, NDMP9_DEV_NOT_OPEN_ERR);
207         if (rc) return rc;
208
209         rc = ndmca_test_tape_open (sess, NDMP9_NO_DEVICE_ERR,
210                         "bogus", NDMP9_TAPE_READ_MODE);
211         if (rc) return rc;
212
213         rc = ndmca_test_tape_open (sess, NDMP9_ILLEGAL_ARGS_ERR, 0, 123);
214         if (rc) return rc;
215
216         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
217         if (rc) return rc;
218
219         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
220         if (rc) return rc;
221
222         rc = ndmca_test_tape_open (sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
223         if (rc) return rc;
224
225         rc = ndmca_test_tape_open (sess, NDMP9_DEVICE_OPENED_ERR,
226                         0, NDMP9_TAPE_READ_MODE);
227         if (rc) return rc;
228
229         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
230         if (rc) return rc;
231
232         return 0;       /* pass */
233 }
234
235 int
236 ndmca_tt_basic_getstate (struct ndm_session *sess)
237 {
238         int             rc;
239
240         ndmca_test_phase (sess, "T-BGS", "Tape Get State Basics");
241
242         rc = ndmca_test_tape_get_state (sess, NDMP9_DEV_NOT_OPEN_ERR);
243         if (rc) return rc;
244
245         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
246         if (rc) return rc;
247
248         rc = ndmca_test_tape_get_state (sess, NDMP9_NO_ERR);
249         if (rc) return rc;
250
251         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
252         if (rc) return rc;
253
254         return 0;       /* pass */
255 }
256
257 /*
258  * Precedes tt_basic_read() so that we can make a "known" tape.
259  */
260 int
261 ndmca_tt_basic_write (struct ndm_session *sess)
262 {
263         int             rc, ix;
264         char            buf[1024];
265         ndmp9_error     expect_errs[5];
266
267         ndmca_test_phase (sess, "T-BW", "Tape Write Basics");
268
269         rc = ndmca_test_tape_write (sess, NDMP9_DEV_NOT_OPEN_ERR, buf, 1024);
270         if (rc) return rc;
271
272         /*
273          * Write w/ read-only open mode
274          */
275         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
276         if (rc) return rc;
277
278         rc = ndmca_test_tape_write (sess, NDMP9_PERMISSION_ERR, buf, 1024);
279         if (rc) return rc;
280
281         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
282         if (rc) return rc;
283
284         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
285         if (rc) return rc;
286
287         /*
288          * Write w/ bogus lengths
289          */
290         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
291         if (rc) return rc;
292
293         /* OPEN Question: what does len==0 mean? */
294         /* write/len=0 MUST be NDMP[234]_NO_ERR or NDMP[234]_ILLEGAL_ARGS */
295         /* write/len=0 MUST be NDMP4_NO_ERR */
296         ix = 0;
297         if (sess->plumb.tape->protocol_version < 5) {
298                 expect_errs[ix++] = NDMP9_ILLEGAL_ARGS_ERR;
299         }
300         expect_errs[ix++] = NDMP9_NO_ERR;
301         expect_errs[ix++] = -1;
302
303         rc = ndmca_tape_write (sess, buf, 0);
304
305         rc = ndmca_test_check_expect_errs (sess->plumb.tape, rc, expect_errs);
306         if (rc) return rc;
307
308         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
309         if (rc) return rc;
310
311         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
312         if (rc) return rc;
313
314         /*
315          * TODO: bogus length
316          */
317
318         /*
319          * Write works
320          */
321         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
322         if (rc) return rc;
323
324         rc = ndmca_test_tape_write (sess, NDMP9_NO_ERR, buf, 1024);
325         if (rc) return rc;
326
327         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_EOF, 1, 0);
328         if (rc) return rc;
329
330         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
331         if (rc) return rc;
332
333         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
334         if (rc) return rc;
335
336         return 0;       /* pass */
337 }
338
339
340 /*
341  * Assumes tt_basic_write() passed. Uses resulting tape.
342  */
343
344 int
345 ndmca_tt_basic_read (struct ndm_session *sess)
346 {
347         int             rc, ix;
348         char            buf[2048];
349         ndmp9_error     expect_errs[5];
350
351         ndmca_test_phase (sess, "T-BR", "Tape Read Basics");
352
353         rc = ndmca_test_tape_read (sess, NDMP9_DEV_NOT_OPEN_ERR, buf, 1024);
354         if (rc) return rc;
355
356
357         /*
358          * Read w/ bogus lengths -- mode=READ_MODE
359          */
360         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
361         if (rc) return rc;
362
363         /* read/len=0 MUST be NDMP[23]_NO_ERR or NDMP[23]_ILLEGAL_ARGS */
364         /* read/len=0 MUST be NDMP4_NO_ERR */
365         ix = 0;
366         if (sess->plumb.tape->protocol_version < 4) {
367                 expect_errs[ix++] = NDMP9_ILLEGAL_ARGS_ERR;
368         }
369         expect_errs[ix++] = NDMP9_NO_ERR;
370         expect_errs[ix++] = -1;
371
372         rc = ndmca_tape_read (sess, buf, 0);
373
374         rc = ndmca_test_check_expect_errs (sess->plumb.tape, rc, expect_errs);
375         if (rc) return rc;
376
377         rc = ndmca_test_tape_read(sess,NDMP9_ILLEGAL_ARGS_ERR,buf,0x80000000);
378         if (rc) return rc;
379
380         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
381         if (rc) return rc;
382
383         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
384         if (rc) return rc;
385
386         /*
387          * Read works -- mode=WRITE_MODE (just to mix it up)
388          */
389         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
390         if (rc) return rc;
391
392         rc = ndmca_test_tape_read (sess, NDMP9_NO_ERR, buf, 1024);
393         if (rc) return rc;
394
395         rc = ndmca_test_tape_read (sess, NDMP9_EOF_ERR, buf, 1024);
396         if (rc) return rc;
397
398         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
399         if (rc) return rc;
400
401         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
402         if (rc) return rc;
403
404
405         /*
406          * Read works w/ oversize -- mode=READ_MODE (just to mix it up)
407          */
408         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
409         if (rc) return rc;
410
411         rc = ndmca_test_tape_read_2cnt (sess, NDMP9_NO_ERR, buf, 2048, 1024);
412         if (rc) return rc;
413
414         rc = ndmca_test_tape_read_2cnt (sess, NDMP9_EOF_ERR, buf, 2048, 1024);
415         if (rc) return rc;
416
417         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
418         if (rc) return rc;
419
420         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
421         if (rc) return rc;
422
423
424         /*
425          * Read works w/ undersize -- mode=READ_MODE (just to mix it up)
426          */
427         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
428         if (rc) return rc;
429
430         rc = ndmca_test_tape_read_2cnt (sess, NDMP9_NO_ERR, buf, 512, 512);
431         if (rc) return rc;
432
433         rc = ndmca_test_tape_read_2cnt (sess, NDMP9_EOF_ERR, buf, 512, 512);
434         if (rc) return rc;
435
436         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
437         if (rc) return rc;
438
439         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
440         if (rc) return rc;
441
442         return 0;       /* pass */
443 }
444
445 #define CHECK_FILENO_RECNO(WHAT,FILENO,RECNO) { \
446         what = WHAT;                                    \
447         rc = ndmca_tt_check_fileno_recno (sess,         \
448                         WHAT, FILENO, RECNO, note);     \
449         if (rc) return -1;                              \
450   }
451
452 /*
453  * Assumes tt_basic_read() and tt_basic_write() have been done verifying
454  * READ and WRITE operations work...
455  */
456 int
457 ndmca_tt_basic_write_and_read (struct ndm_session *sess)
458 {
459     int rc, i, f, pass;
460     char buf[64*1024];
461     char *p;
462
463     ndmca_test_phase (sess, "T-BWR", "Tape Write and Read Basics");
464
465     /*
466      * check EOF and EOM by rewinding and putting on 1 EOF mark
467      */
468     rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
469     if (rc) return rc;
470
471     rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
472     if (rc) return rc;
473
474     rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_BSR, 100, 100);
475     if (rc) return rc;
476
477     rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_BSF, 100, 100);
478     if (rc) return rc;
479
480     rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_EOF, 1, 0);
481     if (rc) return rc;
482
483     rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_BSF, 100, 99);
484     if (rc) return rc;
485
486     rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_FSF, 100, 99);
487     if (rc) return rc;
488
489     /* we are at EOM */
490     if (sess->plumb.tape->protocol_version < 4) {
491         rc = ndmca_test_tape_read (sess, NDMP9_EOF_ERR, buf, sizeof(buf));
492         if (rc) return rc;
493
494         /* check it again */
495         rc = ndmca_test_tape_read (sess, NDMP9_EOF_ERR, buf, 1024);
496         if (rc) return rc;
497
498     } else {
499         rc = ndmca_test_tape_read (sess, NDMP9_EOM_ERR, buf, sizeof(buf));
500         if (rc) return rc;
501
502         /* check it again */
503         rc = ndmca_test_tape_read (sess, NDMP9_EOM_ERR, buf, 1024);
504         if (rc) return rc;
505     }
506
507     /* rewind and place 1 record in tape -- no EOF marker by seeking */
508
509     rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
510     if (rc) return rc;
511
512     rc = ndmca_test_tape_write (sess, NDMP9_NO_ERR, buf, 512);
513     if (rc) return rc;
514
515     rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_BSR, 100, 99);
516     if (rc) return rc;
517
518     rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_FSR, 100, 99);
519     if (rc) return rc;
520
521     rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_FSR, 100, 100);
522     if (rc) return rc;
523
524     rc = ndmca_check_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_FSF, 100, 100);
525     if (rc) return rc;
526
527     rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
528     if (rc) return rc;
529
530     /*
531      * perform tape label type processing with positioning ops
532      */
533     for(pass = 0; pass < 2; pass++) {
534         /*
535          * open the tape and write 1 record and close it
536          */
537         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
538         if (rc) return rc;
539
540         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
541         if (rc) return rc;
542
543         for(p = buf, i = 0; i < 1024; i++, p++)
544             *p = ((i - 4) & 0xff);
545
546         rc = ndmca_test_tape_write (sess, NDMP9_NO_ERR, buf, 1024);
547         if (rc) return rc;
548
549         rc = ndmca_tape_mtio (sess, NDMP9_MTIO_EOF, 1, 0);
550         if (rc) return rc;
551
552         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
553         if (rc) return rc;
554
555         /*
556          * open the tape and read it
557          */
558         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
559         if (rc) return rc;
560
561         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
562         if (rc) return rc;
563
564         if (pass == 1)
565             rc = ndmca_test_tape_read_2cnt (sess, NDMP9_NO_ERR, buf, sizeof(buf), 1024);
566         else
567             rc = ndmca_test_tape_read (sess, NDMP9_NO_ERR, buf, 1024);
568         if (rc) return rc;
569
570         for(p = buf, f = i = 0;
571             f < 64 && i < 1024;
572             i++, p++)
573             if (*p != ((i - 4) & 0xff)) {
574                 char tmp[80];
575                 sprintf (tmp,
576                          "%d: 0x%x => 0x%x",
577                          i, ((i - 4) & 0xff), *p);
578                 ndmalogf (sess, "DATA", 6, tmp);
579                 f++;
580             }
581         if (f > 0) {
582             ndmca_test_fail (sess, "Failed compare");
583             return -1;
584         }
585
586         rc = ndmca_test_tape_read (sess, NDMP9_EOF_ERR, buf, 1024);
587         if (rc) return rc;
588
589         /* check EOM */
590         if (sess->plumb.tape->protocol_version < 4) {
591             rc = ndmca_test_tape_read (sess, NDMP9_EOF_ERR, buf, 1024);
592             if (rc) return rc;
593         } else {
594             /* skip over filemark */
595             rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSF, 1, 0);
596             /* read EOM */
597             rc = ndmca_test_tape_read (sess, NDMP9_EOM_ERR, buf, 1024);
598             if (rc) return rc;
599         }
600
601         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
602         if (rc) return rc;
603     }
604
605     return 0;   /* pass */
606 }
607
608 /*
609  * Precedes tt_read() so that we can make a "known" tape.
610  */
611 int
612 ndmca_tt_write (struct ndm_session *sess)
613 {
614         int             rc;
615         unsigned        n_rec;
616         unsigned        recsize;
617         unsigned        fileno, recno;
618         char *          what;
619         char            note[128];
620         char            buf[64*1024];
621
622         ndmca_test_phase (sess, "T-WRITE", "Tape Write Series");
623
624         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_RDWR_MODE);
625         if (rc) return rc;
626
627         for (fileno = 0; tt_series[fileno].n_rec > 0; fileno++) {
628                 n_rec = tt_series[fileno].n_rec;
629                 recsize = tt_series[fileno].recsize;
630
631                 sprintf (note, "Write tape file %d", fileno+1);
632                 ndmca_test_open (sess, note, 0);
633
634                 sprintf (note, "file #%d, %d records, %d bytes/rec",
635                                 fileno+1, n_rec, recsize);
636                 ndmca_test_log_note (sess, 2, note);
637
638                 for (recno = 0; recno < n_rec; recno++) {
639                         ndmca_test_fill_data (buf, recsize, recno, fileno);
640
641                         what = "write";
642                         rc = ndmca_tape_write (sess, buf, recsize);
643                         if (rc) goto fail;
644
645                         CHECK_FILENO_RECNO ("write", fileno, recno+1);
646                 }
647
648                 what = "write filemark";
649                 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_EOF, 1, 0);
650                 if (rc) goto fail;
651
652                 CHECK_FILENO_RECNO ("wfm", fileno+1, 0);
653
654                 /* no test calls so the file operation is the test */
655                 sprintf (buf, "Passed tape write %s", note);
656                 ndmca_test_log_step (sess, 2, buf);
657         }
658
659         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
660         if (rc) return rc;
661
662         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
663         if (rc) return rc;
664
665         return 0;
666
667   fail:
668         sprintf (buf, "Failed %s recno=%d; %s", what, recno, note);
669         ndmca_test_fail (sess, buf);
670         return -1;
671 }
672
673
674
675
676 /*
677  * Assumes tt_write() passed
678  */
679 int
680 ndmca_tt_read (struct ndm_session *sess)
681 {
682         int             rc;
683         unsigned        n_rec;
684         unsigned        recsize;
685         unsigned        fileno, recno;
686         char *          what;
687         char            note[128];
688         char            pbuf[64*1024];
689         char            buf[64*1024];
690
691         ndmca_test_phase (sess, "T-READ", "Tape Read Series");
692
693         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
694         if (rc) return rc;
695
696         for (fileno = 0; tt_series[fileno].n_rec > 0; fileno++) {
697                 n_rec = tt_series[fileno].n_rec;
698                 recsize = tt_series[fileno].recsize;
699
700                 sprintf (note, "Read tape file %d", fileno+1);
701                 ndmca_test_open (sess, note, 0);
702
703                 sprintf (note, "file #%d, %d records, %d bytes/rec",
704                                 fileno+1, n_rec, recsize);
705                 ndmca_test_log_note (sess, 2, note);
706
707                 for (recno = 0; recno < n_rec; recno++) {
708                         ndmca_test_fill_data (pbuf, recsize, recno, fileno);
709
710                         what = "read";
711                         rc = ndmca_tape_read (sess, buf, recsize);
712                         if (rc) goto fail;
713
714                         CHECK_FILENO_RECNO ("read", fileno, recno+1);
715
716                         what = "compare";
717 #if 0
718                         if (bcmp (buf, pbuf, recsize) != 0)
719                                 goto fail;
720 #else
721                         if (bcmp (buf, pbuf, recsize) != 0) {
722                                 unsigned char *expect_p = (unsigned char *)pbuf;
723                                 unsigned char *got_p = (unsigned char *)buf;
724                                 unsigned int i, f;
725                                 for(f = i = 0;
726                                     f < 64 && i < recsize;
727                                     i++, expect_p++, got_p++) {
728                                     if (*expect_p != *got_p) {
729                                         char tmp[80];
730                                         sprintf (tmp,
731                                                  "%d: 0x%x => 0x%x",
732                                                  i, *expect_p, *got_p);
733                                         ndmalogf (sess, "DATA", 6, tmp);
734                                         f++;
735                                     }
736                                 }
737                                 goto fail;
738                         }
739 #endif
740                 }
741
742                 what = "eof read";
743                 rc = ndmca_test_tape_read (sess, NDMP9_EOF_ERR, buf, recsize);
744                 if (rc) goto fail;
745
746                 if (sess->plumb.tape->protocol_version > 3) {
747                     CHECK_FILENO_RECNO ("eof", fileno, -1);
748
749                     what = "skip filemark";
750                     rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSF, 1, 0);
751                     if (rc) goto fail;
752
753                     CHECK_FILENO_RECNO ("skip", fileno+1, 0);
754                 } else {
755                     CHECK_FILENO_RECNO ("eof", fileno+1, 0);
756                 }
757
758                 sprintf (buf, "Passed tape read %s", note);
759                 ndmca_test_log_step (sess, 2, buf);
760         }
761
762         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
763         if (rc) return rc;
764
765         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
766         if (rc) return rc;
767
768         return 0;
769
770   fail:
771         sprintf (buf, "Failed %s recno=%d; %s", what, recno, note);
772         ndmca_test_fail (sess, buf);
773         return -1;
774 }
775
776
777 /*
778  * Assumes tt_write() passed
779  */
780 int
781 ndmca_tt_mtio (struct ndm_session *sess)
782 {
783         int             rc;
784         unsigned        n_rec;
785         unsigned        recsize;
786         unsigned        fileno, recno;
787         u_long          count, resid;
788         char *          what;
789         char            note[128];
790         char            pbuf[64*1024];
791         char            buf[64*1024];
792
793         ndmca_test_phase (sess, "T-MTIO", "Tape MTIO");
794
795         rc = ndmca_test_tape_open(sess,NDMP9_NO_ERR,0,NDMP9_TAPE_READ_MODE);
796         if (rc) return rc;
797
798         rc = ndmca_test_tape_mtio (sess, NDMP9_NO_ERR, NDMP9_MTIO_REW, 1, 0);
799         if (rc) return rc;
800
801         for (fileno = 0; tt_series[fileno].n_rec > 0; fileno++) {
802                 n_rec = tt_series[fileno].n_rec;
803                 recsize = tt_series[fileno].recsize;
804
805                 sprintf (note, "Seek around tape file %d", fileno+1);
806                 ndmca_test_open (sess, note, 0);
807
808                 sprintf (note, "file #%d, %d records, %d bytes/rec",
809                                 fileno+1, n_rec, recsize);
810                 ndmca_test_log_note (sess, 2, note);
811
812                 what = "rew";
813                 count = 1;
814                 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_REW, count, &resid);
815                 if (rc) goto fail;
816
817                 what = "rew resid";
818                 if (resid != 0)
819                         goto fail;
820
821                 CHECK_FILENO_RECNO ("rew", 0, 0);
822
823
824                 what = "fsf(n)";
825                 count = fileno;
826                 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSF, count, &resid);
827                 if (rc) goto fail;
828
829                 what = "fsf(n) resid";
830                 if (resid != 0)
831                         goto fail;
832
833                 CHECK_FILENO_RECNO ("fsf", fileno, 0);
834
835
836                 what = "fsr(1m)";
837                 count = 1000000;
838                 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSR, count, &resid);
839                 if (rc) goto fail;
840
841                 what = "fsr(1m) resid";
842                 if (n_rec + resid != count)
843                         goto fail;
844
845                 if (sess->plumb.tape->protocol_version < 4) {
846                     CHECK_FILENO_RECNO ("fsr(1m)", fileno + 1, 0);
847
848                     what = "bsf 1 after fsr(1m)";
849                     count = 1;
850                     rc = ndmca_tape_mtio (sess, NDMP9_MTIO_BSF, count, 0);
851                     if (rc) goto fail;
852
853                     CHECK_FILENO_RECNO (what, fileno, -1);
854
855                     recno = n_rec;
856                 } else {
857                     /* EOT side of EOF marker */
858                     recno = n_rec;
859                     CHECK_FILENO_RECNO ("fsr(1m)", fileno, recno);
860                 }
861
862                 what = "bsr(1m)";
863                 count = 1000000;
864                 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_BSR, count, &resid);
865                 if (rc) goto fail;
866
867                 what = "bsr(1m) resid";
868                 if (n_rec + resid != count)
869                         goto fail;
870
871                 if ((fileno > 0) && (sess->plumb.tape->protocol_version < 4)) {
872                     /* at BOT side of EOF marker (not BOT) */
873                     CHECK_FILENO_RECNO ("bsr(1m)", fileno - 1, -1);
874
875                     what = "fsf 1 after bsr(1m)";
876                     count = 1;
877                     rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSF, count, 0);
878                     if (rc) goto fail;
879                 }
880
881                 recno = 0;
882                 CHECK_FILENO_RECNO ("bsr(1m)", fileno, recno);
883
884                 what = "fsr(0)";
885                 count = 0;
886                 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSR, count, &resid);
887                 if (rc) goto fail;
888
889                 what = "fsr(0) resid";
890                 if (resid != 0)
891                         goto fail;
892
893                 recno = 0;
894                 CHECK_FILENO_RECNO ("fsr(0)", fileno, recno);
895
896
897                 what = "fsr(x)";
898                 count = n_rec / 2;
899                 rc = ndmca_tape_mtio (sess, NDMP9_MTIO_FSR, count, &resid);
900                 if (rc) goto fail;
901
902                 what = "fsr(x) resid";
903                 if (resid != 0)
904                         goto fail;
905
906                 recno = n_rec / 2;
907                 CHECK_FILENO_RECNO ("fsr(x)", fileno, recno);
908
909                 what = "fsr(x) read";
910                 rc = ndmca_tape_read (sess, buf, recsize);
911                 if (rc) goto fail;
912
913                 what = "fsr(x) compare";
914                 ndmca_test_fill_data (pbuf, recsize, recno, fileno);
915                 if (bcmp (buf, pbuf, recsize) != 0)
916                         goto fail;
917
918                 recno++;        /* caused by tape_read */
919
920                 if (recno > 1) {
921                         what = "bsr(2)";
922                         count = 2;
923                         rc = ndmca_tape_mtio (sess, NDMP9_MTIO_BSR,
924                                                 count, &resid);
925                         if (rc) goto fail;
926
927                         what = "bsr(2) resid";
928                         if (resid != 0)
929                                 goto fail;
930
931                         recno -= count;
932                         CHECK_FILENO_RECNO ("bsr(2)", fileno, recno);
933
934                         what = "bsr(2) read";
935                         rc = ndmca_tape_read (sess, buf, recsize);
936                         if (rc) goto fail;
937
938                         what = "bsr(2) compare";
939                         ndmca_test_fill_data (pbuf, recsize, recno, fileno);
940                         if (bcmp (buf, pbuf, recsize) != 0)
941                                 goto fail;
942                 }
943
944                 sprintf (buf, "Passed %s", note);
945                 ndmca_test_log_step (sess, 2, buf);
946         }
947
948         rc = ndmca_test_tape_close (sess, NDMP9_NO_ERR);
949         if (rc) return rc;
950
951         return 0;
952
953   fail:
954         sprintf (buf, "Failed %s: %s", what, note);
955         ndmca_test_fail (sess, buf);
956         return -1;
957 }
958
959
960
961 /*
962  * Check the tape_state accurately reflects position
963  */
964
965 int
966 ndmca_tt_check_fileno_recno (struct ndm_session *sess,
967   char *what, u_long file_num, u_long blockno, char *note)
968 {
969         struct ndm_control_agent *ca = &sess->control_acb;
970         struct ndmp9_tape_get_state_reply *ts = 0;
971         char                    buf[100];
972         int                     rc;
973         char *                  oper;
974
975         oper ="get_state";
976         rc = ndmca_tape_get_state (sess);
977         if (rc) goto fail;
978
979         ts = &ca->tape_state;
980
981         oper = "check file_num";
982         if (ts->file_num.value != file_num)
983                 goto fail;
984
985         oper = "check blockno";
986         if ((ts->blockno.value != blockno) && (ts->blockno.value != NDMP9_INVALID_U_LONG))
987                 goto fail;
988
989         return 0;
990
991   fail:
992         sprintf (buf, "Failed %s while testing %s", oper, what);
993         ndmca_test_log_note (sess, 1, buf);
994         if (ts) {
995                 sprintf (buf, "    expect file_num=%ld got file_num=%ld",
996                         (long)file_num, (long)ts->file_num.value);
997                 ndmca_test_log_note (sess, 1, buf);
998
999                 sprintf (buf, "    expect blockno=%ld got blockno=%ld",
1000                         (long)blockno, (long)ts->blockno.value);
1001                 ndmca_test_log_note (sess, 1, buf);
1002         }
1003
1004         sprintf (buf, "    note: %s", note);
1005         ndmca_test_fail (sess, buf);
1006         return -1;
1007 }
1008
1009
1010
1011
1012 #define NDMTEST_CALL(CONN) ndmca_test_call(CONN, xa, expect_err);
1013
1014
1015 int
1016 ndmca_test_tape_open (struct ndm_session *sess, ndmp9_error expect_err,
1017   char *device, int mode)
1018 {
1019         struct ndmconn *        conn = sess->plumb.tape;
1020         struct ndm_control_agent *ca = &sess->control_acb;
1021         int                     rc;
1022
1023         /* close previous test if there is one */
1024         ndmca_test_close (sess);
1025
1026         switch (conn->protocol_version) {
1027         default:        return -1234;
1028
1029 #ifndef NDMOS_OPTION_NO_NDMP2
1030         case NDMP2VER:
1031             NDMC_WITH (ndmp2_tape_open, NDMP2VER)
1032                 if (device)
1033                         request->device.name = device;
1034                 else
1035                         request->device.name = ca->job.tape_device;
1036                 if (mode != -1)
1037                         request->mode = mode;
1038                 else
1039                         request->mode = ca->tape_mode;
1040                 rc = NDMTEST_CALL(conn);
1041             NDMC_ENDWITH
1042             break;
1043 #endif /* !NDMOS_OPTION_NO_NDMP2 */
1044 #ifndef NDMOS_OPTION_NO_NDMP3
1045         case NDMP3VER:
1046             NDMC_WITH (ndmp3_tape_open, NDMP3VER)
1047                 if (device)
1048                         request->device = device;
1049                 else
1050                         request->device = ca->job.tape_device;
1051                 if (mode != -1)
1052                         request->mode = mode;
1053                 else
1054                         request->mode = ca->tape_mode;
1055                 rc = NDMTEST_CALL(conn);
1056             NDMC_ENDWITH
1057             break;
1058 #endif /* !NDMOS_OPTION_NO_NDMP3 */
1059 #ifndef NDMOS_OPTION_NO_NDMP4
1060         case NDMP4VER:
1061             NDMC_WITH (ndmp4_tape_open, NDMP4VER)
1062                 if (device)
1063                         request->device = device;
1064                 else
1065                         request->device = ca->job.tape_device;
1066                 if (mode != -1)
1067                         request->mode = mode;
1068                 else
1069                         request->mode = ca->tape_mode;
1070                 rc = NDMTEST_CALL(conn);
1071             NDMC_ENDWITH
1072             break;
1073 #endif /* !NDMOS_OPTION_NO_NDMP4 */
1074         }
1075
1076         return rc;
1077 }
1078
1079 int
1080 ndmca_test_tape_close (struct ndm_session *sess, ndmp9_error expect_err)
1081 {
1082         struct ndmconn *        conn = sess->plumb.tape;
1083         int                     rc;
1084
1085         /* close previous test if there is one */
1086         ndmca_test_close (sess);
1087
1088         rc = ndmca_tape_close (sess);
1089
1090         rc = ndmca_test_check_expect (conn, rc, expect_err);
1091
1092         return rc;
1093 }
1094
1095 int
1096 ndmca_test_tape_get_state (struct ndm_session *sess, ndmp9_error expect_err)
1097 {
1098         struct ndmconn *        conn = sess->plumb.tape;
1099         int                     rc;
1100
1101         /* close previous test if there is one */
1102         ndmca_test_close (sess);
1103
1104         rc = ndmca_tape_get_state (sess);
1105
1106         rc = ndmca_test_check_expect (conn, rc, expect_err);
1107
1108         return rc;
1109 }
1110
1111 int
1112 ndmca_test_tape_mtio (struct ndm_session *sess, ndmp9_error expect_err,
1113   ndmp9_tape_mtio_op op, u_long count, u_long *resid)
1114 {
1115         struct ndmconn *        conn = sess->plumb.tape;
1116         int                     rc;
1117
1118         /* close previous test if there is one */
1119         ndmca_test_close (sess);
1120
1121         rc = ndmca_tape_mtio (sess, op, count, resid);
1122
1123         rc = ndmca_test_check_expect (conn, rc, expect_err);
1124
1125         return rc;
1126 }
1127
1128 int
1129 ndmca_check_tape_mtio (struct ndm_session *sess, ndmp9_error expect_err,
1130                        ndmp9_tape_mtio_op op, u_long count, u_long resid)
1131 {
1132     struct ndmconn *    conn = sess->plumb.tape;
1133     u_long got_resid;
1134     int rc;
1135
1136     /* close previous test if there is one */
1137     ndmca_test_close (sess);
1138
1139     got_resid = ~resid;
1140
1141     rc = ndmca_tape_mtio (sess, op, count, &got_resid);
1142
1143     rc = ndmca_test_check_expect (conn, rc, expect_err);
1144     if (rc) return rc;
1145
1146     if (resid != got_resid) {
1147         char tmp[128];
1148         sprintf (tmp,
1149                  "Residual incorrect, got %lu expected %lu",
1150                  got_resid,
1151                  resid);
1152         ndmca_test_fail (sess, tmp);
1153         return -1;
1154     }
1155
1156     return rc;
1157 }
1158
1159
1160 int
1161 ndmca_test_tape_write (struct ndm_session *sess, ndmp9_error expect_err,
1162   char *buf, unsigned count)
1163 {
1164         struct ndmconn *        conn = sess->plumb.tape;
1165         int                     rc;
1166
1167         /* close previous test if there is one */
1168         ndmca_test_close (sess);
1169
1170         rc = ndmca_tape_write (sess, buf, count);
1171
1172         rc = ndmca_test_check_expect (conn, rc, expect_err);
1173
1174         return rc;
1175 }
1176
1177 int
1178 ndmca_test_tape_read (struct ndm_session *sess, ndmp9_error expect_err,
1179   char *buf, unsigned count)
1180 {
1181         struct ndmconn *        conn = sess->plumb.tape;
1182         int                     rc;
1183
1184         /* close previous test if there is one */
1185         ndmca_test_close (sess);
1186
1187         rc = ndmca_tape_read (sess, buf, count);
1188
1189         rc = ndmca_test_check_expect (conn, rc, expect_err);
1190
1191         return rc;
1192 }
1193
1194 int
1195 ndmca_test_tape_read_2cnt (struct ndm_session *sess, ndmp9_error expect_err,
1196   char *buf, unsigned count, unsigned true_count)
1197 {
1198         struct ndmconn *        conn = sess->plumb.tape;
1199         int                     rc;
1200
1201         /* close previous test if there is one */
1202         ndmca_test_close (sess);
1203
1204         switch (conn->protocol_version) {
1205         default:        return -1234;
1206
1207 #ifndef NDMOS_OPTION_NO_NDMP2
1208         case NDMP2VER:
1209             NDMC_WITH(ndmp2_tape_read, NDMP2VER)
1210                 request->count = count;
1211                 rc = NDMTEST_CALL(conn);
1212                 if (rc == 0 && expect_err == NDMP9_NO_ERR) {
1213                         if (reply->data_in.data_in_len == true_count) {
1214                                 bcopy (reply->data_in.data_in_val,
1215                                                         buf, true_count);
1216                         } else {
1217                                 rc = -1;
1218                         }
1219                 }
1220                 NDMC_FREE_REPLY();
1221             NDMC_ENDWITH
1222             break;
1223 #endif /* !NDMOS_OPTION_NO_NDMP2 */
1224 #ifndef NDMOS_OPTION_NO_NDMP3
1225         case NDMP3VER:
1226             NDMC_WITH(ndmp3_tape_read, NDMP3VER)
1227                 request->count = count;
1228                 rc = NDMTEST_CALL(conn);
1229                 if (rc == 0 && expect_err == NDMP9_NO_ERR) {
1230                         if (reply->data_in.data_in_len == true_count) {
1231                                 bcopy (reply->data_in.data_in_val,
1232                                                         buf, true_count);
1233                         } else {
1234                                 rc = -1;
1235                         }
1236                 }
1237                 NDMC_FREE_REPLY();
1238             NDMC_ENDWITH
1239             break;
1240 #endif /* !NDMOS_OPTION_NO_NDMP3 */
1241 #ifndef NDMOS_OPTION_NO_NDMP4
1242         case NDMP4VER:
1243             NDMC_WITH(ndmp4_tape_read, NDMP4VER)
1244                 request->count = count;
1245                 rc = NDMTEST_CALL(conn);
1246                 if (rc == 0 && expect_err == NDMP9_NO_ERR) {
1247                         if (reply->data_in.data_in_len == true_count) {
1248                                 bcopy (reply->data_in.data_in_val,
1249                                                         buf, true_count);
1250                         } else {
1251                                 rc = -1;
1252                         }
1253                 }
1254                 NDMC_FREE_REPLY();
1255             NDMC_ENDWITH
1256             break;
1257 #endif /* !NDMOS_OPTION_NO_NDMP4 */
1258         }
1259
1260         return rc;
1261 }
1262 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */