xfs_dir2_db_t xfs_dir2_dataptr_to_db(xfs_mount_t *mp, xfs_dir2_dataptr_t dp) { return XFS_DIR2_DATAPTR_TO_DB(mp, dp); }
int /* error */ xfs_dir2_sf_getdents( xfs_inode_t *dp, /* incore directory inode */ uio_t *uio, /* caller's buffer control */ int *eofp, /* eof reached? (out) */ xfs_dirent_t *dbp, /* caller's buffer */ xfs_dir2_put_t put) /* abi's formatting function */ { int error; /* error return value */ int i; /* shortform entry number */ xfs_mount_t *mp; /* filesystem mount point */ xfs_dir2_dataptr_t off; /* current entry's offset */ xfs_dir2_put_args_t p; /* arg package for put rtn */ xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ xfs_dir2_sf_t *sfp; /* shortform structure */ xfs_off_t dir_offset; mp = dp->i_mount; ASSERT(dp->i_df.if_flags & XFS_IFINLINE); /* * Give up if the directory is way too short. */ if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { ASSERT(XFS_FORCED_SHUTDOWN(mp)); return XFS_ERROR(EIO); } dir_offset = uio->uio_offset; ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); ASSERT(dp->i_df.if_u1.if_data != NULL); sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data; ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count)); /* * If the block number in the offset is out of range, we're done. */ if (XFS_DIR2_DATAPTR_TO_DB(mp, dir_offset) > mp->m_dirdatablk) { *eofp = 1; return 0; } /* * Set up putargs structure. */ p.dbp = dbp; p.put = put; p.uio = uio; /* * Put . entry unless we're starting past it. */ if (dir_offset <= XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, XFS_DIR2_DATA_DOT_OFFSET)) { p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, 0, XFS_DIR2_DATA_DOTDOT_OFFSET); p.ino = dp->i_ino; #if XFS_BIG_INUMS p.ino += mp->m_inoadd; #endif p.name = "."; p.namelen = 1; error = p.put(&p); if (!p.done) { uio->uio_offset = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, XFS_DIR2_DATA_DOT_OFFSET); return error; } } /* * Put .. entry unless we're starting past it. */ if (dir_offset <= XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, XFS_DIR2_DATA_DOTDOT_OFFSET)) { p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, XFS_DIR2_DATA_FIRST_OFFSET); p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent); #if XFS_BIG_INUMS p.ino += mp->m_inoadd; #endif p.name = ".."; p.namelen = 2; error = p.put(&p); if (!p.done) { uio->uio_offset = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, XFS_DIR2_DATA_DOTDOT_OFFSET); return error; } } /* * Loop while there are more entries and put'ing works. */ for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp); i < sfp->hdr.count; i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) { off = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, XFS_DIR2_SF_GET_OFFSET(sfep)); if (dir_offset > off) continue; p.namelen = sfep->namelen; p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, XFS_DIR2_SF_GET_OFFSET(sfep) + XFS_DIR2_DATA_ENTSIZE(p.namelen)); p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep)); #if XFS_BIG_INUMS p.ino += mp->m_inoadd; #endif p.name = (char *)sfep->name; error = p.put(&p); if (!p.done) { uio->uio_offset = off; return error; } } /* * They all fit. */ *eofp = 1; uio->uio_offset = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk + 1, 0); return 0; }