Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / butm / test_ftm.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 #include <limits.h>
16 #include <ctype.h>
17
18 #include <afs/afsutil.h>
19 #include <lwp.h>
20 #include <afs/com_err.h>
21 #include <afs/butm.h>
22
23 #include "error_macros.h"
24
25 int isafile = 0, debugLevel = 1;
26
27 /* Format of the config file is now
28 * <capacity devicename portno isafile>
29 * capacity - size of tape or file in bytes
30 * devicename - tape device or file name to write data into
31 * portno - tape coordinator port no. (irrelevant)
32 * isafile - Is this entry a file or a tape?
33 *
34 * test_ftm goes through the lines in the config file and selects the
35 * entry that has a port no. of 0 and tries to open the device.
36 */
37
38 static char *whoami = "test_TM";
39
40
41 typedef struct TestInfo {
42 char *tapeName; /* tape name */
43 struct tapeConfig *tc_Infop; /* tape config info (size, devname etc..) */
44 int nFiles; /* no. of files to be dumped */
45 char **files; /* names of files to be dumped */
46 char dumpDone; /* event that signals the completion of
47 * the dump test thread.
48 */
49 int appended; /* do an appended test? */
50 } TestInfo;
51
52 struct BufferBlock {
53 char mark[sizeof(struct blockMark)];
54 char data[BUTM_BLKSIZE];
55 } *bufferBlock;
56
57 struct tapeConfig confInfo;
58 char dumpDone;
59 int PerformDumpTest(TestInfo * tip);
60
61 static
62 GetDeviceInfo(filename, config)
63 char *filename;
64 struct tapeConfig *config;
65 {
66 FILE *devFile;
67 char line[356];
68 char devName[256];
69 afs_int32 aport, capacity, notfound;
70 afs_int32 portOffset;
71
72 portOffset = 0;
73 devFile = fopen(filename, "r");
74 if (!devFile) {
75 fprintf(stderr, "failed to open %s\n", filename);
76 return -1;
77 }
78 notfound = 1;
79 while (1) {
80 if (fgets(line, 100, devFile) == NULL)
81 break;
82 sscanf(line, "%u %s %u %u\n", &capacity, devName, &aport, &isafile);
83 if (aport == portOffset) {
84 config->capacity = capacity;
85 config->portOffset = aport;
86 strncpy(config->device, devName, 100);
87 notfound = 0;
88 break;
89 }
90
91 }
92 fclose(devFile);
93 return notfound;
94 }
95
96 #include "AFS_component_version_number.c"
97
98 main(argc, argv)
99 int argc;
100 char *argv[];
101 {
102 char *config = 0;
103 char *tape = "testtape.0", *parent_pid, *pid;
104 afs_int32 code;
105 char **files;
106 int nFiles, i;
107 TestInfo ti;
108
109 whoami = argv[0];
110 initialize_BUTM_error_table();
111 if (argc < 2)
112 goto usage;
113
114 files = malloc(argc * sizeof(char *));
115 nFiles = 0;
116 for (i = 1; i < argc; i++) {
117 if (argv[i][0] == '-') {
118 if (strncmp(argv[i], "-configuration", strlen(argv[i])) == 0)
119 config = argv[++i];
120 else if (strncmp(argv[i], "-tapename", strlen(argv[i])) == 0)
121 tape = argv[++i];
122 else {
123 afs_com_err(whoami, 0, "unexpected command argument: '%s'",
124 argv[i]);
125 goto usage;
126 }
127 } else {
128 struct stat buf;
129 if (stat(argv[i], &buf)) {
130 afs_com_err(whoami, errno, "can't stat filename parameter %s\n",
131 argv[i]);
132 } else {
133 if ((buf.st_mode & S_IFREG) && (buf.st_mode & 0444))
134 files[nFiles++] = argv[i];
135 else
136 printf("skipping non-file '%s'\n", argv[i]);
137 }
138 }
139 }
140 if (nFiles == 0)
141 goto usage;
142
143 if ((strlen(tape) == 0) || (strlen(tape) >= BU_MAXTAPELEN)) {
144 afs_com_err(whoami, 0, "bogus tape name");
145 goto usage;
146 }
147 code = GetDeviceInfo(config, &confInfo);
148 if (code) {
149 afs_com_err(whoami, 0, "cant find tape config info");
150 goto usage;
151 }
152
153 ti.tapeName = tape;
154 ti.tc_Infop = &confInfo;
155 ti.nFiles = nFiles;
156 ti.files = files;
157 ti.appended = 0;
158 printf("%s: Beginning Dump Tests\n", whoami);
159 code = LWP_InitializeProcessSupport(1, &parent_pid);
160 if (code) {
161 afs_com_err(whoami, code, "Can't init LWP lib");
162 exit(1);
163 }
164 code = IOMGR_Initialize();
165 if (code) {
166 afs_com_err(whoami, code, "Can't init LWP IOMGR lib");
167 exit(1);
168 }
169 /* Perform normal test */
170 code =
171 LWP_CreateProcess(PerformDumpTest, 100000, 0, (void *)&ti,
172 "BUTM Tester", &pid);
173 if (code) {
174 afs_com_err(whoami, code, "libbutm.a: Normal Tests failed!. :-( ");
175 exit(code);
176 }
177 LWP_WaitProcess(&ti.dumpDone);
178 LWP_DestroyProcess(pid);
179
180 /* Perform Appended Test, on tapes */
181 if (!isafile) {
182 ti.appended = 1;
183 code =
184 LWP_CreateProcess(PerformDumpTest, 100000, 0, (void *)&ti,
185 "BUTM Tester", &pid);
186 if (code) {
187 afs_com_err(whoami, code, "libbutm.a: Appended Tests failed!. :-( ");
188 exit(code);
189 }
190
191 LWP_WaitProcess(&ti.dumpDone);
192 LWP_DestroyProcess(pid);
193 }
194
195 IOMGR_Finalize();
196 LWP_TerminateProcessSupport();
197
198 exit(code);
199
200 usage:
201 printf
202 ("usage is: %s [-configuration <config file>] [-tapename <name>] <file>*\n",
203 whoami);
204 exit(1);
205 }
206
207
208 int
209 PerformDumpTest(TestInfo * tip)
210 { /* Dump Files into target tape/file */
211 struct butm_tapeInfo info;
212 struct butm_tapeLabel label;
213 int i, past, code;
214 struct timeval tp;
215
216 bufferBlock = malloc(sizeof(struct BufferBlock));
217
218 info.structVersion = BUTM_MAJORVERSION;
219 if (code = butm_file_Instantiate(&info, tip->tc_Infop)) {
220 afs_com_err(whoami, code, "instantiating file tape");
221 ERROR_EXIT(2);
222 }
223
224 memset(&label, 0, sizeof(label));
225 gettimeofday(&tp, NULL);
226 label.structVersion = CUR_TAPE_VERSION;
227 label.creationTime = tp.tv_sec;
228 label.size = info.tapeSize;
229
230 #define T_NAME "AFS 3.5"
231 #define T_INST ""
232 #define T_CELL "cellname"
233 #define T_REALM "cellname"
234 #define T_COMMENT "Testing the butm library.."
235 strcpy(label.AFSName, tip->tapeName);
236 strcpy(label.creator.name, T_NAME);
237 strcpy(label.creator.instance, T_INST);
238 strcpy(label.creator.cell, T_CELL);
239 strcpy(label.cell, T_REALM);
240 strcpy(label.comment, T_COMMENT);
241
242 if (code = butm_Mount(&info, tip->tapeName)) {
243 afs_com_err(whoami, code, "setting up tape");
244 ERROR_EXIT(2);
245 }
246 if (tip->appended) { /* This is to be an appended dump */
247 code = butm_SeekEODump(&info, tip->nFiles + 1);
248 if (code) {
249 afs_com_err(whoami, code,
250 "Can't append: Can't position to end of dump on tape\n");
251 ERROR_EXIT(code);
252 }
253 }
254 if ((code = butm_Create(&info, &label, !tip->appended /*Rewind */ ))) {
255 afs_com_err(whoami, code, "Writing tape label");
256 ERROR_EXIT(2);
257 }
258
259
260 for (i = 0; i < tip->nFiles; i++) {
261 int len;
262 int fid = open(tip->files[i], O_RDONLY, 0);
263 if (fid < 0) {
264 afs_com_err(whoami, errno, "opening file to write on tape");
265 ERROR_EXIT(3);
266 }
267 if (code = butm_WriteFileBegin(&info)) {
268 afs_com_err(whoami, code, "beginning butm write file");
269 ERROR_EXIT(3);
270 }
271 while ((len = read(fid, bufferBlock->data, BUTM_BLKSIZE)) > 0) {
272 if (code = butm_WriteFileData(&info, bufferBlock->data, 1, len)) {
273 afs_com_err(whoami, code, "butm writing file data");
274 ERROR_EXIT(3);
275 }
276 }
277 if (len < 0) {
278 afs_com_err(whoami, errno, "reading file data");
279 ERROR_EXIT(3);
280 }
281 if (code = butm_WriteFileEnd(&info)) {
282 afs_com_err(whoami, code, "ending butm write file");
283 ERROR_EXIT(3);
284 }
285 if (close(fid) < 0) {
286 afs_com_err(whoami, errno, "closing file");
287 ERROR_EXIT(3);
288 }
289 }
290 if ((code = butm_WriteEOT(&info)) || (code = butm_Dismount(&info))) {
291 afs_com_err(whoami, code, "finishing up tape");
292 ERROR_EXIT(4);
293 }
294
295 /* now read the tape back in and make sure everything is OK */
296
297 label.structVersion = BUTM_MAJORVERSION;
298 if (code = butm_Mount(&info, tip->tapeName)) {
299 afs_com_err(whoami, code, "setting up tape");
300 ERROR_EXIT(5);
301 }
302 if (tip->appended) { /* This is to be an appended dump */
303 code = butm_SeekEODump(&info, tip->nFiles + 1);
304 if (code) {
305 afs_com_err(whoami, code,
306 "Can't append: Can't position to end of dump on tape\n");
307 ERROR_EXIT(code);
308 }
309 }
310 if (code = butm_ReadLabel(&info, &label, !tip->appended /*rewind */ )) {
311 afs_com_err(whoami, code, "reading tape label");
312 ERROR_EXIT(5);
313 }
314 past = time(0) - label.creationTime;
315 if ((past < 0) || (past > 5 * 60)) {
316 time_t t = label.creationTime;
317 printf("label creation time is long ago: %s\n", ctime(&t));
318 ERROR_EXIT(5);
319 }
320 if (strcmp(label.AFSName, tip->tapeName) != 0) {
321 printf("label tape name is bogus: %s, should be %s\n", label.AFSName,
322 tip->tapeName);
323 ERROR_EXIT(5);
324 }
325 if ((strcmp(label.creator.name, T_NAME) != 0)
326 || (strcmp(label.creator.instance, T_INST) != 0)
327 || (strcmp(label.creator.cell, T_CELL) != 0)
328 || (strcmp(label.cell, T_REALM) != 0)
329 || (strcmp(label.comment, T_COMMENT) != 0)) {
330 printf("label strings are bad: creator %s.%s@%s from realm %s (%s)\n",
331 label.creator.name, label.creator.instance, label.creator.cell,
332 label.cell, label.comment);
333 ERROR_EXIT(5);
334 }
335 for (i = 0; i < sizeof(label.spare); i++)
336 if (*(char *)label.spare) {
337 printf("Label's spare fields not zero\n");
338 ERROR_EXIT(5);
339 }
340
341 for (i = 0; i < tip->nFiles; i++) {
342 char *tbuffer = bufferBlock->data;
343 int tlen;
344 char fbuffer[BUTM_BLKSIZE];
345 int flen;
346 int tprogress, fprogress;
347 int fid;
348
349 fid = open(tip->files[i], O_RDONLY, 0);
350 if (fid < 0) {
351 afs_com_err(whoami, errno, "Opening %dth file to compare with tape",
352 i + 1);
353 ERROR_EXIT(6);
354 }
355 if (code = butm_ReadFileBegin(&info)) {
356 afs_com_err(whoami, code, "Beginning butm %dth read file", i + 1);
357 ERROR_EXIT(6);
358 }
359
360 tprogress = tlen = fprogress = flen = 0;
361 while (1) {
362 memset(tbuffer, 0, BUTM_BLKSIZE);
363 code = butm_ReadFileData(&info, tbuffer, BUTM_BLKSIZE, &tlen);
364
365 if (code && code != BUTM_STATUS_EOF) {
366 afs_com_err(whoami, code, "Reading %dth tape data", i + 1);
367 ERROR_EXIT(6);
368 }
369 memset(fbuffer, 0, BUTM_BLKSIZE);
370 flen = read(fid, fbuffer, sizeof(fbuffer));
371 if (flen < 0) {
372 afs_com_err(whoami, errno, "Reading %dth file data", i + 1);
373 ERROR_EXIT(6);
374 }
375 if (code == BUTM_STATUS_EOF)
376 break;
377 if ((tlen == 0) && (flen == 0))
378 break; /* correct termination */
379 if (flen != tlen) {
380 printf("File length mismatch for %dth file (%s)\n", i,
381 tip->files[i]);
382 ERROR_EXIT(6);
383 }
384 if (tbuffer[tprogress++] != fbuffer[fprogress++]) {
385 printf("Data mismatch for %dth file (%s)\n", i + 1,
386 tip->files[i]);
387 ERROR_EXIT(6);
388 }
389 if (tlen < BUTM_BLKSIZE)
390 break;
391 }
392
393 if (code = butm_ReadFileEnd(&info)) {
394 afs_com_err(whoami, code, "Ending butm %dth read file", i + 1);
395 ERROR_EXIT(7);
396 }
397 if (close(fid) < 0) {
398 afs_com_err(whoami, errno, "Closing %dth file", i + 1);
399 ERROR_EXIT(7);
400 }
401 }
402
403 if ((info.status & BUTM_STATUS_EOD) == 0) {
404 code = butm_ReadFileBegin(&info);
405 if (code && (code != BUTM_EOD)) {
406 afs_com_err(whoami, code, "Should have encountered an 'End Of Tape'");
407 ERROR_EXIT(8);
408 }
409 }
410 if (code = butm_Dismount(&info)) {
411 afs_com_err(whoami, code, "Finishing up tape");
412 ERROR_EXIT(8);
413 }
414
415 if (tip->appended)
416 printf("%d files Appended: All OK\n", tip->nFiles);
417 else
418 printf("%d files written: All OK\n", tip->nFiles);
419 ERROR_EXIT(0);
420 error_exit:
421 LWP_SignalProcess(&tip->dumpDone);
422 return (code);
423 }