Exemplo n.º 1
0
/* Link an inode number to a directory */
static errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino,
			  ext2_ino_t ino, const char *name)
{
	struct ext2_inode	inode;
	errcode_t		retval;

	retval = ext2fs_read_inode(fs, ino, &inode);
        if (retval) {
		com_err(__func__, retval, _("while reading inode %u"), ino);
		return retval;
	}

	retval = ext2fs_link(fs, parent_ino, name, ino,
			     ext2_file_type(inode.i_mode));
	if (retval == EXT2_ET_DIR_NO_SPACE) {
		retval = ext2fs_expand_dir(fs, parent_ino);
		if (retval) {
			com_err(__func__, retval,
				_("while expanding directory"));
			return retval;
		}
		retval = ext2fs_link(fs, parent_ino, name, ino,
				     ext2_file_type(inode.i_mode));
	}
	if (retval) {
		com_err(__func__, retval, _("while linking \"%s\""), name);
		return retval;
	}

	inode.i_links_count++;

	retval = ext2fs_write_inode(fs, ino, &inode);
	if (retval)
		com_err(__func__, retval, _("while writing inode %u"), ino);

	return retval;
}
Exemplo n.º 2
0
/*
 * This routine will connect a file to lost+found
 */
int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
{
	ext2_filsys fs = ctx->fs;
	errcode_t	retval;
	char		name[80];
	struct problem_context	pctx;
	struct ext2_inode 	inode;
	int		file_type = 0;

	clear_problem_context(&pctx);
	pctx.ino = ino;

	if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
		if (e2fsck_get_lost_and_found(ctx, 1) == 0)
			ctx->bad_lost_and_found++;
	}
	if (ctx->bad_lost_and_found) {
		fix_problem(ctx, PR_3_NO_LPF, &pctx);
		return 1;
	}

	sprintf(name, "#%u", ino);
	if (ext2fs_read_inode(fs, ino, &inode) == 0)
		file_type = ext2_file_type(inode.i_mode);
	retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
	if (retval == EXT2_ET_DIR_NO_SPACE) {
		if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
			return 1;
		retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
						 1, 0);
		if (retval) {
			pctx.errcode = retval;
			fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
			return 1;
		}
		retval = ext2fs_link(fs, ctx->lost_and_found, name,
				     ino, file_type);
	}
	if (retval) {
		pctx.errcode = retval;
		fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
		return 1;
	}
	e2fsck_adjust_inode_count(ctx, ino, 1);

	return 0;
}
Exemplo n.º 3
0
/*
 * Check the directory filetype (if present)
 */
static _INLINE_ int check_filetype(e2fsck_t ctx,
				   struct ext2_dir_entry *dirent,
				   ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
				   struct problem_context *pctx)
{
	int	filetype = dirent->name_len >> 8;
	int	should_be = EXT2_FT_UNKNOWN;
	struct ext2_inode	inode;

	if (!(ctx->fs->super->s_feature_incompat &
	      EXT2_FEATURE_INCOMPAT_FILETYPE)) {
		if (filetype == 0 ||
		    !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
			return 0;
		dirent->name_len = dirent->name_len & 0xFF;
		return 1;
	}

	if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dirent->inode)) {
		should_be = EXT2_FT_DIR;
	} else if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map,
					    dirent->inode)) {
		should_be = EXT2_FT_REG_FILE;
	} else if (ctx->inode_bad_map &&
		   ext2fs_test_inode_bitmap2(ctx->inode_bad_map,
					    dirent->inode))
		should_be = 0;
	else {
		e2fsck_read_inode(ctx, dirent->inode, &inode,
				  "check_filetype");
		should_be = ext2_file_type(inode.i_mode);
	}
	if (filetype == should_be)
		return 0;
	pctx->num = should_be;

	if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
			pctx) == 0)
		return 0;

	dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
	return 1;
}
Exemplo n.º 4
0
int ext2Link(ext2_vd *vd, const char *old_path, const char *new_path)
{
    ext2_inode_t *dir_ni = NULL, *ni = NULL;
    char *dir = NULL;
    char *name = NULL;
    errcode_t err = 0;

    // Sanity check
    if (!vd || !vd->fs) {
        errno = ENODEV;
        return -1;
    }

    if(!(vd->fs->flags & EXT2_FLAG_RW)) {
        errno = EACCES;
        return -1;
    }

    // You cannot link between devices
    if(vd != ext2GetVolume(new_path)) {
        errno = EXDEV;
        return -1;
    }

    // Get the actual paths of the entry
    old_path = ext2RealPath(old_path);
    new_path = ext2RealPath(new_path);
    if (!old_path || !new_path)
        return -1;

    // Lock
    ext2Lock(vd);

    //check for existing in new path
    ni = ext2OpenEntry(vd, new_path);
    if (ni) {
        errno = EEXIST;
        goto cleanup;
    }

    dir = strdup(new_path);
    if (!dir) {
        errno = ENOMEM;
        err = -1;
        goto cleanup;
    }
    char * ptr = strrchr(dir, '/');
    if (ptr)
    {
        name = strdup(ptr+1);
        *ptr = 0;
    }
    else
        name = strdup(dir);

    // Find the entry
    ni = ext2OpenEntry(vd, old_path);
    if (!ni) {
        err = -1;
        goto cleanup;
    }

    // Open the entries new parent directory
    dir_ni = ext2OpenEntry(vd, dir);
    if (!dir_ni) {
        err = -1;
        goto cleanup;
    }

    do
    {
        // Link the entry to its new parent
        err = ext2fs_link(vd->fs, dir_ni->ino, name, ni->ino, ext2_file_type(ni->ni.i_mode));
        if (err == EXT2_ET_DIR_NO_SPACE)
        {
            if (ext2fs_expand_dir(vd->fs, dir_ni->ino) != 0)
                goto cleanup;
        }
        else if(err != EXT2_ET_OK)
        {
            errno = EMLINK;
            goto cleanup;
        }
    }
    while(err == EXT2_ET_DIR_NO_SPACE);

    ni->ni.i_links_count++;

    // Update entry times
    ext2UpdateTimes(vd, ni, EXT2_UPDATE_MCTIME);

    // Sync the entry to disc
    ext2Sync(vd, ni);

cleanup:

    if(dir_ni)
        ext2CloseEntry(vd, dir_ni);

    if(ni)
        ext2CloseEntry(vd, ni);

    if(dir)
        mem_free(dir);

    if(name)
        mem_free(name);

    // Unlock
    ext2Unlock(vd);

    return err;
}