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 #if !defined(NDMOS_OPTION_NO_CONTROL_AGENT) && !defined(NDMOS_OPTION_NO_TEST_AGENTS)
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, uint32_t file_num, uint32_t 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, uint32_t count, uint32_t *resid);
94 extern int	ndmca_check_tape_mtio (struct ndm_session *sess,
95 			ndmp9_error expect_err,
96 			ndmp9_tape_mtio_op op, uint32_t count, uint32_t 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
ndmca_op_test_tape(struct ndm_session * sess)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
ndmca_tt_wrapper(struct ndm_session * sess,int (* func)(struct ndm_session * sess))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
ndmca_tt_openclose(struct ndm_session * sess)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
ndmca_tt_basic_getstate(struct ndm_session * sess)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
ndmca_tt_basic_write(struct ndm_session * sess)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
ndmca_tt_basic_read(struct ndm_session * sess)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
ndmca_tt_basic_write_and_read(struct ndm_session * sess)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 		snprintf (tmp, sizeof(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
ndmca_tt_write(struct ndm_session * sess)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 		snprintf (note, sizeof(note), "Write tape file %d", fileno+1);
632 		ndmca_test_open (sess, note, 0);
633 
634 		snprintf (note, sizeof(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 		snprintf (buf, sizeof(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 	snprintf (buf, sizeof(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
ndmca_tt_read(struct ndm_session * sess)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 		snprintf (note, sizeof(note), "Read tape file %d", fileno+1);
701 		ndmca_test_open (sess, note, 0);
702 
703 		snprintf (note, sizeof(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 					snprintf (tmp, sizeof(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 		snprintf (buf, sizeof(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 	snprintf (buf, sizeof(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
ndmca_tt_mtio(struct ndm_session * sess)781 ndmca_tt_mtio (struct ndm_session *sess)
782 {
783 	int		rc;
784 	unsigned	n_rec;
785 	unsigned	recsize;
786 	unsigned	fileno, recno;
787 	uint32_t	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 		snprintf (note, sizeof(note), "Seek around tape file %d", fileno+1);
806 		ndmca_test_open (sess, note, 0);
807 
808 		snprintf (note, sizeof(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 		snprintf (buf, sizeof(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 	snprintf (buf, sizeof(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
ndmca_tt_check_fileno_recno(struct ndm_session * sess,char * what,uint32_t file_num,uint32_t blockno,char * note)966 ndmca_tt_check_fileno_recno (struct ndm_session *sess,
967   char *what, uint32_t file_num, uint32_t 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 	snprintf (buf, sizeof(buf), "Failed %s while testing %s", oper, what);
993 	ndmca_test_log_note (sess, 1, buf);
994 	if (ts) {
995 		snprintf (buf, sizeof(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 		snprintf (buf, sizeof(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 	snprintf (buf, sizeof(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
ndmca_test_tape_open(struct ndm_session * sess,ndmp9_error expect_err,char * device,int mode)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
ndmca_test_tape_close(struct ndm_session * sess,ndmp9_error expect_err)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
ndmca_test_tape_get_state(struct ndm_session * sess,ndmp9_error expect_err)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
ndmca_test_tape_mtio(struct ndm_session * sess,ndmp9_error expect_err,ndmp9_tape_mtio_op op,uint32_t count,uint32_t * resid)1112 ndmca_test_tape_mtio (struct ndm_session *sess, ndmp9_error expect_err,
1113   ndmp9_tape_mtio_op op, uint32_t count, uint32_t *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
ndmca_check_tape_mtio(struct ndm_session * sess,ndmp9_error expect_err,ndmp9_tape_mtio_op op,uint32_t count,uint32_t resid)1129 ndmca_check_tape_mtio (struct ndm_session *sess, ndmp9_error expect_err,
1130 		       ndmp9_tape_mtio_op op, uint32_t count, uint32_t resid)
1131 {
1132     struct ndmconn *	conn = sess->plumb.tape;
1133     uint32_t 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 	snprintf (tmp, sizeof(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
ndmca_test_tape_write(struct ndm_session * sess,ndmp9_error expect_err,char * buf,unsigned count)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
ndmca_test_tape_read(struct ndm_session * sess,ndmp9_error expect_err,char * buf,unsigned count)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
ndmca_test_tape_read_2cnt(struct ndm_session * sess,ndmp9_error expect_err,char * buf,unsigned count,unsigned true_count)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 /* !defined(NDMOS_OPTION_NO_CONTROL_AGENT) && !defined(NDMOS_OPTION_NO_TEST_AGENTS) */
1263