1d86c58ca337775b9140423cbae80ef09565a18f
[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 = (char **)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 = (struct 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, 0);
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 }