include-afsconfig-before-param-h-20010712
[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("$Header$");
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 GetDeviceInfo(filename,config)
72 char *filename;
73 struct tapeConfig *config;
74 {
75     FILE *devFile;
76     char line[356];
77     char devName[256];
78     afs_int32 aport,capacity,notfound;
79     afs_int32 portOffset;
80
81     portOffset = 0;
82     devFile = fopen(filename,"r");
83     if(!devFile){
84         fprintf(stderr,"failed to open %s\n",filename);
85         return -1;
86     }
87     notfound = 1;
88     while(1){
89         if(fgets(line,100,devFile) == NULL) break;
90         sscanf(line,"%u %s %u %u\n",&capacity,devName,&aport, &isafile);
91         if(aport == portOffset){
92             config->capacity = capacity;
93             config->portOffset = aport;
94             strncpy(config->device,devName,100);
95             notfound = 0;
96             break;
97         }
98             
99     }
100     fclose(devFile);
101     return notfound;
102 }
103
104 #include "AFS_component_version_number.c"
105
106 main (argc, argv)
107   int   argc;
108   char *argv[];
109 {   char *config = 0;
110     char *tape = "testtape.0", *parent_pid, *pid;
111     afs_int32  code;
112     char **files;
113     int   nFiles, i;
114     TestInfo ti;
115
116     whoami = argv[0];
117     initialize_butm_error_table();
118     if (argc < 2) 
119       goto usage;
120
121     files = (char **)malloc (argc*sizeof(char *));
122     nFiles = 0;
123     for (i=1; i<argc; i++) {
124         if (argv[i][0] == '-') {
125             if (strncmp (argv[i], "-configuration", strlen(argv[i])) == 0)
126                 config = argv[++i];
127             else if (strncmp (argv[i], "-tapename", strlen(argv[i])) == 0)
128                 tape = argv[++i];
129             else  {
130                 com_err (whoami, 0, "unexpected command argument: '%s'", argv[i]);
131                 goto usage;
132             }
133         }
134         else {
135             struct stat buf;
136             if (stat (argv[i], &buf)) {
137                 com_err (whoami, errno, "can't stat filename parameter %s\n", argv[i]);
138             } else {
139                 if ((buf.st_mode & S_IFREG) && (buf.st_mode & 0444))
140                     files[nFiles++] = argv[i];
141                 else printf ("skipping non-file '%s'\n", argv[i]);
142             }
143         }
144     }
145     if (nFiles == 0) goto usage;
146
147     if ((strlen (tape) == 0) || (strlen (tape) >= BU_MAXTAPELEN)) {
148         com_err (whoami, 0, "bogus tape name");
149         goto usage;
150     }
151     code = GetDeviceInfo(config, &confInfo);
152     if(code){
153         com_err(whoami,0,"cant find tape config info");
154         goto usage;
155     }
156
157     ti.tapeName = tape;
158     ti.tc_Infop = &confInfo;
159     ti.nFiles = nFiles;
160     ti.files = files;
161     ti.appended = 0;
162     printf("%s: Beginning Dump Tests\n", whoami);
163     code = LWP_InitializeProcessSupport(1, &parent_pid);
164     if (code) {
165       com_err(whoami,code,"Can't init LWP lib");
166       exit(1);
167     }
168     code = IOMGR_Initialize();
169     if (code) {
170       com_err(whoami,code,"Can't init LWP IOMGR lib");
171       exit(1);
172     }
173     /* Perform normal test */
174     code = LWP_CreateProcess(PerformDumpTest, 100000, 0, &ti ,
175                              "BUTM Tester", &pid);
176     if (code) {
177       com_err(whoami,code,"libbutm.a: Normal Tests failed!. :-( ");
178       exit(code);
179     }
180     LWP_WaitProcess(&ti.dumpDone);
181     LWP_DestroyProcess(pid);
182
183     /* Perform Appended Test, on tapes */
184     if (!isafile) {
185       ti.appended = 1;
186       code = LWP_CreateProcess(PerformDumpTest, 100000, 0, &ti ,
187                                "BUTM Tester", &pid);
188       if (code) {
189         com_err(whoami,code,"libbutm.a: Appended Tests failed!. :-( ");
190         exit(code);
191       }
192       
193       LWP_WaitProcess(&ti.dumpDone);
194       LWP_DestroyProcess(pid);
195     }
196
197     IOMGR_Finalize();
198     LWP_TerminateProcessSupport();
199
200     exit(code);
201
202   usage:
203     printf ("usage is: %s [-configuration <config file>] [-tapename <name>] <file>*\n", whoami);
204     exit (1);
205 }
206
207
208 int PerformDumpTest(TestInfo *tip)
209 { /* Dump Files into target tape/file */
210   struct butm_tapeInfo info;
211   struct butm_tapeLabel label;
212   int i, past, code;
213   struct timeval tp;
214
215   bufferBlock = (struct BufferBlock *) malloc(sizeof(struct BufferBlock));
216
217   info.structVersion = BUTM_MAJORVERSION;
218   if (code = butm_file_Instantiate (&info, tip->tc_Infop)) {
219     com_err (whoami, code, "instantiating file tape");
220     ERROR_EXIT (2);
221   }
222   
223   bzero(&label, sizeof(label));
224   gettimeofday(&tp, 0);
225   label.structVersion = CUR_TAPE_VERSION;
226   label.creationTime = tp.tv_sec;
227   label.size = info.tapeSize;
228
229 #define T_NAME "AFS 3.5"
230 #define T_INST ""
231 #define T_CELL "cellname"
232 #define T_REALM "cellname"
233 #define T_COMMENT "Testing the butm library.."
234   strcpy(label.AFSName, tip->tapeName);
235   strcpy (label.creator.name, T_NAME);
236   strcpy (label.creator.instance, T_INST);
237   strcpy (label.creator.cell, T_CELL);
238   strcpy (label.cell, T_REALM);
239   strcpy (label.comment, T_COMMENT);
240   
241   if (code = butm_Mount (&info, tip->tapeName)) {
242     com_err (whoami, code, "setting up tape");
243     ERROR_EXIT(2);
244   } 
245   if (tip->appended) { /* This is to be an appended dump */
246     code = butm_SeekEODump(&info, tip->nFiles+1);
247     if (code)       {
248       com_err(whoami, code, 
249                "Can't append: Can't position to end of dump on tape\n");
250       ERROR_EXIT(code);
251     }
252   }
253   if ((code = butm_Create(&info, &label, !tip->appended/*Rewind*/))){
254     com_err (whoami, code, "Writing tape label");
255     ERROR_EXIT(2);
256   }
257   
258   
259   for (i=0; i<tip->nFiles; i++) {
260     int len;
261     int fid = open (tip->files[i], O_RDONLY, 0);
262     if (fid < 0) {
263       com_err (whoami, errno, "opening file to write on tape");
264       ERROR_EXIT(3);
265     }
266     if (code = butm_WriteFileBegin (&info)) {
267       com_err (whoami, code, "beginning butm write file");
268       ERROR_EXIT(3);
269     }
270     while ((len = read (fid, bufferBlock->data, BUTM_BLKSIZE)) > 0) {
271       if (code = butm_WriteFileData (&info, bufferBlock->data, 1, len)) {
272         com_err (whoami, code, "butm writing file data");
273         ERROR_EXIT(3);
274       }
275     }
276     if (len < 0) {
277       com_err (whoami, errno, "reading file data");
278       ERROR_EXIT(3);
279     }
280     if (code = butm_WriteFileEnd (&info)) {
281       com_err (whoami, code, "ending butm write file");
282       ERROR_EXIT(3);
283     }
284     if (close (fid) < 0) {
285       com_err (whoami, errno, "closing file");
286       ERROR_EXIT(3);
287     }
288   }
289   if ((code = butm_WriteEOT (&info)) ||
290       (code = butm_Dismount (&info))) {
291     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     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       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     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     printf ("label creation time is long ago: %s\n", ctime (&label.creationTime));
317     ERROR_EXIT(5);
318   }
319   if (strcmp (label.AFSName, tip->tapeName) != 0) {
320     printf ("label tape name is bogus: %s, should be %s\n", label.AFSName, tip->tapeName);
321     ERROR_EXIT(5);
322   }
323   if ((strcmp (label.creator.name, T_NAME) != 0) ||
324       (strcmp (label.creator.instance, T_INST) != 0) ||
325       (strcmp (label.creator.cell, T_CELL) != 0) ||
326       (strcmp (label.cell, T_REALM) != 0) ||
327       (strcmp (label.comment, T_COMMENT) != 0)){
328     printf ("label strings are bad: creator %s.%s@%s from realm %s (%s)\n",
329             label.creator.name, label.creator.instance, label.creator.cell,
330             label.cell, label.comment);
331     ERROR_EXIT(5);
332   }
333   for (i=0; i<sizeof(label.spare); i++) if (*(char *)label.spare) {
334     printf ("Label's spare fields not zero\n");
335     ERROR_EXIT(5);
336   }
337   
338   for (i=0; i<tip->nFiles; i++) {
339     char *tbuffer = bufferBlock->data;
340     int  tlen;
341     char fbuffer[BUTM_BLKSIZE];
342     int  flen;
343     int  tprogress, fprogress;
344     int  fid;
345     
346     fid = open (tip->files[i], O_RDONLY, 0);
347     if (fid < 0) {
348       com_err (whoami, errno, "Opening %dth file to compare with tape", i+1);
349       ERROR_EXIT(6);
350     }
351     if (code = butm_ReadFileBegin (&info)) {
352       com_err (whoami, code, "Beginning butm %dth read file", i+1);
353       ERROR_EXIT(6);
354     }
355     
356     tprogress = tlen = fprogress = flen = 0;
357     while (1) {
358       bzero(tbuffer,BUTM_BLKSIZE);
359       code = butm_ReadFileData (&info, tbuffer, BUTM_BLKSIZE, &tlen);
360       
361       if (code && code != BUTM_STATUS_EOF) {
362         com_err (whoami, code, "Reading %dth tape data", i+1);
363         ERROR_EXIT(6);
364       }
365       bzero(fbuffer,BUTM_BLKSIZE);
366       flen = read (fid, fbuffer, sizeof(fbuffer));
367       if (flen < 0) {
368         com_err (whoami, errno, "Reading %dth file data", i+1);
369         ERROR_EXIT(6);
370       }
371       if(code == BUTM_STATUS_EOF)
372         break;
373       if ((tlen == 0) && (flen == 0)) break; /* correct termination */
374       if (flen != tlen) {
375         printf ("File length mismatch for %dth file (%d)\n", i, tip->files[i]);
376         ERROR_EXIT(6);
377       }
378       if (tbuffer[tprogress++] != fbuffer[fprogress++]) {
379         printf ("Data mismatch for %dth file (%s)\n", i+1, tip->files[i]);
380         ERROR_EXIT(6);
381       }
382       if(tlen < BUTM_BLKSIZE)
383         break;
384     }
385     
386     if (code = butm_ReadFileEnd (&info)) {
387       com_err (whoami, code,"Ending butm %dth read file", i+1);
388       ERROR_EXIT(7);
389     }
390     if (close (fid) < 0) {
391       com_err (whoami, errno, "Closing %dth file", i+1);
392       ERROR_EXIT(7);
393     }
394   }
395   
396   if ((info.status & BUTM_STATUS_EOD) == 0) {
397     code = butm_ReadFileBegin (&info);
398     if (code && (code != BUTM_EOD)) {
399     should_eot:
400       com_err (whoami, code, "Should have encountered an 'End Of Tape'");
401       ERROR_EXIT(8);
402     }
403   }
404   if (code = butm_Dismount (&info)) {
405     com_err (whoami, code, "Finishing up tape");
406     ERROR_EXIT(8);
407   }
408   
409   if (tip->appended)
410     printf ("%d files Appended: All OK\n", tip->nFiles);
411   else
412     printf ("%d files written: All OK\n", tip->nFiles);
413   ERROR_EXIT(0);
414 error_exit:
415   LWP_SignalProcess(&tip->dumpDone);
416   return(code);
417 }
418
419