vlserver: remove an unused global
[openafs.git] / src / vlserver / sascnvldb.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 #include <afs/stds.h>
13
14 #include <sys/file.h>
15 #include <afs/venus.h>
16 #include <afs/cmd.h>
17 #include <afs/afs_consts.h>
18
19 #include "cnvldb.h"             /* CHANGEME! */
20
21 static char pn[] = "cnvldb";
22 static char tempname[] = "XXnewvldb";
23 static char space[AFS_PIOCTL_MAXSIZE];
24 static int MaxServers[2] = { 30, 254 }; /* max server # permitted in this version */
25
26 #ifdef notdef                   /* postpone this... */
27 static int
28 saferead(fd, addr, osize)
29      int fd, osize;
30      char *addr;
31 {
32     int rc, size;
33     char *ptr;
34
35     if (size == EOF)
36         return (EOF);
37
38     ptr = addr;
39     rc = osize = size;
40
41     while (rc != EOF) {
42         rc = read(fd, ptr, size)) {
43             if (rc == size)
44                 return osize;
45             else {
46                 if (errno != EINTR) {
47                     perror(pn);
48                     exit(-1);
49                 }
50             }
51         }
52     }
53
54
55     static int
56       saferead(fd, addr, osize)
57     int fd, osize;
58     char *addr;
59     {
60         int rc;
61
62         rc = read(fd, addr, osize);
63         if (rc != osize && rc != EOF) {
64             perror(pn);
65             exit(-1);
66         }
67         return (rc);
68     }
69 #else
70 #define saferead(fd,addr,siz) read((fd),(addr),(siz))
71 #endif
72
73 static char tspace[1024];       /* chdir can't handle anything bigger, anyway */
74 /* return a static pointer to a buffer */
75 static char *
76 Parent(apath)
77      char *apath;
78 {
79     char *tp;
80     strcpy(tspace, apath);
81     tp = strrchr(tspace, '/');
82     if (tp) {
83         *tp = 0;
84     } else
85         strcpy(tspace, ".");
86     return tspace;
87 }
88
89 #ifdef notdef
90
91 /* this function returns TRUE (1) if the file is in AFS, otherwise false (0) */
92 static int
93 InAFS(apath)
94      char *apath;
95 {
96     struct ViceIoctl blob;
97     afs_int32 code;
98
99     blob.in_size = 0;
100     blob.out_size = AFS_PIOCTL_MAXSIZE;
101     blob.out = space;
102
103     code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1);
104     if (code) {
105         if ((errno == EINVAL) || (errno == ENOENT))
106             return 0;
107     }
108     return 1;
109 }
110
111 QuickPrintStatus(status, name)
112      struct VolumeStatus *status;
113      char *name;
114 {
115     double QuotaUsed = 0.0;
116     double PartUsed = 0.0;
117     int WARN = 0;
118
119     if (status->MaxQuota != 0) {
120         QuotaUsed =
121             ((((double)status->BlocksInUse) / status->MaxQuota) * 100.0);
122     } else {
123         /* no limit */
124     }
125     PartUsed =
126         (100.0 -
127          ((((double)status->PartBlocksAvail) / status->PartMaxBlocks) *
128           100.0));
129 }
130
131
132 static int
133 ListQuotaCmd(struct cmd_syndesc *as, void *arock)
134 {
135     afs_int32 code;
136     struct ViceIoctl blob;
137     struct cmd_item *ti;
138     struct VolumeStatus *status;
139     char *name;
140
141     for (ti = as->parms[0].items; ti; ti = ti->next) {
142         /* once per file */
143         blob.out_size = AFS_PIOCTL_MAXSIZE;
144         blob.in_size = 0;
145         blob.out = space;
146         code = pioctl(ti->data, VIOCGETVOLSTAT, &blob, 1);
147         if (code) {
148             Die(code, ti->data);
149             continue;
150         }
151         status = (struct VolumeStatus *)space;
152         name = (char *)status + sizeof(*status);
153         QuickPrintStatus(status, name);
154     }
155     return 0;
156 }
157 #endif /* notdef */
158
159 int gc = 1, fromvers = 1, tovers = 2;
160 char *pathname = NULL, *defaultpath = "/usr/afs/db/vl.DB0";
161
162 usage()
163 {
164     fprintf(stderr, "usage: %s ", pn);
165     fprintf(stderr, "[-name <pathname>] [-help]\n");
166 }
167
168 getargs(argc, argv)
169      int argc;
170      char **argv;
171 {
172     int pos, i;
173     pos = 0;
174
175     for (i = 1; i < argc; i++) {
176         if (!argv[i])
177             break;
178         else if (*(argv[i]) != '-') {   /* positional params */
179             if (!pathname)
180                 pathname = argv[i];
181             else {
182                 fprintf(stderr, "%s: Too many parameters!\n");
183                 usage();
184                 exit(-1);
185             }
186         } else                  /* keyword params */
187             switch (argv[i][1]) {
188
189             case 't':           /* -to */
190                 fprintf(stderr, "%s: can't specify version with this tool!\n",
191                         pn);
192                 exit(-1);
193                 break;
194
195             case 'f':           /* -from */
196                 fprintf(stderr, "%s: can't specify version with this tool!\n",
197                         pn);
198                 break;
199
200             case 'n':           /* -name */
201                 if (pathname) {
202                     fprintf(stderr,
203                             "%s: -name specified (or implied) twice!\n", pn);
204                     exit(-1);
205                 }
206                 pathname = argv[++i];
207                 break;
208
209             case 'h':           /* -help */
210                 usage();
211                 exit(0);
212                 break;
213
214             case 'g':           /* -gc == No GC */
215                 gc = 0;
216                 break;
217
218             default:
219                 usage();
220                 exit(EINVAL);
221             }
222     }
223
224     if (!pathname)
225         pathname = defaultpath;
226 }
227
228 #include "AFS_component_version_number.c"
229
230 main(argc, argv)
231      int argc;
232      char **argv;
233 {
234     afs_int32 code;
235     int old, new, rc;
236     short uvers;
237     char ubik[80];              /* space for some ubik header */
238
239     union {
240         struct vlheader_1 header1;
241         struct vlheader_2 header2;
242     } oldheader, newheader;     /* large enough for either */
243
244     union {
245         struct vlentry_1 entry1;
246         struct vlentry_2 entry2;
247     } vlentry;
248
249
250     getargs(argc, argv);
251
252     /* should stat() the old vldb, get its size, and see if there's */
253     /* room for another.  It might be in AFS, so check the quota, too */
254     if (!(old = open(pathname, O_RDONLY))) {
255         perror(pn);
256         exit(-1);
257     }
258
259     if (chdir(Parent(pathname))) {
260         perror(pn);
261         exit(-1);
262     }
263
264     if (!(new = open(tempname, O_WRONLY | O_CREAT | O_TRUNC, 0600))) {
265         perror(pn);
266         exit(-1);
267     }
268
269     if (fromvers == 0) {        /* not set */
270         lseek(old, 64, L_SET);
271         read(old, &fromvers, sizeof(int));
272         fromvers = ntohl(fromvers);
273         lseek(old, 0, L_SET);   /* go back to beginning */
274     }
275
276     /* skip the UBIK data */
277     read(old, ubik, 64);
278 #ifdef notdef
279     uvers = ntohs(uvers);
280     uvers += 10;                /* hey, if you screw with the VLDB, you lose */
281     uvers = htons(uvers);
282 #endif
283     write(new, ubik, 64);
284
285     readheader(old, fromvers, &oldheader);
286     convert_header(new, fromvers, tovers, &oldheader, &newheader);
287     while ((rc = read(old, &vlentry, sizeof(struct vlentry_1))) && rc != EOF) {
288         convert_vlentry(new, fromvers, tovers, &oldheader, &newheader,
289                         &vlentry);
290     }
291
292
293     if (gc)
294         rewrite_header(new, tovers, &newheader);
295
296     close(old);
297     if (fsync(new)) {
298         perror(pn);
299         exit(-1);
300     }
301
302     close(new);
303     rename(tempname, pathname);
304     exit(0);
305 }
306
307 readheader(fd, version, addr)
308      int fd;
309      int version;
310      char *addr;
311 {
312     if (version == 1) {
313         read(fd, addr, sizeof(struct vlheader_2));      /* it's not a bug, it's SAS */
314     } else if (version == 2) {
315         read(fd, addr, sizeof(struct vlheader_2));
316     } else
317         return EINVAL;
318
319     return 0;
320 }
321
322 /* SAS special */
323 convert_header(fd, fromv, tov, fromaddr, toaddr)
324      int fd, fromv, tov;
325      char *fromaddr, *toaddr;
326 {
327     struct vlheader_2 *tvp1;
328     struct vlheader_2 *tvp2;
329     int i, j, diff;
330
331     memcpy(toaddr, fromaddr, sizeof(struct vlheader_2));
332     tvp2 = (struct vlheader_2 *)toaddr;
333     tvp2->vital_header.vldbversion = htonl(2);
334
335     write(fd, tvp2, sizeof(struct vlheader_2));
336
337     /* for garbage-collecting... */
338     if (gc)
339         for (i = 0; i < 254; i++)
340             tvp2->IpMappedAddr[i] = 0;
341
342     return 0;
343 }
344
345 static int
346 convert_vlentry(new, fromvers, tovers, oldheader, newheader, vlentry)
347      int new, fromvers, tovers;
348      struct vlheader_1 *oldheader, *newheader;  /* close enough */
349      struct vlentry_1 *vlentry; /* 1 and 2 are identical */
350 {
351     int diff, i, s;
352
353 #ifndef DEBUG
354     if (fromvers != tovers) {   /* only supports 1 and 2 currently */
355 #endif
356
357         diff =
358             (tovers ==
359              1 ? sizeof(struct vlheader_1) : sizeof(struct vlheader_2))
360             - (fromvers ==
361                1 ? sizeof(struct vlheader_1) : sizeof(struct vlheader_2));
362
363         for (i = 0; i < 3; i++)
364             vlentry->nextIdHash[i] =
365                 htonl(ntohl(vlentry->nextIdHash[i]) + diff);
366
367         vlentry->nextNameHash = htonl(ntohl(vlentry->nextNameHash) + diff);
368
369 #ifndef DEBUG
370     } else {
371         ;                       /* no change, we're just in it for the GC */
372     }
373 #endif
374
375     for (i = 0; i < 8; i++) {
376         s = vlentry->serverNumber[i];
377         if (s != 255) {
378             if (s > 254) {
379                 fprintf(stderr,
380                         "%s: Too Many Servers (%d) for this version!\n", pn,
381                         s + 1);
382                 exit(-1);
383             } else {
384                 newheader->IpMappedAddr[s] = oldheader->IpMappedAddr[s];
385             }
386         }
387     }
388     write(new, vlentry, sizeof(struct vlentry_2));
389
390     return;
391 }
392
393 static int
394 rewrite_header(new, tovers, newheader)
395      int new, tovers;
396      char *newheader;
397 {
398     int pos;
399
400     pos = lseek(new, 64, L_SET);        /* leave room for ubik */
401
402     if (pos == -1) {
403         perror(pn);
404         fprintf(stderr, "%s: no garbage collection\n", pn);
405         return;
406     } else if (pos != 64) {
407         fprintf(stderr, "%s: Can't rewind: no garbage collection\n", pn);
408         return;
409     }
410
411     if (tovers = 1) {
412         write(new, newheader, sizeof(struct vlheader_1));
413     } else {
414         write(new, newheader, sizeof(struct vlheader_2));
415     }
416
417     return;
418 }