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