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