BlobScan is used by the Linux port in a separate file, so it should not
become static.
*/
-#if defined(AFS_SGI62_ENV) || defined(AFS_SUN57_64BIT_ENV)
int
-BlobScan(ino64_t * afile, afs_int32 ablob)
-#else
-#if defined(AFS_HPUX1123_ENV)
-/*DEE should use afs_inode_t for all */
-int
-BlobScan(ino_t * afile, afs_int32 ablob)
-#else
-#ifdef AFS_LINUX_64BIT_KERNEL
-int
-BlobScan(long *afile, afs_int32 ablob)
-#else
-int
-BlobScan(afs_int32 * afile, afs_int32 ablob)
-#endif
-#endif
-#endif
+BlobScan(struct dcache * afile, afs_int32 ablob)
{
register afs_int32 relativeBlob;
afs_int32 pageBlob;
u_short d_reclen;
u_char d_type;
u_char d_namlen;
-#else
-#ifdef AFS_SUN5_ENV
+#elif defined(AFS_SUN5_ENV)
afs_uint32 d_fileno;
afs_int32 d_off;
u_short d_reclen;
#else
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV)
+#if defined(AFS_AIX32_ENV)
afs_int32 d_off;
-#endif
-#if defined(AFS_HPUX100_ENV)
+#elif defined(AFS_HPUX100_ENV)
unsigned long long d_off;
#endif
afs_uint32 d_fileno;
u_short d_reclen;
u_short d_namlen;
#endif
-#endif
};
#endif /* AFS_SGI_ENV */
afs_size_t off;
{
int code = 0;
+ struct volume *tvp;
+ afs_uint32 Volume = vc->fid.Fid.Volume;
+ afs_uint32 Vnode = de->fid.vnode;
#if defined(AFS_SUN56_ENV)
struct dirent64 *direntp;
#else
#endif /* AFS_SGI53_ENV */
AFS_STATCNT(afs_readdir_move);
+
+#define READDIR_CORRECT_INUMS
+#ifdef READDIR_CORRECT_INUMS
+ if (de->name[0] == '.' && !de->name[1]) {
+ /* This is the '.' entry; if we are a volume root, we need to
+ * ignore the directory and use the inum for the mount point.
+ */
+ if (!FidCmp(&afs_rootFid, &vc->fid)) {
+ Volume = 0;
+ Vnode = 2;
+ } else if (vc->mvstat == 2) {
+ tvp = afs_GetVolume(&vc->fid, 0, READ_LOCK);
+ if (tvp) {
+ Volume = tvp->mtpoint.Fid.Volume;
+ Vnode = tvp->mtpoint.Fid.Vnode;
+ afs_PutVolume(tvp, READ_LOCK);
+ }
+ }
+ }
+ else if (de->name[0] == '.' && de->name[1] == '.' && !de->name[2]) {
+ /* This is the '..' entry. Getting this right is very tricky,
+ * because we might be a volume root (so our parent is in a
+ * different volume), or our parent might be a volume root
+ * (so we actually want the mount point) or BOTH! */
+ if (!FidCmp(&afs_rootFid, &vc->fid)) {
+ /* We are the root of the AFS root, and thus our own parent */
+ Volume = 0;
+ Vnode = 2;
+ } else if (vc->mvstat == 2) {
+ /* We are a volume root, which means our parent is in another
+ * volume. Luckily, we should have his fid cached... */
+ if (vc->mvid) {
+ if (!FidCmp(&afs_rootFid, vc->mvid)) {
+ /* Parent directory is the root of the AFS root */
+ Volume = 0;
+ Vnode = 2;
+ } else if (vc->mvid->Fid.Vnode == 1
+ && vc->mvid->Fid.Unique == 1) {
+ /* XXX The above test is evil and probably breaks DFS */
+ /* Parent directory is the target of a mount point */
+ tvp = afs_GetVolume(vc->mvid, 0, READ_LOCK);
+ if (tvp) {
+ Volume = tvp->mtpoint.Fid.Volume;
+ Vnode = tvp->mtpoint.Fid.Vnode;
+ afs_PutVolume(tvp, READ_LOCK);
+ }
+ } else {
+ /* Parent directory is not a volume root */
+ Volume = vc->mvid->Fid.Volume;
+ Vnode = vc->mvid->Fid.Vnode;
+ }
+ }
+ } else if (de->fid.vnode == 1 && de->fid.vunique == 1) {
+ /* XXX The above test is evil and probably breaks DFS */
+ /* Parent directory is a volume root; use the right inum */
+ tvp = afs_GetVolume(&vc->fid, 0, READ_LOCK);
+ if (tvp) {
+ if (tvp->cell == afs_rootFid.Cell
+ && tvp->volume == afs_rootFid.Fid.Volume) {
+ /* Parent directory is the root of the AFS root */
+ Volume = 0;
+ Vnode = 2;
+ } else {
+ /* Parent directory is the target of a mount point */
+ Volume = tvp->mtpoint.Fid.Volume;
+ Vnode = tvp->mtpoint.Fid.Vnode;
+ }
+ afs_PutVolume(tvp, READ_LOCK);
+ }
+ }
+ }
+#endif
+
#ifdef AFS_SGI53_ENV
{
afs_int32 use64BitDirent;
if (use64BitDirent) {
struct min_dirent sdirEntry;
- sdirEntry.d_fileno =
- (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
+ sdirEntry.d_fileno = (Volume << 16) + ntohl(Vnode);
FIXUPSTUPIDINODE(sdirEntry.d_fileno);
sdirEntry.d_reclen = rlen;
sdirEntry.d_off = (off_t) off;
}
} else {
struct irix5_min_dirent sdirEntry;
- sdirEntry.d_fileno =
- (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
+ sdirEntry.d_fileno = (Volume << 16) + ntohl(Vnode);
FIXUPSTUPIDINODE(sdirEntry.d_fileno);
sdirEntry.d_reclen = rlen;
sdirEntry.d_off = (afs_int32) off;
#else
direntp = (struct dirent *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
#endif
- direntp->d_ino = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
+ direntp->d_ino = (Volume << 16) + ntohl(Vnode);
FIXUPSTUPIDINODE(direntp->d_ino);
#if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
direntp->d_offset = off;
osi_FreeLargeSpace((char *)direntp);
#else /* AFS_SUN5_ENV */
/* Note the odd mechanism for building the inode number */
- sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
+ sdirEntry.d_fileno = (Volume << 16) + ntohl(Vnode);
FIXUPSTUPIDINODE(sdirEntry.d_fileno);
sdirEntry.d_reclen = rlen;
#if !defined(AFS_SGI_ENV)
sdirEntry.d_namlen = slen;
#endif
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV)
+#if defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV)
sdirEntry.d_off = off;
#endif
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
#if defined(AFS_SGI53_ENV)
afs_int32 use64BitDirent, dirsiz;
#endif /* defined(AFS_SGI53_ENV) */
+#ifndef AFS_HPUX_ENV
OSI_VC_CONVERT(avc);
-#ifdef AFS_HPUX_ENV
+#else
/*
* XXX All the hacks for alloced sdirEntry and inlining of afs_readdir_move instead of calling
* it is necessary for hpux due to stack problems that seem to occur when coming thru the nfs
if (eofp)
*eofp = 0;
#endif
+#ifndef AFS_64BIT_CLIENT
if (AfsLargeFileUio(auio) /* file is large than 2 GB */
||AfsLargeFileSize(auio->uio_offset, auio->uio_resid))
return EFBIG;
+#endif
if ((code = afs_InitReq(&treq, acred))) {
#ifdef AFS_HPUX_ENV
origOffset = auio->afsio_offset;
/* scan for the next interesting entry scan for in-use blob otherwise up point at
* this blob note that ode, if non-zero, also represents a held dir page */
- if (!(us = BlobScan(&tdc->f.inode, (origOffset >> 5)))
- || !(nde = (struct DirEntry *)afs_dir_GetBlob(&tdc->f.inode, us))) {
+ if (!(us = BlobScan(tdc, (origOffset >> 5)))
+ || !(nde = (struct DirEntry *)afs_dir_GetBlob(tdc, us))) {
/* failed to setup nde, return what we've got, and release ode */
if (len) {
/* something to hand over. */
FIXUPSTUPIDINODE(sdirEntry->d_fileno);
sdirEntry->d_reclen = rlen = auio->afsio_resid;
sdirEntry->d_namlen = o_slen;
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
+#if defined(AFS_SUN5_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
sdirEntry->d_off = origOffset;
#endif
AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
FIXUPSTUPIDINODE(sdirEntry->d_fileno);
sdirEntry->d_reclen = rlen = auio->afsio_resid;
sdirEntry->d_namlen = o_slen;
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
+#if defined(AFS_SUN5_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
sdirEntry->d_off = origOffset;
#endif
AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
FIXUPSTUPIDINODE(sdirEntry->d_fileno);
sdirEntry->d_reclen = rlen = len;
sdirEntry->d_namlen = o_slen;
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
+#if defined(AFS_SUN5_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
sdirEntry->d_off = origOffset;
#endif
AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio,
/* scan for the next interesting entry scan for in-use blob otherwise up point at
* this blob note that ode, if non-zero, also represents a held dir page */
- if (!(us = BlobScan(&tdc->f.inode, (origOffset >> 5)))
- || !(nde = (struct DirEntry *)afs_dir_GetBlob(&tdc->f.inode, us))) {
+ if (!(us = BlobScan(tdc, (origOffset >> 5)))
+ || !(nde = (struct DirEntry *)afs_dir_GetBlob(tdc, us))) {
/* failed to setup nde, return what we've got, and release ode */
if (len) {
/* something to hand over. */