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