backport to buster
[hcoop/debian/openafs.git] / src / vlserver / sascnvldb.c
CommitLineData
805e021f
CE
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
21static char pn[] = "cnvldb";
22static char tempname[] = "XXnewvldb";
23static char space[AFS_PIOCTL_MAXSIZE];
24static int MaxServers[2] = { 30, 254 }; /* max server # permitted in this version */
25
26#ifdef notdef /* postpone this... */
27static int
28saferead(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
73static char tspace[1024]; /* chdir can't handle anything bigger, anyway */
74/* return a static pointer to a buffer */
75static char *
76Parent(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) */
92static int
93InAFS(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
111QuickPrintStatus(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
132static int
133ListQuotaCmd(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
159int gc = 1, fromvers = 1, tovers = 2;
160char *pathname = NULL, *defaultpath = "/usr/afs/db/vl.DB0";
161
162usage()
163{
164 fprintf(stderr, "usage: %s ", pn);
165 fprintf(stderr, "[-name <pathname>] [-help]\n");
166}
167
168getargs(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
230main(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
307readheader(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 */
323convert_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
345static int
346convert_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
393static int
394rewrite_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}