# include "h/user.h"
# endif /* AFS_SGI64_ENV */
# include "h/uio.h"
-# ifdef AFS_OSF_ENV
-# include <sys/mount.h>
-# include <sys/vnode.h>
-# include <ufs/inode.h>
-# endif
# if !defined(AFS_SUN5_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_HPUX110_ENV)
# include "h/mbuf.h"
# endif
# include "dir.h"
#endif /* KERNEL */
-afs_int32 DErrno;
-
/* Local static prototypes */
static int FindBlobs(dir_file_t, int);
static void AddPage(dir_file_t, int);
struct DirBuffer entrybuf, prevbuf, headerbuf;
struct DirEntry *ep;
struct DirHeader *dhp;
+ int code;
/* check name quality */
if (*entry == 0)
return EINVAL;
/* First check if file already exists. */
- if (FindItem(dir, entry, &prevbuf, &entrybuf) == 0) {
+ code = FindItem(dir, entry, &prevbuf, &entrybuf);
+ if (code && code != ENOENT) {
+ return code;
+ }
+ if (code == 0) {
DRelease(&entrybuf, 0);
DRelease(&prevbuf, 0);
return EEXIST;
struct DirBuffer entrybuf, prevbuf;
struct DirEntry *firstitem;
unsigned short *previtem;
+ int code;
- if (FindItem(dir, entry, &prevbuf, &entrybuf) != 0)
- return ENOENT;
+ code = FindItem(dir, entry, &prevbuf, &entrybuf);
+ if (code) {
+ return code;
+ }
firstitem = (struct DirEntry *)entrybuf.data;
previtem = (unsigned short *)prevbuf.data;
DRelease(&pagehdbuf, 1);
}
-/*
+/*!
* Format an empty directory properly. Note that the first 13 entries in a
* directory header page are allocated, 1 to the page header, 4 to the
* allocation map and 8 to the hash table.
+ *
+ * \param dir pointer to the directory object
+ * \param me fid (vnode+uniq) for new dir
+ * \param parent fid (vnode+uniq) for parent dir
+ *
+ * \retval 0 success
+ * \retval nonzero error code
*/
int
afs_dir_MakeDir(dir_file_t dir, afs_int32 * me, afs_int32 * parent)
int i;
struct DirBuffer buffer;
struct DirHeader *dhp;
+ int code;
DNew(dir, 0, &buffer);
dhp = (struct DirHeader *)buffer.data;
for (i = 0; i < NHASHENT; i++)
dhp->hashTable[i] = 0;
DRelease(&buffer, 1);
- afs_dir_Create(dir, ".", me);
- afs_dir_Create(dir, "..", parent); /* Virtue is its own .. */
+ code = afs_dir_Create(dir, ".", me);
+ if (code)
+ return code;
+ code = afs_dir_Create(dir, "..", parent);
+ if (code)
+ return code;
return 0;
}
afs_int32 *fid = (afs_int32 *) voidfid;
struct DirBuffer firstbuf, prevbuf;
struct DirEntry *firstitem;
+ int code;
- if (FindItem(dir, entry, &prevbuf, &firstbuf) != 0)
- return ENOENT;
+ code = FindItem(dir, entry, &prevbuf, &firstbuf);
+ if (code) {
+ return code;
+ }
DRelease(&prevbuf, 0);
firstitem = (struct DirEntry *)firstbuf.data;
afs_int32 *fid = (afs_int32 *) voidfid;
struct DirBuffer firstbuf, prevbuf;
struct DirEntry *firstitem;
+ int code;
- if (FindItem(dir, entry, &prevbuf, &firstbuf) != 0)
- return ENOENT;
+ code = FindItem(dir, entry, &prevbuf, &firstbuf);
+ if (code) {
+ return code;
+ }
DRelease(&prevbuf, 0);
firstitem = (struct DirEntry *)firstbuf.data;
/* Return a pointer to an entry, given its number. Also return the maximum
* size of the entry, which is determined by its position within the directory
* page.
+ *
+ * If physerr is supplied by caller, it will be set to:
+ * 0 for logical errors
+ * errno for physical errors
*/
-
static int
GetBlobWithLimit(dir_file_t dir, afs_int32 blobno,
- struct DirBuffer *buffer, afs_size_t *maxlen)
+ struct DirBuffer *buffer, afs_size_t *maxlen, int *physerr)
{
afs_size_t pos;
int code;
*maxlen = 0;
memset(buffer, 0, sizeof(struct DirBuffer));
- code = DRead(dir, blobno >> LEPP, buffer);
+ code = DReadWithErrno(dir, blobno >> LEPP, buffer, physerr);
if (code)
return code;
return 0;
}
+/*
+ * Given an entry's number, return a pointer to that entry.
+ * If physerr is supplied by caller, it will be set to:
+ * 0 for logical errors
+ * errno for physical errors
+ */
+int
+afs_dir_GetBlobWithErrno(dir_file_t dir, afs_int32 blobno, struct DirBuffer *buffer,
+ int *physerr)
+{
+ afs_size_t maxlen = 0;
+ return GetBlobWithLimit(dir, blobno, buffer, &maxlen, physerr);
+}
+
/* Given an entries number, return a pointer to that entry */
int
afs_dir_GetBlob(dir_file_t dir, afs_int32 blobno, struct DirBuffer *buffer)
{
afs_size_t maxlen = 0;
- return GetBlobWithLimit(dir, blobno, buffer, &maxlen);
+ return GetBlobWithLimit(dir, blobno, buffer, &maxlen, NULL);
}
/* Return an entry, having verified that the name held within the entry
int code;
char *cp;
- code = GetBlobWithLimit(file, blobno, &buffer, &maxlen);
+ code = GetBlobWithLimit(file, blobno, &buffer, &maxlen, NULL);
if (code)
return code;
i = afs_dir_DirHash(ename);
if (dhp->hashTable[i] == 0) {
/* no such entry */
- DRelease(&prev, 0);
- return ENOENT;
+ code = ENOENT;
+ goto out;
}
code = afs_dir_GetVerifiedBlob(dir,
(u_short) ntohs(dhp->hashTable[i]),
&curr);
if (code) {
- DRelease(&prev, 0);
- return code;
+ goto out;
}
prev.data = &(dhp->hashTable[i]);
prev = curr;
prev.data = &(tp->next);
- if (tp->next == 0)
- goto out; /* The end of the line */
+ if (tp->next == 0) {
+ /* The end of the line */
+ code = ENOENT;
+ goto out;
+ }
code = afs_dir_GetVerifiedBlob(dir, (u_short) ntohs(tp->next),
&curr);
goto out;
}
+ /* If we've reached here, we've hit our loop limit. Something is weird with
+ * the directory; maybe a circular hash chain? */
+ code = EIO;
+
out:
DRelease(&prev, 0);
- return ENOENT;
+ return code;
}
static int
struct DirEntry *entry;
int code = 0;
- if (FindFid(dir, vnode, unique, &entrybuf) != 0)
- return ENOENT;
+ code = FindFid(dir, vnode, unique, &entrybuf);
+ if (code) {
+ return code;
+ }
entry = (struct DirEntry *)entrybuf.data;
if (strlen(entry->name) >= length)
struct DirEntry *firstitem;
struct MKFid *fid_old = (struct MKFid *) old_fid;
struct MKFid *fid_new = (struct MKFid *) new_fid;
+ int code;
/* Find entry. */
- if (FindItem(dir, entry, &prevbuf, &entrybuf) != 0)
- return ENOENT;
+ code = FindItem(dir, entry, &prevbuf, &entrybuf);
+ if (code) {
+ return code;
+ }
firstitem = (struct DirEntry *)entrybuf.data;
DRelease(&prevbuf, 1);