Exemplo n.º 1
0
/*
 * ext2fs_rename_replace_dotdot: Change the target of the `..' entry of
 * the directory vp from fdvp to tdvp.
 */
static int
ext2fs_rename_replace_dotdot(struct vnode *vp,
    struct vnode *fdvp, struct vnode *tdvp,
    kauth_cred_t cred)
{
	struct ext2fs_dirtemplate dirbuf;
	int error;

	/* XXX Does it make sense to do this before the sanity checks below?  */
	KASSERT(0 < VTOI(fdvp)->i_e2fs_nlink);
	VTOI(fdvp)->i_e2fs_nlink--;
	VTOI(fdvp)->i_flag |= IN_CHANGE;

	error = ufs_bufio(UIO_READ, vp, &dirbuf, sizeof dirbuf, (off_t)0,
	    IO_NODELOCKED, cred, NULL, NULL);
	if (error)
		return error;

	if (dirbuf.dotdot_namlen != 2 ||
	    dirbuf.dotdot_name[0] != '.' ||
	    dirbuf.dotdot_name[1] != '.') {
		ufs_dirbad(VTOI(vp), (doff_t)12, "bad `..' entry");
		return 0;
	}

	if (fs2h32(dirbuf.dotdot_ino) != VTOI(fdvp)->i_number) {
		ufs_dirbad(VTOI(vp), (doff_t)12,
		    "`..' does not point at parent");
		return 0;
	}

	dirbuf.dotdot_ino = h2fs32(VTOI(tdvp)->i_number);
	/* XXX WTF?  Why not check error?  */
	(void)ufs_bufio(UIO_WRITE, vp, &dirbuf, sizeof dirbuf, (off_t)0,
	    (IO_NODELOCKED | IO_SYNC), cred, NULL, NULL);

	return 0;
}
/*
 * Check if a directory is empty or not.
 * Inode supplied must be locked.
 *
 * Using a struct dirtemplate here is not precisely
 * what we want, but better than using a struct ext2fs_direct.
 *
 * NB: does not handle corrupted directories.
 */
int
ext2fs_dirempty(struct inode *ip, ino_t parentino, kauth_cred_t cred)
{
	off_t off;
	struct ext2fs_dirtemplate dbuf;
	struct ext2fs_direct *dp = (struct ext2fs_direct *)&dbuf;
	int error, namlen;
	size_t count;

#define	MINDIRSIZ (sizeof (struct ext2fs_dirtemplate) / 2)

	for (off = 0; off < ext2fs_size(ip); off += fs2h16(dp->e2d_reclen)) {
		error = ufs_bufio(UIO_READ, ITOV(ip), (void *)dp, MINDIRSIZ,
		    off, IO_NODELOCKED, cred, &count, NULL);
		/*
		 * Since we read MINDIRSIZ, residual must
		 * be 0 unless we're at end of file.
		 */
		if (error || count != 0)
			return (0);
		/* avoid infinite loops */
		if (dp->e2d_reclen == 0)
			return (0);
		/* skip empty entries */
		if (dp->e2d_ino == 0)
			continue;
		/* accept only "." and ".." */
		namlen = dp->e2d_namlen;
		if (namlen > 2)
			return (0);
		if (dp->e2d_name[0] != '.')
			return (0);
		/*
		 * At this point namlen must be 1 or 2.
		 * 1 implies ".", 2 implies ".." if second
		 * char is also "."
		 */
		if (namlen == 1)
			continue;
		if (dp->e2d_name[1] == '.' && fs2h32(dp->e2d_ino) == parentino)
			continue;
		return (0);
	}
	return (1);
}
Exemplo n.º 3
0
/*
 * ext2fs_read_dotdot: Store in *ino_ret the inode number of the parent
 * of the directory vp.
 */
static int
ext2fs_read_dotdot(struct vnode *vp, kauth_cred_t cred, ino_t *ino_ret)
{
	struct ext2fs_dirtemplate dirbuf;
	int error;

	KASSERT(vp != NULL);
	KASSERT(ino_ret != NULL);
	KASSERT(vp->v_type == VDIR);

	error = ufs_bufio(UIO_READ, vp, &dirbuf, sizeof dirbuf, (off_t)0,
	    IO_NODELOCKED, cred, NULL, NULL);
	if (error)
		return error;

	if (dirbuf.dotdot_namlen != 2 ||
	    dirbuf.dotdot_name[0] != '.' ||
	    dirbuf.dotdot_name[1] != '.')
		/* XXX Panic?  Print warning?  */
		return ENOTDIR;

	*ino_ret = fs2h32(dirbuf.dotdot_ino);
	return 0;
}