2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include <afs/param.h>
15 #include <afs/venus.h>
17 #include <afs/afs_consts.h>
19 #include "cnvldb.h" /* CHANGEME! */
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 */
26 #ifdef notdef /* postpone this... */
28 saferead(fd
, addr
, osize
)
42 rc
= read(fd
, ptr
, size
)) {
56 saferead(fd
, addr
, osize
)
62 rc
= read(fd
, addr
, osize
);
63 if (rc
!= osize
&& rc
!= EOF
) {
70 #define saferead(fd,addr,siz) read((fd),(addr),(siz))
73 static char tspace
[1024]; /* chdir can't handle anything bigger, anyway */
74 /* return a static pointer to a buffer */
80 strcpy(tspace
, apath
);
81 tp
= strrchr(tspace
, '/');
91 /* this function returns TRUE (1) if the file is in AFS, otherwise false (0) */
96 struct ViceIoctl blob
;
100 blob
.out_size
= AFS_PIOCTL_MAXSIZE
;
103 code
= pioctl(apath
, VIOC_FILE_CELL_NAME
, &blob
, 1);
105 if ((errno
== EINVAL
) || (errno
== ENOENT
))
111 QuickPrintStatus(status
, name
)
112 struct VolumeStatus
*status
;
115 double QuotaUsed
= 0.0;
116 double PartUsed
= 0.0;
119 if (status
->MaxQuota
!= 0) {
121 ((((double)status
->BlocksInUse
) / status
->MaxQuota
) * 100.0);
127 ((((double)status
->PartBlocksAvail
) / status
->PartMaxBlocks
) *
133 ListQuotaCmd(struct cmd_syndesc
*as
, void *arock
)
136 struct ViceIoctl blob
;
138 struct VolumeStatus
*status
;
141 for (ti
= as
->parms
[0].items
; ti
; ti
= ti
->next
) {
143 blob
.out_size
= AFS_PIOCTL_MAXSIZE
;
146 code
= pioctl(ti
->data
, VIOCGETVOLSTAT
, &blob
, 1);
151 status
= (struct VolumeStatus
*)space
;
152 name
= (char *)status
+ sizeof(*status
);
153 QuickPrintStatus(status
, name
);
159 int gc
= 1, fromvers
= 1, tovers
= 2;
160 char *pathname
= NULL
, *defaultpath
= "/usr/afs/db/vl.DB0";
164 fprintf(stderr
, "usage: %s ", pn
);
165 fprintf(stderr
, "[-name <pathname>] [-help]\n");
175 for (i
= 1; i
< argc
; i
++) {
178 else if (*(argv
[i
]) != '-') { /* positional params */
182 fprintf(stderr
, "%s: Too many parameters!\n");
186 } else /* keyword params */
187 switch (argv
[i
][1]) {
190 fprintf(stderr
, "%s: can't specify version with this tool!\n",
195 case 'f': /* -from */
196 fprintf(stderr
, "%s: can't specify version with this tool!\n",
200 case 'n': /* -name */
203 "%s: -name specified (or implied) twice!\n", pn
);
206 pathname
= argv
[++i
];
209 case 'h': /* -help */
214 case 'g': /* -gc == No GC */
225 pathname
= defaultpath
;
228 #include "AFS_component_version_number.c"
237 char ubik
[80]; /* space for some ubik header */
240 struct vlheader_1 header1
;
241 struct vlheader_2 header2
;
242 } oldheader
, newheader
; /* large enough for either */
245 struct vlentry_1 entry1
;
246 struct vlentry_2 entry2
;
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
))) {
259 if (chdir(Parent(pathname
))) {
264 if (!(new = open(tempname
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0600))) {
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 */
276 /* skip the UBIK data */
279 uvers
= ntohs(uvers
);
280 uvers
+= 10; /* hey, if you screw with the VLDB, you lose */
281 uvers
= htons(uvers
);
283 write(new, ubik
, 64);
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
,
294 rewrite_header(new, tovers
, &newheader
);
303 rename(tempname
, pathname
);
307 readheader(fd
, version
, addr
)
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
));
323 convert_header(fd
, fromv
, tov
, fromaddr
, toaddr
)
325 char *fromaddr
, *toaddr
;
327 struct vlheader_2
*tvp1
;
328 struct vlheader_2
*tvp2
;
331 memcpy(toaddr
, fromaddr
, sizeof(struct vlheader_2
));
332 tvp2
= (struct vlheader_2
*)toaddr
;
333 tvp2
->vital_header
.vldbversion
= htonl(2);
335 write(fd
, tvp2
, sizeof(struct vlheader_2
));
337 /* for garbage-collecting... */
339 for (i
= 0; i
< 254; i
++)
340 tvp2
->IpMappedAddr
[i
] = 0;
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 */
354 if (fromvers
!= tovers
) { /* only supports 1 and 2 currently */
359 1 ? sizeof(struct vlheader_1
) : sizeof(struct vlheader_2
))
361 1 ? sizeof(struct vlheader_1
) : sizeof(struct vlheader_2
));
363 for (i
= 0; i
< 3; i
++)
364 vlentry
->nextIdHash
[i
] =
365 htonl(ntohl(vlentry
->nextIdHash
[i
]) + diff
);
367 vlentry
->nextNameHash
= htonl(ntohl(vlentry
->nextNameHash
) + diff
);
371 ; /* no change, we're just in it for the GC */
375 for (i
= 0; i
< 8; i
++) {
376 s
= vlentry
->serverNumber
[i
];
380 "%s: Too Many Servers (%d) for this version!\n", pn
,
384 newheader
->IpMappedAddr
[s
] = oldheader
->IpMappedAddr
[s
];
388 write(new, vlentry
, sizeof(struct vlentry_2
));
394 rewrite_header(new, tovers
, newheader
)
400 pos
= lseek(new, 64, L_SET
); /* leave room for ubik */
404 fprintf(stderr
, "%s: no garbage collection\n", pn
);
406 } else if (pos
!= 64) {
407 fprintf(stderr
, "%s: Can't rewind: no garbage collection\n", pn
);
412 write(new, newheader
, sizeof(struct vlheader_1
));
414 write(new, newheader
, sizeof(struct vlheader_2
));