libafscp: code cleanup
[openafs.git] / src / libafscp / afscp_dir.c
index d761a0b..2dee41c 100644 (file)
@@ -24,647 +24,726 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
+#include <afsconfig.h>
 #include <afs/param.h>
-#include <afs/afsint.h>
+
+#include <roken.h>
+
+#include <search.h>
+
 #include <afs/vlserver.h>
 #include <afs/vldbint.h>
 #include <afs/dir.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <search.h>
 #include "afscp.h"
 #include "afscp_internal.h"
 
-static int dirmode=DIRMODE_CELL;
+static int dirmode = DIRMODE_CELL;
 
-int SetDirMode(int mode) {
-
-     if (mode != DIRMODE_CELL && mode != DIRMODE_DYNROOT) {
-          afs_errno=EINVAL;
-          return -1;
-     }
-     dirmode=mode;
-     return 0;
+int
+afscp_SetDirMode(int mode)
+{
+    if ((mode != DIRMODE_CELL) && (mode != DIRMODE_DYNROOT)) {
+       afscp_errno = EINVAL;
+       return -1;
+    }
+    dirmode = mode;
+    return 0;
 }
 
 /* comparison function for tsearch */
-static int dircompare(const void *a, const void *b)
+static int
+dircompare(const void *a, const void *b)
 {
-     const struct afs_dircache *sa=a,*sb=b;
-     if (sa->me.fid.Vnode < sb->me.fid.Vnode) return -1;
-     if (sa->me.fid.Vnode > sb->me.fid.Vnode) return 1;
-     if (sa->me.fid.Unique < sb->me.fid.Unique) return -1;
-     if (sa->me.fid.Unique > sb->me.fid.Unique) return 1;
-     return 0;
+    const struct afscp_dircache *sa = a, *sb = b;
+    if (sa->me.fid.Vnode < sb->me.fid.Vnode)
+       return -1;
+    if (sa->me.fid.Vnode > sb->me.fid.Vnode)
+       return 1;
+    if (sa->me.fid.Unique < sb->me.fid.Unique)
+       return -1;
+    if (sa->me.fid.Unique > sb->me.fid.Unique)
+       return 1;
+    return 0;
 }
 
 /* make sure the dirstream contains the most up to date directory contents */
-static int _DirUpdate (struct afs_dirstream *d) {
-     struct AFSFetchStatus s;
-     int code;
-     struct afs_volume *v;
-     struct afs_dircache key, *stored;
-     void **cached;
-
-
-     code=afs_GetStatus(&d->fid, &s);
-     if (code)
-         return code;
-
-     if (d->dirbuffer && d->dv == s.DataVersion)
-         return 0;
-     v=afs_volumebyid(d->fid.cell, d->fid.fid.Volume);
-     if (!v) {
-          afs_errno=ENOENT;
-          return -1;
-     }
-
-     memcpy(&key.me, &d->fid, sizeof(struct afs_venusfid));
-     cached=tfind(&key, &v->dircache, dircompare);
-     if (cached) {
-          stored=*(struct afs_dircache **)cached;
-          if (d->dv == s.DataVersion) {
-               d->dirbuffer = stored->dirbuffer;
-               d->buflen = stored->buflen;
-               d->dv = stored->dv;
-               return 0;
-          }
-          tdelete(&key, &v->dircache, dircompare);
-          if (d->dirbuffer != stored->dirbuffer)
-               free(stored->dirbuffer);
-          free(stored);
-     }
-     if (s.Length > BIGMAXPAGES * AFS_PAGESIZE) {
-         afs_errno=EFBIG;
-         return -1;
-     }
-     if (d->buflen != s.Length) {
-         char *new;
-         if (d->dirbuffer) {
-              new=realloc(d->dirbuffer, s.Length);
-         } else {
-              new=malloc(s.Length);
-         }
-         if (new) {
-              d->dirbuffer=new;
-         } else {
-              afs_errno=ENOMEM;
-              return -1;
-         }
-         d->buflen=s.Length;
-     }
-
-     code=afs_pread(&d->fid, d->dirbuffer, s.Length, 0);
-     if (code < 0) {
-         return -1;
-     }
-     d->dv=s.DataVersion;
-     cached=tsearch(&key, &v->dircache, dircompare);
-     if (cached) {
-          stored=malloc(sizeof(struct afs_dircache));
-          if (stored) {
-               memcpy(&stored->me, &d->fid, sizeof(struct afs_venusfid));
-               stored->buflen=d->buflen;
-               stored->dirbuffer=d->dirbuffer;
-               stored->dv=d->dv;
-               *(struct afs_dircache **)cached=stored;
-          } else {
-               tdelete(&key, &v->dircache, dircompare);
-          }
-     }
-     return 0;
+static int
+_DirUpdate(struct afscp_dirstream *d)
+{
+    struct AFSFetchStatus s;
+    int code;
+    struct afscp_volume *v;
+    struct afscp_dircache key, *stored;
+    void **cached;
+
+
+    code = afscp_GetStatus(&d->fid, &s);
+    if (code != 0) {
+       return code;
+    }
+
+    if (d->dirbuffer && d->dv == s.DataVersion) {
+       return 0;
+    }
+    v = afscp_VolumeById(d->fid.cell, d->fid.fid.Volume);
+    if (v == NULL) {
+       afscp_errno = ENOENT;
+       return -1;
+    }
+
+    memcpy(&key.me, &d->fid, sizeof(struct afscp_venusfid));
+    cached = tfind(&key, &v->dircache, dircompare);
+    if (cached != NULL) {
+       stored = *(struct afscp_dircache **)cached;
+       if (d->dv == s.DataVersion) {
+           d->dirbuffer = stored->dirbuffer;
+           d->buflen = stored->buflen;
+           d->dv = stored->dv;
+           return 0;
+       }
+       tdelete(&key, &v->dircache, dircompare);
+       if (d->dirbuffer != stored->dirbuffer)
+           free(stored->dirbuffer);
+       free(stored);
+    }
+    if (s.Length > BIGMAXPAGES * AFS_PAGESIZE) {
+       afscp_errno = EFBIG;
+       return -1;
+    }
+    if (d->buflen != s.Length) {
+       char *new;
+       if (d->dirbuffer) {
+           new = realloc(d->dirbuffer, s.Length);
+       } else {
+           new = malloc(s.Length);
+       }
+       if (new != NULL) {
+           d->dirbuffer = new;
+       } else {
+           afscp_errno = ENOMEM;
+           return -1;
+       }
+       d->buflen = s.Length;
+    }
+
+    code = afscp_PRead(&d->fid, d->dirbuffer, s.Length, 0);
+    if (code < 0) {
+       return -1;
+    }
+    d->dv = s.DataVersion;
+    cached = tsearch(&key, &v->dircache, dircompare);
+    if (cached != NULL) {
+       stored = malloc(sizeof(struct afscp_dircache));
+       if (stored != NULL) {
+           memcpy(&stored->me, &d->fid, sizeof(struct afscp_venusfid));
+           stored->buflen = d->buflen;
+           stored->dirbuffer = d->dirbuffer;
+           stored->dv = d->dv;
+           *(struct afscp_dircache **)cached = stored;
+       } else {
+           tdelete(&key, &v->dircache, dircompare);
+       }
+    }
+    return 0;
 }
 
-
-static struct DirEntry *dir_get_entry(struct afs_dirstream *d, int entry) {
-
-     struct DirHeader *h=(struct DirHeader *)d->dirbuffer;
-     struct PageHeader *p;
-     struct DirEntry *ret;
-     int fr;
-     int pg, off;
-
-
-     pg=entry >> LEPP;
-     off=entry & (EPP-1);
-
-     if (pg * AFS_PAGESIZE >= d->buflen) { /* beyond end of file */
-         return NULL;
-     }
-     if (!off || (!pg && off < DHE + 1)) { /* offset refers to metadata */
-         return NULL;
-     }
-     if (pg < MAXPAGES && h->alloMap[pg] == EPP) { /* page is empty */
-         return NULL;
-     }
-     p=(struct PageHeader *)&d->dirbuffer[pg * AFS_PAGESIZE];
-     fr=p->freebitmap[off >> 8];
-#if 0
-     if ((fr & (1<<(off & 7))) == 0 ) { /* entry isn't allocated */
-         return NULL;
-     }
-#endif
-
-     ret=(struct DirEntry *)&d->dirbuffer[pg * AFS_PAGESIZE + 32 * off];
-
-     return ret;
+static struct DirEntry *
+dir_get_entry(struct afscp_dirstream *d, int entry)
+{
+    struct DirHeader *h = (struct DirHeader *)d->dirbuffer;
+    /* struct PageHeader *p; */
+    struct DirEntry *ret;
+    /* int fr; */
+    int pg, off;
+
+    pg = entry >> LEPP;
+    off = entry & (EPP - 1);
+
+    if (pg * AFS_PAGESIZE >= d->buflen) {      /* beyond end of file */
+       return NULL;
+    }
+    if (!off || (!pg && off < DHE + 1)) {      /* offset refers to metadata */
+       return NULL;
+    }
+    if (pg < MAXPAGES && h->alloMap[pg] == EPP) {      /* page is empty */
+       return NULL;
+    }
+    /* p = (struct PageHeader *)&d->dirbuffer[pg * AFS_PAGESIZE]; */
+    /* p is set but not referenced later */
+    /* fr = p->freebitmap[off >> 8]; */
+    /* fr is set but not referenced later */
+    ret = (struct DirEntry *)&d->dirbuffer[pg * AFS_PAGESIZE + 32 * off];
+    return ret;
 }
 
-struct afs_dirstream *afs_opendir(const struct afs_venusfid *fid) {
-     struct afs_dirstream *ret;
-     struct AFSFetchStatus s;
-     int code;
-
-     code=afs_GetStatus(fid, &s);
-     if (code) {
-         return NULL;
-     }
-
-     if (s.FileType != Directory) {
-         afs_errno=ENOTDIR;
-         return NULL;
-     }
-     ret=malloc(sizeof(struct afs_dirstream));
-     if (!ret) {
-         afs_errno=ENOMEM;
-         return NULL;
-     }
-     memset(ret,0,sizeof(struct afs_dirstream));
-     memmove(&ret->fid, fid, sizeof(struct afs_venusfid));
-     code=_DirUpdate(ret);
-     if (code < 0) {
-         afs_closedir(ret);
-         return NULL;
-     }
-     ret->hashent=-1;
-     ret->entry=0;
-     return ret;
+struct afscp_dirstream *
+afscp_OpenDir(const struct afscp_venusfid *fid)
+{
+    struct afscp_dirstream *ret;
+    struct AFSFetchStatus s;
+    int code;
+
+    code = afscp_GetStatus(fid, &s);
+    if (code != 0) {
+       return NULL;
+    }
+
+    if (s.FileType != Directory) {
+       afscp_errno = ENOTDIR;
+       return NULL;
+    }
+    ret = malloc(sizeof(struct afscp_dirstream));
+    if (ret == NULL) {
+       afscp_errno = ENOMEM;
+       return NULL;
+    }
+    memset(ret, 0, sizeof(struct afscp_dirstream));
+    memmove(&ret->fid, fid, sizeof(struct afscp_venusfid));
+    code = _DirUpdate(ret);
+    if (code < 0) {
+       afscp_CloseDir(ret);
+       return NULL;
+    }
+    ret->hashent = -1;
+    ret->entry = 0;
+
+    return ret;
 }
 
-struct afs_dirent *afs_readdir(struct afs_dirstream *d) {
-     struct DirHeader *h=(struct DirHeader *)d->dirbuffer;
-     struct DirEntry *info;
-     int ent;
-
-
-     ent=d->entry;
-     while (ent == 0 && d->hashent < NHASHENT-1) {
-         d->hashent++;
-         ent=ntohs(h->hashTable[d->hashent]);
-     }
-     if (ent == 0) {
-         afs_errno=0;
-         return NULL;
-     }
-     info=dir_get_entry(d, ent);
-     if (!info) {
-         afs_errno=0;
-         return NULL;
-     }
-     d->ret.vnode=ntohl(info->fid.vnode);
-     d->ret.unique=ntohl(info->fid.vunique);
-     strcpy(d->ret.name, info->name); /* guaranteed to be NULL terminated? */
-     d->entry=ntohs(info->next);
-
-     return &d->ret;
+struct afscp_dirent *
+afscp_ReadDir(struct afscp_dirstream *d)
+{
+    struct DirHeader *h = (struct DirHeader *)d->dirbuffer;
+    struct DirEntry *info;
+    int ent;
+
+
+    ent = d->entry;
+    while (ent == 0 && d->hashent < NHASHENT - 1) {
+       d->hashent++;
+       ent = ntohs(h->hashTable[d->hashent]);
+    }
+    if (ent == 0) {
+       afscp_errno = 0;
+       return NULL;
+    }
+    info = dir_get_entry(d, ent);
+    if (info == NULL) {
+       afscp_errno = 0;
+       return NULL;
+    }
+    d->ret.vnode = ntohl(info->fid.vnode);
+    d->ret.unique = ntohl(info->fid.vunique);
+    strlcpy(d->ret.name, info->name, sizeof(d->ret.name));     /* guaranteed to be NULL terminated? */
+    d->entry = ntohs(info->next);
+
+    return &d->ret;
 }
 
 /* as it calls _DirUpdate, this may corrupt any previously returned dirent's */
-int afs_rewinddir(struct afs_dirstream *d) {
-     _DirUpdate(d);
-     d->hashent=-1;
-     d->entry=0;
-     return 0;
-}
-int afs_closedir(struct afs_dirstream *d) {
-     free(d);
-     return 0;
+int
+afscp_RewindDir(struct afscp_dirstream *d)
+{
+    _DirUpdate(d);
+    d->hashent = -1;
+    d->entry = 0;
+    return 0;
 }
 
-static int namehash(const char *name)
+int
+afscp_CloseDir(struct afscp_dirstream *d)
 {
-  int hval, tval;
-
-  hval=0;
-  while (*name) hval = (hval * 173) + *name++;
-  tval = hval & (NHASHENT - 1);
-  return tval ?
-       (hval < 0 ? NHASHENT - tval : tval)
-       : 0;
+    free(d);
+    return 0;
 }
 
-
-struct afs_venusfid *DirLookup(struct afs_dirstream *d, const char *name) {
-     int fid[3];
-     int code;
-     int hval, entry;
-     struct DirHeader *h=(struct DirHeader *)d->dirbuffer;
-     struct DirEntry *info;
-
-     code=_DirUpdate(d);
-     if (code)
-         return NULL;
-     hval=namehash(name);
-     entry=ntohs(h->hashTable[hval]);
-
-     while (entry) {
-         info=dir_get_entry(d, entry);
-         if (!info) {
-              afs_errno=EIO;
-              return NULL;
-         }
-         if (!strcmp(info->name, name))
-              break;
-         entry=ntohs(info->next);
-     }
-     if (entry) {
-         return makefid(d->fid.cell, d->fid.fid.Volume,
-                        ntohl(info->fid.vnode),
-                        ntohl(info->fid.vunique));
-     } else {
-         afs_errno=ENOENT;
-         return NULL;
-     }
+static int
+namehash(const char *name)
+{
+    int hval, tval;
+
+    hval = 0;
+    while (*name != '\0')
+       hval = (hval * 173) + *name++;
+    tval = hval & (NHASHENT - 1);
+    return tval ? (hval < 0 ? NHASHENT - tval : tval)
+       : 0;
 }
 
-struct afs_venusfid *ResolveName(const struct afs_venusfid *dir, const char *name) {
-     struct afs_venusfid *ret;
-     struct afs_dirstream *d;
+struct afscp_venusfid *
+afscp_DirLookup(struct afscp_dirstream *d, const char *name)
+{
+    int code;
+    int hval, entry;
+    struct DirHeader *h = (struct DirHeader *)d->dirbuffer;
+    struct DirEntry *info;
+
+    code = _DirUpdate(d);
+    if (code != 0) {
+       return NULL;
+    }
+    hval = namehash(name);
+    entry = ntohs(h->hashTable[hval]);
+
+    while (entry != 0) {
+       info = dir_get_entry(d, entry);
+       if (info == NULL) {
+           afscp_errno = EIO;
+           return NULL;
+       }
+       if (strcmp(info->name, name) == 0)
+           break;
+       entry = ntohs(info->next);
+    }
+    if (entry != 0) {
+       return afscp_MakeFid(d->fid.cell, d->fid.fid.Volume,
+                            ntohl(info->fid.vnode),
+                            ntohl(info->fid.vunique));
+    } else {
+       afscp_errno = ENOENT;
+       return NULL;
+    }
+}
 
-     d=afs_opendir(dir);
-     if (!d)
-         return NULL;
-     ret=DirLookup(d, name);
-     afs_closedir(d);
-     return ret;
+struct afscp_venusfid *
+afscp_ResolveName(const struct afscp_venusfid *dir, const char *name)
+{
+    struct afscp_venusfid *ret;
+    struct afscp_dirstream *d;
+
+    d = afscp_OpenDir(dir);
+    if (d == NULL) {
+       return NULL;
+    }
+    ret = afscp_DirLookup(d, name);
+    afscp_CloseDir(d);
+    return ret;
 }
 
-static int gettoproot(struct afs_cell *cell, char *p, char **q, struct afs_venusfid **root) {
-     struct afs_volume *rootvol;
-     char *r;
-
-     if (dirmode == DIRMODE_DYNROOT && !strcmp(p, "/afs")) {
-          afs_errno=EINVAL;
-          return 1;
-     }
-     if (!strncmp(p,"/afs",4)) {
-         afscp_dprintf(("gettoproot: path is absolute\n"));
-          p=&p[5];
-          while (*p == '/') p++;
-          if (dirmode == DIRMODE_DYNROOT) {
-              int voltype;
+static int
+gettoproot(struct afscp_cell *cell, char *p, char **q,
+          struct afscp_venusfid **root)
+{
+    struct afscp_volume *rootvol;
+    char *r;
+
+    if (dirmode == DIRMODE_DYNROOT && (strcmp(p, "/afs") == 0)) {
+       afscp_errno = EINVAL;
+       return 1;
+    }
+    if (strncmp(p, "/afs", 4) == 0) {
+       afs_dprintf(("gettoproot: path is absolute\n"));
+       p = &p[5];
+       while (*p == '/')
+           p++;
+       if (dirmode == DIRMODE_DYNROOT) {
+           int voltype;
          retry_dot:
-              voltype = VOLTYPE_RO;
-               if (*p == '.') {
-                     p++;
-                     voltype=VOLTYPE_RW;
-               }
-              if (*p == '/') {
-                   while (*p == '/') p++;
-                    goto retry_dot;
-               }
-              if (*p == '.' || *p == 0) {
-                     afs_errno=EINVAL;
-                     return 1;
-               }
-               r=p;
-               while (*r && *r != '/') r++;
-               if (!*r) {
-                    afs_errno=ENODEV;
-                    return 1;
-               }
-               *r++=0;
-               *q=r;
-               afscp_dprintf(("gettoproot: dynroot looking up cell %s\n", p));
-               cell=afs_cellbyname(p);
-               if (!cell) {
-                    afscp_dprintf(("gettoproot: no such cell\n"));
-                    afs_errno=ENODEV;
-                    return 1;
-               }
-               rootvol=afs_volumebyname(cell, "root.cell", voltype);
-               if (!rootvol && voltype == VOLTYPE_RO)
-                   rootvol=afs_volumebyname(cell, "root.cell", VOLTYPE_RW);
-          } else {
-               *q=p;
-               rootvol=afs_volumebyname(cell, "root.afs", VOLTYPE_RO);
-               if (!rootvol)
-                   rootvol=afs_volumebyname(cell, "root.afs", VOLTYPE_RW);
-          }
-          if (!rootvol)
-               afscp_dprintf(("gettoproot: volume not found\n"));
-     } else {
-         afscp_dprintf(("gettoproot: path is relative\n"));
-          if (p[0] == '/') {
-               afs_errno=EXDEV;
-               return 1;
-          }
-          rootvol=afs_volumebyname(cell, "root.cell", VOLTYPE_RO);
-          if (!rootvol)
-              rootvol=afs_volumebyname(cell, "root.cell", VOLTYPE_RW);
-          *q=p;
-     }
-     if (!rootvol) { afs_errno=ENODEV; return 1;}
-     *root=makefid(cell, rootvol->id, 1, 1);
-     return 0;
+           voltype = ROVOL;
+           if (*p == '.') {
+               p++;
+               voltype = RWVOL;
+           }
+           if (*p == '/') {
+               while (*p == '/')
+                   p++;
+               goto retry_dot;
+           }
+           if (*p == '.' || *p == 0) {
+               afscp_errno = EINVAL;
+               return 1;
+           }
+           r = p;
+           while (*r && *r != '/')
+               r++;
+           if (!*r) {
+               afscp_errno = ENODEV;
+               return 1;
+           }
+           *r++ = 0;
+           *q = r;
+           afs_dprintf(("gettoproot: dynroot looking up cell %s\n", p));
+           cell = afscp_CellByName(p, NULL);
+           if (cell == NULL) {
+               afs_dprintf(("gettoproot: no such cell\n"));
+               afscp_errno = ENODEV;
+               return 1;
+           }
+           rootvol = afscp_VolumeByName(cell, "root.cell", voltype);
+           if (!rootvol && voltype == ROVOL)
+               rootvol = afscp_VolumeByName(cell, "root.cell", RWVOL);
+       } else {
+           *q = p;
+           rootvol = afscp_VolumeByName(cell, "root.afs", ROVOL);
+           if (!rootvol)
+               rootvol = afscp_VolumeByName(cell, "root.afs", RWVOL);
+       }
+       if (!rootvol)
+           afs_dprintf(("gettoproot: volume not found\n"));
+    } else {
+       afs_dprintf(("gettoproot: path is relative\n"));
+       if (p[0] == '/') {
+           afscp_errno = EXDEV;
+           return 1;
+       }
+       rootvol = afscp_VolumeByName(cell, "root.cell", ROVOL);
+       if (!rootvol)
+           rootvol = afscp_VolumeByName(cell, "root.cell", RWVOL);
+       *q = p;
+    }
+    if (rootvol == NULL) {
+       afscp_errno = ENODEV;
+       return 1;
+    }
+    *root = afscp_MakeFid(cell, rootvol->id, 1, 1);
+    return 0;
 }
 
-static int getvolumeroot(struct afs_cell *cell, int voltype, const char *vname, struct afs_venusfid **root) {
-     struct afs_volume *vol;
-     vol=afs_volumebyname(cell, vname, voltype);
-     if (!vol && voltype == VOLTYPE_RO)
-          vol=afs_volumebyname(cell, vname, VOLTYPE_RW);
-     if (!vol) { afs_errno=ENODEV; return 1;}
-     *root=makefid(cell, vol->id, 1, 1);
-     return 0;
+static int
+getvolumeroot(struct afscp_cell *cell, int voltype, const char *vname,
+             struct afscp_venusfid **root)
+{
+    struct afscp_volume *vol;
+    vol = afscp_VolumeByName(cell, vname, voltype);
+    if (!vol && voltype == ROVOL)
+       vol = afscp_VolumeByName(cell, vname, RWVOL);
+    if (vol == NULL) {
+       afscp_errno = ENODEV;
+       return 1;
+    }
+    *root = afscp_MakeFid(cell, vol->id, 1, 1);
+    return 0;
 }
 
-typedef struct fidstack_s
-{
-     int alloc;
-     int count;
-     struct afs_venusfid ** entries;
+typedef struct fidstack_s {
+    int alloc;
+    int count;
+    struct afscp_venusfid **entries;
 } *fidstack;
 
-static fidstack fidstack_alloc() {
-     fidstack ret;
-
-     ret=malloc(sizeof(struct fidstack_s));
-     if (!ret) {
-         afs_errno=ENOMEM;
-         return NULL;
-     }
-     ret->alloc=10;
-     ret->count=0;
-     ret->entries=malloc(ret->alloc * sizeof(struct afs_venusfid *));
-     if (!ret->entries) {
-          free(ret);
-          afs_errno=ENOMEM;
-          return NULL;
-     }
-     return ret;
+static fidstack
+fidstack_alloc(void)
+{
+    fidstack ret;
+
+    ret = malloc(sizeof(struct fidstack_s));
+    if (ret == NULL) {
+       afscp_errno = ENOMEM;
+       return NULL;
+    }
+    ret->alloc = 10;
+    ret->count = 0;
+    ret->entries = malloc(ret->alloc * sizeof(struct afscp_venusfid *));
+    if (ret->entries == NULL) {
+       free(ret);
+       afscp_errno = ENOMEM;
+       return NULL;
+    }
+    return ret;
 }
 
-static void fidstack_push(fidstack s, struct afs_venusfid *entry) {
-     struct afs_venusfid **new;
-     if (s->count >= s->alloc) {
-          new=realloc(s->entries, (s->alloc + 10) *
-                      sizeof(struct afs_venusfid *));
-          if (!new)
-               return;
-          s->entries=new;
-          s->alloc += 10;
-     }
-     s->entries[s->count++]=entry;
-     return;
+static void
+fidstack_push(fidstack s, struct afscp_venusfid *entry)
+{
+    struct afscp_venusfid **new;
+    if (s->count >= s->alloc) {
+       new = realloc(s->entries, (s->alloc + 10) *
+                     sizeof(struct afscp_venusfid *));
+       if (new == NULL) {
+           return;
+       }
+       s->entries = new;
+       s->alloc += 10;
+    }
+    s->entries[s->count++] = entry;
+    return;
 }
 
-static struct afs_venusfid *fidstack_pop(fidstack s) {
-     if (s->count)
-          return s->entries[-- s->count];
-     return NULL;
+static struct afscp_venusfid *
+fidstack_pop(fidstack s)
+{
+    if (s->count)
+       return s->entries[--s->count];
+    return NULL;
 }
 
-static void fidstack_free(fidstack s) {
-     int i;
+static void
+fidstack_free(fidstack s)
+{
+    int i;
 
-     for (i=0;i<s->count;i++)
-          free(s->entries[i]);
-     free (s->entries);
-     free(s);
+    for (i = 0; i < s->count; i++)
+       free(s->entries[i]);
+    free(s->entries);
+    free(s);
 }
 
-static struct afs_venusfid *_ResolvePath(const struct afs_venusfid *, fidstack, char *, int);
-
-static struct afs_venusfid *HandleLink(struct afs_venusfid *in, const struct afs_venusfid *parent, fidstack fids, int follow,
-                                      const struct AFSFetchStatus *s, int terminal) {
-     char *linkbuf, *linkbufq;
-     struct afs_cell *cell;
-     struct afs_volume *v;
-     struct afs_venusfid *root,*ret;
-     int voltype;
-     int code;
-     if ((s->UnixModeBits & 0111) &&
-        (follow == 0) &&
-        terminal) { /* normal link */
-         return in;
-     }
-     linkbuf=malloc(s->Length + 1);
-     code=afs_pread(in, linkbuf, s->Length, 0);
-     if (code < 0) {
-         free(linkbuf);
-         free(in);
-         return NULL;
-     }
-     if (code != s->Length) {
-         afs_errno=EIO;
-         free(linkbuf);
-         free(in);
-         return NULL;
-     }
-     linkbuf[s->Length]=0;
-     if (s->UnixModeBits & 0111) { /* normal link */
-         afscp_dprintf(("Recursing on symlink %s...\n", linkbuf));
-          if (linkbuf[0] == '/') {
-               if (gettoproot(in->cell, linkbuf, &linkbufq, &root)) {
-                    free(linkbuf);
-                    free(in);
-                    return NULL;
-               }
-               free(in);
-               ret=_ResolvePath(root, 0, linkbufq, 0);
-               free(root);
-          } else {
-               free(in);
-               ret=_ResolvePath(parent, fids, linkbuf, 0);
-          }
-
-         free(linkbuf);
-
-     } else { /* mountpoint */
-         afscp_dprintf(("EvalMountPoint %s...\n", linkbuf));
-         linkbufq=strchr(linkbuf, ':');
-         cell=in->cell;
-          v=afs_volumebyid(cell, in->fid.Volume);
-         free(in);
-          if (!v) {
-              free(linkbuf);
-               afs_errno=ENODEV;
-              return NULL;
-          }
-          voltype=v->voltype;
-          if (linkbuf[0] == '%')
-               voltype=VOLTYPE_RW;
-         if (!linkbufq) {
-              linkbufq=linkbuf+1;
-         } else {
-              *linkbufq++ = 0;
-              cell=afs_cellbyname(linkbuf+1);
-               if (linkbuf[0] != '%')
-                    voltype=VOLTYPE_RO;
-         }
-         if (!cell) {
-              free(linkbuf);
-              afs_errno=ENODEV;
-              return NULL;
-         }
-         if (strlen(linkbufq) < 2) {
-              free(linkbuf);
-               afs_errno=ENODEV;
-              return NULL;
-         }
-         linkbufq[strlen(linkbufq)-1]=0; /* eliminate trailer */
-         if (getvolumeroot(cell, voltype, linkbufq, &ret)) {
-              free(linkbuf);
-              return NULL;
-         }
-         free(linkbuf);
-     }
-     return ret;
+static struct afscp_venusfid *_ResolvePath(const struct afscp_venusfid *,
+                                          fidstack, char *, int);
+
+static struct afscp_venusfid *
+afscp_HandleLink(struct afscp_venusfid *in,
+                const struct afscp_venusfid *parent, fidstack fids,
+                int follow, const struct AFSFetchStatus *s, int terminal)
+{
+    char *linkbuf, *linkbufq;
+    struct afscp_cell *cell;
+    struct afscp_volume *v;
+    struct afscp_venusfid *root, *ret;
+    int voltype;
+    int code;
+    ssize_t len;
+    if ((s->UnixModeBits & 0111) && (follow == 0) && terminal) {       /* normal link */
+       return in;
+    }
+    linkbuf = malloc(s->Length + 1);
+    code = afscp_PRead(in, linkbuf, s->Length, 0);
+    if (code < 0) {
+       free(linkbuf);
+       free(in);
+       return NULL;
+    }
+    if (code != s->Length) {
+       afscp_errno = EIO;
+       free(linkbuf);
+       free(in);
+       return NULL;
+    }
+    linkbuf[s->Length] = 0;
+    if (s->UnixModeBits & 0111) {      /* normal link */
+       afs_dprintf(("Recursing on symlink %s...\n", linkbuf));
+       if (linkbuf[0] == '/') {
+           if (gettoproot(in->cell, linkbuf, &linkbufq, &root)) {
+               free(linkbuf);
+               free(in);
+               return NULL;
+           }
+           free(in);
+           ret = _ResolvePath(root, 0, linkbufq, 0);
+           free(root);
+       } else {
+           free(in);
+           ret = _ResolvePath(parent, fids, linkbuf, 0);
+       }
+       free(linkbuf);
+    } else {                   /* mountpoint */
+       afs_dprintf(("EvalMountPoint %s...\n", linkbuf));
+       linkbufq = strchr(linkbuf, ':');
+       cell = in->cell;
+       v = afscp_VolumeById(cell, in->fid.Volume);
+       free(in);
+       if (v == NULL) {
+           free(linkbuf);
+           afscp_errno = ENODEV;
+           return NULL;
+       }
+       voltype = v->voltype;
+       if (linkbuf[0] == '%')
+           voltype = RWVOL;
+       if (linkbufq == NULL) {
+           linkbufq = linkbuf + 1;
+       } else {
+           *linkbufq++ = 0;
+           cell = afscp_CellByName(linkbuf + 1, NULL);
+           if (linkbuf[0] != '%')
+               voltype = ROVOL;
+       }
+       if (cell == NULL) {
+           free(linkbuf);
+           afscp_errno = ENODEV;
+           return NULL;
+       }
+       len = strnlen(linkbufq, s->Length + 1);
+       if (len < 2) {
+           free(linkbuf);
+           afscp_errno = ENODEV;
+           return NULL;
+       }
+       len = strnlen(linkbufq, s->Length + 1);
+       linkbufq[len - 1] = 0;  /* eliminate trailer */
+       if (getvolumeroot(cell, voltype, linkbufq, &ret)) {
+           free(linkbuf);
+           return NULL;
+       }
+       free(linkbuf);
+    }
+    return ret;
 }
 
-static struct afs_venusfid *_ResolvePath(const struct afs_venusfid *start,
-                                         fidstack infids, char *path,
-                                         int follow) {
-     struct afs_venusfid *ret,*cwd,*parent;
-     struct AFSFetchStatus s;
-     char *p,*q;
-     int code;
-     int linkcount;
-     fidstack fids;
-
-     p=path;
-     ret=cwd=dupfid(start);
-     fids=infids;
-     if (!fids)
-          fids=fidstack_alloc();
-     if (!fids)
-          return NULL;
-
-     while (p && *p) {
-         q=strchr(p, '/');
-         if (q) *q++=0;
-          if (!strcmp(p,".")) {
-          } else if (!strcmp(p,"..")) {
-               ret=fidstack_pop(fids);
-               if (!ret)
-                    ret=cwd;
-               else
-                    free(cwd);
-          } else {
-               ret=ResolveName(cwd, p);
-               if (!ret) {
-                    afscp_dprintf(("Lookup %s in %lu.%lu.%lu failed\n", p, cwd->fid.Volume, cwd->fid.Vnode, cwd->fid.Unique));
-                    free(cwd);
-                    if (!infids)
-                         fidstack_free(fids);
-                    return NULL;
-
-               }
-               afscp_dprintf(("Lookup %s in %lu.%lu.%lu->%lu.%lu.%lu\n", p, cwd->fid.Volume, cwd->fid.Vnode, cwd->fid.Unique, ret->fid.Volume, ret->fid.Vnode, ret->fid.Unique));
-               linkcount=0;
-
-          retry:
-               if ((ret->fid.Vnode & 1) == 0) { /* not a directory; check for link */
-                    code=afs_GetStatus(ret, &s);
-                    if (code) {
-                         if (!infids)
-                              fidstack_free(fids);
-                         free(cwd);
-                         free(ret);
-                         return NULL;
-                    }
-                    if (s.FileType == SymbolicLink) {
-                         if (linkcount++ > 5) {
-                              afs_errno=ELOOP;
-                              if (!infids)
-                                   fidstack_free(fids);
-                              free(cwd);
-                              free(ret);
-                              return NULL;
-                         }
-                         ret=HandleLink(ret, cwd, fids, follow, &s, (q==NULL));
-                         if (!ret) {
-                              free(cwd);
-                              if (!infids)
-                                   fidstack_free(fids);
-                              return NULL;
-                         }
-                         afscp_dprintf(("   ....-> %lu.%lu.%lu\n", ret->fid.Volume, ret->fid.Vnode, ret->fid.Unique));
-                         goto retry;
-                    } else {
-                         if (q) {
-                              afs_errno=ENOTDIR;
-                              free(cwd);
-                              free(ret);
-                              if (!infids)
-                                   fidstack_free(fids);
-                              return NULL;
-                         }
-                    }
-               }
-               fidstack_push(fids,cwd);
-          }
-          cwd=ret;
-
-         if (q)
-              while (*q == '/')
-                   q++;
-         p=q;
-     }
-     if (!infids)
-          fidstack_free(fids);
-     return ret;
+static struct afscp_venusfid *
+_ResolvePath(const struct afscp_venusfid *start, fidstack infids,
+            char *path, int follow)
+{
+    struct afscp_venusfid *ret, *cwd;
+    struct AFSFetchStatus s;
+    char *p, *q;
+    int code;
+    int linkcount;
+    fidstack fids;
+
+    p = path;
+    ret = cwd = afscp_DupFid(start);
+    fids = infids;
+    if (fids == NULL)
+       fids = fidstack_alloc();
+    if (fids == NULL) {
+       return NULL;
+    }
+
+    while (p && *p) {
+       q = strchr(p, '/');
+       if (q)
+           *q++ = 0;
+       if (strcmp(p, ".") == 0) {
+           /* do nothing */
+       } else if (strcmp(p, "..") == 0) {
+           ret = fidstack_pop(fids);
+           if (ret == NULL)
+               ret = cwd;
+           else
+               free(cwd);
+       } else {
+           ret = afscp_ResolveName(cwd, p);
+           if (ret == NULL) {
+               afs_dprintf(("Lookup %s in %lu.%lu.%lu failed\n", p,
+                            cwd->fid.Volume, cwd->fid.Vnode,
+                            cwd->fid.Unique));
+               free(cwd);
+               if (infids == NULL)
+                   fidstack_free(fids);
+               return NULL;
+           }
+           afs_dprintf(("Lookup %s in %lu.%lu.%lu->%lu.%lu.%lu\n", p,
+                        cwd->fid.Volume, cwd->fid.Vnode, cwd->fid.Unique,
+                        ret->fid.Volume, ret->fid.Vnode, ret->fid.Unique));
+           linkcount = 0;
+
+         retry:
+           if ((ret->fid.Vnode & 1) == 0) {    /* not a directory; check for link */
+               code = afscp_GetStatus(ret, &s);
+               if (code != 0) {
+                   if (infids == NULL)
+                       fidstack_free(fids);
+                   free(cwd);
+                   free(ret);
+                   return NULL;
+               }
+               if (s.FileType == SymbolicLink) {
+                   if (linkcount++ > 5) {
+                       afscp_errno = ELOOP;
+                       if (infids == NULL)
+                           fidstack_free(fids);
+                       free(cwd);
+                       free(ret);
+                       return NULL;
+                   }
+                   ret =
+                       afscp_HandleLink(ret, cwd, fids, follow, &s,
+                                        (q == NULL));
+                   if (ret == NULL) {
+                       free(cwd);
+                       if (infids == NULL)
+                           fidstack_free(fids);
+                       return NULL;
+                   }
+                   afs_dprintf(("   ....-> %lu.%lu.%lu\n", ret->fid.Volume,
+                                ret->fid.Vnode, ret->fid.Unique));
+                   goto retry;
+               } else {
+                   if (q != NULL) {
+                       afscp_errno = ENOTDIR;
+                       free(cwd);
+                       free(ret);
+                       if (infids == NULL)
+                           fidstack_free(fids);
+                       return NULL;
+                   }
+               }
+           }
+           fidstack_push(fids, cwd);
+       }
+       cwd = ret;
+
+       while ((q != NULL) && (*q == '/'))
+           q++;
+       p = q;
+    }
+    if (infids == NULL)
+       fidstack_free(fids);
+    return ret;
 }
-/* 3 cases:
-   begins with /afs: start in root.afs of cell or home cell
-   else begins with /: error
-   else start in root.cell of cell or home cell
-*/
-struct afs_venusfid *ResolvePath(const char *path) {
-     struct afs_venusfid *root,*ret;
-     struct afs_cell *cell;
-
-     char *p,*q;
-     /* so we can modify the string */
-     p=strdup(path);
-     if (!p) {
-         afs_errno=ENOMEM;
-         return NULL;
-     }
-     cell=afs_defaultcell();
-     if (!cell) { afs_errno=EINVAL; return NULL;}
-     if (gettoproot(cell, p, &q, &root)) {
-         free(p);
-         return NULL;
-     }
-     if (q && *q) {
-         ret=_ResolvePath(root, 0, q, 1);
-          free(root);
-     } else
-         ret=root;
-     free(p);
-     return ret;
+
+/*!
+ * Resolve a path to a FID starting from the root volume
+ *
+ * \param[in]  path    full path
+ *
+ * \post Returns a venusfid representing the final element of path
+ *
+ * \note There are three cases:
+ *       (1) begins with /afs: start in root.afs of cell or home cell
+ *       (2) else begins with /: error
+ *       (3) else start in root.cell of cell or home cell
+ */
+struct afscp_venusfid *
+afscp_ResolvePath(const char *path)
+{
+    struct afscp_venusfid *root, *ret;
+    struct afscp_cell *cell;
+    int code;
+    char *p, *q;
+    p = strdup(path);          /* so we can modify the string */
+    if (p == NULL) {
+       afscp_errno = ENOMEM;
+       return NULL;
+    }
+    cell = afscp_DefaultCell();
+    if (cell == NULL) {
+       afscp_errno = EINVAL;
+       return NULL;
+    }
+    code = gettoproot(cell, p, &q, &root);
+    if (code != 0) {
+       free(p);
+       return NULL;
+    }
+    if (q && *q) {
+       ret = _ResolvePath(root, 0, q, 1);
+       free(root);
+    } else
+       ret = root;
+    free(p);
+    return ret;
 }
 
-struct afs_venusfid *ResolvePath2(const struct afs_volume *v, const char *path) {
-     struct afs_venusfid *root,*ret;
-
-     char *p,*q;
-     /* so we can modify the string */
-     p=strdup(path);
-     if (!p) {
-         afs_errno=ENOMEM;
-         return NULL;
-     }
-     root=makefid(v->cell, v->id, 1,1);
-     while (*p == '/') p++;
-     if (*p) {
-         ret=_ResolvePath(root, 0, p, 1);
-          free(root);
-     } else
-         ret=root;
-     free(p);
-     return ret;
+/*!
+ * Resolve a path to a FID starting from the given volume
+ *
+ * \param[in]  v       volume structure containing id and cell info
+ * \param[in]  path    path relative to volume v
+ *
+ * \post Returns a venusfid representing the final element of path
+ */
+struct afscp_venusfid *
+afscp_ResolvePathFromVol(const struct afscp_volume *v, const char *path)
+{
+    struct afscp_venusfid *root, *ret;
+    char *p;
+
+    /* so we can modify the string */
+    p = strdup(path);
+    if (p == NULL) {
+       afscp_errno = ENOMEM;
+       return NULL;
+    }
+    root = afscp_MakeFid(v->cell, v->id, 1, 1);
+    while (*p == '/')
+       p++;
+    if (*p != '\0') {
+       ret = _ResolvePath(root, 0, p, 1);
+       free(root);
+    } else
+       ret = root;
+    free(p);
+    return ret;
 }