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