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>
16 #define OSVERS "SunOS 5.6"
17 #include <sys/types.h>
19 #include <afs/afsint.h>
20 #include <sys/param.h>
21 #include <sys/fs/ufs_fs.h>
24 #include <sys/mount.h>
28 #endif /* ITIMER_REAL */
30 #ifdef AFS_VFSINCL_ENV
31 #include <sys/vnode.h>
32 #include <sys/fs/ufs_inode.h>
33 #else /* AFS_VFSINCL_ENV */
34 #include <sys/inode.h>
35 #endif /* AFS_VFSINCL_ENV */
36 #include <sys/mnttab.h>
37 #include <sys/mntent.h>
38 #include <sys/vfstab.h>
40 #include <afs/osi_inode.h>
44 #include <afs/ihandle.h>
45 #include <afs/partition.h>
50 int icount
= 0, iarraysize
= 0, *iarray
;
52 char *rawname(), *unrawname(), *vol_DevName(), *blockcheck();
54 int force
= 0, verbose
= 0, unconv
= 0;
57 handleit(struct cmd_syndesc
*as
)
61 afs_int32 haspart
= 0, hasDevice
= 0;
64 if (as
->parms
[1].items
)
68 if (as
->parms
[2].items
)
75 ("Unconverts from a %s AFS partition to a pre-%s compatible format.\n\n",
79 ("Converts a pre-%s AFS partition to a %s compatible format.\n\n",
84 ("*** Must use the '-force' option for command to have effect! ***\n");
87 ("*** Use the '-verbose' option to report what will be converted ***\n");
92 for (ti
= as
->parms
[0].items
; ti
; ti
= ti
->next
) {
94 char *namep
= ti
->data
;
98 if ((fsent
= fopen(VFSTAB
, "r")) == NULL
) {
99 printf("Unable to open %s ( errno = %d)\n", VFSTAB
, errno
);
102 while (!getvfsent(fsent
, &mnt
)) {
103 char *part
= mnt
.vfs_mountp
;
108 if (!strncmp(namep
, VICE_PARTITION_PREFIX
, VICE_PREFIX_SIZE
)) {
109 if (!strncmp(part
, VICE_PARTITION_PREFIX
, VICE_PREFIX_SIZE
)) {
110 if (!strncmp(part
, namep
, strlen(part
) + 1)) {
111 if (dname
= mnt
.vfs_fsckdev
) {
112 printf("ProcessFileSys %s %s\n", dname
, namep
);
113 ProcessFileSys(dname
, namep
);
122 printf("Unknown input AFS partition name or device: %s\n", namep
);
126 /* if raw devices are specified */
127 for (ti
= as
->parms
[3].items
; ti
; ti
= ti
->next
) {
128 char *namep
= ti
->data
;
132 if (!CheckMountedDevice(namep
)) {
133 printf("Device %s may be mounted, aborting...\n", namep
);
136 ProcessFileSys(namep
, namep
);
140 if (!haspart
&& !hasDevice
) {
144 if ((fsent
= fopen(VFSTAB
, "r")) == NULL
) {
145 printf("Unable to open %s ( errno = %d)\n", VFSTAB
, errno
);
148 while (!getvfsent(fsent
, &mnt
)) {
149 char *part
= mnt
.vfs_mountp
;
154 if (strncmp(part
, VICE_PARTITION_PREFIX
, VICE_PREFIX_SIZE
) == 0) {
155 if (dname
= mnt
.vfs_fsckdev
)
156 ProcessFileSys(dname
, part
);
163 ("No file system partitions named %s* found; not processed\n",
164 VICE_PARTITION_PREFIX
);
169 ConvCmd(struct cmd_syndesc
*as
, void *arock
)
176 UnConvCmd(struct cmd_syndesc
*as
, void *arock
)
183 #include "AFS_component_version_number.c"
188 struct cmd_syndesc
*ts
;
191 if (geteuid() != 0) {
192 printf("must be run as root; sorry\n");
195 ts
= cmd_CreateSyntax("convert", ConvCmd
, NULL
, 0,
196 "Convert to AFS SunOS 5.6 format");
197 cmd_AddParm(ts
, "-part", CMD_LIST
, CMD_OPTIONAL
, "AFS partition name");
198 cmd_AddParm(ts
, "-verbose", CMD_FLAG
, CMD_OPTIONAL
, "verbose mode");
199 cmd_AddParm(ts
, "-force", CMD_FLAG
, CMD_OPTIONAL
,
200 "Safeguard enforce switch");
201 cmd_AddParm(ts
, "-device", CMD_LIST
, CMD_OPTIONAL
, "AFS raw device name");
202 ts
= cmd_CreateSyntax("unconvert", UnConvCmd
, NULL
, 0,
203 "Convert back from AFS SunOS 5.6 to earlier formats");
204 cmd_AddParm(ts
, "-part", CMD_LIST
, CMD_OPTIONAL
, "AFS partition name");
205 cmd_AddParm(ts
, "-verbose", CMD_FLAG
, CMD_OPTIONAL
, "verbose mode");
206 cmd_AddParm(ts
, "-force", CMD_FLAG
, CMD_OPTIONAL
,
207 "Safeguard enforce switch");
208 cmd_AddParm(ts
, "-device", CMD_LIST
, CMD_OPTIONAL
, "AFS raw device name");
210 code
= cmd_Dispatch(argc
, argv
);
215 ProcessFileSys(dname
, path
)
218 struct stat status
, stat1
;
219 char devbuffer
[120], *devname
;
220 int i
, j
, mounted
= 0, code
;
222 if (stat(path
, &status
) == -1) {
223 printf("Couldn't find file system \"%s\"\n", path
);
226 if (status
.st_ino
== ROOTINODE
) {
229 ("Partition %s is mounted; only unmounted partitions are processed\n",
235 strcpy(devbuffer
, dname
);
238 if (stat(path
, &status
) == -1) {
239 printf("Couldn't find file system \"%s\"\n", path
);
243 if (ProcessAfsInodes(devname
, path
) == -1)
244 printf("Unable to get inodes for \"%s\"; not processed\n", path
);
249 ProcessAfsInodes(devname
, partition
)
250 char *devname
, *partition
;
256 int pfd
, i
, c
, e
, bufsize
, cnt
= 0, mod
= 0, wcnt
= 0, ccnt
= 0, ncnt
;
257 FILE *inodeFile
= NULL
;
259 struct dinode
*inodes
= NULL
, *einodes
, *p
;
264 sprintf(rdev
, "%s", devname
);
265 pfd
= open(rdev
, O_RDWR
);
267 printf("Could not read device %s to get inode list\n", rdev
);
268 printf("errno %d: %s\n", errno
, strerror(errno
));
271 if (bread(pfd
, super
.block
, SBLOCK
, SBSIZE
) == -1) {
272 printf("Unable to read superblock, partition %s\n", partition
);
277 * run a few consistency checks of the superblock
278 * (Cribbed from vfsck)
280 if ((super
.fs
.fs_magic
!= FS_MAGIC
) || (super
.fs
.fs_ncg
< 1)
281 || (super
.fs
.fs_cpg
< 1)
282 || (super
.fs
.fs_ncg
* super
.fs
.fs_cpg
< super
.fs
.fs_ncyl
283 || (super
.fs
.fs_ncg
- 1) * super
.fs
.fs_cpg
>= super
.fs
.fs_ncyl
)
284 || (super
.fs
.fs_sbsize
> SBSIZE
)) {
286 ("There's something wrong with the superblock for partition %s; run vfsck\n",
290 bufsize
= super
.fs
.fs_ipg
* sizeof(struct dinode
);
291 if (!(inodes
= malloc(bufsize
))) {
292 printf("Unable to allocate enough memory to scan inodes; help!\n");
295 einodes
= (struct dinode
*)(((char *)inodes
) + bufsize
);
296 printf("Processing all AFS inodes on partition %s (device %s)...\n",
298 for (c
= 0; c
< super
.fs
.fs_ncg
; c
++) {
303 i
= c
* super
.fs
.fs_ipg
;
304 e
= i
+ super
.fs
.fs_ipg
;
305 f1
= fsbtodb(&super
.fs
, itod(&super
.fs
, i
));
306 off
= (offset_t
) f1
<< DEV_BSHIFT
;
307 code
= llseek(pfd
, off
, L_SET
);
309 printf("Error reading inodes for partition %s; run vfsck\n",
311 printf("%d: %s\n", errno
, strerror(errno
));
312 printf("file number = %d; offset = %ld\n", pfd
, off
);
316 wcnt
= ncnt
= mod
= 0;
317 code
= read(pfd
, inodes
, bufsize
);
318 if (code
!= bufsize
) {
319 printf("Error reading inodes for partition %s; run vfsck\n",
322 printf("errno %d: %s\n", errno
, strerror(errno
));
327 /* Step through each inode */
328 for (p
= inodes
; p
< einodes
&& i
< e
; i
++, p
++)
330 afs_uint32 p1
, p2
, p3
, p4
;
334 q
= (quad
*) & (p
->di_ic
.ic_lsize
);
337 p2
= p
->di_ic
.ic_flags
;
339 p4
= p
->di_ic
.ic_uid
;
340 p5
= p
->di_ic
.ic_gid
;
342 /* the game is afoot, Dr Watson! */
343 if (!verbose
&& !((ccnt
+ cnt
+ ncnt
) % 5000)) {
350 * Convert from a 5.6 format to a pre 5.6 format
352 if ((p2
|| p3
) && !p4
&& (p5
== -2)) {
355 ("AFS Inode %d: Already in pre-%s AFS format (%x,%x,%x,%x,%x) ignoring..\n",
356 i
, OSVERS
, p1
, p2
, p3
, p4
, p5
);
361 if (p5
== VICEMAGIC
) {
362 /* This is a sol 2.6 AFS inode */
368 ("AFS Inode %d: %s from Sol5.6 (%x,%x,%x,%x,%x) \n",
370 (force
? "Unconverting" :
371 "Would have unconverted"), p1
, p2
, p3
, p4
,
374 q
->val
[0] = p
->di_uid
;
377 p
->di_suid
= UID_LONG
;
378 p
->di_sgid
= GID_LONG
;
383 if (p5
== VICEMAGIC
) { /* Assume an already converted 5.6 afs inode */
386 ("AFS Inode %d: Already in %s AFS format (p1=%x,p2=%x,p3=%x,p4=%x,p5=%x); ignoring..\n",
387 i
, OSVERS
, p1
, p2
, p3
, p4
, p5
);
392 /* for inodes created in solaris 2.4, there is a possibility
393 ** that the gid gets chopped off to an unsigned short(2 bytes)
395 if ((p2
|| p3
) && !p4
&& ((p5
== -2)
396 || ((unsigned short)p5
==
397 (unsigned short)-2))) {
398 /* This is a pre Sol2.6 inode */
404 ("AFS Inode %d: %s to 5.6 format (p1=%x,p2=%x,p3=%x,p4=%x, p5=%x)\n",
406 (force
? "Converting" :
407 "Would have converted"), p1
, p2
, p3
, p4
,
410 p
->di_gid
= VICEMAGIC
;
411 p
->di_uid
= q
->val
[0];
412 p
->di_suid
= UID_LONG
;
413 p
->di_sgid
= GID_LONG
;
419 /* If not an AFS inode, ignore */
423 ("Non AFS Inode %d: (p1=%x,p2=%x,p3=%x, p4=%x,p5=%x) ignoring..\n",
424 i
, p1
, p2
, p3
, p4
, p5
);
428 if (lseek(pfd
, -bufsize
, SEEK_CUR
) == -1) { /* Point to loc bef read */
429 printf("Error Seeking backwards %d bytes\n", bufsize
);
430 printf("errno %d: %s\n", errno
, strerror(errno
));
433 code
= write(pfd
, inodes
, bufsize
);
434 if (code
!= bufsize
) { /* Update inodes */
435 printf("Error writing modified inodes for partition %s\n",
438 printf("errno %d: %s\n", errno
, strerror(errno
));
443 (" Write %d AFS inodes and %d non-AFS inodes to disk\n",
450 printf("\n%s: %d AFS inodes %s ", partition
, cnt
,
451 (force
? "were" : "would have been"));
453 printf("unconverted to a pre-%s format; %d already unconverted.\n",
456 printf("converted to a %s format; %d already converted.\n", OSVERS
,
471 bread(fd
, buf
, blk
, size
)
477 if (lseek(fd
, (off_t
) dbtob(blk
), L_SET
) < 0
478 || read(fd
, buf
, size
) != size
) {
479 printf("bread: lseek failed (errno = %d)\n", errno
);
487 * Ensure that we don't have a "/" instead of a "/dev/rxd0a" type of device.
488 * returns pointer to static storage; copy it out quickly!
495 static char pbuffer
[128];
501 /* now, look in /dev for the appropriate file */
502 dirp
= opendir(dirName
= "/dev");
503 while (dp
= readdir(dirp
)) {
504 strcpy(pbuffer
, dirName
);
505 strcat(pbuffer
, "/");
506 strcat(pbuffer
, dp
->d_name
);
507 if (stat(pbuffer
, &tstat
) != -1 && (tstat
.st_mode
& S_IFMT
) == S_IFBLK
508 && (tstat
.st_rdev
== adev
)) {
509 strcpy(pbuffer
, dp
->d_name
);
515 return NULL
; /* failed */
525 if ((dp
= strrchr(name
, '/')) == 0)
527 if (stat(name
, &stb
) < 0)
529 if ((stb
.st_mode
& S_IFMT
) != S_IFCHR
)
531 if (*(dp
+ 1) != 'r')
533 (void)strcpy(dp
+ 1, dp
+ 2);
541 static char rawbuf
[32];
544 if ((dp
= strrchr(name
, '/')) == 0)
547 (void)strcpy(rawbuf
, name
);
549 (void)strcat(rawbuf
, "/r");
550 (void)strcat(rawbuf
, dp
+ 1);
558 struct stat stslash
, stblock
, stchar
;
563 if (stat(name
, &stblock
) < 0) {
565 printf("Can't stat %s\n", name
);
568 if ((stblock
.st_mode
& S_IFMT
) == S_IFBLK
) {
570 if (stat(raw
, &stchar
) < 0) {
572 printf("Can't stat %s\n", raw
);
575 if ((stchar
.st_mode
& S_IFMT
) == S_IFCHR
) {
578 printf("%s is not a character device\n", raw
);
581 } else if ((stblock
.st_mode
& S_IFMT
) == S_IFCHR
&& !retried
) {
582 name
= unrawname(name
);
586 printf("Can't make sense out of name %s\n", name
);
591 /* ensure that we don't have a "/" instead of a "/dev/rxd0a" type of device.
592 * Overwrites abuffer with the corrected name.
594 EnsureDevice(abuffer
)
605 code
= stat(abuffer
, &tstat
);
608 if (((tstat
.st_mode
& S_IFMT
) == S_IFBLK
)
609 || ((tstat
.st_mode
& S_IFMT
) == S_IFCHR
)) {
610 return 0; /* already a block or char device */
612 /* otherwise, assume we've got a normal file, and we look up its device */
613 dev
= tstat
.st_dev
; /* remember device for this file */
615 /* now, look in /dev for the appropriate file */
616 dirp
= opendir(dirName
= "/dev");
618 while (dp
= readdir(dirp
)) {
619 strcpy(pbuffer
, dirName
);
620 strcat(pbuffer
, "/");
621 strcat(pbuffer
, dp
->d_name
);
622 if (stat(pbuffer
, &tstat
) != -1 && (tstat
.st_mode
& S_IFMT
) == S_IFBLK
623 && (tstat
.st_rdev
== dev
)) {
624 strcpy(abuffer
, pbuffer
);
630 return 1; /* failed */
634 ** Open the /etc/vfstab file to map the raw device name to the mountable
635 ** device name. Then open the /etc/mnttab file to see if this mountable
636 ** device is mounted.
638 ** Returns 1 if the conversion process should continue, otherwise returns 0
640 CheckMountedDevice(devName
)
641 char *devName
; /* raw device name */
643 FILE *vfsent
, *mntent
;
650 if ((vfsent
= fopen(VFSTAB
, "r")) == NULL
) {
651 printf("Unable to open %s ( errno = %d)\n", VFSTAB
, errno
);
654 while (!getvfsent(vfsent
, &vnt
)) {
655 char *rawDev
= vnt
.vfs_fsckdev
;
656 if (rawDev
&& !strcmp(rawDev
, devName
)) {
657 /* this is the device we are looking for */
658 unRawDev
= vnt
.vfs_special
;
665 goto done
; /* could not find it in /etc/vfstab */
667 /* we found the entry in /etc/vfstab. Now we open /etc/mnnttab and
668 ** verify that it is not mounted
670 if ((mntent
= fopen(MNTTAB
, "r")) == NULL
) {
671 printf("Unable to open %s ( errno = %d)\n", VFSTAB
, errno
);
675 while (!getmntent(mntent
, &mnt
)) {
676 char *resource
= mnt
.mnt_special
;
677 if (resource
&& !strcmp(resource
, unRawDev
)) {
685 /* if we found an entry in the /etc/mnttab file, then this
686 ** device must be mounted
692 ("Device %s may be mounted. Can corrupt data. Continue anyway(y/n)?",
698 while (YesNo
!= 'y' && YesNo
!= 'Y' && YesNo
!= 'n' && YesNo
!= 'N');
700 if ((YesNo
== 'y') || (YesNo
== 'Y'))