openafs/src/vol/listinodes.c
Simon Wilkinson ac3e0ed031 Rename printf cast helpers and clean up format string warnings
Some confusion had ensued about the usage of our printf cast helper
functions. Rename these to attempt to allay that confusion, and restore
the functions themselves to their original definitions.

Essentially, afs_printable_int32_ld() and friends are helpers to go
from afs specifc types to things that can be emitted by printf without
causing compiler warnings.

Also clean up some additional warnings from type mismatches between
escapes in printf format strings and the variables being printed.

Reviewed-on: http://gerrit.openafs.org/50
Verified-by: Russ Allbery <rra@stanford.edu>
Reviewed-by: Russ Allbery <rra@stanford.edu>
2009-07-10 18:28:02 -06:00

1582 lines
42 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
*/
/*
System: VICE-TWO
Module: listinodes.c
Institution: The Information Technology Center, Carnegie-Mellon University
*/
#define ITC /* Required by inode.h */
#include <afsconfig.h>
#include <afs/param.h>
#include <string.h>
#ifndef AFS_NAMEI_ENV
#if defined(AFS_LINUX20_ENV) || defined(AFS_SUN4_ENV)
/* ListViceInodes
*
* Return codes:
* 0 - success
* -1 - Unable to read the inodes.
* -2 - Unable to completely write temp file. Produces warning message in log.
*/
int
ListViceInodes(char *devname, char *mountedOn, char *resultFile,
afs_uint32 (*judgeInode) (), afs_uint32 judgeParam, int *forcep, int forceR,
char *wpath, void *rock)
{
Log("ListViceInodes not implemented for this platform!\n");
return -1;
}
#else
#include <ctype.h>
#include <sys/param.h>
#if defined(AFS_SGI_ENV)
#else
#ifdef AFS_OSF_ENV
#include <ufs/fs.h>
#else /* AFS_OSF_ENV */
#ifdef AFS_VFSINCL_ENV
#define VFS
#ifdef AFS_SUN5_ENV
#include <sys/fs/ufs_fs.h>
#else
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#define itod ino_to_fsba
#else
#include <ufs/fs.h>
#endif
#endif
#else /* AFS_VFSINCL_ENV */
#ifdef AFS_AIX_ENV
#include <sys/filsys.h>
#else
#include <sys/fs.h>
#endif
#endif /* AFS_VFSINCL_ENV */
#endif /* AFS_OSF_ENV */
#include <sys/time.h>
#ifdef AFS_VFSINCL_ENV
#include <sys/vnode.h>
#ifdef AFS_SUN5_ENV
#include <sys/fs/ufs_inode.h>
#else
#if !defined(AFS_DARWIN_ENV)
#include <ufs/inode.h>
#endif
#endif
#else /* AFS_VFSINCL_ENV */
#ifdef AFS_OSF_ENV
#include <ufs/inode.h>
#else /* AFS_OSF_ENV */
#include <sys/inode.h>
#endif
#endif /* AFS_VFSINCL_ENV */
#endif /* AFS_SGI_ENV */
#include <afs/osi_inode.h>
#include <sys/file.h>
#include <stdio.h>
#include <rx/xdr.h>
#include <afs/afsint.h>
#include "nfs.h"
#include <afs/afssyscalls.h>
#include "viceinode.h"
#include <sys/stat.h>
#if defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV)
#include <sys/ino.h>
#endif
#ifdef AFS_PTHREAD_ENV
#include <assert.h>
#else /* AFS_PTHREAD_ENV */
#include <afs/assert.h>
#endif /* AFS_PTHREAD_ENV */
#if defined(AFS_HPUX101_ENV)
#include <unistd.h>
#endif
#include "lock.h"
#include "ihandle.h"
#include "vnode.h"
#include "volume.h"
#include "volinodes.h"
#include "partition.h"
#include "fssync.h"
/*@+fcnmacros +macrofcndecl@*/
#ifdef O_LARGEFILE
#ifdef S_SPLINT_S
extern off64_t afs_lseek(int FD, off64_t O, int F);
#endif /*S_SPLINT_S */
#define afs_lseek(FD, O, F) lseek64(FD, (off64_t) (O), F)
#define afs_stat stat64
#define afs_fstat fstat64
#define afs_open open64
#define afs_fopen fopen64
#else /* !O_LARGEFILE */
#ifdef S_SPLINT_S
extern off_t afs_lseek(int FD, off_t O, int F);
#endif /*S_SPLINT_S */
#define afs_lseek(FD, O, F) lseek(FD, (off_t) (O), F)
#define afs_stat stat
#define afs_fstat fstat
#define afs_open open
#define afs_fopen fopen
#endif /* !O_LARGEFILE */
/*@=fcnmacros =macrofcndecl@*/
/* Notice: parts of this module have been cribbed from vfsck.c */
#define ROOTINODE 2
static char *partition;
int Testing=0;
int pfd;
#ifdef AFS_AIX32_ENV
#include <jfs/filsys.h>
#ifndef FSBSIZE
#define FSBSIZE (4096) /* filesystem block size */
#define FSBSHIFT (12) /* log2(FSBSIZE) */
#define FSBMASK (FSBSIZE - 1) /* FSBSIZE mask */
#define MIN_FSIZE DISKMAP_B /* minimum fs size (FSblocks) */
#define LAST_RSVD_I 15 /* last reserved inode */
#endif
#ifndef INOPB
/*
* This will hopefully eventually make it into the system include files
*/
#define INOPB (FSBSIZE / sizeof (struct dinode))
#endif
#ifdef AFS_AIX41_ENV
int fragsize;
int iagsize;
int ag512;
int agblocks;
#endif /* AFS_AIX41_ENV */
/*
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XX This was lifted from some `com/cmd/fs/fshlpr_aix3/Fs.h', which indicated X
XX a longing to see it make it into a readily accessible include file. XXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
*
* itoo - inode number to offset within disk block
*/
#undef itoo
#define itoo(x) (int) ((unsigned)(x) % INOPB)
int Bsize = FSBSIZE; /* block size for this system */
daddr_t fmax; /* total number of blocks n file system */
ino_t imax, inum; /* total number of I-nodes in file system */
static struct superblock fs;
struct dinode *ginode();
int
ListViceInodes(char *devname, char *mountedOn, char *resultFile,
int (*judgeInode) (), afs_uint32 judgeParam, int *forcep, int forceR,
char *wpath, void *rock)
{
FILE *inodeFile = NULL;
char dev[50], rdev[51];
struct stat status;
struct dinode *p;
struct ViceInodeInfo info;
struct stat root_inode;
int ninodes = 0, err = 0;
pfd = -1; /* initialize so we don't close on error output below. */
*forcep = 0;
sync();
sleep(1); /* simulate operator */
sync();
sleep(1);
sync();
sleep(1);
partition = mountedOn;
sprintf(dev, "/dev/%s", devname);
sprintf(rdev, "/dev/r%s", devname);
if (stat(mountedOn, &root_inode) < 0) {
Log("cannot stat: %s\n", mountedOn);
return -1;
}
if (root_inode.st_ino != ROOTDIR_I) {
Log("%s is not root of a filesystem\n", mountedOn);
return -1;
}
/*
* done with the superblock, now try to read the raw device.
*/
if (ReadSuper(&fs, dev) < 0)
return -1;
switch (fs.s_fmod) {
default:
case FM_CLEAN: /* clean and unmounted */
Log("Most peculiar - Super blk in FM_CLEAN state!\n");
goto out;
case FM_MOUNT: /* mounted cleanly */
break;
case FM_MDIRTY: /* dirty when mounted or commit fail */
case FM_LOGREDO: /* log redo attempted but failed */
Log("File system %s is in a bad state.\n", rdev);
Log("Call your IBM representative.\n");
return -1;
}
#ifdef AFS_AIX42_ENV
if (IsBigFilesFileSystem(&fs, (char *)0)) {
Log("%s is a big files filesystem, can't salvage.\n", mountedOn);
return -1;
}
#else
if (strncmp(fs.s_magic, fsv3magic, strlen(fsv3magic)) != 0) {
#ifdef AFS_AIX41_ENV
if ((strncmp(fs.s_magic, fsv3pmagic, strlen(fsv3pmagic)) != 0)
|| (fs.s_version != fsv3pvers)) {
Log("Super block doesn't have the problem magic (%s vs v3magic %s v3pmagic %s)\n", fs.s_magic, fsv3magic, fsv3pmagic);
return -1;
}
#else
Log("Super block doesn't have the problem magic (%s vs v3magic %s)\n",
fs.s_magic, fsv3magic);
return -1;
#endif
}
#endif
#ifdef AFS_AIX41_ENV
fragsize = (fs.s_fragsize) ? fs.s_fragsize : FSBSIZE;
iagsize = (fs.s_iagsize) ? fs.s_iagsize : fs.s_agsize;
ag512 = fragsize * fs.s_agsize / 512;
agblocks = fragsize * fs.s_agsize >> BSHIFT;
#endif /* AFS_AIX41_ENV */
fmax = fs.s_fsize / (FSBSIZE / 512); /* first invalid blk num */
pfd = afs_open(rdev, O_RDONLY);
if (pfd < 0) {
Log("Unable to open `%s' inode for reading\n", rdev);
return -1;
}
if (resultFile) {
inodeFile = fopen(resultFile, "w");
if (inodeFile == NULL) {
Log("Unable to create inode description file %s\n", resultFile);
goto out;
}
}
/*
* calculate the maximum number of inodes possible
*/
#ifdef AFS_AIX41_ENV
imax = iagsize * (fs.s_fsize / ag512) - 1;
#else /* AFS_AIX41_ENV */
imax =
((fmax / fs.s_agsize +
((fmax % fs.s_agsize) >= fs.s_agsize / INOPB ? 1 : 0))
* fs.s_agsize) - 1;
#endif /* AFS_AIX41_ENV */
/*
* check for "FORCESALVAGE" equivalent:
* LAST_RSVD_I is a vice inode, with dead beef, and
* di_nlink == 2 to indicate the FORCE.
*/
assert(p = ginode(LAST_RSVD_I));
if (p->di_vicemagic == VICEMAGIC && p->di_vicep1 == 0xdeadbeef
&& p->di_nlink == 2) {
*forcep = 1;
idec(root_inode.st_dev, LAST_RSVD_I, 0xdeadbeef);
}
for (inum = LAST_RSVD_I + 1; inum <= imax; ++inum) {
if ((p = ginode(inum)) == NULL || p->di_vicemagic != VICEMAGIC
|| (p->di_mode & IFMT) != IFREG)
continue;
info.inodeNumber = inum;
info.byteCount = p->di_size;
info.linkCount = p->di_nlink;
info.u.param[0] = p->di_vicep1;
info.u.param[1] = p->di_vicep2;
info.u.param[2] = p->di_vicep3;
info.u.param[3] = p->di_vicep4;
if (judgeInode && (*judgeInode) (&info, judgeParam, rock) == 0)
continue;
if (inodeFile) {
if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
Log("Error writing inode file for partition %s\n", partition);
goto out;
}
}
++ninodes;
}
if (inodeFile) {
if (fflush(inodeFile) == EOF) {
Log("Unable to successfully flush inode file for %s\n", partition);
err = -2;
goto out1;
}
if (fsync(fileno(inodeFile)) == -1) {
Log("Unable to successfully fsync inode file for %s\n", partition);
err = -2;
goto out1;
}
if (fclose(inodeFile) == EOF) {
Log("Unable to successfully close inode file for %s\n", partition);
err = -2;
goto out1;
}
/*
* Paranoia: check that the file is really the right size
*/
if (stat(resultFile, &status) == -1) {
Log("Unable to successfully stat inode file for %s\n", partition);
err = -2;
goto out1;
}
if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
Log("Wrong size (%d instead of %d) in inode file for %s\n",
status.st_size, ninodes * sizeof(struct ViceInodeInfo),
partition);
err = -2;
goto out1;
}
}
close(pfd);
return 0;
out:
err = -1;
out1:
if (pfd >= 0)
close(pfd);
if (inodeFile)
fclose(inodeFile);
return err;
}
/* Read in the superblock for devName */
int
ReadSuper(struct superblock *fs, char *devName)
{
int pfd;
pfd = afs_open(devName, O_RDONLY);
if (pfd < 0) {
Log("Unable to open inode on %s for reading superblock.\n", devName);
return -1;
}
if (bread(pfd, fs, SUPER_B, sizeof(struct superblock)) < 0) {
Log("Unable to read superblock on %s.\n", devName);
return -1;
}
close(pfd);
return (0);
}
#ifdef AFS_AIX42_ENV
/* IsBigFilesFileSystem returns 1 if it's a big files filesystem, 0 otherwise. */
int
IsBigFilesFileSystem(struct superblock *sb)
{
if ((strncmp(sb->s_magic, fsv3pmagic, 4) == 0)
&& (sb->s_version == fsbigfile)
&& (sb->s_bigexp))
return 1;
else
return 0;
}
#endif
struct dinode *
ginode(inum)
{
int ag;
daddr_t pblk;
struct dinode *dp;
static char buf[FSBSIZE];
static daddr_t last_blk = -1;
#ifdef AFS_AIX41_ENV
ag = inum / iagsize;
pblk =
(ag ==
0) ? INODES_B + inum / INOPB : ag * agblocks + (inum -
ag * iagsize) /
INOPB;
#else /* AFS_AIX41_ENV */
ag = inum / fs.s_agsize;
pblk =
(ag ==
0) ? INODES_B + inum / INOPB : ag * fs.s_agsize + (inum -
ag *
fs.s_agsize) /
INOPB;
#endif /* AFS_AIX41_ENV */
if (last_blk != pblk) {
if (bread(pfd, buf, pblk, sizeof(buf)) < 0) {
last_blk = -1;
return 0;
}
last_blk = pblk;
}
dp = (struct dinode *)buf;
dp += itoo(inum);
return (dp);
}
#else /* !AFS_AIX31_ENV */
#if defined(AFS_SGI_ENV)
/* libefs.h includes <assert.h>, which we don't want */
#define __ASSERT_H__
#ifdef AFS_SGI_XFS_IOPS_ENV
#include <dirent.h>
#include <afs/xfsattrs.h>
/* xfs_ListViceInodes
*
* xfs_ListViceInodes verifies and correct the XFS namespace as it collects
* the inode information. The name is required for the idec operation to work.
* Steps 2 and 3 below are for the AFS_XFS_NAME_VERS == 1. If the name space
* changes, the algorithm will need to change.
* 1) If the parent inode number does not match the directory's inod number,
* change it in the attribute.
* 2) If the unqifier in the attribute does not match the name, rename the
* file. This is done by doing an exclusive open, incrementing the tag
* number until a file can be created. If the tag changes, then the
* attribute will need updating.
* 3) If the tag in the attribute does not match the name, change the
* attribute.
* 4) Verify uid = RW volume id and gid = XFS_VICEMAGIC.
*
*/
/* xfs_VerifyInode
*
* Does the verifications listed above.
* We can't change the names until the readdir is complete, so we set the
* rename flag if the file needs renaming.
*/
int
xfs_VerifyInode(char *dir, uint64_t pino, char *name, i_list_inode_t * info,
int *rename)
{
char path[1024];
int vno;
int update_pino = 0;
int update_tag = 0;
int update_chown = 0;
int retCode = 0;
char tmpName[32];
b64_string_t stmp;
int tag;
*rename = 0;
(void)sprintf(path, "%s/%s", dir, name);
/* Verify uid and gid fields */
if (info->ili_magic != XFS_VICEMAGIC) {
Log("%s magic for %s/%s (inode %s) from %d to %d\n",
Testing ? "Would have changed" : "Changing", dir, name,
PrintInode(NULL, info->ili_info.inodeNumber), info->ili_magic,
XFS_VICEMAGIC);
if (!Testing)
update_chown = 1;
}
vno = info->ili_info.param[0];
if (info->ili_vno != AFS_XFS_VNO_CLIP(vno)) {
Log("%s volume id for %s/%s (inode %s) from %d to %d\n",
Testing ? "Would have changed" : "Changing", dir, name,
PrintInode(NULL, info->ili_info.inodeNumber), info->ili_vno,
AFS_XFS_VNO_CLIP(vno));
if (!Testing)
update_chown = 1;
}
if (update_chown) {
if (chown(path, AFS_XFS_VNO_CLIP(vno), XFS_VICEMAGIC) < 0) {
Log("Can't chown %s to uid=%d, gid=0x%x\n", path,
AFS_XFS_VNO_CLIP(vno), XFS_VICEMAGIC);
retCode = -1;
}
}
/* Check Parent inode number. */
if (info->ili_pino != pino) {
afs_ino_str_t sino, sipino, spino;
(void)PrintInode(sino, info->ili_info.inodeNumber);
(void)PrintInode(sipino, info->ili_pino);
(void)PrintInode(spino, pino);
Log("%s parent ino for %s (inode %s) from %s to %s.\n",
Testing ? "Would have changed" : "Changing", path, sino, sipino,
spino);
if (!Testing)
update_pino = 1;
}
/* Verify the file name. */
(void)strcpy(tmpName, ".");
(void)strcat(tmpName, int_to_base64(stmp, info->ili_info.param[2]));
if (strncmp(name, tmpName, strlen(tmpName))) {
Log("%s name %s (inode %s) in directory %s, unique=%d, tag=%d\n",
Testing ? "Would have returned bad" : "Bad", name,
PrintInode(NULL, info->ili_info.inodeNumber), dir,
info->ili_info.param[2], info->ili_tag);
if (!Testing)
*rename = 1;
}
if (!*rename) {
/* update the tag? */
(void)strcat(tmpName, ".");
(void)strcat(tmpName, int_to_base64(stmp, info->ili_tag));
if (strcmp(name, tmpName)) {
char *p;
(void)strcpy(tmpName, name);
p = strchr(tmpName + 1, '.');
if (!p) {
Log("No tag found on name %s (inode %s)in directory, %s.\n",
name, PrintInode(NULL, info->ili_info.inodeNumber), dir,
Testing ? "would have renamed" : "will rename");
if (!Testing)
*rename = 1;
} else {
tag = base64_to_int(p + 1);
Log("%s the tag for %s (inode %s) from %d to %d.\n",
Testing ? "Would have changed" : "Will change", path,
PrintInode(NULL, info->ili_info.inodeNumber), dir, tag,
info->ili_tag);
if (!Testing)
update_tag = 1;
}
}
}
if (update_pino || update_tag) {
afs_xfs_attr_t attrs;
int length;
length = SIZEOF_XFS_ATTR_T;
if (attr_get(path, AFS_XFS_ATTR, (char *)&attrs, &length, ATTR_ROOT) <
0) {
Log("Can't get AFS attribute for %s\n", path);
return -1;
}
if (update_pino)
attrs.at_pino = pino;
if (update_tag)
attrs.at_tag = tag;
if (attr_set
(path, AFS_XFS_ATTR, (char *)&attrs, length,
ATTR_ROOT | ATTR_REPLACE) < 0) {
Log("Can't set AFS attribute into %s\n", path);
retCode = -1;
}
}
return retCode;
}
typedef struct {
int uniq;
char name[28];
} xfs_Rename_t;
int
xfs_RenameFiles(char *dir, xfs_Rename_t * renames, int n_renames)
{
int i, j;
char opath[128], nbase[128], npath[128];
afs_xfs_attr_t attrs;
int length = SIZEOF_XFS_ATTR_T;
b64_string_t stmp;
int tag;
int fd;
for (i = 0; i < n_renames; i++) {
(void)sprintf(opath, "%s/%s", dir, renames[i].name);
(void)sprintf(nbase, "%s/.%s", dir,
int_to_base64(stmp, renames[i].uniq));
for (tag = 2, j = 0; j < 64; tag++, j++) {
(void)sprintf(npath, "%s.%s", nbase, int_to_base64(stmp, tag));
fd = afs_open(npath, O_CREAT | O_EXCL | O_RDWR, 0);
if (fd > 0) {
close(fd);
break;
}
}
if (j != 64) {
Log("Can't find a new name for %s\n", opath);
return -1;
}
if (rename(opath, npath) < 0) {
Log("Can't rename %s to %s\n", opath, npath);
return -1;
}
Log("Renamed %s to %s\n", opath, npath);
return 0;
}
}
int
xfs_ListViceInodes(char *devname, char *mountedOn, char *resultFile,
int (*judgeInode) (), afs_uint32 judgeParam, int *forcep,
int forceR, char *wpath, void *rock)
{
FILE *inodeFile = NULL;
i_list_inode_t info;
int info_size = sizeof(i_list_inode_t);
int fd;
DIR *top_dirp;
dirent64_t *top_direntp;
DIR *vol_dirp;
dirent64_t *vol_direntp;
struct stat64 sdirbuf;
struct stat64 sfilebuf;
afs_xfs_attr_t attrs;
afs_xfs_dattr_t dattrs;
int length;
char vol_dirname[1024];
int ninodes = 0;
int code = 0;
xfs_Rename_t *renames = (xfs_Rename_t *) 0;
int rename;
#define N_RENAME_STEP 64
int n_renames = 0;
int n_avail = 0;
uint64_t pino;
struct stat status;
int errors = 0;
*forcep = 0;
if (stat64(mountedOn, &sdirbuf) < 0) {
perror("xfs_ListViceInodes: stat64");
return -1;
}
if (resultFile) {
inodeFile = fopen(resultFile, "w");
if (inodeFile == NULL) {
Log("Unable to create inode description file %s\n", resultFile);
return -1;
}
}
if ((top_dirp = opendir(mountedOn)) == NULL) {
Log("Can't open directory %s to read inodes.\n", mountedOn);
return -1;
}
while (top_direntp = readdir64(top_dirp)) {
/* Only descend directories with the AFSDIR attribute set.
* Could also verify the contents of the atribute, but currently
* they are not used.
* Performance could be improved for single volume salvages by
* only going through the directory containing the volume's inodes.
* But I'm being complete as a first pass.
*/
(void)sprintf(vol_dirname, "%s/%s", mountedOn, top_direntp->d_name);
length = SIZEOF_XFS_DATTR_T;
if (attr_get
(vol_dirname, AFS_XFS_DATTR, (char *)&dattrs, &length, ATTR_ROOT))
continue;
if ((vol_dirp = opendir(vol_dirname)) == NULL) {
if (errno == ENOTDIR)
continue;
Log("Can't open directory %s to read inodes.\n", vol_dirname);
goto err1_exit;
}
pino = top_direntp->d_ino;
n_renames = 0;
while (vol_direntp = readdir64(vol_dirp)) {
if (vol_direntp->d_name[1] == '\0'
|| vol_direntp->d_name[1] == '.')
continue;
info.ili_version = AFS_XFS_ILI_VERSION;
info_size = sizeof(i_list_inode_t);
code =
ilistinode64(sdirbuf.st_dev, vol_direntp->d_ino, &info,
&info_size);
if (code) {
/* Where possible, give more explicit messages. */
switch (errno) {
case ENXIO:
case ENOSYS:
Log("%s (device id %d) is not on an XFS filesystem.\n",
vol_dirname, sdirbuf.st_dev);
goto err1_exit;
break;
case EINVAL:
case E2BIG:
if (info_size != sizeof(i_list_inode_t)
|| info.ili_version != AFS_XFS_ILI_VERSION) {
Log("Version skew between kernel and salvager.\n");
goto err1_exit;
}
break;
}
/* Continue, so we collect all the errors in the first pass. */
Log("Error listing inode named %s/%s: %s\n", vol_dirname,
vol_direntp->d_name, strerror(errno));
errors++;
continue;
}
if (info.ili_attr_version != AFS_XFS_ATTR_VERS) {
Log("Unrecognized XFS attribute version %d in %s/%s. Upgrade salvager\n", info.ili_attr_version, vol_dirname, vol_direntp->d_name);
goto err1_exit;
}
if (judgeInode && (*judgeInode) (&info.ili_info, judgeParam, rock) == 0)
continue;
rename = 0;
if (xfs_VerifyInode
(vol_dirname, pino, vol_direntp->d_name, &info,
&rename) < 0) {
errors++;
}
if (rename) {
/* Add this name to the list of items to rename. */
if (n_renames >= n_avail) {
n_avail += N_RENAME_STEP;
if (n_avail == N_RENAME_STEP)
renames = (xfs_Rename_t *)
malloc(n_avail * sizeof(xfs_Rename_t));
else
renames = (xfs_Rename_t *)
realloc((char *)renames,
n_avail * sizeof(xfs_Rename_t));
if (!renames) {
Log("Can't %salloc %lu bytes for rename list.\n",
(n_avail == N_RENAME_STEP) ? "m" : "re",
n_avail * sizeof(xfs_Rename_t));
goto err1_exit;
}
}
(void)strcpy(renames[n_renames].name, vol_direntp->d_name);
renames[n_renames].uniq = info.ili_info.param[2];
n_renames++;
}
if (inodeFile) {
if (fwrite
(&info.ili_info, sizeof(vice_inode_info_t), 1, inodeFile)
!= 1) {
Log("Error writing inode file for partition %s\n", mountedOn);
goto err1_exit;
}
}
ninodes++;
} /* end while vol_direntp */
closedir(vol_dirp);
vol_dirp = (DIR *) 0;
if (n_renames) {
Log("Renaming files.\n");
if (xfs_RenameFiles(vol_dirname, renames, n_renames) < 0) {
goto err1_exit;
}
}
}
closedir(top_dirp);
if (renames)
free((char *)renames);
if (inodeFile) {
if (fflush(inodeFile) == EOF) {
("Unable to successfully flush inode file for %s\n", mountedOn);
fclose(inodeFile);
return errors ? -1 : -2;
}
if (fsync(fileno(inodeFile)) == -1) {
Log("Unable to successfully fsync inode file for %s\n", mountedOn);
fclose(inodeFile);
return errors ? -1 : -2;
}
if (fclose(inodeFile) == EOF) {
Log("Unable to successfully close inode file for %s\n", mountedOn);
return errors ? -1 : -2;
}
/*
* Paranoia: check that the file is really the right size
*/
if (stat(resultFile, &status) == -1) {
Log("Unable to successfully stat inode file for %s\n", partition);
return errors ? -1 : -2;
}
if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
Log("Wrong size (%d instead of %d) in inode file for %s\n",
status.st_size, ninodes * sizeof(struct ViceInodeInfo),
partition);
return errors ? -1 : -2;
}
}
if (errors) {
Log("Errors encontered listing inodes, not salvaging partition.\n");
return -1;
}
return 0;
err1_exit:
if (vol_dirp)
closedir(vol_dirp);
if (top_dirp)
closedir(top_dirp);
if (renames)
free((char *)renames);
if (inodeFile)
fclose(inodeFile);
return -1;
}
#endif
int
ListViceInodes(char *devname, char *mountedOn, char *resultFile,
int (*judgeInode) (), afs_uint32 judgeParam, int *forcep, int forceR,
char *wpath, void *rock)
{
FILE *inodeFile = NULL;
char dev[50], rdev[51];
struct stat status;
struct efs_dinode *p;
struct ViceInodeInfo info;
struct stat root_inode;
int ninodes = 0, err = 0;
struct efs_dinode *dinodeBuf = NULL;
int last_cgno;
ino_t imax, inum; /* total number of I-nodes in file system */
*forcep = 0;
sync();
sleep(1); /* simulate operator */
sync();
sleep(1);
sync();
sleep(1);
if (stat(mountedOn, &root_inode) < 0) {
Log("cannot stat: %s\n", mountedOn);
return -1;
}
#ifdef AFS_SGI_XFS_IOPS_ENV
if (!strcmp("xfs", root_inode.st_fstype)) {
return xfs_ListViceInodes(devname, mountedOn, resultFile, judgeInode,
judgeParam, forcep, forceR, wpath, rock);
} else
#endif
{
Log("%s is not root of a filesystem\n", mountedOn);
return -1;
}
}
#else /* AFS_SGI_ENV */
#ifdef AFS_HPUX_ENV
#define SPERB (MAXBSIZE / sizeof(short))
#define MAXNINDIR (MAXBSIZE / sizeof(daddr_t))
struct bufarea {
struct bufarea *b_next; /* must be first */
daddr_t b_bno;
int b_size;
union {
char b_buf[MAXBSIZE]; /* buffer space */
short b_lnks[SPERB]; /* link counts */
daddr_t b_indir[MAXNINDIR]; /* indirect block */
struct fs b_fs; /* super block */
struct cg b_cg; /* cylinder group */
} b_un;
char b_dirty;
};
typedef struct bufarea BUFAREA;
BUFAREA sblk;
#define sblock sblk.b_un.b_fs
#endif /* AFS_HPUX_ENV */
extern char *afs_rawname();
int
ListViceInodes(char *devname, char *mountedOn, char *resultFile,
int (*judgeInode) (), afs_uint32 judgeParam, int *forcep, int forceR,
char *wpath, void *rock)
{
union {
#ifdef AFS_AIX_ENV
struct filsys fs;
char block[BSIZE];
#else /* !AFS_AIX_ENV */
struct fs fs;
char block[SBSIZE];
#endif
} super;
int i, c, e, bufsize, code, err = 0;
FILE *inodeFile = NULL;
char dev[50], rdev[100], err1[512], *ptr1;
struct dinode *inodes = NULL, *einodes, *dptr;
struct stat status;
int ninodes = 0;
struct dinode *p;
struct ViceInodeInfo info;
*forcep = 0;
partition = mountedOn;
sprintf(rdev, "%s/%s", wpath, devname);
ptr1 = afs_rawname(rdev);
strcpy(rdev, ptr1);
sync();
/* Bletch: this is terrible; is there a better way to do this? Does this work? vfsck doesn't even sleep!! */
#ifdef AFS_AIX_ENV
sleep(5); /* Trying a smaller one for aix */
#else
sleep(10);
#endif
pfd = afs_open(rdev, O_RDONLY);
if (pfd <= 0) {
sprintf(err1, "Could not open device %s to get inode list\n", rdev);
perror(err1);
return -1;
}
#ifdef AFS_AIX_ENV
if (bread(pfd, (char *)&super.fs, SUPERB, sizeof super.fs) == -1) {
#else
#ifdef AFS_HPUX_ENV
if (bread(pfd, (char *)&sblock, SBLOCK, SBSIZE) == -1) {
#else
if (bread(pfd, super.block, SBLOCK, SBSIZE) == -1) {
#endif /* AFS_HPUX_ENV */
#endif
Log("Unable to read superblock, partition %s\n", partition);
goto out;
}
if (resultFile) {
inodeFile = fopen(resultFile, "w");
if (inodeFile == NULL) {
Log("Unable to create inode description file %s\n", resultFile);
goto out;
}
}
#ifdef AFS_AIX_ENV
/*
* char *FSlabel(), *fslabel=0;
* fslabel = FSlabel(&super.fs);
*/
if (super.fs.s_bsize == 0)
super.fs.s_bsize = 512;
if (super.fs.s_bsize != BSIZE) {
Log("SuperBlk: Cluster size not %d; run vfsck\n", BSIZE);
goto out;
}
fmax = super.fs.s_fsize; /* first invalid blk num */
imax = ((ino_t) super.fs.s_isize - (SUPERB + 1)) * INOPB;
if (imax == 0) {
Log("Size check: imax==0!\n");
goto out;
}
if (GetAuxInodeFile(partition, &status) == 0) {
Log("Can't access Aux inode file for partition %s, aborting\n",
partition);
goto out;
}
for (inum = 1; inum <= imax; inum++) {
struct dauxinode *auxp;
if ((auxp = IsAfsInode(inum)) == NULL) {
/* Not an afs inode, keep going */
continue;
}
if ((p = ginode(inum)) == NULL)
continue;
/* deleted/non-existent inode when di_mode == 0 */
if (!p->di_mode)
continue;
info.inodeNumber = (int)inum;
info.byteCount = p->di_size;
info.linkCount = p->di_nlink;
info.u.param[0] = auxp->aux_param1;
info.u.param[1] = auxp->aux_param2;
info.u.param[2] = auxp->aux_param3;
info.u.param[3] = auxp->aux_param4;
if (judgeInode && (*judgeInode) (&info, judgeParam, rock) == 0)
continue;
if (inodeFile) {
if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
Log("Error writing inode file for partition %s\n", partition);
goto out;
}
}
ninodes++;
}
#else
/*
* run a few consistency checks of the superblock
* (Cribbed from vfsck)
*/
#ifdef AFS_HPUX_ENV
#if defined(FD_FSMAGIC)
if ((sblock.fs_magic != FS_MAGIC) && (sblock.fs_magic != FS_MAGIC_LFN)
&& (sblock.fs_magic != FD_FSMAGIC)
#if defined(AFS_HPUX101_ENV)
&& (sblock.fs_magic != FD_FSMAGIC_2)
#endif
) {
#else
if ((sblock.fs_magic != FS_MAGIC) && (sblock.fs_magic != FS_MAGIC_LFN)) {
#endif
Log("There's something wrong with the superblock for partition %s; bad magic (%d) run vfsck\n", partition, sblock.fs_magic);
goto out;
}
if (sblock.fs_ncg < 1) {
Log("There's something wrong with the superblock for partition %s; NCG OUT OF RANGE (%d) run vfsck\n", partition, sblock.fs_ncg);
goto out;
}
if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG) {
Log("There's something wrong with the superblock for partition %s; CPG OUT OF RANGE (%d) run vfsck\n", partition, sblock.fs_cpg);
goto out;
}
if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl
|| (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) {
Log("There's something wrong with the superblock for partition %s; NCYL LESS THAN NCG*CPG run vfsck\n", partition);
goto out;
}
if (sblock.fs_sbsize > SBSIZE) {
Log("There's something wrong with the superblock for partition %s; bsize too large (%d vs. %d) run vfsck\n", partition, sblock.fs_sbsize, sblock.fs_bsize);
goto out;
}
#else
if ((super.fs.fs_magic != FS_MAGIC)
|| (super.fs.fs_ncg < 1)
#if defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
|| (super.fs.fs_cpg < 1)
#else
|| (super.fs.fs_cpg < 1 || super.fs.fs_cpg > MAXCPG)
#endif
|| (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)) {
Log("There's something wrong with the superblock for partition %s; run vfsck\n", partition);
goto out;
}
#endif /* AFS_HPUX_ENV */
#ifdef AFS_HPUX_ENV
bufsize = sblock.fs_ipg * sizeof(struct dinode);
#else
bufsize = super.fs.fs_ipg * sizeof(struct dinode);
#endif /* AFS_HPUX_ENV */
inodes = (struct dinode *)malloc(bufsize);
einodes = (struct dinode *)(((char *)inodes) + bufsize);
if (inodes == NULL) {
Log("Unable to allocate enough memory to scan inodes; help!\n");
goto out;
}
Log("Scanning inodes on device %s...\n", rdev);
#ifdef AFS_HPUX_ENV
for (c = 0; c < sblock.fs_ncg; c++) {
i = c * sblock.fs_ipg;
e = i + sblock.fs_ipg;
#if defined(AFS_HPUX102_ENV)
if (afs_lseek(pfd, dbtoo(fsbtodb(&sblock, itod(&sblock, i))), L_SET) ==
-1) {
#else
if (afs_lseek(pfd, dbtob(fsbtodb(&sblock, itod(&sblock, i))), L_SET) ==
-1) {
#endif
#else
for (c = 0; c < super.fs.fs_ncg; c++) {
daddr_t dblk1;
#if defined(AFS_SUN5_ENV) || defined(AFS_DARWIN_ENV)
daddr_t f1;
#if defined(AFS_DARWIN_ENV)
#define offset_t off_t
#define llseek lseek
#endif
offset_t off;
#endif /* AFS_SUN5_ENV */
i = c * super.fs.fs_ipg;
e = i + super.fs.fs_ipg;
#ifdef AFS_OSF_ENV
dblk1 = fsbtodb(&super.fs, itod(&super.fs, i));
if (afs_lseek(pfd, (off_t) ((off_t) dblk1 * DEV_BSIZE), L_SET) == -1) {
#else
#if defined(AFS_SUN5_ENV) || defined(AFS_DARWIN_ENV)
f1 = fsbtodb(&super.fs, itod(&super.fs, i));
off = (offset_t) f1 << DEV_BSHIFT;
if (llseek(pfd, off, L_SET) == -1) {
#else
if (afs_lseek(pfd, dbtob(fsbtodb(&super.fs, itod(&super.fs, i))), L_SET)
== -1) {
#endif /* AFS_SUN5_ENV */
#endif /* AFS_OSF_ENV */
#endif /* AFS_HPUX_ENV */
Log("Error reading inodes for partition %s; run vfsck\n",
partition);
goto out;
}
while (i < e) {
if (!forceR) {
if (read(pfd, inodes, bufsize) != bufsize) {
Log("Error reading inodes for partition %s; run vfsck\n",
partition);
goto out;
}
} else {
register int bj, bk;
dptr = inodes;
for (bj = bk = 0; bj < bufsize; bj = bj + 512, bk++) {
if ((code = read(pfd, dptr, 512)) != 512) {
Log("Error reading inode %d? for partition %s (errno = %d); run vfsck\n", bk + i, partition, errno);
if (afs_lseek(pfd, 512, L_SET) == -1) {
Log("Lseek failed\n");
goto out;
}
dptr->di_mode = 0;
dptr++;
dptr->di_mode = 0;
dptr++;
dptr->di_mode = 0;
dptr++;
dptr->di_mode = 0;
dptr++;
} else
dptr += 4;
}
}
for (p = inodes; p < einodes && i < e; i++, p++) {
#ifdef notdef
Log("Ino=%d, v1=%x, v2=%x, v3=%x, mode=%x size=%d, lcnt=%d\n",
i, p->di_vicep1, p->di_vicep2, p->di_vicep3, p->di_mode,
p->di_size, p->di_nlink);
printf
("Ino=%d, v1=%x, v2=%x, v3=%x, mode=%x size=%d, lcnt=%d\n",
i, p->di_vicep1, p->di_vicep2, p->di_vicep3, p->di_mode,
p->di_size, p->di_nlink);
#endif
#ifdef AFS_OSF_ENV
#ifdef AFS_3DISPARES
/* Check to see if this inode is a pre-"OSF1 4.0D" inode */
if ((p->di_uid || p->di_gid)
&& !(p->di_flags & (IC_XUID | IC_XGID))) {
Log("Found unconverted inode %d: Use 'fs_conv_dux40D convert' on partition %s\n", i, partition);
goto out;
}
#else
assert(0); /* define AFS_3DISPARES in param.h */
#endif
#endif
#if defined(AFS_SUN56_ENV)
/* if this is a pre-sol2.6 unconverted inode, bail out */
{
afs_uint32 p1, p2, p3, p4;
int p5;
quad *q;
q = (quad *) & (p->di_ic.ic_lsize);
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;
if ((p2 || p3) && !p4 && (p5 == -2)) {
Log("Found unconverted inode %d\n", i);
Log("You should run the AFS file conversion utility\n");
goto out;
}
}
#endif
if (IS_DVICEMAGIC(p) && (p->di_mode & IFMT) == IFREG) {
afs_uint32 p2 = p->di_vicep2, p3 = DI_VICEP3(p);
info.u.param[0] = p->di_vicep1;
#ifdef AFS_3DISPARES
if (((p2 >> 3) == INODESPECIAL) && (p2 & 0x3)) {
info.u.param[1] = INODESPECIAL;
info.u.param[2] = p3;
info.u.param[3] = p2 & 0x3;
} else {
info.u.param[1] = ((p2 >> 27) << 16) + (p3 & 0xffff);
info.u.param[2] = (p2 & 0x3fffff);
info.u.param[3] =
(((p2 >> 22) & 0x1f) << 16) + (p3 >> 16);
}
#else
info.u.param[1] = p->di_vicep2;
info.u.param[2] = DI_VICEP3(p);
info.u.param[3] = p->di_vicep4;
#endif
info.inodeNumber = i;
info.byteCount = p->di_size;
info.linkCount = p->di_nlink;
if (judgeInode && (*judgeInode) (&info, judgeParam, rock) == 0)
continue;
if (inodeFile) {
if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
Log("Error writing inode file for partition %s\n",
partition);
goto out;
}
}
ninodes++;
}
}
}
}
if (inodes)
free(inodes);
#endif
if (inodeFile) {
if (fflush(inodeFile) == EOF) {
Log("Unable to successfully flush inode file for %s\n", partition);
err = -2;
goto out1;
}
if (fsync(fileno(inodeFile)) == -1) {
Log("Unable to successfully fsync inode file for %s\n", partition);
err = -2;
goto out1;
}
if (fclose(inodeFile) == EOF) {
Log("Unable to successfully close inode file for %s\n", partition);
err = -2;
goto out1;
}
/*
* Paranoia: check that the file is really the right size
*/
if (stat(resultFile, &status) == -1) {
Log("Unable to successfully stat inode file for %s\n", partition);
err = -2;
goto out1;
}
if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
Log("Wrong size (%d instead of %d) in inode file for %s\n",
status.st_size, ninodes * sizeof(struct ViceInodeInfo),
partition);
err = -2;
goto out1;
}
}
close(pfd);
return 0;
out:
err = -1;
out1:
close(pfd);
if (inodeFile)
fclose(inodeFile);
if (inodes)
free(inodes);
return err;
}
#endif /* !AFS_SGI_ENV */
#endif /* !AFS_AIX31_ENV */
#ifdef AFS_DARWIN_ENV
#undef dbtob
#define dbtob(db) ((unsigned)(db) << DEV_BSHIFT)
#endif
int
bread(int fd, char *buf, daddr_t blk, afs_int32 size)
{
#ifdef AFS_AIX_ENV
#ifdef AFS_AIX41_ENV
offset_t off = (offset_t) blk << FSBSHIFT;
if (llseek(fd, off, 0) < 0) {
Log("Unable to seek to offset %llu for block %u\n", off, blk);
return -1;
}
#else /* AFS_AIX41_ENV */
if (afs_lseek(fd, blk * Bsize, 0) < 0) {
Log("Unable to seek to offset %u for block %u\n", blk * Bsize, blk);
}
#endif /* AFS_AIX41_ENV */
#else
if (afs_lseek(fd, (off_t) dbtob(blk), L_SET) < 0) {
Log("Unable to seek to offset %u for block %u\n", dbtob(blk), blk);
}
#endif
if (read(fd, buf, size) != size) {
Log("Unable to read block %d, partition %s\n", blk, partition);
return -1;
}
return 0;
}
#endif /* AFS_LINUX20_ENV */
static afs_int32
convertVolumeInfo(int fdr, int fdw, afs_uint32 vid)
{
struct VolumeDiskData vd;
char *p;
if (read(fdr, &vd, sizeof(struct VolumeDiskData)) !=
sizeof(struct VolumeDiskData)) {
Log("1 convertiVolumeInfo: read failed for %lu with code %d\n", vid,
errno);
return -1;
}
vd.restoredFromId = vd.id; /* remember the RO volume here */
vd.cloneId = vd.id;
vd.id = vd.parentId;
vd.type = RWVOL;
vd.dontSalvage = 0;
vd.inUse = 0;
vd.uniquifier += 5000; /* just in case there are still file copies
from the old RW volume around */
p = strrchr(vd.name, '.');
if (p && !strcmp(p, ".readonly")) {
memset(p, 0, 9);
}
if (write(fdw, &vd, sizeof(struct VolumeDiskData)) !=
sizeof(struct VolumeDiskData)) {
Log("1 convertiVolumeInfo: write failed for %lu with code %d\n", vid,
errno);
return -1;
}
return 0;
}
struct specino {
afs_int32 inodeType;
Inode inodeNumber;
Inode ninodeNumber;
};
int
UpdateThisVolume(struct ViceInodeInfo *inodeinfo, VolumeId singleVolumeNumber,
struct specino *specinos)
{
struct dinode *p;
if ((inodeinfo->u.vnode.vnodeNumber == INODESPECIAL) &&
(inodeinfo->u.vnode.volumeId == singleVolumeNumber)) {
specinos[inodeinfo->u.special.type].inodeNumber =
inodeinfo->inodeNumber;
}
return 0; /* We aren't using a result file, we're caching */
}
static char *
getDevName(char *pbuffer, char *wpath)
{
char pbuf[128], *ptr;
strcpy(pbuf, pbuffer);
ptr = (char *)strrchr(pbuf, '/');
if (ptr) {
*ptr = '\0';
strcpy(wpath, pbuf);
} else
return NULL;
ptr = (char *)strrchr(pbuffer, '/');
if (ptr) {
strcpy(pbuffer, ptr + 1);
return pbuffer;
} else
return NULL;
}
#ifdef FSSYNC_BUILD_CLIENT
int
inode_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
{
char dir_name[512], oldpath[512], newpath[512];
char volname[20];
char headername[16];
char *name;
int fd, err, forcep, len, j, code;
struct dirent *dp;
struct DiskPartition64 *partP;
struct ViceInodeInfo info;
struct VolumeDiskHeader h;
IHandle_t *ih, *ih2;
FdHandle_t *fdP, *fdP2;
char wpath[100];
char tmpDevName[100];
char buffer[128];
struct specino specinos[VI_LINKTABLE+1];
Inode nearInode = 0;
memset(&specinos, 0, sizeof(specinos));
(void)afs_snprintf(headername, sizeof headername, VFORMAT, afs_printable_uint32_lu(volumeId));
(void)afs_snprintf(oldpath, sizeof oldpath, "%s/%s", pname, headername);
fd = open(oldpath, O_RDONLY);
if (fd < 0) {
Log("1 inode_ConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
return ENOENT;
}
if (read(fd, &h, sizeof(h)) != sizeof(h)) {
Log("1 inode_ConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n", volumeId);
close(fd);
return EIO;
}
close(fd);
FSYNC_VolOp(volumeId, pname, FSYNC_VOL_BREAKCBKS, 0, NULL);
/* now do the work */
for (partP = DiskPartitionList; partP && strcmp(partP->name, pname);
partP = partP->next);
if (!partP) {
Log("1 inode_ConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
return EIO;
}
strcpy(tmpDevName, partP->devName);
name = getDevName(tmpDevName, wpath);
if ((err = ListViceInodes(name, VPartitionPath(partP),
NULL, UpdateThisVolume, volumeId,
&forcep, 0, wpath, &specinos)) < 0)
{
Log("1 inode_ConvertROtoRWvolume: Couldn't get special inodes\n");
return EIO;
}
#if defined(NEARINODE_HINT)
nearInodeHash(volumeId, nearInode);
nearInode %= partP->f_files;
#endif
for (j = VI_VOLINFO; j < VI_LINKTABLE+1; j++) {
if (specinos[j].inodeNumber > 0) {
specinos[j].ninodeNumber =
IH_CREATE(NULL, partP->device, VPartitionPath(partP),
nearInode, h.parent, INODESPECIAL, j, h.parent);
IH_INIT(ih, partP->device, volumeId,
specinos[j].inodeNumber);
fdP = IH_OPEN(ih);
if (!fdP) {
Log("1 inode_ConvertROtoRWvolume: Couldn't find special inode %d for %d\n", j, volumeId);
return -1;
}
IH_INIT(ih2, partP->device, h.parent, specinos[j].ninodeNumber);
fdP2 = IH_OPEN(ih2);
if (!fdP2) {
Log("1 inode_ConvertROtoRWvolume: Couldn't find special inode %d for %d\n", j, h.parent);
return -1;
}
if (j == VI_VOLINFO)
convertVolumeInfo(fdP->fd_fd, fdP2->fd_fd, ih2->ih_vid);
else {
while (1) {
len = read(fdP->fd_fd, buffer, sizeof(buffer));
if (len < 0)
return errno;
if (len == 0)
break;
code = write(fdP2->fd_fd, buffer, len);
if (code != len)
return -1;
}
}
FDH_CLOSE(fdP);
FDH_CLOSE(fdP2);
IH_RELEASE(ih);
IH_RELEASE(ih2);
}
}
h.id = h.parent;
#ifdef AFS_64BIT_IOPS_ENV
h.volumeInfo_lo = (afs_int32)specinos[VI_VOLINFO].ninodeNumber & 0xffffffff;
h.volumeInfo_hi = (afs_int32)(specinos[VI_VOLINFO].ninodeNumber >> 32) && 0xffffffff;
h.smallVnodeIndex_lo = (afs_int32)specinos[VI_SMALLINDEX].ninodeNumber & 0xffffffff;
h.smallVnodeIndex_hi = (afs_int32)(specinos[VI_SMALLINDEX].ninodeNumber >> 32) & 0xffffffff;
h.largeVnodeIndex_lo = (afs_int32)specinos[VI_LARGEINDEX].ninodeNumber & 0xffffffff;
h.largeVnodeIndex_hi = (afs_int32)(specinos[VI_LARGEINDEX].ninodeNumber >> 32) & 0xffffffff;
if (specinos[VI_LINKTABLE].ninodeNumber) {
h.linkTable_lo = (afs_int32)specinos[VI_LINKTABLE].ninodeNumber & 0xffffffff;
h.linkTable_hi = (afs_int32)specinos[VI_LINKTABLE].ninodeNumber & 0xffffffff;
}
#else
h.volumeInfo_lo = specinos[VI_VOLINFO].ninodeNumber;
h.smallVnodeIndex_lo = specinos[VI_SMALLINDEX].ninodeNumber;
h.largeVnodeIndex_lo = specinos[VI_LARGEINDEX].ninodeNumber;
if (specinos[VI_LINKTABLE].ninodeNumber) {
h.linkTable_lo = specinos[VI_LINKTABLE].ninodeNumber;
}
#endif
(void)afs_snprintf(headername, sizeof headername, VFORMAT, afs_printable_uint32_lu(h.id));
(void)afs_snprintf(newpath, sizeof newpath, "%s/%s", pname, headername);
fd = open(newpath, O_CREAT | O_EXCL | O_RDWR, 0644);
if (fd < 0) {
Log("1 inode_ConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
return EIO;
}
if (write(fd, &h, sizeof(h)) != sizeof(h)) {
Log("1 inode_ConvertROtoRWvolume: Couldn't write header for RW-volume %lu.\n", h.id);
close(fd);
return EIO;
}
close(fd);
if (unlink(oldpath) < 0) {
Log("1 inode_ConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", errno);
}
FSYNC_VolOp(volumeId, pname, FSYNC_VOL_DONE, 0, NULL);
FSYNC_VolOp(h.id, pname, FSYNC_VOL_ON, 0, NULL);
return 0;
}
#endif /* FSSYNC_BUILD_CLIENT */
#endif /* AFS_NAMEI_ENV */