6a2cdb292bfd2771f4a1ce3e500601eaa6f3359e
[openafs.git] / src / vol / fs_conv_411.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 #if     defined(AFS_DUX40_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)) || defined(AFS_SUN54_ENV)
17 #if defined AFS_DUX40_ENV
18 #define OSVERS "DUX 4.0D"
19 #else
20 #if     defined(AFS_SUN54_ENV)
21 #define OSVERS "SunOS 5.6"
22 #else
23 #define OSVERS "SunOS 4.1.1"
24 #endif
25 #endif
26 #include <sys/types.h>
27 #include <rx/xdr.h>
28 #include <afs/afsint.h>
29 #include <sys/param.h>
30 #include <stdio.h>
31 #ifdef  AFS_SUN5_ENV
32 #include <sys/fs/ufs_fs.h>
33 #else
34 #include <ufs/fs.h>
35 #endif
36 #include <sys/stat.h>
37 #include <dirent.h>
38 #include <sys/mount.h>
39 #include <sys/file.h>
40 #ifndef ITIMER_REAL
41 #include <sys/time.h>
42 #endif /* ITIMER_REAL */
43 #include <time.h>
44 #ifdef AFS_VFSINCL_ENV
45 #include <sys/vnode.h>
46 #ifdef  AFS_SUN5_ENV
47 #include <sys/fs/ufs_inode.h>
48 #else
49 #include <ufs/inode.h>
50 #endif
51 #else /* AFS_VFSINCL_ENV */
52 #ifdef  AFS_DUX40_ENV
53 #include <ufs/inode.h>
54 #else
55 #include <sys/inode.h>
56 #endif
57 #endif /* AFS_VFSINCL_ENV */
58 #ifdef  AFS_AIX_ENV
59 #include <sys/vfs.h>
60 #include <sys/lockf.h>
61 #else
62 #ifdef  AFS_HPUX_ENV
63 #include <unistd.h>
64 #include <checklist.h>
65 #else
66 #ifdef    AFS_SUN5_ENV
67 #include <sys/mnttab.h>
68 #include <sys/mntent.h>
69 #include <sys/vfstab.h>
70 #else
71 #include <fstab.h>
72 #endif
73 #endif
74 #endif
75 #include <fcntl.h>
76 #include <afs/osi_inode.h>
77 #include <errno.h>
78
79 #include <nfs.h>
80 #include <partition.h>
81 #include <afs/cmd.h>
82 #include <stdlib.h>
83 #include <unistd.h>
84
85 int icount = 0, iarraysize = 0, *iarray;
86
87 char *rawname(), *unrawname(), *vol_DevName(), *blockcheck();
88 #define ROOTINODE       2
89 int force = 0, verbose = 0, unconv = 0;
90
91 #ifdef  AFS_DUX40_ENV
92 int
93 sortinodes(a, b)
94      int *a, *b;
95 {
96     if (*a < *b)
97         return -1;
98     if (*a > *b)
99         return +1;
100     return 0;
101 }
102
103 int
104 BuildInodes(path)
105      char *path;
106 {
107     DIR *d;
108     struct dirent *de;
109     char p[256];
110     struct stat stats;
111     int code = 0;
112
113     d = opendir(path);
114     if (!d) {
115         printf("Cannot open %s: error %d\n", path, errno);
116         return -1;
117     }
118
119     while (de = readdir(d)) {
120         if (iarraysize == 0) {
121             iarraysize = 1000;
122             iarray = (int *)malloc(iarraysize * sizeof(int));
123         }
124         if (icount >= iarraysize) {
125             iarraysize += 1000;
126             iarray = (int *)realloc(iarray, iarraysize * sizeof(int));
127         }
128         iarray[icount] = de->d_ino;
129         icount++;
130
131         if ((strcmp(de->d_name, ".") == 0) || (strcmp(de->d_name, "..") == 0))
132             continue;
133
134         strcpy(p, path);
135         strcat(p, "/");
136         strcat(p, de->d_name);
137
138         code = stat(p, &stats);
139         if (code) {
140             printf("Cannot stat %s: error %d\n", path, errno);
141             return -1;
142         }
143         if (S_ISDIR(stats.st_mode)) {
144             code = BuildInodes(p);
145             if (code)
146                 break;
147         }
148     }
149
150     closedir(d);
151     return code;
152 }
153 #endif
154
155 static
156 ConvCmd(as)
157      struct cmd_syndesc *as;
158 {
159     unconv = 0;
160     handleit(as);
161 }
162
163 static
164 UnConvCmd(as)
165      struct cmd_syndesc *as;
166 {
167     unconv = 1;
168     handleit(as);
169 }
170
171 #if     defined(AFS_SUN54_ENV)
172
173 static
174 handleit(as)
175      struct cmd_syndesc *as;
176 {
177     register struct cmd_item *ti;
178     char *dname;
179     afs_int32 haspart = 0, hasDevice = 0;
180     struct vfstab mnt;
181
182     if (as->parms[1].items)
183         verbose = 1;
184     else
185         verbose = 0;
186     if (as->parms[2].items)
187         force = 1;
188     else
189         force = 0;
190
191     if (unconv) {
192         printf
193             ("Unconverts from a %s AFS partition to a pre-%s compatible format.\n\n",
194              OSVERS, OSVERS);
195     } else {
196         printf
197             ("Converts a pre-%s AFS partition to a %s compatible format.\n\n",
198              OSVERS, OSVERS);
199     }
200     if (!force) {
201         printf
202             ("*** Must use the '-force' option for command to have effect! ***\n");
203         if (!verbose) {
204             printf
205                 ("*** Use the '-verbose' option to report what will be converted ***\n");
206             exit(1);
207         }
208     }
209
210     for (ti = as->parms[0].items; ti; ti = ti->next) {
211         FILE *fsent;
212         char *namep = ti->data;
213         int found = 0;
214
215         haspart = 1;
216         if ((fsent = fopen(VFSTAB, "r")) == NULL) {
217             printf("Unable to open %s ( errno = %d)\n", VFSTAB, errno);
218             exit(2);
219         }
220         while (!getvfsent(fsent, &mnt)) {
221             char *part = mnt.vfs_mountp;
222
223             if (!part)
224                 continue;
225
226             if (!strncmp(namep, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) {
227                 if (!strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) {
228                     if (!strncmp(part, namep, strlen(part) + 1)) {
229                         if (dname = mnt.vfs_fsckdev) {
230                             printf("ProcessFileSys %s %s\n", dname, namep);
231                             ProcessFileSys(dname, namep);
232                             found = 1;
233                             break;
234                         }
235                     }
236                 }
237             }
238         }
239         if (!found)
240             printf("Unknown input AFS partition name or device: %s\n", namep);
241         fclose(fsent);
242     }
243
244     /* if raw devices are specified */
245     for (ti = as->parms[3].items; ti; ti = ti->next) {
246         char *namep = ti->data;
247
248         hasDevice = 1;
249         if (namep) {
250             if (!CheckMountedDevice(namep)) {
251                 printf("Device %s may be mounted, aborting...\n", namep);
252                 continue;
253             }
254             ProcessFileSys(namep, namep);
255         }
256     }
257
258     if (!haspart && !hasDevice) {
259         int didSome = 0;
260         FILE *fsent;
261
262         if ((fsent = fopen(VFSTAB, "r")) == NULL) {
263             printf("Unable to open %s ( errno = %d)\n", VFSTAB, errno);
264             exit(2);
265         }
266         while (!getvfsent(fsent, &mnt)) {
267             char *part = mnt.vfs_mountp;
268
269             if (!part)
270                 continue;
271
272             if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE) == 0) {
273                 if (dname = mnt.vfs_fsckdev)
274                     ProcessFileSys(dname, part);
275                 didSome++;
276             }
277         }
278         fclose(fsent);
279         if (!didSome)
280             printf
281                 ("No file system partitions named %s* found; not processed\n",
282                  VICE_PARTITION_PREFIX);
283     }
284 }
285
286 #else /* AFS_SUN54_ENV */
287
288 handleit(as)
289      struct cmd_syndesc *as;
290 {
291     register struct cmd_item *ti;
292     char *dname;
293     afs_int32 haspart = 0;
294
295     if (as->parms[1].items)
296         verbose = 1;
297     else
298         verbose = 0;
299     if (as->parms[2].items)
300         force = 1;
301     else
302         force = 0;
303
304     if (unconv) {
305         printf
306             ("Unconverts from a %s AFS partition to a pre-%s compatible format.\n\n",
307              OSVERS, OSVERS);
308     } else {
309         printf
310             ("Converts a pre-%s AFS partition to a %s compatible format.\n\n",
311              OSVERS, OSVERS);
312     }
313     if (!force) {
314         printf
315             ("*** Must use the '-force' option for command to have effect! ***\n");
316         if (!verbose) {
317             printf
318                 ("*** Use the '-verbose' option to report what will be converted ***\n");
319             exit(1);
320         }
321     }
322
323     for (ti = as->parms[0].items; ti; ti = ti->next) {
324         struct fstab *fsent;
325         char *namep = ti->data;
326         int found = 0;
327
328         haspart = 1;
329         setfsent();
330         while (fsent = getfsent()) {
331             char *part = fsent->fs_file;
332
333             if (!strncmp(namep, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) {
334                 if (!strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) {
335                     if (!strncmp(part, namep, strlen(part) + 1)) {
336                         if (dname = unrawname(fsent->fs_spec)) {
337                             ProcessFileSys(dname, namep);
338                             found = 1;
339                             break;
340                         }
341                     }
342                 }
343             } else {
344                 if (!rawname(namep) || !unrawname(namep))
345                     break;
346                 if (!strcmp(fsent->fs_spec, rawname(namep))
347                     || !strcmp(fsent->fs_spec, unrawname(namep))) {
348                     if (dname = unrawname(fsent->fs_spec)) {
349                         ProcessFileSys(dname, fsent->fs_file);
350                         found = 1;
351                         break;
352                     }
353                 }
354             }
355         }
356         if (!found)
357             printf("Unknown input AFS partition name or device: %s\n", namep);
358         endfsent();
359     }
360
361     if (!haspart) {
362         int didSome = 0;
363         struct fstab *fsent;
364
365         setfsent();
366         while (fsent = getfsent()) {
367             char *part = fsent->fs_file;
368
369             if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE) == 0) {
370                 if (dname = unrawname(fsent->fs_spec)) {
371                     ProcessFileSys(dname, part);
372                     didSome++;
373                 }
374             }
375         }
376         endfsent();
377         if (!didSome)
378             printf
379                 ("No file system partitions named %s* found; not processed\n",
380                  VICE_PARTITION_PREFIX);
381     }
382 }
383 #endif /* AFS_SUN54_ENV */
384
385
386 #include "AFS_component_version_number.c"
387
388 main(argc, argv)
389      char **argv;
390 {
391     register struct cmd_syndesc *ts;
392     afs_int32 code;
393
394     if (geteuid() != 0) {
395         printf("must be run as root; sorry\n");
396         exit(1);
397     }
398 #ifdef  AFS_DUX40_ENV
399     ts = cmd_CreateSyntax("convert", ConvCmd, 0,
400                           "Convert to DUX 4.0D format");
401 #else
402 #if     defined(AFS_SUN54_ENV)
403     ts = cmd_CreateSyntax("convert", ConvCmd, 0,
404                           "Convert to AFS SunOS 5.6 format");
405 #else
406     ts = cmd_CreateSyntax("convert", ConvCmd, 0,
407                           "Convert to AFS 4.1.1 format");
408 #endif
409 #endif
410     cmd_AddParm(ts, "-part", CMD_LIST, CMD_OPTIONAL, "AFS partition name");
411     cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, "verbose mode");
412     cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL,
413                 "Safeguard enforce switch");
414     cmd_AddParm(ts, "-device", CMD_LIST, CMD_OPTIONAL, "AFS raw device name");
415 #ifdef  AFS_DUX40_ENV
416     ts = cmd_CreateSyntax("unconvert", UnConvCmd, 0,
417                           "Convert back from OSF 4.0D to earlier formats");
418 #else
419 #if     defined(AFS_SUN54_ENV)
420     ts = cmd_CreateSyntax("unconvert", UnConvCmd, 0,
421                           "Convert back from AFS SunOS 5.6 to earlier formats");
422 #else
423     ts = cmd_CreateSyntax("unconvert", UnConvCmd, 0,
424                           "Convert back from AFS 4.1.1 to earlier formats");
425 #endif
426 #endif
427     cmd_AddParm(ts, "-part", CMD_LIST, CMD_OPTIONAL, "AFS partition name");
428     cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, "verbose mode");
429     cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL,
430                 "Safeguard enforce switch");
431     cmd_AddParm(ts, "-device", CMD_LIST, CMD_OPTIONAL, "AFS raw device name");
432
433     code = cmd_Dispatch(argc, argv);
434     exit(code);
435 }
436
437
438 ProcessFileSys(dname, path)
439      char *dname, *path;
440 {
441     struct stat status, stat1;
442 #if     !defined(AFS_SUN54_ENV)
443     struct ufs_args ufsargs;
444 #endif
445     char devbuffer[120], *devname;
446     int i, j, mounted = 0, code;
447
448     if (stat(path, &status) == -1) {
449         printf("Couldn't find file system \"%s\"\n", path);
450         return;
451     }
452     if (status.st_ino == ROOTINODE) {
453         if (force) {
454             printf
455                 ("Partition %s is mounted; only unmounted partitions are processed\n",
456                  path);
457             return;
458         }
459         mounted = 1;
460     }
461     strcpy(devbuffer, dname);
462     devname = devbuffer;
463 #if     !defined(AFS_SUN54_ENV)
464     EnsureDevice(devname);
465 #endif
466     if (!mounted) {
467 #ifdef  AFS_DUX40_ENV
468         ufsargs.fspec = devname;
469         code = mount(MOUNT_UFS, path, 0, &ufsargs);
470 #else
471 #if     defined(AFS_SUN54_ENV)
472         code = 0;
473 #else
474         ufsargs.fspec = devname;
475         code = mount("4.2", path, M_NEWTYPE, &ufsargs);
476 #endif
477 #endif
478         if (code < 0) {
479             printf("Couldn't mount %s on %s (err=%d)\n", devname, path,
480                    errno);
481             return;
482         }
483     }
484
485     if (stat(path, &status) == -1) {
486         printf("Couldn't find file system \"%s\"\n", path);
487         return;
488     }
489 #ifdef  AFS_DUX40_ENV
490     icount = 0;
491     code = BuildInodes(path);
492     if (code) {
493         printf("Couldn't generate list of all inodes in directory %s\n",
494                path);
495         return;
496     }
497     if (icount)
498         qsort(iarray, icount, sizeof(int), sortinodes);
499 #endif
500
501 #if     !defined(AFS_SUN54_ENV)
502     if (!(devname = vol_DevName(status.st_dev))) {
503         printf("Couldn't get devname for %d\n", status.st_dev);
504         return;
505     }
506 #endif
507
508     if (ProcessAfsInodes(devname, path) == -1)
509         printf("Unable to get inodes for \"%s\"; not processed\n", path);
510     if (!mounted) {
511 #ifdef  AFS_DUX40_ENV
512         umount(path);
513 #endif
514     }
515 }
516
517
518 int
519 ProcessAfsInodes(devname, partition)
520      char *devname, *partition;
521 {
522     union {
523         struct fs fs;
524         char block[SBSIZE];
525     } super;
526     int pfd, i, c, e, bufsize, cnt = 0, mod = 0, wcnt = 0, ccnt = 0, ncnt;
527     FILE *inodeFile = NULL;
528     char rdev[25];
529     struct dinode *inodes = NULL, *einodes, *p;
530     int code, istep = 0;
531
532     sync();
533     sleep(5);                   /* XXXX */
534 #if     defined(AFS_SUN54_ENV)
535     sprintf(rdev, "%s", devname);
536 #else
537     sprintf(rdev, "/dev/r%s", devname);
538 #endif
539     pfd = open(rdev, O_RDWR);
540     if (pfd < 0) {
541         printf("Could not read device %s to get inode list\n", rdev);
542         printf("errno %d: %s\n", errno, strerror(errno));
543         return -1;
544     }
545     if (bread(pfd, super.block, SBLOCK, SBSIZE) == -1) {
546         printf("Unable to read superblock, partition %s\n", partition);
547         goto out;
548     }
549
550     /*
551      * run a few consistency checks of the superblock
552      * (Cribbed from vfsck)
553      */
554     if ((super.fs.fs_magic != FS_MAGIC) || (super.fs.fs_ncg < 1)
555         || (super.fs.fs_cpg < 1)
556         || (super.fs.fs_ncg * super.fs.fs_cpg < super.fs.fs_ncyl
557             || (super.fs.fs_ncg - 1) * super.fs.fs_cpg >= super.fs.fs_ncyl)
558         || (super.fs.fs_sbsize > SBSIZE)) {
559         printf
560             ("There's something wrong with the superblock for partition %s; run vfsck\n",
561              partition);
562         goto out;
563     }
564     bufsize = super.fs.fs_ipg * sizeof(struct dinode);
565     if (!(inodes = (struct dinode *)malloc(bufsize))) {
566         printf("Unable to allocate enough memory to scan inodes; help!\n");
567         goto out;
568     }
569     einodes = (struct dinode *)(((char *)inodes) + bufsize);
570     printf("Processing all AFS inodes on partition %s (device %s)...\n",
571            partition, rdev);
572     for (c = 0; c < super.fs.fs_ncg; c++) {
573         daddr_t dblk1;
574 #if     defined(AFS_SUN54_ENV)
575         daddr_t f1;
576         offset_t off;
577 #endif
578
579         i = c * super.fs.fs_ipg;
580         e = i + super.fs.fs_ipg;
581 #ifdef  AFS_DUX40_ENV
582         dblk1 = fsbtodb(&super.fs, itod(&super.fs, i));
583         code = lseek(pfd, (off_t) ((off_t) dblk1 * DEV_BSIZE), L_SET);
584 #else
585 #if     defined(AFS_SUN54_ENV)
586         f1 = fsbtodb(&super.fs, itod(&super.fs, i));
587         off = (offset_t) f1 << DEV_BSHIFT;
588         code = llseek(pfd, off, L_SET);
589 #else
590         code =
591             lseek(pfd, dbtob(fsbtodb(&super.fs, itod(&super.fs, i))), L_SET);
592 #endif
593 #endif
594         if (code == -1) {
595             printf("Error reading inodes for partition %s; run vfsck\n",
596                    partition);
597             printf("%d: %s\n", errno, strerror(errno));
598 #if     defined(AFS_SUN54_ENV)
599             printf("file number = %d; offset = %ld\n", pfd, off);
600 #else
601             printf("file number = %d\n", pfd);
602 #endif
603             goto out;
604         }
605         while (i < e) {
606             wcnt = ncnt = mod = 0;
607             code = read(pfd, inodes, bufsize);
608             if (code != bufsize) {
609                 printf("Error reading inodes for partition %s; run vfsck\n",
610                        partition);
611                 if (code < 0) {
612                     printf("errno %d: %s\n", errno, strerror(errno));
613                 }
614                 goto out;
615             }
616
617             /* Step through each inode */
618             for (p = inodes; p < einodes && i < e; i++, p++)
619 #ifdef  AFS_DUX40_ENV
620             {
621                 afs_uint32 v1, v2, v3, v4;
622                 afs_uint32 volid, vnode, uniq, vers;
623                 afs_uint32 type, rwvol;
624                 afs_uint32 t;
625                 int special;
626
627                 if ((p->di_mode & IFMT) != IFREG) {
628                     /* This inode is not an AFS inode so 
629                      * zero out all the spare fields.
630                      */
631                   zeroSpares:
632                     if (!(p->di_flags & IC_PROPLIST)) {
633                         p->di_proplb = 0;
634                     }
635                     if (!(p->di_flags & IC_XUID)) {
636                         p->di_uid = 0;
637                     }
638                     if (!(p->di_flags & IC_XGID)) {
639                         p->di_gid = 0;
640                     }
641                     mod = 1;
642                     ncnt++;
643                     continue;
644                 }
645
646 /*          printf("Inode %d: proplb=%u, uid=%u, bcuid=0x%x, bcgid=0x%x, gid=0x%x\n",
647  *                 i , p->di_proplb, p->di_uid, p->di_bcuid, p->di_bcgid,
648  *                     p->di_gid);
649  */
650
651                 if (unconv) {   /*unconvert */
652                     /* Check if the inode is not a DUX40D AFS inode */
653                     if (p->di_proplb != VICEMAGIC
654                         || (p->di_flags & IC_PROPLIST)) {
655                         ccnt++;
656                         if (verbose)
657                             printf("   AFS Inode %d: already unconverted\n",
658                                    i);
659                         continue;
660                     }
661
662                     v1 = p->di_uid;
663                     v2 = p->di_gid;
664                     v3 = ((u_int) (p->di_bcuid)) << 16 |
665                         ((u_int) (p->di_bcgid));
666
667                     /* We have a sorted list of ufs inodes. Is it one of these */
668                     while ((istep < icount) && (i > iarray[istep])) {
669                         istep++;
670                     }
671                     if ((istep < icount) && (i == iarray[istep])) {
672                         /* Yes, its a ufs inode */
673                         if (verbose)
674                             printf("   Inode %d: Not an AFS Inode\n", i);
675                         goto zeroSpares;
676                     }
677
678                     /* Is it not an AFS inode. !IS_VICEMAGIC check */
679                     if (!(v2 || v3)) {
680                         if (verbose)
681                             printf("Warning: Inode %d: Unreferenced inode\n",
682                                    i);
683                         continue;       /* skip, making no change */
684                     }
685
686                     volid = v1;
687                     if (((v2 >> 3) == 0x1fffffff) && (v2 & 0x3)) {
688                         special = 1;    /* INODESPECIAL */
689                         type = v2 & 0x3;
690                         rwvol = v3;
691                         if (verbose) {
692                             printf
693                                 ("   %s AFS Inode %d: Vol=%u, RWVol=%u, Type=%d\n",
694                                  (force ? "Unconverting" :
695                                   "Would have unconverted"), i, volid, rwvol,
696                                  type);
697                         }
698                     } else {
699                         special = 0;
700                         vnode = ((v2 >> 27) << 16) + (v3 & 0xffff);
701                         uniq = (v2 & 0x3fffff);
702                         vers =
703                             (((v2 >> 22) & 0x1f) << 16) +
704                             ((v3 >> 16) & 0xffff);
705                         if (verbose) {
706                             printf
707                                 ("   %s AFS Inode %d: RWVol=%u, VNode=%u, Uniq=%u, Vers=%u\n",
708                                  (force ? "Unconverting" :
709                                   "Would have unconverted"), i, volid, vnode,
710                                  uniq, vers);
711                         }
712                     }
713
714                     /* Now unconvert the DUX40D AFS inode to the OSF30 version */
715                     p->di_proplb = v1;
716                     p->di_uid = v2;
717                     p->di_gid = v3;
718                     p->di_flags &= ~(IC_PROPLIST | IC_XUID | IC_XGID);
719                     p->di_bcuid = 0;
720                     p->di_bcgid = -2;
721                     mod = 1;
722                     cnt++;
723                     wcnt++;
724
725                 } else {        /*convert */
726                     if ((p->di_proplb == VICEMAGIC
727                          && !(p->di_flags & IC_PROPLIST))
728                         || (p->di_uid == 0 && p->di_gid == 0)
729                         || (p->di_flags & (IC_XUID | IC_XGID))) {
730                         /* This inode is either already converted or not an AFS inode */
731                         /* We have a sorted list of ufs inodes. Is it one of these    */
732                         while ((istep < icount) && (i > iarray[istep])) {
733                             istep++;
734                         }
735                         if ((istep < icount) && (i == iarray[istep])) {
736                             /* Yes, its a ufs inode */
737                             if (verbose) {
738                                 printf("   Inode %d: Not an AFS Inode %s\n",
739                                        i, ((p->di_spare[1]
740                                             || p->
741                                             di_spare[2]) ? "(fixed)" : ""));
742                             }
743                             goto zeroSpares;
744                         }
745
746                         /* Is it a AFS inode. IS_VICEMAGIC check */
747                         if ((p->di_uid || p->di_gid)
748                             && !(p->di_flags & (IC_XUID | IC_XGID))) {
749                             ccnt++;
750                             if (verbose)
751                                 printf("   AFS Inode %d: already converted\n",
752                                        i);
753                             continue;
754                         }
755
756                         /* Not an AFS nor UFS inode */
757                         printf("Warning: Inode %d: Unreferenced inode\n", i);
758                         continue;       /* skip, making no changes */
759                     }
760
761                     v1 = p->di_proplb;
762                     v2 = p->di_uid;
763                     v3 = p->di_gid;
764
765                     volid = v1;
766                     if (((v2 >> 3) == 0x1fffffff) && (v2 & 0x3)) {
767                         special = 1;    /* INODESPECIAL */
768                         type = v2 & 0x3;
769                         rwvol = v3;
770                         if (verbose) {
771                             printf
772                                 ("   %s AFS Inode %d: Vol=%u, RWVol=%u, Type=%d\n",
773                                  (force ? "Converting" :
774                                   "Would have converted"), i, volid, rwvol,
775                                  type);
776                         }
777                     } else {
778                         special = 0;
779                         vnode = ((v2 >> 27) << 16) + (v3 & 0xffff);
780                         uniq = (v2 & 0x3fffff);
781                         vers =
782                             (((v2 >> 22) & 0x1f) << 16) +
783                             ((v3 >> 16) & 0xffff);
784                         if (verbose) {
785                             printf
786                                 ("   %s AFS Inode %d: RWVol=%u, VNode=%u, Uniq=%u, Vers=%u\n",
787                                  (force ? "Converting" :
788                                   "Would have converted"), i, volid,
789                                  (vnode & 0x1fffff), (uniq & 0x3fffff),
790                                  (vers & 0x1fffff));
791                         }
792                     }
793
794                     /* Now convert the OSF30 AFS inode to the DUX40D version */
795                     p->di_proplb = VICEMAGIC;
796                     p->di_uid = v1;
797                     p->di_gid = v2;
798                     p->di_bcuid = (u_short) (v3 >> 16);
799                     p->di_bcgid = (u_short) v3;
800                     p->di_flags &= ~(IC_PROPLIST);
801                     p->di_flags |= (IC_XUID | IC_XGID);
802                     mod = 1;
803                     cnt++;
804                     wcnt++;
805                 }               /*convert */
806             }
807 #else
808             {
809                 afs_uint32 p1, p2, p3, p4;
810                 int p5;
811                 quad *q;
812
813 #if     defined(AFS_SUN56_ENV)
814                 q = (quad *) & (p->di_ic.ic_lsize);
815 #else
816                 q = &(p->di_ic.ic_size);
817 #endif
818
819                 p1 = p->di_gen;
820                 p2 = p->di_ic.ic_flags;
821                 p3 = q->val[0];
822                 p4 = p->di_ic.ic_uid;
823                 p5 = p->di_ic.ic_gid;
824
825                 /* the game is afoot, Dr Watson! */
826                 if (!verbose && !((ccnt + cnt + ncnt) % 5000)) {
827                     printf(".");
828                     fflush(stdout);
829                 }
830
831                 if (unconv) {
832                     /*
833                      * Convert from a 5.6 format to a pre 5.6 format
834                      */
835                     if ((p2 || p3) && !p4 && (p5 == -2)) {
836                         if (verbose)
837                             printf
838                                 ("AFS Inode %d: Already in pre-%s AFS format (%x,%x,%x,%x,%x) ignoring..\n",
839                                  i, OSVERS, p1, p2, p3, p4, p5);
840                         ccnt++;
841                         continue;
842                     }
843
844                     if (p5 == VICEMAGIC) {
845                         /* This is a sol 2.6 AFS inode */
846                         mod = 1;
847                         cnt++;
848                         wcnt++;
849                         if (verbose)
850                             printf
851                                 ("AFS Inode %d: %s from Sol5.6 (%x,%x,%x,%x,%x) \n",
852                                  i,
853                                  (force ? "Unconverting" :
854                                   "Would have unconverted"), p1, p2, p3, p4,
855                                  p5);
856                         if (force) {
857                             q->val[0] = p->di_uid;
858                             p->di_uid = 0;
859                             p->di_gid = -2;
860                             p->di_suid = UID_LONG;
861                             p->di_sgid = GID_LONG;
862                         }
863                         continue;
864                     }
865                 } else {
866                     if (p5 == VICEMAGIC) {      /* Assume an already converted 5.6 afs inode */
867                         if (verbose)
868                             printf
869                                 ("AFS Inode %d: Already in %s AFS format (p1=%x,p2=%x,p3=%x,p4=%x,p5=%x); ignoring..\n",
870                                  i, OSVERS, p1, p2, p3, p4, p5);
871                         ccnt++;
872                         continue;
873                     }
874
875                     /* for inodes created in solaris 2.4, there is a possibility
876                      ** that the gid gets chopped off to an unsigned short(2 bytes)
877                      */
878                     if ((p2 || p3) && !p4
879                         && ((p5 == -2)
880                             || ((unsigned short)p5 == (unsigned short)-2))) {
881                         /* This is a pre Sol2.6 inode */
882                         mod = 1;
883                         cnt++;
884                         wcnt++;
885                         if (verbose)
886                             printf
887                                 ("AFS Inode %d: %s to 5.6 format (p1=%x,p2=%x,p3=%x,p4=%x, p5=%x)\n",
888                                  i,
889                                  (force ? "Converting" :
890                                   "Would have converted"), p1, p2, p3, p4,
891                                  p5);
892                         if (force) {
893                             p->di_gid = VICEMAGIC;
894                             p->di_uid = q->val[0];
895                             p->di_suid = UID_LONG;
896                             p->di_sgid = GID_LONG;
897                             q->val[0] = 0;
898                         }
899                         continue;
900                     }
901                 }
902                 /* If not an AFS inode, ignore */
903                 ncnt++;
904                 if (verbose)
905                     printf
906                         ("Non AFS Inode %d: (p1=%x,p2=%x,p3=%x, p4=%x,p5=%x) ignoring..\n",
907                          i, p1, p2, p3, p4, p5);
908             }
909 #endif
910
911             if (mod && force) {
912                 if (lseek(pfd, -bufsize, SEEK_CUR) == -1) {     /* Point to loc bef read */
913                     printf("Error Seeking backwards %d bytes\n", bufsize);
914                     printf("errno %d: %s\n", errno, strerror(errno));
915                     goto out;
916                 }
917                 code = write(pfd, inodes, bufsize);
918                 if (code != bufsize) {  /* Update inodes */
919                     printf("Error writing modified inodes for partition %s\n",
920                            partition);
921                     if (code < 0)
922                         printf("errno %d: %s\n", errno, strerror(errno));
923                     goto out;
924                 }
925                 if (verbose) {
926                     printf
927                         ("  Write %d AFS inodes and %d non-AFS inodes to disk\n",
928                          wcnt, ncnt);
929                 }
930             }
931         }
932     }
933
934     printf("\n%s: %d AFS inodes %s ", partition, cnt,
935            (force ? "were" : "would have been"));
936     if (unconv)
937         printf("unconverted to a pre-%s format; %d already unconverted.\n",
938                OSVERS, ccnt);
939     else
940         printf("converted to a %s format; %d already converted.\n", OSVERS,
941                ccnt);
942
943     close(pfd);
944     return 0;
945
946   out:
947     close(pfd);
948     return -1;
949 }
950
951
952
953
954 int
955 bread(fd, buf, blk, size)
956      int fd;
957      char *buf;
958      daddr_t blk;
959      afs_int32 size;
960 {
961     if (lseek(fd, (off_t) dbtob(blk), L_SET) < 0
962         || read(fd, buf, size) != size) {
963         printf("bread: lseek failed (errno = %d)\n", errno);
964         return -1;
965     }
966     return 0;
967 }
968
969
970 /* 
971  * Ensure that we don't have a "/" instead of a "/dev/rxd0a" type of device.
972  * returns pointer to static storage; copy it out quickly!
973  */
974 char *
975 vol_DevName(adev)
976      dev_t adev;
977 {
978     struct dirent *dp;
979     static char pbuffer[128];
980     struct stat tstat;
981     DIR *dirp;
982     char *dirName;
983     int code;
984
985     /* now, look in /dev for the appropriate file */
986     dirp = opendir(dirName = "/dev");
987     while (dp = readdir(dirp)) {
988         strcpy(pbuffer, dirName);
989         strcat(pbuffer, "/");
990         strcat(pbuffer, dp->d_name);
991         if (stat(pbuffer, &tstat) != -1 && (tstat.st_mode & S_IFMT) == S_IFBLK
992             && (tstat.st_rdev == adev)) {
993             strcpy(pbuffer, dp->d_name);
994             closedir(dirp);
995             return pbuffer;
996         }
997     }
998     closedir(dirp);
999     return NULL;                /* failed */
1000 }
1001
1002 char *
1003 unrawname(name)
1004      char *name;
1005 {
1006     char *dp;
1007     struct stat stb;
1008
1009     if ((dp = strrchr(name, '/')) == 0)
1010         return (name);
1011     if (stat(name, &stb) < 0)
1012         return (name);
1013     if ((stb.st_mode & S_IFMT) != S_IFCHR)
1014         return (name);
1015     if (*(dp + 1) != 'r')
1016         return (name);
1017     (void)strcpy(dp + 1, dp + 2);
1018     return (name);
1019 }
1020
1021 char *
1022 rawname(name)
1023      char *name;
1024 {
1025     static char rawbuf[32];
1026     char *dp;
1027
1028     if ((dp = strrchr(name, '/')) == 0)
1029         return (0);
1030     *dp = 0;
1031     (void)strcpy(rawbuf, name);
1032     *dp = '/';
1033     (void)strcat(rawbuf, "/r");
1034     (void)strcat(rawbuf, dp + 1);
1035     return (rawbuf);
1036 }
1037
1038 char *
1039 blockcheck(name)
1040      char *name;
1041 {
1042     struct stat stslash, stblock, stchar;
1043     char *raw;
1044     int retried = 0;
1045
1046   retry:
1047     if (stat(name, &stblock) < 0) {
1048         perror(name);
1049         printf("Can't stat %s\n", name);
1050         return (0);
1051     }
1052     if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
1053         raw = rawname(name);
1054         if (stat(raw, &stchar) < 0) {
1055             perror(raw);
1056             printf("Can't stat %s\n", raw);
1057             return (name);
1058         }
1059         if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
1060             return (raw);
1061         } else {
1062             printf("%s is not a character device\n", raw);
1063             return (name);
1064         }
1065     } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
1066         name = unrawname(name);
1067         retried++;
1068         goto retry;
1069     }
1070     printf("Can't make sense out of name %s\n", name);
1071     return (0);
1072 }
1073
1074
1075 /* ensure that we don't have a "/" instead of a "/dev/rxd0a" type of device.
1076  * Overwrites abuffer with the corrected name.
1077  */
1078 EnsureDevice(abuffer)
1079      char *abuffer;
1080 {
1081     struct dirent *dp;
1082     char pbuffer[128];
1083     struct stat tstat;
1084     DIR *dirp;
1085     char *dirName;
1086     int code;
1087     short dev;
1088
1089     code = stat(abuffer, &tstat);
1090     if (code)
1091         return code;
1092     if (((tstat.st_mode & S_IFMT) == S_IFBLK)
1093         || ((tstat.st_mode & S_IFMT) == S_IFCHR)) {
1094         return 0;               /* already a block or char device */
1095     }
1096     /* otherwise, assume we've got a normal file, and we look up its device */
1097     dev = tstat.st_dev;         /* remember device for this file */
1098
1099     /* now, look in /dev for the appropriate file */
1100     dirp = opendir(dirName = "/dev");
1101
1102     while (dp = readdir(dirp)) {
1103         strcpy(pbuffer, dirName);
1104         strcat(pbuffer, "/");
1105         strcat(pbuffer, dp->d_name);
1106         if (stat(pbuffer, &tstat) != -1 && (tstat.st_mode & S_IFMT) == S_IFBLK
1107             && (tstat.st_rdev == dev)) {
1108             strcpy(abuffer, pbuffer);
1109             closedir(dirp);
1110             return 0;
1111         }
1112     }
1113     closedir(dirp);
1114     return 1;                   /* failed */
1115 }
1116 #else
1117
1118 #include "AFS_component_version_number.c"
1119
1120 main(argc, argv)
1121      int argc;
1122      char *argv[];
1123 {
1124     printf
1125         ("%s: **ONLY** supported for SunOS 3.5-4.x and dux4.0D systems ...\n",
1126          argv[0]);
1127 }
1128 #endif /*       defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV) */
1129
1130 #if     defined(AFS_SUN54_ENV)
1131
1132 /*
1133 ** Open the /etc/vfstab file to map the raw device name to the mountable
1134 ** device name. Then open the /etc/mnttab file to see if this mountable 
1135 ** device is mounted.
1136 **
1137 ** Returns 1 if the conversion process should continue, otherwise returns 0
1138 */
1139 CheckMountedDevice(devName)
1140      char *devName;             /* raw device name */
1141 {
1142     FILE *vfsent, *mntent;
1143     struct mnttab mnt;
1144     struct vfstab vnt;
1145     char *unRawDev = 0;
1146     char YesNo = 'y';
1147     int found = 0;
1148
1149     if ((vfsent = fopen(VFSTAB, "r")) == NULL) {
1150         printf("Unable to open %s ( errno = %d)\n", VFSTAB, errno);
1151         exit(2);
1152     }
1153     while (!getvfsent(vfsent, &vnt)) {
1154         char *rawDev = vnt.vfs_fsckdev;
1155         if (rawDev && !strcmp(rawDev, devName)) {
1156             /* this is the device we are looking for */
1157             unRawDev = vnt.vfs_special;
1158             break;
1159         }
1160     }
1161     fclose(vfsent);
1162
1163     if (!unRawDev)
1164         goto done;              /* could not find it in /etc/vfstab */
1165
1166     /* we found the entry in /etc/vfstab. Now we open /etc/mnnttab and
1167      ** verify that it is not mounted 
1168      */
1169     if ((mntent = fopen(MNTTAB, "r")) == NULL) {
1170         printf("Unable to open %s ( errno = %d)\n", VFSTAB, errno);
1171         exit(2);
1172     }
1173
1174     while (!getmntent(mntent, &mnt)) {
1175         char *resource = mnt.mnt_special;
1176         if (resource && !strcmp(resource, unRawDev)) {
1177             found = 1;
1178             break;
1179         }
1180     }
1181     fclose(mntent);
1182
1183
1184     /* if we found an entry in the /etc/mnttab file, then this 
1185      ** device must be mounted
1186      */
1187     if (found) {
1188       done:
1189         do {
1190             printf
1191                 ("Device %s may be mounted. Can corrupt data. Continue anyway(y/n)?",
1192                  devName);
1193             fflush(stdout);
1194             fflush(stdin);
1195             YesNo = getc(stdin);
1196         }
1197         while (YesNo != 'y' && YesNo != 'Y' && YesNo != 'n' && YesNo != 'N');
1198     }
1199     if ((YesNo == 'y') || (YesNo == 'Y'))
1200         return 1;
1201     return 0;
1202 }
1203
1204 #endif /* AFS_SUN54_ENV */