Exemplo n.º 1
0
xfs_dir2_dataptr_t
xfs_dir2_db_off_to_dataptr(xfs_mount_t *mp, xfs_dir2_db_t db,
                           xfs_dir2_data_aoff_t o)
{
    return XFS_DIR2_DB_OFF_TO_DATAPTR(mp, db, o);
}
Exemplo n.º 2
0
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;
}