cmd: add flags argument to create syntax function
[openafs.git] / src / bu_utils / fms.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 <afs/procmgmt.h>
14 #include <roken.h>
15
16 #include <afs/cmd.h>
17 #include <afs/usd.h>
18
19 /* structure for writing data to tape */
20 typedef struct tapeDataBuffer {
21     struct tapeDataBuffer *tdb_next;
22     char *tdb_buffer;
23 } tapeDataBufferT;
24 typedef tapeDataBufferT *tapeDataBufferP;
25
26 /* globals */
27 char *tapeDevice = 0;           /* device pathname */
28 afs_int32 eotEnabled = 1;
29
30 /* prototypes */
31 int fileMark(usd_handle_t hTape);
32 int fileMarkSize(char *tapeDevice);
33 static int tt_fileMarkSize(struct cmd_syndesc *as, void *arock);
34 afs_int32 rewindTape(usd_handle_t hTape);
35 int dataBlock(usd_handle_t, afs_int32);
36
37 #define ERROR(evalue) do {                                      \
38             code = evalue;                                      \
39             goto error_exit;                                    \
40         } while (0)
41
42 #define MAXV    100
43
44 #ifndef AFS_NT40_ENV
45 #include "AFS_component_version_number.c"
46 #endif
47
48 void quitFms(int);
49
50 int
51 main(int argc, char **argv)
52 {
53     struct sigaction intaction, oldaction;
54     struct cmd_syndesc *cptr;
55
56     memset(&intaction, 0, sizeof(intaction));
57     intaction.sa_handler = quitFms;
58
59     sigaction(SIGINT, &intaction, &oldaction);
60
61     cptr =
62         cmd_CreateSyntax(NULL, tt_fileMarkSize, NULL, 0,
63                          "write a tape full of file marks");
64     cmd_AddParm(cptr, "-tape", CMD_SINGLE, CMD_REQUIRED, "tape special file");
65
66     cmd_Dispatch(argc, argv);
67     return 0;
68 }
69
70 static int
71 tt_fileMarkSize(struct cmd_syndesc *as, void *arock)
72 {
73     char *tapeDevice;
74
75     tapeDevice = as->parms[0].items->data;
76
77     fileMarkSize(tapeDevice);
78
79     return 0;
80 }
81
82
83 int
84 fileMarkSize(char *tapeDevice)
85 {
86     afs_uint32 nFileMarks, nBlocks, nbfTape;
87     double tpSize, fmSize;
88     afs_uint32 bufferSize = 16384;
89     usd_handle_t hTape;
90     FILE *logFile;
91     int count = 0;
92     afs_uint32 countr;
93     afs_int32 code = 0;
94
95     code =
96         usd_Open(tapeDevice, (USD_OPEN_RDWR | USD_OPEN_WLOCK), 0777, &hTape);
97     if (code) {
98         printf("Can't open tape device %s\n", tapeDevice);
99         fflush(stdout);
100         exit(1);
101     }
102
103     logFile = fopen("fms.log", "w+");
104     if (logFile == NULL) {
105         printf("Can't open log file\n");
106         fflush(stdout);
107         exit(1);
108     }
109     fprintf(logFile, "fms test started\n");
110     fflush(logFile);
111
112     code = rewindTape(hTape);
113     if (code) {
114         fprintf(logFile, "Can't rewind tape\n");
115         fflush(logFile);
116         ERROR(code);
117     }
118
119     /* measure capacity of tape */
120     nbfTape = 0;
121     countr = 0;
122     while (1) {
123         code = dataBlock(hTape, bufferSize);
124         nbfTape++;
125         count++;
126         countr++;
127         if (code)
128             break;
129
130         if (count >= 5) {
131             count = 0;
132             printf("\rwrote block: %d", nbfTape);
133         }
134
135     }
136
137     fprintf(logFile, "wrote %d blocks\n", nbfTape);
138     fflush(logFile);
139     printf("\rwrote %d blocks\n", nbfTape);
140     printf("Finished data capacity test - rewinding\n");
141     /* reset the tape device */
142     code = USD_CLOSE(hTape);
143     if (code) {
144         fprintf(logFile, "Can't close tape device at end of pass 1\n");
145         fflush(logFile);
146         printf("Can't close tape device %s\n", tapeDevice);
147         goto error_exit;
148     }
149     code =
150         usd_Open(tapeDevice, (USD_OPEN_RDWR | USD_OPEN_WLOCK), 0777, &hTape);
151     if (code) {
152         fprintf(logFile, "Can't open tape device for pass 2\n");
153         fflush(logFile);
154         printf("Can't open tape device %s\n", tapeDevice);
155         goto error_exit;
156     }
157
158     code = rewindTape(hTape);
159     if (code) {
160         fprintf(logFile, "Can't rewind tape\n");
161         fflush(logFile);
162         ERROR(code);
163     }
164
165     /* now measure file mark size */
166     nFileMarks = 0;
167     nBlocks = 0;
168     count = 0;
169     countr = 0;
170     while (1) {
171         code = dataBlock(hTape, bufferSize);
172         nBlocks++;
173         if (code)
174             break;
175         code = fileMark(hTape);
176         nFileMarks++;
177         if (code)
178             break;
179         count++;
180         countr++;
181
182         if (count >= 2) {
183             count = 0;
184             printf("\rwrote %d blocks, %d filemarks", nBlocks, nFileMarks);
185         }
186
187     }
188     printf("\nFinished filemark test\n");
189     tpSize = (double)nbfTape *(double)bufferSize;
190     fmSize =
191         (((double)nbfTape -
192           (double)nBlocks) * (double)bufferSize) / (double)nFileMarks;
193     printf("Tape capacity is %.0f bytes\n", tpSize);
194     printf("File marks are %.0f bytes\n", fmSize);
195     fprintf(logFile, "Tape capacity is %.0f bytes\n", tpSize);
196     fprintf(logFile, "File marks are %.0f bytes\n", fmSize);
197     fflush(logFile);
198     fclose(logFile);
199   error_exit:
200     USD_CLOSE(hTape);
201     return (code);
202 }
203
204 void
205 quitFms(int sig)
206 {
207     exit(0);
208 }
209
210
211 /* --------------------------
212  * device handling routines
213  * --------------------------
214  */
215
216 /* rewindTape() - rewinds tape to beginning */
217 afs_int32
218 rewindTape(usd_handle_t hTape)
219 {
220     usd_tapeop_t tapeop;
221     int rcode;
222
223     tapeop.tp_op = USDTAPE_REW;
224     tapeop.tp_count = 1;
225     rcode = USD_IOCTL(hTape, USD_IOCTL_TAPEOPERATION, (void *)&tapeop);
226     return rcode;
227 }
228
229 /* write an EOF marker */
230 int
231 fileMark(usd_handle_t hTape)
232 {
233     usd_tapeop_t tapeop;
234     int rcode;
235
236     tapeop.tp_op = USDTAPE_WEOF;
237     tapeop.tp_count = 1;
238     rcode = USD_IOCTL(hTape, USD_IOCTL_TAPEOPERATION, (void *)&tapeop);
239     return rcode;
240 }
241
242 /* dataBlock
243  *      write a block of data on tape
244  * entry:
245  *      blocksize - size of block in bytes
246  */
247 int
248 dataBlock(usd_handle_t hTape, afs_int32 reqSize)
249 {
250     static char *dB_buffer = 0;
251     static afs_int32 dB_buffersize = 0;
252     static int dB_count = 0;
253     int *ptr;
254     afs_int32 code = 0;
255     afs_uint32 xferd;
256
257     /* dbBuffersize is only valid when dB_buffer is non-zero */
258
259     if ((dB_buffer != 0)
260         && (dB_buffersize != reqSize)
261         ) {
262         free(dB_buffer);
263         dB_buffer = 0;
264     }
265
266     if (dB_buffer == 0) {
267         dB_buffer = calloc(1, reqSize);
268         if (dB_buffer == 0)
269             ERROR(-1);
270         dB_buffersize = reqSize;
271     }
272
273     ptr = (int *)dB_buffer;
274     *ptr = dB_count++;
275
276     code = USD_WRITE(hTape, dB_buffer, dB_buffersize, &xferd);
277     if (code || xferd != dB_buffersize)
278         ERROR(-1);
279
280   error_exit:
281     return (code);
282 }