1
0
Files
irix-657m-src/eoe/cmd/efs/nlib/efs_dirent.c
2022-09-29 17:59:04 +03:00

138 lines
2.6 KiB
C

#ident "$Revision: 1.9 $"
/*
* peruse EFS directories
*/
#include "libefs.h"
/*
* Create the EFS_DIR for inum (which requires reading the efs_dinode,
* the extents and the dirblks).
*/
EFS_DIR *
efs_opendiri(EFS_MOUNT *mp, efs_ino_t inum)
{
EFS_DIR *dirp;
struct efs_dinode *dip;
extent *ex;
char *bp;
if ((dip = efs_figet(mp, inum)) == 0)
return 0;
if ((ex = efs_getextents(mp, dip, inum)) == 0)
return 0;
if ((bp = efs_getdirblks(mp->m_fd, dip, ex, inum)) == 0)
return 0;
free(ex);
if ((dirp = efs_opendirb(bp, DATABLKS(ex, dip->di_numextents))) == 0)
return 0;
dirp->dir_mp = mp;
return dirp;
}
EFS_DIR *
efs_opendir(EFS_MOUNT *mp, char *filename)
{
return efs_opendiri(mp, efs_namei(mp, filename));
}
/*
* Given nblocks of dirblks at dp make a EFS_DIR
*/
EFS_DIR *
efs_opendirb(char *dp, int nblocks)
{
EFS_DIR *dirp;
if ((dirp = malloc(sizeof(EFS_DIR))) == NULL) {
fprintf(stderr,"malloc failed in efs_opendirb()\n");
return 0;
}
dirp->dir_curblk = 0;
dirp->dir_curslot = 0;
dirp->dir_mp = 0;
dirp->dir_blkp = dp; /* XXX call better not call efs_closedir */
dirp->dir_nblocks = nblocks;
return dirp;
}
struct efs_dent *
efs_readdir(EFS_DIR *dirp)
{
struct efs_dirblk *dp;
struct efs_dent *dentp;
nextblock:
if (dirp->dir_curblk >= dirp->dir_nblocks)
return NULL;
dp = ((struct efs_dirblk*)dirp->dir_blkp) + dirp->dir_curblk;
if (dp->magic != EFS_DIRBLK_MAGIC) { /* XXX */
fprintf(stderr,"bad magic: %d dirblk=%d, skipping...\n",
dp->magic, dirp->dir_curblk);
dirp->dir_curblk++;
goto nextblock;
}
if (dirp->dir_curslot >= dp->slots) {
dirp->dir_curslot = 0;
dirp->dir_curblk++;
goto nextblock;
}
while (EFS_SLOTAT(dp, dirp->dir_curslot) == 0) {
dirp->dir_curslot++;
if (dirp->dir_curslot >= dp->slots)
goto nextblock;
}
dentp = EFS_SLOTOFF_TO_DEP(dp, EFS_SLOTAT(dp, dirp->dir_curslot));
dirp->dir_curslot++;
return dentp;
}
/*
* The other half of efs_opendiri,opendir()
*/
void
efs_closedir(EFS_DIR *dirp)
{
free(dirp->dir_blkp);
free(dirp);
}
void
efs_rewinddir(EFS_DIR *dirp)
{
dirp->dir_curslot = dirp->dir_curblk = 0;
}
char *
efs_getdirblks(int fd, struct efs_dinode *dp, extent *ex, efs_ino_t inum)
{
int i, nblocks = DATABLKS(ex, dp->di_numextents);
char *retbp, *bp;
if ((retbp = bp = malloc(nblocks * EFS_BBSIZE)) == 0) {
return 0;
}
for (i = 0; i < dp->di_numextents; i++, ex++) {
if (efs_readb(fd, bp, ex->ex_bn, ex->ex_length) !=
ex->ex_length) {
fprintf(stderr,
"efs_getblocks(i%d) efs_readb(%d+%d) failed: %s\n",
inum, ex->ex_bn, ex->ex_length,
strerror(errno));
return 0;
}
bp += ex->ex_length * EFS_BBSIZE;
}
return retbp;
}