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>
18 #if defined(AFS_SUN54_ENV)
19 #define OSVERS "SunOS 5.6"
20 #include <sys/types.h>
22 #include <afs/afsint.h>
23 #include <sys/param.h>
24 #include <sys/fs/ufs_fs.h>
27 #include <sys/mount.h>
31 #endif /* ITIMER_REAL */
33 #ifdef AFS_VFSINCL_ENV
34 #include <sys/vnode.h>
35 #include <sys/fs/ufs_inode.h>
36 #else /* AFS_VFSINCL_ENV */
37 #include <sys/inode.h>
38 #endif /* AFS_VFSINCL_ENV */
39 #include <sys/mnttab.h>
40 #include <sys/mntent.h>
41 #include <sys/vfstab.h>
43 #include <afs/osi_inode.h>
47 #include <partition.h>
52 int icount = 0, iarraysize = 0, *iarray;
54 char *rawname(), *unrawname(), *vol_DevName(), *blockcheck();
56 int force = 0, verbose = 0, unconv = 0;
59 ConvCmd(struct cmd_syndesc *as, void *arock)
66 UnConvCmd(struct cmd_syndesc *as, void *arock)
73 handleit(struct cmd_syndesc *as)
75 register struct cmd_item *ti;
77 afs_int32 haspart = 0, hasDevice = 0;
80 if (as->parms[1].items)
84 if (as->parms[2].items)
91 ("Unconverts from a %s AFS partition to a pre-%s compatible format.\n\n",
95 ("Converts a pre-%s AFS partition to a %s compatible format.\n\n",
100 ("*** Must use the '-force' option for command to have effect! ***\n");
103 ("*** Use the '-verbose' option to report what will be converted ***\n");
108 for (ti = as->parms[0].items; ti; ti = ti->next) {
110 char *namep = ti->data;
114 if ((fsent = fopen(VFSTAB, "r")) == NULL) {
115 printf("Unable to open %s ( errno = %d)\n", VFSTAB, errno);
118 while (!getvfsent(fsent, &mnt)) {
119 char *part = mnt.vfs_mountp;
124 if (!strncmp(namep, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) {
125 if (!strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) {
126 if (!strncmp(part, namep, strlen(part) + 1)) {
127 if (dname = mnt.vfs_fsckdev) {
128 printf("ProcessFileSys %s %s\n", dname, namep);
129 ProcessFileSys(dname, namep);
138 printf("Unknown input AFS partition name or device: %s\n", namep);
142 /* if raw devices are specified */
143 for (ti = as->parms[3].items; ti; ti = ti->next) {
144 char *namep = ti->data;
148 if (!CheckMountedDevice(namep)) {
149 printf("Device %s may be mounted, aborting...\n", namep);
152 ProcessFileSys(namep, namep);
156 if (!haspart && !hasDevice) {
160 if ((fsent = fopen(VFSTAB, "r")) == NULL) {
161 printf("Unable to open %s ( errno = %d)\n", VFSTAB, errno);
164 while (!getvfsent(fsent, &mnt)) {
165 char *part = mnt.vfs_mountp;
170 if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE) == 0) {
171 if (dname = mnt.vfs_fsckdev)
172 ProcessFileSys(dname, part);
179 ("No file system partitions named %s* found; not processed\n",
180 VICE_PARTITION_PREFIX);
185 #include "AFS_component_version_number.c"
190 register struct cmd_syndesc *ts;
193 if (geteuid() != 0) {
194 printf("must be run as root; sorry\n");
197 ts = cmd_CreateSyntax("convert", ConvCmd, NULL,
198 "Convert to AFS SunOS 5.6 format");
199 cmd_AddParm(ts, "-part", CMD_LIST, CMD_OPTIONAL, "AFS partition name");
200 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, "verbose mode");
201 cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL,
202 "Safeguard enforce switch");
203 cmd_AddParm(ts, "-device", CMD_LIST, CMD_OPTIONAL, "AFS raw device name");
204 ts = cmd_CreateSyntax("unconvert", UnConvCmd, NULL,
205 "Convert back from AFS SunOS 5.6 to earlier formats");
206 cmd_AddParm(ts, "-part", CMD_LIST, CMD_OPTIONAL, "AFS partition name");
207 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, "verbose mode");
208 cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL,
209 "Safeguard enforce switch");
210 cmd_AddParm(ts, "-device", CMD_LIST, CMD_OPTIONAL, "AFS raw device name");
212 code = cmd_Dispatch(argc, argv);
217 ProcessFileSys(dname, path)
220 struct stat status, stat1;
221 char devbuffer[120], *devname;
222 int i, j, mounted = 0, code;
224 if (stat(path, &status) == -1) {
225 printf("Couldn't find file system \"%s\"\n", path);
228 if (status.st_ino == ROOTINODE) {
231 ("Partition %s is mounted; only unmounted partitions are processed\n",
237 strcpy(devbuffer, dname);
240 if (stat(path, &status) == -1) {
241 printf("Couldn't find file system \"%s\"\n", path);
245 if (ProcessAfsInodes(devname, path) == -1)
246 printf("Unable to get inodes for \"%s\"; not processed\n", path);
251 ProcessAfsInodes(devname, partition)
252 char *devname, *partition;
258 int pfd, i, c, e, bufsize, cnt = 0, mod = 0, wcnt = 0, ccnt = 0, ncnt;
259 FILE *inodeFile = NULL;
261 struct dinode *inodes = NULL, *einodes, *p;
266 sprintf(rdev, "%s", devname);
267 pfd = open(rdev, O_RDWR);
269 printf("Could not read device %s to get inode list\n", rdev);
270 printf("errno %d: %s\n", errno, strerror(errno));
273 if (bread(pfd, super.block, SBLOCK, SBSIZE) == -1) {
274 printf("Unable to read superblock, partition %s\n", partition);
279 * run a few consistency checks of the superblock
280 * (Cribbed from vfsck)
282 if ((super.fs.fs_magic != FS_MAGIC) || (super.fs.fs_ncg < 1)
283 || (super.fs.fs_cpg < 1)
284 || (super.fs.fs_ncg * super.fs.fs_cpg < super.fs.fs_ncyl
285 || (super.fs.fs_ncg - 1) * super.fs.fs_cpg >= super.fs.fs_ncyl)
286 || (super.fs.fs_sbsize > SBSIZE)) {
288 ("There's something wrong with the superblock for partition %s; run vfsck\n",
292 bufsize = super.fs.fs_ipg * sizeof(struct dinode);
293 if (!(inodes = (struct dinode *)malloc(bufsize))) {
294 printf("Unable to allocate enough memory to scan inodes; help!\n");
297 einodes = (struct dinode *)(((char *)inodes) + bufsize);
298 printf("Processing all AFS inodes on partition %s (device %s)...\n",
300 for (c = 0; c < super.fs.fs_ncg; c++) {
305 i = c * super.fs.fs_ipg;
306 e = i + super.fs.fs_ipg;
307 f1 = fsbtodb(&super.fs, itod(&super.fs, i));
308 off = (offset_t) f1 << DEV_BSHIFT;
309 code = llseek(pfd, off, L_SET);
311 printf("Error reading inodes for partition %s; run vfsck\n",
313 printf("%d: %s\n", errno, strerror(errno));
314 printf("file number = %d; offset = %ld\n", pfd, off);
318 wcnt = ncnt = mod = 0;
319 code = read(pfd, inodes, bufsize);
320 if (code != bufsize) {
321 printf("Error reading inodes for partition %s; run vfsck\n",
324 printf("errno %d: %s\n", errno, strerror(errno));
329 /* Step through each inode */
330 for (p = inodes; p < einodes && i < e; i++, p++)
332 afs_uint32 p1, p2, p3, p4;
336 #if defined(AFS_SUN56_ENV)
337 q = (quad *) & (p->di_ic.ic_lsize);
339 q = &(p->di_ic.ic_size);
343 p2 = p->di_ic.ic_flags;
345 p4 = p->di_ic.ic_uid;
346 p5 = p->di_ic.ic_gid;
348 /* the game is afoot, Dr Watson! */
349 if (!verbose && !((ccnt + cnt + ncnt) % 5000)) {
356 * Convert from a 5.6 format to a pre 5.6 format
358 if ((p2 || p3) && !p4 && (p5 == -2)) {
361 ("AFS Inode %d: Already in pre-%s AFS format (%x,%x,%x,%x,%x) ignoring..\n",
362 i, OSVERS, p1, p2, p3, p4, p5);
367 if (p5 == VICEMAGIC) {
368 /* This is a sol 2.6 AFS inode */
374 ("AFS Inode %d: %s from Sol5.6 (%x,%x,%x,%x,%x) \n",
376 (force ? "Unconverting" :
377 "Would have unconverted"), p1, p2, p3, p4,
380 q->val[0] = p->di_uid;
383 p->di_suid = UID_LONG;
384 p->di_sgid = GID_LONG;
389 if (p5 == VICEMAGIC) { /* Assume an already converted 5.6 afs inode */
392 ("AFS Inode %d: Already in %s AFS format (p1=%x,p2=%x,p3=%x,p4=%x,p5=%x); ignoring..\n",
393 i, OSVERS, p1, p2, p3, p4, p5);
398 /* for inodes created in solaris 2.4, there is a possibility
399 ** that the gid gets chopped off to an unsigned short(2 bytes)
401 if ((p2 || p3) && !p4 && ((p5 == -2)
402 || ((unsigned short)p5 ==
403 (unsigned short)-2))) {
404 /* This is a pre Sol2.6 inode */
410 ("AFS Inode %d: %s to 5.6 format (p1=%x,p2=%x,p3=%x,p4=%x, p5=%x)\n",
412 (force ? "Converting" :
413 "Would have converted"), p1, p2, p3, p4,
416 p->di_gid = VICEMAGIC;
417 p->di_uid = q->val[0];
418 p->di_suid = UID_LONG;
419 p->di_sgid = GID_LONG;
425 /* If not an AFS inode, ignore */
429 ("Non AFS Inode %d: (p1=%x,p2=%x,p3=%x, p4=%x,p5=%x) ignoring..\n",
430 i, p1, p2, p3, p4, p5);
434 if (lseek(pfd, -bufsize, SEEK_CUR) == -1) { /* Point to loc bef read */
435 printf("Error Seeking backwards %d bytes\n", bufsize);
436 printf("errno %d: %s\n", errno, strerror(errno));
439 code = write(pfd, inodes, bufsize);
440 if (code != bufsize) { /* Update inodes */
441 printf("Error writing modified inodes for partition %s\n",
444 printf("errno %d: %s\n", errno, strerror(errno));
449 (" Write %d AFS inodes and %d non-AFS inodes to disk\n",
456 printf("\n%s: %d AFS inodes %s ", partition, cnt,
457 (force ? "were" : "would have been"));
459 printf("unconverted to a pre-%s format; %d already unconverted.\n",
462 printf("converted to a %s format; %d already converted.\n", OSVERS,
477 bread(fd, buf, blk, size)
483 if (lseek(fd, (off_t) dbtob(blk), L_SET) < 0
484 || read(fd, buf, size) != size) {
485 printf("bread: lseek failed (errno = %d)\n", errno);
493 * Ensure that we don't have a "/" instead of a "/dev/rxd0a" type of device.
494 * returns pointer to static storage; copy it out quickly!
501 static char pbuffer[128];
507 /* now, look in /dev for the appropriate file */
508 dirp = opendir(dirName = "/dev");
509 while (dp = readdir(dirp)) {
510 strcpy(pbuffer, dirName);
511 strcat(pbuffer, "/");
512 strcat(pbuffer, dp->d_name);
513 if (stat(pbuffer, &tstat) != -1 && (tstat.st_mode & S_IFMT) == S_IFBLK
514 && (tstat.st_rdev == adev)) {
515 strcpy(pbuffer, dp->d_name);
521 return NULL; /* failed */
531 if ((dp = strrchr(name, '/')) == 0)
533 if (stat(name, &stb) < 0)
535 if ((stb.st_mode & S_IFMT) != S_IFCHR)
537 if (*(dp + 1) != 'r')
539 (void)strcpy(dp + 1, dp + 2);
547 static char rawbuf[32];
550 if ((dp = strrchr(name, '/')) == 0)
553 (void)strcpy(rawbuf, name);
555 (void)strcat(rawbuf, "/r");
556 (void)strcat(rawbuf, dp + 1);
564 struct stat stslash, stblock, stchar;
569 if (stat(name, &stblock) < 0) {
571 printf("Can't stat %s\n", name);
574 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
576 if (stat(raw, &stchar) < 0) {
578 printf("Can't stat %s\n", raw);
581 if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
584 printf("%s is not a character device\n", raw);
587 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
588 name = unrawname(name);
592 printf("Can't make sense out of name %s\n", name);
597 /* ensure that we don't have a "/" instead of a "/dev/rxd0a" type of device.
598 * Overwrites abuffer with the corrected name.
600 EnsureDevice(abuffer)
611 code = stat(abuffer, &tstat);
614 if (((tstat.st_mode & S_IFMT) == S_IFBLK)
615 || ((tstat.st_mode & S_IFMT) == S_IFCHR)) {
616 return 0; /* already a block or char device */
618 /* otherwise, assume we've got a normal file, and we look up its device */
619 dev = tstat.st_dev; /* remember device for this file */
621 /* now, look in /dev for the appropriate file */
622 dirp = opendir(dirName = "/dev");
624 while (dp = readdir(dirp)) {
625 strcpy(pbuffer, dirName);
626 strcat(pbuffer, "/");
627 strcat(pbuffer, dp->d_name);
628 if (stat(pbuffer, &tstat) != -1 && (tstat.st_mode & S_IFMT) == S_IFBLK
629 && (tstat.st_rdev == dev)) {
630 strcpy(abuffer, pbuffer);
636 return 1; /* failed */
640 ** Open the /etc/vfstab file to map the raw device name to the mountable
641 ** device name. Then open the /etc/mnttab file to see if this mountable
642 ** device is mounted.
644 ** Returns 1 if the conversion process should continue, otherwise returns 0
646 CheckMountedDevice(devName)
647 char *devName; /* raw device name */
649 FILE *vfsent, *mntent;
656 if ((vfsent = fopen(VFSTAB, "r")) == NULL) {
657 printf("Unable to open %s ( errno = %d)\n", VFSTAB, errno);
660 while (!getvfsent(vfsent, &vnt)) {
661 char *rawDev = vnt.vfs_fsckdev;
662 if (rawDev && !strcmp(rawDev, devName)) {
663 /* this is the device we are looking for */
664 unRawDev = vnt.vfs_special;
671 goto done; /* could not find it in /etc/vfstab */
673 /* we found the entry in /etc/vfstab. Now we open /etc/mnnttab and
674 ** verify that it is not mounted
676 if ((mntent = fopen(MNTTAB, "r")) == NULL) {
677 printf("Unable to open %s ( errno = %d)\n", VFSTAB, errno);
681 while (!getmntent(mntent, &mnt)) {
682 char *resource = mnt.mnt_special;
683 if (resource && !strcmp(resource, unRawDev)) {
691 /* if we found an entry in the /etc/mnttab file, then this
692 ** device must be mounted
698 ("Device %s may be mounted. Can corrupt data. Continue anyway(y/n)?",
704 while (YesNo != 'y' && YesNo != 'Y' && YesNo != 'n' && YesNo != 'N');
706 if ((YesNo == 'y') || (YesNo == 'Y'))
711 #else /* !AFS_SUN54_ENV */
713 #include "AFS_component_version_number.c"
720 ("%s: **ONLY** supported for Solaris 2.4 and later ...\n",
723 #endif /* !AFS_SUN5_ENV */