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