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