mirror of
https://git.openafs.org/openafs.git
synced 2025-01-19 15:30:14 +00:00
8f00fdfd5f
FIXES 1774 catch things which crept in. if emacs hadn't started ignoring my code formatting settings this would suck so much less....
1205 lines
27 KiB
C
1205 lines
27 KiB
C
/*
|
|
* Copyright 2000, International Business Machines Corporation and others.
|
|
* All Rights Reserved.
|
|
*
|
|
* This software has been released under the terms of the IBM Public
|
|
* License. For details, see the LICENSE file in the top-level source
|
|
* directory or online at http://www.openafs.org/dl/license10.html
|
|
*/
|
|
|
|
#include <afsconfig.h>
|
|
#include <afs/param.h>
|
|
|
|
RCSID
|
|
("$Header$");
|
|
|
|
#if defined(AFS_DUX40_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)) || defined(AFS_SUN54_ENV)
|
|
#if defined AFS_DUX40_ENV
|
|
#define OSVERS "DUX 4.0D"
|
|
#else
|
|
#if defined(AFS_SUN54_ENV)
|
|
#define OSVERS "SunOS 5.6"
|
|
#else
|
|
#define OSVERS "SunOS 4.1.1"
|
|
#endif
|
|
#endif
|
|
#include <sys/types.h>
|
|
#include <rx/xdr.h>
|
|
#include <afs/afsint.h>
|
|
#include <sys/param.h>
|
|
#include <stdio.h>
|
|
#ifdef AFS_SUN5_ENV
|
|
#include <sys/fs/ufs_fs.h>
|
|
#else
|
|
#include <ufs/fs.h>
|
|
#endif
|
|
#include <sys/stat.h>
|
|
#include <dirent.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/file.h>
|
|
#ifndef ITIMER_REAL
|
|
#include <sys/time.h>
|
|
#endif /* ITIMER_REAL */
|
|
#include <time.h>
|
|
#ifdef AFS_VFSINCL_ENV
|
|
#include <sys/vnode.h>
|
|
#ifdef AFS_SUN5_ENV
|
|
#include <sys/fs/ufs_inode.h>
|
|
#else
|
|
#include <ufs/inode.h>
|
|
#endif
|
|
#else /* AFS_VFSINCL_ENV */
|
|
#ifdef AFS_DUX40_ENV
|
|
#include <ufs/inode.h>
|
|
#else
|
|
#include <sys/inode.h>
|
|
#endif
|
|
#endif /* AFS_VFSINCL_ENV */
|
|
#ifdef AFS_AIX_ENV
|
|
#include <sys/vfs.h>
|
|
#include <sys/lockf.h>
|
|
#else
|
|
#ifdef AFS_HPUX_ENV
|
|
#include <unistd.h>
|
|
#include <checklist.h>
|
|
#else
|
|
#ifdef AFS_SUN5_ENV
|
|
#include <sys/mnttab.h>
|
|
#include <sys/mntent.h>
|
|
#include <sys/vfstab.h>
|
|
#else
|
|
#include <fstab.h>
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#include <fcntl.h>
|
|
#include <afs/osi_inode.h>
|
|
#include <errno.h>
|
|
|
|
#include <nfs.h>
|
|
#include <partition.h>
|
|
#include <afs/cmd.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
int icount = 0, iarraysize = 0, *iarray;
|
|
|
|
char *rawname(), *unrawname(), *vol_DevName(), *blockcheck();
|
|
#define ROOTINODE 2
|
|
int force = 0, verbose = 0, unconv = 0;
|
|
|
|
#ifdef AFS_DUX40_ENV
|
|
int
|
|
sortinodes(a, b)
|
|
int *a, *b;
|
|
{
|
|
if (*a < *b)
|
|
return -1;
|
|
if (*a > *b)
|
|
return +1;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
BuildInodes(path)
|
|
char *path;
|
|
{
|
|
DIR *d;
|
|
struct dirent *de;
|
|
char p[256];
|
|
struct stat stats;
|
|
int code = 0;
|
|
|
|
d = opendir(path);
|
|
if (!d) {
|
|
printf("Cannot open %s: error %d\n", path, errno);
|
|
return -1;
|
|
}
|
|
|
|
while (de = readdir(d)) {
|
|
if (iarraysize == 0) {
|
|
iarraysize = 1000;
|
|
iarray = (int *)malloc(iarraysize * sizeof(int));
|
|
}
|
|
if (icount >= iarraysize) {
|
|
iarraysize += 1000;
|
|
iarray = (int *)realloc(iarray, iarraysize * sizeof(int));
|
|
}
|
|
iarray[icount] = de->d_ino;
|
|
icount++;
|
|
|
|
if ((strcmp(de->d_name, ".") == 0) || (strcmp(de->d_name, "..") == 0))
|
|
continue;
|
|
|
|
strcpy(p, path);
|
|
strcat(p, "/");
|
|
strcat(p, de->d_name);
|
|
|
|
code = stat(p, &stats);
|
|
if (code) {
|
|
printf("Cannot stat %s: error %d\n", path, errno);
|
|
return -1;
|
|
}
|
|
if (S_ISDIR(stats.st_mode)) {
|
|
code = BuildInodes(p);
|
|
if (code)
|
|
break;
|
|
}
|
|
}
|
|
|
|
closedir(d);
|
|
return code;
|
|
}
|
|
#endif
|
|
|
|
static
|
|
ConvCmd(as)
|
|
struct cmd_syndesc *as;
|
|
{
|
|
unconv = 0;
|
|
handleit(as);
|
|
}
|
|
|
|
static
|
|
UnConvCmd(as)
|
|
struct cmd_syndesc *as;
|
|
{
|
|
unconv = 1;
|
|
handleit(as);
|
|
}
|
|
|
|
#if defined(AFS_SUN54_ENV)
|
|
|
|
static
|
|
handleit(as)
|
|
struct cmd_syndesc *as;
|
|
{
|
|
register struct cmd_item *ti;
|
|
char *dname;
|
|
afs_int32 haspart = 0, hasDevice = 0;
|
|
struct vfstab mnt;
|
|
|
|
if (as->parms[1].items)
|
|
verbose = 1;
|
|
else
|
|
verbose = 0;
|
|
if (as->parms[2].items)
|
|
force = 1;
|
|
else
|
|
force = 0;
|
|
|
|
if (unconv) {
|
|
printf
|
|
("Unconverts from a %s AFS partition to a pre-%s compatible format.\n\n",
|
|
OSVERS, OSVERS);
|
|
} else {
|
|
printf
|
|
("Converts a pre-%s AFS partition to a %s compatible format.\n\n",
|
|
OSVERS, OSVERS);
|
|
}
|
|
if (!force) {
|
|
printf
|
|
("*** Must use the '-force' option for command to have effect! ***\n");
|
|
if (!verbose) {
|
|
printf
|
|
("*** Use the '-verbose' option to report what will be converted ***\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
for (ti = as->parms[0].items; ti; ti = ti->next) {
|
|
FILE *fsent;
|
|
char *namep = ti->data;
|
|
int found = 0;
|
|
|
|
haspart = 1;
|
|
if ((fsent = fopen(VFSTAB, "r")) == NULL) {
|
|
printf("Unable to open %s ( errno = %d)\n", VFSTAB, errno);
|
|
exit(2);
|
|
}
|
|
while (!getvfsent(fsent, &mnt)) {
|
|
char *part = mnt.vfs_mountp;
|
|
|
|
if (!part)
|
|
continue;
|
|
|
|
if (!strncmp(namep, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) {
|
|
if (!strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) {
|
|
if (!strncmp(part, namep, strlen(part) + 1)) {
|
|
if (dname = mnt.vfs_fsckdev) {
|
|
printf("ProcessFileSys %s %s\n", dname, namep);
|
|
ProcessFileSys(dname, namep);
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!found)
|
|
printf("Unknown input AFS partition name or device: %s\n", namep);
|
|
fclose(fsent);
|
|
}
|
|
|
|
/* if raw devices are specified */
|
|
for (ti = as->parms[3].items; ti; ti = ti->next) {
|
|
char *namep = ti->data;
|
|
|
|
hasDevice = 1;
|
|
if (namep) {
|
|
if (!CheckMountedDevice(namep)) {
|
|
printf("Device %s may be mounted, aborting...\n", namep);
|
|
continue;
|
|
}
|
|
ProcessFileSys(namep, namep);
|
|
}
|
|
}
|
|
|
|
if (!haspart && !hasDevice) {
|
|
int didSome = 0;
|
|
FILE *fsent;
|
|
|
|
if ((fsent = fopen(VFSTAB, "r")) == NULL) {
|
|
printf("Unable to open %s ( errno = %d)\n", VFSTAB, errno);
|
|
exit(2);
|
|
}
|
|
while (!getvfsent(fsent, &mnt)) {
|
|
char *part = mnt.vfs_mountp;
|
|
|
|
if (!part)
|
|
continue;
|
|
|
|
if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE) == 0) {
|
|
if (dname = mnt.vfs_fsckdev)
|
|
ProcessFileSys(dname, part);
|
|
didSome++;
|
|
}
|
|
}
|
|
fclose(fsent);
|
|
if (!didSome)
|
|
printf
|
|
("No file system partitions named %s* found; not processed\n",
|
|
VICE_PARTITION_PREFIX);
|
|
}
|
|
}
|
|
|
|
#else /* AFS_SUN54_ENV */
|
|
|
|
handleit(as)
|
|
struct cmd_syndesc *as;
|
|
{
|
|
register struct cmd_item *ti;
|
|
char *dname;
|
|
afs_int32 haspart = 0;
|
|
|
|
if (as->parms[1].items)
|
|
verbose = 1;
|
|
else
|
|
verbose = 0;
|
|
if (as->parms[2].items)
|
|
force = 1;
|
|
else
|
|
force = 0;
|
|
|
|
if (unconv) {
|
|
printf
|
|
("Unconverts from a %s AFS partition to a pre-%s compatible format.\n\n",
|
|
OSVERS, OSVERS);
|
|
} else {
|
|
printf
|
|
("Converts a pre-%s AFS partition to a %s compatible format.\n\n",
|
|
OSVERS, OSVERS);
|
|
}
|
|
if (!force) {
|
|
printf
|
|
("*** Must use the '-force' option for command to have effect! ***\n");
|
|
if (!verbose) {
|
|
printf
|
|
("*** Use the '-verbose' option to report what will be converted ***\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
for (ti = as->parms[0].items; ti; ti = ti->next) {
|
|
struct fstab *fsent;
|
|
char *namep = ti->data;
|
|
int found = 0;
|
|
|
|
haspart = 1;
|
|
setfsent();
|
|
while (fsent = getfsent()) {
|
|
char *part = fsent->fs_file;
|
|
|
|
if (!strncmp(namep, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) {
|
|
if (!strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) {
|
|
if (!strncmp(part, namep, strlen(part) + 1)) {
|
|
if (dname = unrawname(fsent->fs_spec)) {
|
|
ProcessFileSys(dname, namep);
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (!rawname(namep) || !unrawname(namep))
|
|
break;
|
|
if (!strcmp(fsent->fs_spec, rawname(namep))
|
|
|| !strcmp(fsent->fs_spec, unrawname(namep))) {
|
|
if (dname = unrawname(fsent->fs_spec)) {
|
|
ProcessFileSys(dname, fsent->fs_file);
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!found)
|
|
printf("Unknown input AFS partition name or device: %s\n", namep);
|
|
endfsent();
|
|
}
|
|
|
|
if (!haspart) {
|
|
int didSome = 0;
|
|
struct fstab *fsent;
|
|
|
|
setfsent();
|
|
while (fsent = getfsent()) {
|
|
char *part = fsent->fs_file;
|
|
|
|
if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE) == 0) {
|
|
if (dname = unrawname(fsent->fs_spec)) {
|
|
ProcessFileSys(dname, part);
|
|
didSome++;
|
|
}
|
|
}
|
|
}
|
|
endfsent();
|
|
if (!didSome)
|
|
printf
|
|
("No file system partitions named %s* found; not processed\n",
|
|
VICE_PARTITION_PREFIX);
|
|
}
|
|
}
|
|
#endif /* AFS_SUN54_ENV */
|
|
|
|
|
|
#include "AFS_component_version_number.c"
|
|
|
|
main(argc, argv)
|
|
char **argv;
|
|
{
|
|
register struct cmd_syndesc *ts;
|
|
afs_int32 code;
|
|
|
|
if (geteuid() != 0) {
|
|
printf("must be run as root; sorry\n");
|
|
exit(1);
|
|
}
|
|
#ifdef AFS_DUX40_ENV
|
|
ts = cmd_CreateSyntax("convert", ConvCmd, 0,
|
|
"Convert to DUX 4.0D format");
|
|
#else
|
|
#if defined(AFS_SUN54_ENV)
|
|
ts = cmd_CreateSyntax("convert", ConvCmd, 0,
|
|
"Convert to AFS SunOS 5.6 format");
|
|
#else
|
|
ts = cmd_CreateSyntax("convert", ConvCmd, 0,
|
|
"Convert to AFS 4.1.1 format");
|
|
#endif
|
|
#endif
|
|
cmd_AddParm(ts, "-part", CMD_LIST, CMD_OPTIONAL, "AFS partition name");
|
|
cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, "verbose mode");
|
|
cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL,
|
|
"Safeguard enforce switch");
|
|
cmd_AddParm(ts, "-device", CMD_LIST, CMD_OPTIONAL, "AFS raw device name");
|
|
#ifdef AFS_DUX40_ENV
|
|
ts = cmd_CreateSyntax("unconvert", UnConvCmd, 0,
|
|
"Convert back from OSF 4.0D to earlier formats");
|
|
#else
|
|
#if defined(AFS_SUN54_ENV)
|
|
ts = cmd_CreateSyntax("unconvert", UnConvCmd, 0,
|
|
"Convert back from AFS SunOS 5.6 to earlier formats");
|
|
#else
|
|
ts = cmd_CreateSyntax("unconvert", UnConvCmd, 0,
|
|
"Convert back from AFS 4.1.1 to earlier formats");
|
|
#endif
|
|
#endif
|
|
cmd_AddParm(ts, "-part", CMD_LIST, CMD_OPTIONAL, "AFS partition name");
|
|
cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, "verbose mode");
|
|
cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL,
|
|
"Safeguard enforce switch");
|
|
cmd_AddParm(ts, "-device", CMD_LIST, CMD_OPTIONAL, "AFS raw device name");
|
|
|
|
code = cmd_Dispatch(argc, argv);
|
|
exit(code);
|
|
}
|
|
|
|
|
|
ProcessFileSys(dname, path)
|
|
char *dname, *path;
|
|
{
|
|
struct stat status, stat1;
|
|
#if !defined(AFS_SUN54_ENV)
|
|
struct ufs_args ufsargs;
|
|
#endif
|
|
char devbuffer[120], *devname;
|
|
int i, j, mounted = 0, code;
|
|
|
|
if (stat(path, &status) == -1) {
|
|
printf("Couldn't find file system \"%s\"\n", path);
|
|
return;
|
|
}
|
|
if (status.st_ino == ROOTINODE) {
|
|
if (force) {
|
|
printf
|
|
("Partition %s is mounted; only unmounted partitions are processed\n",
|
|
path);
|
|
return;
|
|
}
|
|
mounted = 1;
|
|
}
|
|
strcpy(devbuffer, dname);
|
|
devname = devbuffer;
|
|
#if !defined(AFS_SUN54_ENV)
|
|
EnsureDevice(devname);
|
|
#endif
|
|
if (!mounted) {
|
|
#ifdef AFS_DUX40_ENV
|
|
ufsargs.fspec = devname;
|
|
code = mount(MOUNT_UFS, path, 0, &ufsargs);
|
|
#else
|
|
#if defined(AFS_SUN54_ENV)
|
|
code = 0;
|
|
#else
|
|
ufsargs.fspec = devname;
|
|
code = mount("4.2", path, M_NEWTYPE, &ufsargs);
|
|
#endif
|
|
#endif
|
|
if (code < 0) {
|
|
printf("Couldn't mount %s on %s (err=%d)\n", devname, path,
|
|
errno);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (stat(path, &status) == -1) {
|
|
printf("Couldn't find file system \"%s\"\n", path);
|
|
return;
|
|
}
|
|
#ifdef AFS_DUX40_ENV
|
|
icount = 0;
|
|
code = BuildInodes(path);
|
|
if (code) {
|
|
printf("Couldn't generate list of all inodes in directory %s\n",
|
|
path);
|
|
return;
|
|
}
|
|
if (icount)
|
|
qsort(iarray, icount, sizeof(int), sortinodes);
|
|
#endif
|
|
|
|
#if !defined(AFS_SUN54_ENV)
|
|
if (!(devname = vol_DevName(status.st_dev))) {
|
|
printf("Couldn't get devname for %d\n", status.st_dev);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (ProcessAfsInodes(devname, path) == -1)
|
|
printf("Unable to get inodes for \"%s\"; not processed\n", path);
|
|
if (!mounted) {
|
|
#ifdef AFS_DUX40_ENV
|
|
umount(path);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
ProcessAfsInodes(devname, partition)
|
|
char *devname, *partition;
|
|
{
|
|
union {
|
|
struct fs fs;
|
|
char block[SBSIZE];
|
|
} super;
|
|
int pfd, i, c, e, bufsize, cnt = 0, mod = 0, wcnt = 0, ccnt = 0, ncnt;
|
|
FILE *inodeFile = NULL;
|
|
char rdev[25];
|
|
struct dinode *inodes = NULL, *einodes, *p;
|
|
int code, istep = 0;
|
|
|
|
sync();
|
|
sleep(5); /* XXXX */
|
|
#if defined(AFS_SUN54_ENV)
|
|
sprintf(rdev, "%s", devname);
|
|
#else
|
|
sprintf(rdev, "/dev/r%s", devname);
|
|
#endif
|
|
pfd = open(rdev, O_RDWR);
|
|
if (pfd < 0) {
|
|
printf("Could not read device %s to get inode list\n", rdev);
|
|
printf("errno %d: %s\n", errno, strerror(errno));
|
|
return -1;
|
|
}
|
|
if (bread(pfd, super.block, SBLOCK, SBSIZE) == -1) {
|
|
printf("Unable to read superblock, partition %s\n", partition);
|
|
goto out;
|
|
}
|
|
|
|
/*
|
|
* run a few consistency checks of the superblock
|
|
* (Cribbed from vfsck)
|
|
*/
|
|
if ((super.fs.fs_magic != FS_MAGIC) || (super.fs.fs_ncg < 1)
|
|
|| (super.fs.fs_cpg < 1)
|
|
|| (super.fs.fs_ncg * super.fs.fs_cpg < super.fs.fs_ncyl
|
|
|| (super.fs.fs_ncg - 1) * super.fs.fs_cpg >= super.fs.fs_ncyl)
|
|
|| (super.fs.fs_sbsize > SBSIZE)) {
|
|
printf
|
|
("There's something wrong with the superblock for partition %s; run vfsck\n",
|
|
partition);
|
|
goto out;
|
|
}
|
|
bufsize = super.fs.fs_ipg * sizeof(struct dinode);
|
|
if (!(inodes = (struct dinode *)malloc(bufsize))) {
|
|
printf("Unable to allocate enough memory to scan inodes; help!\n");
|
|
goto out;
|
|
}
|
|
einodes = (struct dinode *)(((char *)inodes) + bufsize);
|
|
printf("Processing all AFS inodes on partition %s (device %s)...\n",
|
|
partition, rdev);
|
|
for (c = 0; c < super.fs.fs_ncg; c++) {
|
|
daddr_t dblk1;
|
|
#if defined(AFS_SUN54_ENV)
|
|
daddr_t f1;
|
|
offset_t off;
|
|
#endif
|
|
|
|
i = c * super.fs.fs_ipg;
|
|
e = i + super.fs.fs_ipg;
|
|
#ifdef AFS_DUX40_ENV
|
|
dblk1 = fsbtodb(&super.fs, itod(&super.fs, i));
|
|
code = lseek(pfd, (off_t) ((off_t) dblk1 * DEV_BSIZE), L_SET);
|
|
#else
|
|
#if defined(AFS_SUN54_ENV)
|
|
f1 = fsbtodb(&super.fs, itod(&super.fs, i));
|
|
off = (offset_t) f1 << DEV_BSHIFT;
|
|
code = llseek(pfd, off, L_SET);
|
|
#else
|
|
code =
|
|
lseek(pfd, dbtob(fsbtodb(&super.fs, itod(&super.fs, i))), L_SET);
|
|
#endif
|
|
#endif
|
|
if (code == -1) {
|
|
printf("Error reading inodes for partition %s; run vfsck\n",
|
|
partition);
|
|
printf("%d: %s\n", errno, strerror(errno));
|
|
#if defined(AFS_SUN54_ENV)
|
|
printf("file number = %d; offset = %ld\n", pfd, off);
|
|
#else
|
|
printf("file number = %d\n", pfd);
|
|
#endif
|
|
goto out;
|
|
}
|
|
while (i < e) {
|
|
wcnt = ncnt = mod = 0;
|
|
code = read(pfd, inodes, bufsize);
|
|
if (code != bufsize) {
|
|
printf("Error reading inodes for partition %s; run vfsck\n",
|
|
partition);
|
|
if (code < 0) {
|
|
printf("errno %d: %s\n", errno, strerror(errno));
|
|
}
|
|
goto out;
|
|
}
|
|
|
|
/* Step through each inode */
|
|
for (p = inodes; p < einodes && i < e; i++, p++)
|
|
#ifdef AFS_DUX40_ENV
|
|
{
|
|
afs_uint32 v1, v2, v3, v4;
|
|
afs_uint32 volid, vnode, uniq, vers;
|
|
afs_uint32 type, rwvol;
|
|
afs_uint32 t;
|
|
int special;
|
|
|
|
if ((p->di_mode & IFMT) != IFREG) {
|
|
/* This inode is not an AFS inode so
|
|
* zero out all the spare fields.
|
|
*/
|
|
zeroSpares:
|
|
if (!(p->di_flags & IC_PROPLIST)) {
|
|
p->di_proplb = 0;
|
|
}
|
|
if (!(p->di_flags & IC_XUID)) {
|
|
p->di_uid = 0;
|
|
}
|
|
if (!(p->di_flags & IC_XGID)) {
|
|
p->di_gid = 0;
|
|
}
|
|
mod = 1;
|
|
ncnt++;
|
|
continue;
|
|
}
|
|
|
|
/* printf("Inode %d: proplb=%u, uid=%u, bcuid=0x%x, bcgid=0x%x, gid=0x%x\n",
|
|
* i , p->di_proplb, p->di_uid, p->di_bcuid, p->di_bcgid,
|
|
* p->di_gid);
|
|
*/
|
|
|
|
if (unconv) { /*unconvert */
|
|
/* Check if the inode is not a DUX40D AFS inode */
|
|
if (p->di_proplb != VICEMAGIC
|
|
|| (p->di_flags & IC_PROPLIST)) {
|
|
ccnt++;
|
|
if (verbose)
|
|
printf(" AFS Inode %d: already unconverted\n",
|
|
i);
|
|
continue;
|
|
}
|
|
|
|
v1 = p->di_uid;
|
|
v2 = p->di_gid;
|
|
v3 = ((u_int) (p->di_bcuid)) << 16 |
|
|
((u_int) (p->di_bcgid));
|
|
|
|
/* We have a sorted list of ufs inodes. Is it one of these */
|
|
while ((istep < icount) && (i > iarray[istep])) {
|
|
istep++;
|
|
}
|
|
if ((istep < icount) && (i == iarray[istep])) {
|
|
/* Yes, its a ufs inode */
|
|
if (verbose)
|
|
printf(" Inode %d: Not an AFS Inode\n", i);
|
|
goto zeroSpares;
|
|
}
|
|
|
|
/* Is it not an AFS inode. !IS_VICEMAGIC check */
|
|
if (!(v2 || v3)) {
|
|
if (verbose)
|
|
printf("Warning: Inode %d: Unreferenced inode\n",
|
|
i);
|
|
continue; /* skip, making no change */
|
|
}
|
|
|
|
volid = v1;
|
|
if (((v2 >> 3) == 0x1fffffff) && (v2 & 0x3)) {
|
|
special = 1; /* INODESPECIAL */
|
|
type = v2 & 0x3;
|
|
rwvol = v3;
|
|
if (verbose) {
|
|
printf
|
|
(" %s AFS Inode %d: Vol=%u, RWVol=%u, Type=%d\n",
|
|
(force ? "Unconverting" :
|
|
"Would have unconverted"), i, volid, rwvol,
|
|
type);
|
|
}
|
|
} else {
|
|
special = 0;
|
|
vnode = ((v2 >> 27) << 16) + (v3 & 0xffff);
|
|
uniq = (v2 & 0x3fffff);
|
|
vers =
|
|
(((v2 >> 22) & 0x1f) << 16) +
|
|
((v3 >> 16) & 0xffff);
|
|
if (verbose) {
|
|
printf
|
|
(" %s AFS Inode %d: RWVol=%u, VNode=%u, Uniq=%u, Vers=%u\n",
|
|
(force ? "Unconverting" :
|
|
"Would have unconverted"), i, volid, vnode,
|
|
uniq, vers);
|
|
}
|
|
}
|
|
|
|
/* Now unconvert the DUX40D AFS inode to the OSF30 version */
|
|
p->di_proplb = v1;
|
|
p->di_uid = v2;
|
|
p->di_gid = v3;
|
|
p->di_flags &= ~(IC_PROPLIST | IC_XUID | IC_XGID);
|
|
p->di_bcuid = 0;
|
|
p->di_bcgid = -2;
|
|
mod = 1;
|
|
cnt++;
|
|
wcnt++;
|
|
|
|
} else { /*convert */
|
|
if ((p->di_proplb == VICEMAGIC
|
|
&& !(p->di_flags & IC_PROPLIST))
|
|
|| (p->di_uid == 0 && p->di_gid == 0)
|
|
|| (p->di_flags & (IC_XUID | IC_XGID))) {
|
|
/* This inode is either already converted or not an AFS inode */
|
|
/* We have a sorted list of ufs inodes. Is it one of these */
|
|
while ((istep < icount) && (i > iarray[istep])) {
|
|
istep++;
|
|
}
|
|
if ((istep < icount) && (i == iarray[istep])) {
|
|
/* Yes, its a ufs inode */
|
|
if (verbose) {
|
|
printf(" Inode %d: Not an AFS Inode %s\n",
|
|
i, ((p->di_spare[1]
|
|
|| p->
|
|
di_spare[2]) ? "(fixed)" : ""));
|
|
}
|
|
goto zeroSpares;
|
|
}
|
|
|
|
/* Is it a AFS inode. IS_VICEMAGIC check */
|
|
if ((p->di_uid || p->di_gid)
|
|
&& !(p->di_flags & (IC_XUID | IC_XGID))) {
|
|
ccnt++;
|
|
if (verbose)
|
|
printf(" AFS Inode %d: already converted\n",
|
|
i);
|
|
continue;
|
|
}
|
|
|
|
/* Not an AFS nor UFS inode */
|
|
printf("Warning: Inode %d: Unreferenced inode\n", i);
|
|
continue; /* skip, making no changes */
|
|
}
|
|
|
|
v1 = p->di_proplb;
|
|
v2 = p->di_uid;
|
|
v3 = p->di_gid;
|
|
|
|
volid = v1;
|
|
if (((v2 >> 3) == 0x1fffffff) && (v2 & 0x3)) {
|
|
special = 1; /* INODESPECIAL */
|
|
type = v2 & 0x3;
|
|
rwvol = v3;
|
|
if (verbose) {
|
|
printf
|
|
(" %s AFS Inode %d: Vol=%u, RWVol=%u, Type=%d\n",
|
|
(force ? "Converting" :
|
|
"Would have converted"), i, volid, rwvol,
|
|
type);
|
|
}
|
|
} else {
|
|
special = 0;
|
|
vnode = ((v2 >> 27) << 16) + (v3 & 0xffff);
|
|
uniq = (v2 & 0x3fffff);
|
|
vers =
|
|
(((v2 >> 22) & 0x1f) << 16) +
|
|
((v3 >> 16) & 0xffff);
|
|
if (verbose) {
|
|
printf
|
|
(" %s AFS Inode %d: RWVol=%u, VNode=%u, Uniq=%u, Vers=%u\n",
|
|
(force ? "Converting" :
|
|
"Would have converted"), i, volid,
|
|
(vnode & 0x1fffff), (uniq & 0x3fffff),
|
|
(vers & 0x1fffff));
|
|
}
|
|
}
|
|
|
|
/* Now convert the OSF30 AFS inode to the DUX40D version */
|
|
p->di_proplb = VICEMAGIC;
|
|
p->di_uid = v1;
|
|
p->di_gid = v2;
|
|
p->di_bcuid = (u_short) (v3 >> 16);
|
|
p->di_bcgid = (u_short) v3;
|
|
p->di_flags &= ~(IC_PROPLIST);
|
|
p->di_flags |= (IC_XUID | IC_XGID);
|
|
mod = 1;
|
|
cnt++;
|
|
wcnt++;
|
|
} /*convert */
|
|
}
|
|
#else
|
|
{
|
|
afs_uint32 p1, p2, p3, p4;
|
|
int p5;
|
|
quad *q;
|
|
|
|
#if defined(AFS_SUN56_ENV)
|
|
q = (quad *) & (p->di_ic.ic_lsize);
|
|
#else
|
|
q = &(p->di_ic.ic_size);
|
|
#endif
|
|
|
|
p1 = p->di_gen;
|
|
p2 = p->di_ic.ic_flags;
|
|
p3 = q->val[0];
|
|
p4 = p->di_ic.ic_uid;
|
|
p5 = p->di_ic.ic_gid;
|
|
|
|
/* the game is afoot, Dr Watson! */
|
|
if (!verbose && !((ccnt + cnt + ncnt) % 5000)) {
|
|
printf(".");
|
|
fflush(stdout);
|
|
}
|
|
|
|
if (unconv) {
|
|
/*
|
|
* Convert from a 5.6 format to a pre 5.6 format
|
|
*/
|
|
if ((p2 || p3) && !p4 && (p5 == -2)) {
|
|
if (verbose)
|
|
printf
|
|
("AFS Inode %d: Already in pre-%s AFS format (%x,%x,%x,%x,%x) ignoring..\n",
|
|
i, OSVERS, p1, p2, p3, p4, p5);
|
|
ccnt++;
|
|
continue;
|
|
}
|
|
|
|
if (p5 == VICEMAGIC) {
|
|
/* This is a sol 2.6 AFS inode */
|
|
mod = 1;
|
|
cnt++;
|
|
wcnt++;
|
|
if (verbose)
|
|
printf
|
|
("AFS Inode %d: %s from Sol5.6 (%x,%x,%x,%x,%x) \n",
|
|
i,
|
|
(force ? "Unconverting" :
|
|
"Would have unconverted"), p1, p2, p3, p4,
|
|
p5);
|
|
if (force) {
|
|
q->val[0] = p->di_uid;
|
|
p->di_uid = 0;
|
|
p->di_gid = -2;
|
|
p->di_suid = UID_LONG;
|
|
p->di_sgid = GID_LONG;
|
|
}
|
|
continue;
|
|
}
|
|
} else {
|
|
if (p5 == VICEMAGIC) { /* Assume an already converted 5.6 afs inode */
|
|
if (verbose)
|
|
printf
|
|
("AFS Inode %d: Already in %s AFS format (p1=%x,p2=%x,p3=%x,p4=%x,p5=%x); ignoring..\n",
|
|
i, OSVERS, p1, p2, p3, p4, p5);
|
|
ccnt++;
|
|
continue;
|
|
}
|
|
|
|
/* for inodes created in solaris 2.4, there is a possibility
|
|
** that the gid gets chopped off to an unsigned short(2 bytes)
|
|
*/
|
|
if ((p2 || p3) && !p4 && ((p5 == -2)
|
|
|| ((unsigned short)p5 ==
|
|
(unsigned short)-2))) {
|
|
/* This is a pre Sol2.6 inode */
|
|
mod = 1;
|
|
cnt++;
|
|
wcnt++;
|
|
if (verbose)
|
|
printf
|
|
("AFS Inode %d: %s to 5.6 format (p1=%x,p2=%x,p3=%x,p4=%x, p5=%x)\n",
|
|
i,
|
|
(force ? "Converting" :
|
|
"Would have converted"), p1, p2, p3, p4,
|
|
p5);
|
|
if (force) {
|
|
p->di_gid = VICEMAGIC;
|
|
p->di_uid = q->val[0];
|
|
p->di_suid = UID_LONG;
|
|
p->di_sgid = GID_LONG;
|
|
q->val[0] = 0;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
/* If not an AFS inode, ignore */
|
|
ncnt++;
|
|
if (verbose)
|
|
printf
|
|
("Non AFS Inode %d: (p1=%x,p2=%x,p3=%x, p4=%x,p5=%x) ignoring..\n",
|
|
i, p1, p2, p3, p4, p5);
|
|
}
|
|
#endif
|
|
|
|
if (mod && force) {
|
|
if (lseek(pfd, -bufsize, SEEK_CUR) == -1) { /* Point to loc bef read */
|
|
printf("Error Seeking backwards %d bytes\n", bufsize);
|
|
printf("errno %d: %s\n", errno, strerror(errno));
|
|
goto out;
|
|
}
|
|
code = write(pfd, inodes, bufsize);
|
|
if (code != bufsize) { /* Update inodes */
|
|
printf("Error writing modified inodes for partition %s\n",
|
|
partition);
|
|
if (code < 0)
|
|
printf("errno %d: %s\n", errno, strerror(errno));
|
|
goto out;
|
|
}
|
|
if (verbose) {
|
|
printf
|
|
(" Write %d AFS inodes and %d non-AFS inodes to disk\n",
|
|
wcnt, ncnt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
printf("\n%s: %d AFS inodes %s ", partition, cnt,
|
|
(force ? "were" : "would have been"));
|
|
if (unconv)
|
|
printf("unconverted to a pre-%s format; %d already unconverted.\n",
|
|
OSVERS, ccnt);
|
|
else
|
|
printf("converted to a %s format; %d already converted.\n", OSVERS,
|
|
ccnt);
|
|
|
|
close(pfd);
|
|
return 0;
|
|
|
|
out:
|
|
close(pfd);
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
bread(fd, buf, blk, size)
|
|
int fd;
|
|
char *buf;
|
|
daddr_t blk;
|
|
afs_int32 size;
|
|
{
|
|
if (lseek(fd, (off_t) dbtob(blk), L_SET) < 0
|
|
|| read(fd, buf, size) != size) {
|
|
printf("bread: lseek failed (errno = %d)\n", errno);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Ensure that we don't have a "/" instead of a "/dev/rxd0a" type of device.
|
|
* returns pointer to static storage; copy it out quickly!
|
|
*/
|
|
char *
|
|
vol_DevName(adev)
|
|
dev_t adev;
|
|
{
|
|
struct dirent *dp;
|
|
static char pbuffer[128];
|
|
struct stat tstat;
|
|
DIR *dirp;
|
|
char *dirName;
|
|
int code;
|
|
|
|
/* now, look in /dev for the appropriate file */
|
|
dirp = opendir(dirName = "/dev");
|
|
while (dp = readdir(dirp)) {
|
|
strcpy(pbuffer, dirName);
|
|
strcat(pbuffer, "/");
|
|
strcat(pbuffer, dp->d_name);
|
|
if (stat(pbuffer, &tstat) != -1 && (tstat.st_mode & S_IFMT) == S_IFBLK
|
|
&& (tstat.st_rdev == adev)) {
|
|
strcpy(pbuffer, dp->d_name);
|
|
closedir(dirp);
|
|
return pbuffer;
|
|
}
|
|
}
|
|
closedir(dirp);
|
|
return NULL; /* failed */
|
|
}
|
|
|
|
char *
|
|
unrawname(name)
|
|
char *name;
|
|
{
|
|
char *dp;
|
|
struct stat stb;
|
|
|
|
if ((dp = strrchr(name, '/')) == 0)
|
|
return (name);
|
|
if (stat(name, &stb) < 0)
|
|
return (name);
|
|
if ((stb.st_mode & S_IFMT) != S_IFCHR)
|
|
return (name);
|
|
if (*(dp + 1) != 'r')
|
|
return (name);
|
|
(void)strcpy(dp + 1, dp + 2);
|
|
return (name);
|
|
}
|
|
|
|
char *
|
|
rawname(name)
|
|
char *name;
|
|
{
|
|
static char rawbuf[32];
|
|
char *dp;
|
|
|
|
if ((dp = strrchr(name, '/')) == 0)
|
|
return (0);
|
|
*dp = 0;
|
|
(void)strcpy(rawbuf, name);
|
|
*dp = '/';
|
|
(void)strcat(rawbuf, "/r");
|
|
(void)strcat(rawbuf, dp + 1);
|
|
return (rawbuf);
|
|
}
|
|
|
|
char *
|
|
blockcheck(name)
|
|
char *name;
|
|
{
|
|
struct stat stslash, stblock, stchar;
|
|
char *raw;
|
|
int retried = 0;
|
|
|
|
retry:
|
|
if (stat(name, &stblock) < 0) {
|
|
perror(name);
|
|
printf("Can't stat %s\n", name);
|
|
return (0);
|
|
}
|
|
if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
|
|
raw = rawname(name);
|
|
if (stat(raw, &stchar) < 0) {
|
|
perror(raw);
|
|
printf("Can't stat %s\n", raw);
|
|
return (name);
|
|
}
|
|
if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
|
|
return (raw);
|
|
} else {
|
|
printf("%s is not a character device\n", raw);
|
|
return (name);
|
|
}
|
|
} else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
|
|
name = unrawname(name);
|
|
retried++;
|
|
goto retry;
|
|
}
|
|
printf("Can't make sense out of name %s\n", name);
|
|
return (0);
|
|
}
|
|
|
|
|
|
/* ensure that we don't have a "/" instead of a "/dev/rxd0a" type of device.
|
|
* Overwrites abuffer with the corrected name.
|
|
*/
|
|
EnsureDevice(abuffer)
|
|
char *abuffer;
|
|
{
|
|
struct dirent *dp;
|
|
char pbuffer[128];
|
|
struct stat tstat;
|
|
DIR *dirp;
|
|
char *dirName;
|
|
int code;
|
|
short dev;
|
|
|
|
code = stat(abuffer, &tstat);
|
|
if (code)
|
|
return code;
|
|
if (((tstat.st_mode & S_IFMT) == S_IFBLK)
|
|
|| ((tstat.st_mode & S_IFMT) == S_IFCHR)) {
|
|
return 0; /* already a block or char device */
|
|
}
|
|
/* otherwise, assume we've got a normal file, and we look up its device */
|
|
dev = tstat.st_dev; /* remember device for this file */
|
|
|
|
/* now, look in /dev for the appropriate file */
|
|
dirp = opendir(dirName = "/dev");
|
|
|
|
while (dp = readdir(dirp)) {
|
|
strcpy(pbuffer, dirName);
|
|
strcat(pbuffer, "/");
|
|
strcat(pbuffer, dp->d_name);
|
|
if (stat(pbuffer, &tstat) != -1 && (tstat.st_mode & S_IFMT) == S_IFBLK
|
|
&& (tstat.st_rdev == dev)) {
|
|
strcpy(abuffer, pbuffer);
|
|
closedir(dirp);
|
|
return 0;
|
|
}
|
|
}
|
|
closedir(dirp);
|
|
return 1; /* failed */
|
|
}
|
|
#else
|
|
|
|
#include "AFS_component_version_number.c"
|
|
|
|
main(argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
printf
|
|
("%s: **ONLY** supported for SunOS 3.5-4.x and dux4.0D systems ...\n",
|
|
argv[0]);
|
|
}
|
|
#endif /* defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV) */
|
|
|
|
#if defined(AFS_SUN54_ENV)
|
|
|
|
/*
|
|
** Open the /etc/vfstab file to map the raw device name to the mountable
|
|
** device name. Then open the /etc/mnttab file to see if this mountable
|
|
** device is mounted.
|
|
**
|
|
** Returns 1 if the conversion process should continue, otherwise returns 0
|
|
*/
|
|
CheckMountedDevice(devName)
|
|
char *devName; /* raw device name */
|
|
{
|
|
FILE *vfsent, *mntent;
|
|
struct mnttab mnt;
|
|
struct vfstab vnt;
|
|
char *unRawDev = 0;
|
|
char YesNo = 'y';
|
|
int found = 0;
|
|
|
|
if ((vfsent = fopen(VFSTAB, "r")) == NULL) {
|
|
printf("Unable to open %s ( errno = %d)\n", VFSTAB, errno);
|
|
exit(2);
|
|
}
|
|
while (!getvfsent(vfsent, &vnt)) {
|
|
char *rawDev = vnt.vfs_fsckdev;
|
|
if (rawDev && !strcmp(rawDev, devName)) {
|
|
/* this is the device we are looking for */
|
|
unRawDev = vnt.vfs_special;
|
|
break;
|
|
}
|
|
}
|
|
fclose(vfsent);
|
|
|
|
if (!unRawDev)
|
|
goto done; /* could not find it in /etc/vfstab */
|
|
|
|
/* we found the entry in /etc/vfstab. Now we open /etc/mnnttab and
|
|
** verify that it is not mounted
|
|
*/
|
|
if ((mntent = fopen(MNTTAB, "r")) == NULL) {
|
|
printf("Unable to open %s ( errno = %d)\n", VFSTAB, errno);
|
|
exit(2);
|
|
}
|
|
|
|
while (!getmntent(mntent, &mnt)) {
|
|
char *resource = mnt.mnt_special;
|
|
if (resource && !strcmp(resource, unRawDev)) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
fclose(mntent);
|
|
|
|
|
|
/* if we found an entry in the /etc/mnttab file, then this
|
|
** device must be mounted
|
|
*/
|
|
if (found) {
|
|
done:
|
|
do {
|
|
printf
|
|
("Device %s may be mounted. Can corrupt data. Continue anyway(y/n)?",
|
|
devName);
|
|
fflush(stdout);
|
|
fflush(stdin);
|
|
YesNo = getc(stdin);
|
|
}
|
|
while (YesNo != 'y' && YesNo != 'Y' && YesNo != 'n' && YesNo != 'N');
|
|
}
|
|
if ((YesNo == 'y') || (YesNo == 'Y'))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
#endif /* AFS_SUN54_ENV */
|