Example #1
0
static int namei_iscan(ext2_ino_t ino, struct ext2_inode *inode,
		       struct ea_info *eas)
{
	struct target_inode *t = namei_find_inode(ino);

	/* If it isn't in our tree, we don't care about it */
	if (!t)
		return ACTION_COMPLETE;

	if (namei_all_names && !LINUX_S_ISDIR(inode->i_mode))
		t->nlinks = inode->i_links_count;
	else
		t->nlinks = 1;

	return ACTION_WANT_PATH;
}
Example #2
0
/*
 * This fuction deallocates an inode
 */
static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
{
    ext2_filsys fs = ctx->fs;
    struct ext2_inode	inode;
    struct problem_context	pctx;

    ext2fs_icount_store(ctx->inode_link_info, ino, 0);
    e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
    inode.i_links_count = 0;
    inode.i_dtime = time(0);
    e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
    clear_problem_context(&pctx);
    pctx.ino = ino;

    /*
     * Fix up the bitmaps...
     */
    e2fsck_read_bitmaps(ctx);
    ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
    ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
    if (ctx->inode_bad_map)
        ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
    ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
    ext2fs_mark_ib_dirty(fs);

    if (!ext2fs_inode_has_valid_blocks(&inode))
        return;

    if (!LINUX_S_ISDIR(inode.i_mode) &&
            (inode.i_size_high || inode.i_size & 0x80000000UL))
        ctx->large_files--;

    if (inode.i_file_acl) {
        ext2fs_unmark_block_bitmap(ctx->block_found_map,
                                   inode.i_file_acl);
        ext2fs_unmark_block_bitmap(fs->block_map, inode.i_file_acl);
    }

    ext2fs_mark_bb_dirty(fs);
    pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
                                         deallocate_inode_block, ctx);
    if (pctx.errcode) {
        fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
        ctx->flags |= E2F_FLAG_ABORT;
        return;
    }
}
Example #3
0
int ext2_chdir_r (struct _reent *r, const char *name)
{
    ext2_log_trace("name %s\n", name);

    ext2_vd *vd = NULL;
    ext2_inode_t *ni = NULL;

    // Get the volume descriptor for this path
    vd = ext2GetVolume(name);
    if (!vd) {
        r->_errno = ENODEV;
        return -1;
    }

    // Lock
    ext2Lock(vd);

    // Find the directory
    ni = ext2OpenEntry(vd, name);
    if (!ni) {
        ext2Unlock(vd);
        r->_errno = ENOENT;
        return -1;
    }

    // Ensure that this directory is indeed a directory
    if (!LINUX_S_ISDIR(ni->ni.i_mode)) {
        ext2CloseEntry(vd, ni);
        ext2Unlock(vd);
        r->_errno = ENOTDIR;
        return -1;
    }

    // Close the old current directory (if any)
    if (vd->cwd_ni)
        ext2CloseEntry(vd, vd->cwd_ni);

    // Set the new current directory
    vd->cwd_ni = ni;

    // Unlock
    ext2Unlock(vd);

    return 0;
}
// Top-level function to find the inode number for a file by its full path.
__u32 _ref_get_inode_by_path(void * fs, char * path) {
    char ** parts = split_path(path);
    __u32 ino_num = EXT2_ROOT_INO;
    for (char ** part = parts; *part != NULL; part++) {
        struct ext2_inode * ino = get_inode(fs, ino_num);
        if (!LINUX_S_ISDIR(ino->i_mode)) break;
        ino_num = get_inode_from_dir(fs, ino, *part);
        if (ino_num == 0) {
            break;
        }
    }

    if (ino_num == EXT2_ROOT_INO){
        return 0;
    } else {
        return ino_num;
    }
}
Example #5
0
errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino)
{
	struct	ext2_inode	inode;
	errcode_t		retval;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	if (ino > fs->super->s_inodes_count)
		return EXT2_ET_BAD_INODE_NUM;

	if (fs->check_directory) {
		retval = (fs->check_directory)(fs, ino);
		if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
			return retval;
	}
	retval = ext2fs_read_inode(fs, ino, &inode);
	if (retval)
		return retval;
	if (!LINUX_S_ISDIR(inode.i_mode))
		return EXT2_ET_NO_DIRECTORY;
	return 0;
}
Example #6
0
/*
 * This function expands '%IX' expressions
 */
static _INLINE_ void expand_inode_expression(char ch, 
					     struct problem_context *ctx)
{
	struct ext2_inode	*inode;
	struct ext2_inode_large	*large_inode;
	const char *		time_str;
	time_t			t;
	int			do_gmt = -1;

	if (!ctx || !ctx->inode)
		goto no_inode;
	
	inode = ctx->inode;
	large_inode = (struct ext2_inode_large *) inode;

	switch (ch) {
	case 's':
		if (LINUX_S_ISDIR(inode->i_mode))
			printf("%u", inode->i_size);
		else {
#ifdef EXT2_NO_64_TYPE
			if (inode->i_size_high)
				printf("0x%x%08x", inode->i_size_high,
				       inode->i_size);
			else
				printf("%u", inode->i_size);
#else
			printf("%llu", inode->i_size |
				       ((long long)inode->i_size_high << 32));
#endif
		}
		break;
	case 'S':
		printf("%u", large_inode->i_extra_isize);
		break;
	case 'b':
		printf("%u", inode->i_blocks);
		break;
	case 'l':
		printf("%d", inode->i_links_count);
		break;
	case 'm':
		printf("0%o", inode->i_mode);
		break;
	case 'M':
		/* The diet libc doesn't respect the TZ environemnt variable */
		if (do_gmt == -1) {
			time_str = getenv("TZ");
			if (!time_str)
				time_str = "";
			do_gmt = !strcmp(time_str, "GMT");
		}
		t = inode->i_mtime;
		time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
		printf("%.24s", time_str);
		break;
	case 'F':
		printf("%u", inode->i_faddr);
		break;
	case 'f':
		printf("%u", inode->i_file_acl);
		break;
	case 'd':
		printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
			      inode->i_dir_acl : 0));
		break;
	case 'u':
		printf("%d", inode_uid(*inode));
		break;
	case 'g':
		printf("%d", inode_gid(*inode));
		break;
	case 't':
		if (LINUX_S_ISREG(inode->i_mode)) 
			printf(_("regular file"));
		else if (LINUX_S_ISDIR(inode->i_mode)) 
			printf(_("directory"));
		else if (LINUX_S_ISCHR(inode->i_mode)) 
			printf(_("character device"));
		else if (LINUX_S_ISBLK(inode->i_mode)) 
			printf(_("block device"));
		else if (LINUX_S_ISFIFO(inode->i_mode)) 
			printf(_("named pipe"));
		else if (LINUX_S_ISLNK(inode->i_mode)) 
			printf(_("symbolic link"));
		else if (LINUX_S_ISSOCK(inode->i_mode))
			printf(_("socket"));
		else
			printf(_("unknown file type with mode 0%o"),
			       inode->i_mode);
		break;
	default:
	no_inode:
		printf("%%I%c", ch);
		break;
	}
}
Example #7
0
int ext2fs_inline_data_dir_iterate(ext2_filsys fs, ext2_ino_t ino,
                                   void *priv_data)
{
    struct dir_context *ctx;
    struct ext2_inode inode;
    struct ext2_dir_entry dirent;
    struct ext2_inline_data data;
    int ret = BLOCK_ABORT;
    e2_blkcnt_t blockcnt = 0;
    char *old_buf;
    unsigned int old_buflen;
    int old_flags;

    ctx = (struct dir_context *)priv_data;
    old_buf = ctx->buf;
    old_buflen = ctx->buflen;
    old_flags = ctx->flags;
    ctx->flags |= DIRENT_FLAG_INCLUDE_INLINE_DATA;

    ctx->errcode = ext2fs_read_inode(fs, ino, &inode);
    if (ctx->errcode)
        goto out;

    if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) {
        ctx->errcode = EXT2_ET_NO_INLINE_DATA;
        goto out;
    }

    if (!LINUX_S_ISDIR(inode.i_mode)) {
        ctx->errcode = EXT2_ET_NO_DIRECTORY;
        goto out;
    }
    ret = 0;

    /* we first check '.' and '..' dir */
    dirent.inode = ino;
    dirent.name_len = 1;
    ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(2), &dirent);
    dirent.name[0] = '.';
    dirent.name[1] = '\0';
    ctx->buf = (char *)&dirent;
    ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
    ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
    if (ret & BLOCK_ABORT)
        goto out;

    dirent.inode = ext2fs_le32_to_cpu(inode.i_block[0]);
    dirent.name_len = 2;
    ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(3), &dirent);
    dirent.name[0] = '.';
    dirent.name[1] = '.';
    dirent.name[2] = '\0';
    ctx->buf = (char *)&dirent;
    ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
    ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
    if (ret & BLOCK_INLINE_DATA_CHANGED) {
        errcode_t err;

        inode.i_block[0] = ext2fs_cpu_to_le32(dirent.inode);
        err = ext2fs_write_inode(fs, ino, &inode);
        if (err)
            goto out;
        ret &= ~BLOCK_INLINE_DATA_CHANGED;
    }
    if (ret & BLOCK_ABORT)
        goto out;

    ctx->buf = (char *)inode.i_block + EXT4_INLINE_DATA_DOTDOT_SIZE;
    ctx->buflen = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE;
#ifdef WORDS_BIGENDIAN
    ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
    if (ctx->errcode) {
        ret |= BLOCK_ABORT;
        goto out;
    }
#endif
    ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
    if (ret & BLOCK_INLINE_DATA_CHANGED) {
#ifdef WORDS_BIGENDIAN
        ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
                                               ctx->buflen, 0);
        if (ctx->errcode) {
            ret |= BLOCK_ABORT;
            goto out;
        }
#endif
        ctx->errcode = ext2fs_write_inode(fs, ino, &inode);
        if (ctx->errcode)
            ret |= BLOCK_ABORT;
        ret &= ~BLOCK_INLINE_DATA_CHANGED;
    }
    if (ret & BLOCK_ABORT)
        goto out;

    data.fs = fs;
    data.ino = ino;
    ctx->errcode = ext2fs_inline_data_ea_get(&data);
    if (ctx->errcode) {
        ret |= BLOCK_ABORT;
        goto out;
    }
    if (data.ea_size <= 0)
        goto out1;

    ctx->buf = data.ea_data;
    ctx->buflen = data.ea_size;
#ifdef WORDS_BIGENDIAN
    ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
    if (ctx->errcode) {
        ret |= BLOCK_ABORT;
        goto out1;
    }
#endif

    ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
    if (ret & BLOCK_INLINE_DATA_CHANGED) {
#ifdef WORDS_BIGENDIAN
        ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
                                               ctx->buflen, 0);
        if (ctx->errcode) {
            ret |= BLOCK_ABORT;
            goto out1;
        }
#endif
        ctx->errcode = ext2fs_inline_data_ea_set(&data);
        if (ctx->errcode)
            ret |= BLOCK_ABORT;
    }

out1:
    ext2fs_free_mem(&data.ea_data);
out:
    ctx->buf = old_buf;
    ctx->buflen = old_buflen;
    ctx->flags = old_flags;
    ret &= ~(BLOCK_ABORT | BLOCK_INLINE_DATA_CHANGED);
    return ret;
}
Example #8
0
/*
 * This function expands '%IX' expressions
 */
static _INLINE_ void expand_inode_expression(char ch,
					       struct problem_context *ctx)
{
	struct ext2_inode	*inode;
	char *			time_str;
	time_t			t;

	if (!ctx || !ctx->inode)
		goto no_inode;
	
	inode = ctx->inode;
	
	switch (ch) {
	case 's':
		if (LINUX_S_ISDIR(inode->i_mode))
			printf("%u", inode->i_size);
		else {
#ifdef EXT2_NO_64_TYPE
			if (inode->i_size_high)
				printf("0x%x%08x", inode->i_size_high,
				       inode->i_size);
			else
				printf("%u", inode->i_size);
#else
			printf("%llu", (inode->i_size | 
					((__u64) inode->i_size_high << 32)));
#endif
		}
		break;
	case 'b':
		printf("%u", inode->i_blocks);
		break;
	case 'l':
		printf("%d", inode->i_links_count);
		break;
	case 'm':
		printf("0%o", inode->i_mode);
		break;
	case 'M':
		t = inode->i_mtime;
		time_str = ctime(&t);
		printf("%.24s", time_str);
		break;
	case 'F':
		printf("%u", inode->i_faddr);
		break;
	case 'f':
		printf("%u", inode->i_file_acl);
		break;
	case 'd':
		printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
			      inode->i_dir_acl : 0));
		break;
	case 'u':
		printf("%d", (inode->i_uid |
			      (inode->osd2.linux2.l_i_uid_high << 16)));
		break;
	case 'g':
		printf("%d", (inode->i_gid |
			      (inode->osd2.linux2.l_i_gid_high << 16)));
		break;
	default:
	no_inode:
		printf("%%I%c", ch);
		break;
	}
}
Example #9
0
extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
				    ext2_ino_t ino, char *buf)
{
	ext2_filsys fs = ctx->fs;
	struct ext2_inode	inode;
	int			inode_modified = 0;
	int			not_fixed = 0;
	unsigned char		*frag, *fsize;
	struct problem_context	pctx;
	int	problem = 0;

	e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");

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

	if (ext2fs_file_acl_block(fs, &inode) &&
	    !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
		if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
			ext2fs_file_acl_block_set(fs, &inode, 0);
			inode_modified++;
		} else
			not_fixed++;
	}

	if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
	    !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
	    !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
	    !(LINUX_S_ISSOCK(inode.i_mode)))
		problem = PR_2_BAD_MODE;
	else if (LINUX_S_ISCHR(inode.i_mode)
		 && !e2fsck_pass1_check_device_inode(fs, &inode))
		problem = PR_2_BAD_CHAR_DEV;
	else if (LINUX_S_ISBLK(inode.i_mode)
		 && !e2fsck_pass1_check_device_inode(fs, &inode))
		problem = PR_2_BAD_BLOCK_DEV;
	else if (LINUX_S_ISFIFO(inode.i_mode)
		 && !e2fsck_pass1_check_device_inode(fs, &inode))
		problem = PR_2_BAD_FIFO;
	else if (LINUX_S_ISSOCK(inode.i_mode)
		 && !e2fsck_pass1_check_device_inode(fs, &inode))
		problem = PR_2_BAD_SOCKET;
	else if (LINUX_S_ISLNK(inode.i_mode)
		 && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) {
		problem = PR_2_INVALID_SYMLINK;
	}

	if (problem) {
		if (fix_problem(ctx, problem, &pctx)) {
			deallocate_inode(ctx, ino, 0);
			if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
				return 0;
			return 1;
		} else
			not_fixed++;
		problem = 0;
	}

	if (inode.i_faddr) {
		if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
			inode.i_faddr = 0;
			inode_modified++;
		} else
			not_fixed++;
	}

	switch (fs->super->s_creator_os) {
	    case EXT2_OS_HURD:
		frag = &inode.osd2.hurd2.h_i_frag;
		fsize = &inode.osd2.hurd2.h_i_fsize;
		break;
	    default:
		frag = fsize = 0;
	}
	if (frag && *frag) {
		pctx.num = *frag;
		if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
			*frag = 0;
			inode_modified++;
		} else
			not_fixed++;
		pctx.num = 0;
	}
	if (fsize && *fsize) {
		pctx.num = *fsize;
		if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
			*fsize = 0;
			inode_modified++;
		} else
			not_fixed++;
		pctx.num = 0;
	}

	if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
	    !(fs->super->s_feature_ro_compat &
	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
	    (inode.osd2.linux2.l_i_blocks_hi != 0)) {
		pctx.num = inode.osd2.linux2.l_i_blocks_hi;
		if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) {
			inode.osd2.linux2.l_i_blocks_hi = 0;
			inode_modified++;
		}
	}

	if (!(fs->super->s_feature_incompat & 
	     EXT4_FEATURE_INCOMPAT_64BIT) &&
	    inode.osd2.linux2.l_i_file_acl_high != 0) {
		pctx.num = inode.osd2.linux2.l_i_file_acl_high;
		if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) {
			inode.osd2.linux2.l_i_file_acl_high = 0;
			inode_modified++;
		} else
			not_fixed++;
	}

	if (ext2fs_file_acl_block(fs, &inode) &&
	    ((ext2fs_file_acl_block(fs, &inode) < fs->super->s_first_data_block) ||
	     (ext2fs_file_acl_block(fs, &inode) >= ext2fs_blocks_count(fs->super)))) {
		if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
			ext2fs_file_acl_block_set(fs, &inode, 0);
			inode_modified++;
		} else
			not_fixed++;
	}
	if (inode.i_dir_acl &&
	    LINUX_S_ISDIR(inode.i_mode)) {
		if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
			inode.i_dir_acl = 0;
			inode_modified++;
		} else
			not_fixed++;
	}

	if (inode_modified)
		e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
	if (!not_fixed && ctx->inode_bad_map)
		ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino);
	return 0;
}
Example #10
0
int ext2_file_to_sectors (struct _reent *r,const char *path,uint32_t *sec_out,uint32_t *size_out,int max,int phys)
{
    ntfs_file_state fileStruct;
   
    ext2_file_state* file = STATE(&fileStruct);

    // Get the volume descriptor for this path
    file->vd = ext2GetVolume(path);
    if (!file->vd) {
        r->_errno = ENODEV;
        return -1;
    }

    // Lock
    ext2Lock(file->vd);

    file->flags = 0;
    file->read = true;
    file->write = false;
    file->append = false;

    // Try and find the file and (if found) ensure that it is not a directory
    file->ni = ext2OpenEntry(file->vd, path);

    if (file->ni && LINUX_S_ISDIR(file->ni->ni.i_mode))
    {
        ext2CloseEntry(file->vd, file->ni);
        ext2Unlock(file->vd);
        r->_errno = EISDIR;
        return -1;
    }

    // Sanity check, the file should be open by now
    if (!file->ni) {
        ext2Unlock(file->vd);
        r->_errno = ENOENT;
        return -1;
    }

    errcode_t err = ext2fs_file_open2(file->vd->fs, file->ni->ino, &file->ni->ni,
                                       0, &file->fd);
    if(err != 0)
    {
        ext2CloseEntry(file->vd, file->ni);
        ext2Unlock(file->vd);
        r->_errno = ENOENT;
        return -1;
    }

    //ext2_log_trace("file->len %lld\n", EXT2_I_SIZE(&file->ni->ni));

    // Update file times
    ext2UpdateTimes(file->vd, file->ni, EXT2_UPDATE_ATIME);

    // Insert the file into the double-linked FILO list of open files
    if (file->vd->firstOpenFile) {
        file->nextOpenFile = file->vd->firstOpenFile;
        file->vd->firstOpenFile->prevOpenFile = file;
    } else {
        file->nextOpenFile = NULL;
    }
    file->prevOpenFile = NULL;
    file->vd->firstOpenFile = file;
    file->vd->openFileCount++;

    // Sync access time
    ext2Sync(file->vd, file->ni);

    file->is_ntfs = 0;

    u64 read = 0;
    err = 0;

    // Read from the files data attribute
    //err = ext2fs_file_read(file->fd, ptr, len, &read);
    u64 len = 0;

    ext2fs_file_llseek(file->fd, 0, SEEK_END, (__u64 *) &len);

    // Set the files current position
	ext2fs_file_llseek(file->fd, 0, SEEK_SET, 0);

    u32 current_block = 0;
    err = ext2fs_file_read_sectors(file->fd, len, &read, sec_out, size_out, &current_block, max);
    if (err || read <= 0 || read > len) {
        ext2Unlock(file->vd);
        r->_errno = errno;
        current_block = err ? err : -1;
        goto end;
    }

end:
     // Close the file
    ext2CloseFile(file);

    // Remove the file from the double-linked FILO list of open files
    file->vd->openFileCount--;
    if (file->nextOpenFile)
        file->nextOpenFile->prevOpenFile = file->prevOpenFile;
    if (file->prevOpenFile)
        file->prevOpenFile->nextOpenFile = file->nextOpenFile;
    else
        file->vd->firstOpenFile = file->nextOpenFile;

    ext2Unlock(file->vd);

    return current_block;
}
Example #11
0
static int copy_dir(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_data_t *dir)
{
  static unsigned int dir_nbr=0;
  static unsigned long int inode_known[MAX_DIR_NBR];
  file_data_t *dir_list;
  const unsigned int current_directory_namelength=strlen(dir_data->current_directory);
  file_data_t *current_file;
  char *dir_name;
  int copy_bad=0;
  int copy_ok=0;
  if(dir_data->get_dir==NULL || dir_data->copy_file==NULL)
    return -2;
  inode_known[dir_nbr++]=dir->st_ino;
  dir_name=mkdir_local(dir_data->local_dir, dir_data->current_directory);
  dir_list=dir_data->get_dir(disk, partition, dir_data, (const unsigned long int)dir->st_ino);
  for(current_file=dir_list;current_file!=NULL;current_file=current_file->next)
  {
    dir_data->current_directory[current_directory_namelength]='\0';
    if(current_directory_namelength+1+strlen(current_file->name)<sizeof(dir_data->current_directory)-1)
    {
      if(strcmp(dir_data->current_directory,"/"))
	strcat(dir_data->current_directory,"/");
      strcat(dir_data->current_directory,current_file->name);
      if(LINUX_S_ISDIR(current_file->st_mode)!=0)
      {
	const unsigned long int new_inode=current_file->st_ino;
	unsigned int new_inode_ok=1;
	unsigned int i;
	if(new_inode<2)
	  new_inode_ok=0;
	if(strcmp(current_file->name,"..")==0 || strcmp(current_file->name,".")==0)
	  new_inode_ok=0;
	for(i=0;i<dir_nbr && new_inode_ok!=0;i++)
	  if(new_inode==inode_known[i]) /* Avoid loop */
	    new_inode_ok=0;
	if(new_inode_ok>0)
	{
	  int tmp;
	  tmp=copy_dir(disk, partition, dir_data, current_file);
	  if(tmp>=-1)
	    copy_ok=1;
	  if(tmp<0)
	    copy_bad=1;
	}
      }
      else if(LINUX_S_ISREG(current_file->st_mode)!=0)
      {
//	log_trace("copy_file %s\n",dir_data->current_directory);
	int tmp;
	tmp=dir_data->copy_file(disk, partition, dir_data, current_file);
	if(tmp==0)
	  copy_ok=1;
	else
	  copy_bad=1;
      }
    }
  }
  dir_data->current_directory[current_directory_namelength]='\0';
  delete_list_file(dir_list);
  set_date(dir_name, dir->td_atime, dir->td_mtime);
  free(dir_name);
  dir_nbr--;
  return (copy_bad>0?(copy_ok>0?-1:-2):0);
}
Example #12
0
DIR_ITER *ext2_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path)
{
    ext2_log_trace("dirState %p, path %s\n", dirState, path);

    if(!dirState)
    {
        r->_errno = EINVAL;
        return NULL;
    }

    ext2_dir_state* dir = STATE(dirState);

    if(!dir)
    {
        r->_errno = EINVAL;
        return NULL;
    }

    // Get the volume descriptor for this path
    dir->vd = ext2GetVolume(path);
    if (!dir->vd) {
        r->_errno = ENODEV;
        return NULL;
    }

    // Lock
    ext2Lock(dir->vd);

    // Find the directory
    dir->ni = ext2OpenEntry(dir->vd, path);
    if (!dir->ni) {
        ext2Unlock(dir->vd);
        r->_errno = ENOENT;
        return NULL;
    }

    // Ensure that this directory is indeed a directory
    if (!LINUX_S_ISDIR(dir->ni->ni.i_mode)) {
        ext2CloseEntry(dir->vd, dir->ni);
        ext2Unlock(dir->vd);
        r->_errno = ENOTDIR;
        return NULL;
    }

    // Read the directory
    dir->first = dir->current = NULL;
    if (ext2fs_dir_iterate(dir->vd->fs, dir->ni->ino, 0, 0, DirIterateCallback, dirState) != EXT2_ET_OK) {
        ext2CloseDir(dir);
        ext2Unlock(dir->vd);
        r->_errno = errno;
        return NULL;
    }

    // Move to the first entry in the directory
    dir->current = dir->first;

    // Update directory times
    ext2UpdateTimes(dir->vd, dir->ni, EXT2_UPDATE_ATIME);

    // Insert the directory into the double-linked FILO list of open directories
    if (dir->vd->firstOpenDir) {
        dir->nextOpenDir = dir->vd->firstOpenDir;
        dir->vd->firstOpenDir->prevOpenDir = dir;
    } else {
        dir->nextOpenDir = NULL;
    }
    dir->prevOpenDir = NULL;
    dir->vd->cwd_ni = dir->ni;
    dir->vd->firstOpenDir = dir;
    dir->vd->openDirCount++;

    // Unlock
    ext2Unlock(dir->vd);

    return dirState;
}
Example #13
0
// search inode by use imap (step1: flag 1 = only directory ; step2: flag 0 = only file)
static void search_imap_inode(char* des_dir, __u32 t_after, __u32 t_before, int flag)
{
struct ext2_group_desc 			*gdp;
struct 	ext2_inode_large 		*inode;
//struct dir_list_head_t 			*dir = NULL;
struct ring_buf* 			i_list = NULL;
r_item*					item = NULL;
int  					zero_flag, retval, load, x ,i ;
char 					*pathname = NULL;
char					*i_pathname = NULL;
char 					*buf= NULL;
unsigned char				*tmp_buf = NULL;
__u32 					blocksize, inodesize, inode_max, inode_per_group, block_count;
__u32 					inode_per_block , inode_block_group, group;
blk_t 					block_nr;
__u32   				c_time, d_time, mode;
ext2_ino_t 				first_block_inode_nr , inode_nr;


pathname = malloc(26);
blocksize = current_fs->blocksize;
inodesize = current_fs->super->s_inode_size;
inode_max = current_fs->super->s_inodes_count;
inode_per_group = current_fs->super->s_inodes_per_group;
buf = malloc(blocksize);
if (! (flag & 0x01) ){
	tmp_buf = malloc (12 * blocksize);
	if (!tmp_buf)
		goto errout;
	cookie = magic_open(MAGIC_MIME | MAGIC_NO_CHECK_COMPRESS | MAGIC_NO_CHECK_ELF | MAGIC_CONTINUE);
	if ((! cookie) ||  magic_load(cookie, NULL)){
		fprintf(stderr,"ERROR: can't find libmagic\n");
		goto errout;
	}
}

inode_per_block = blocksize / inodesize;
inode_block_group = inode_per_group / inode_per_block;

for (group = 0 ; group < current_fs->group_desc_count ; group++){
#ifdef EXT2_FLAG_64BITS
	gdp = ext2fs_group_desc(current_fs, current_fs->group_desc, group);
#else
	gdp = &current_fs->group_desc[group];
#endif
	zero_flag = 0;

	if (!(flag & 0x02)){ //skip this in disaster mode
		// NEXT GROUP IF INODE NOT INIT
		if (gdp->bg_flags & (EXT2_BG_INODE_UNINIT)) continue;
	
		// SET ZERO-FLAG IF FREE INODES == INODE/GROUP for fast ext3 
		if (gdp->bg_free_inodes_count == inode_per_group) zero_flag = 1;
	}

//FIXME for struct ext4_group_desc 48/64BIT	
	for (block_nr = gdp->bg_inode_table , block_count = 0 ;
			 block_nr < (gdp->bg_inode_table + inode_block_group); block_nr++, block_count++) {
		
		if (!(flag & 0x02)){ //skip this in disaster mode
			// break if the first block only zero inode
			if ((block_count ==1) && (zero_flag == (inode_per_block + 1))) break;
		}

//FIXME  inode_max ????	
		first_block_inode_nr = (group * inode_per_group) + (block_count * inode_per_block) + 1;
		load = 0;
		for (i = 0; i<inode_per_block;i++){
			if ( ! ext2fs_test_block_bitmap(imap,first_block_inode_nr + i)){
				load++;
				break;
			}
		}

		if (load){		 
			retval = read_block ( current_fs , &block_nr , buf);
			if (retval) return;

			for (inode_nr = first_block_inode_nr ,x = 0; x < inode_per_block ; inode_nr++ , x++){

				if ( ! ext2fs_test_block_bitmap(imap,inode_nr)){
	
					inode = (struct ext2_inode_large*) (buf + (x*inodesize));
					c_time = ext2fs_le32_to_cpu(inode->i_ctime);
					mode = ext2fs_le32_to_cpu(inode->i_mode);
					if ( ! ( flag & 0x02)) { 
						//no check this inode in disaster mode
 						if ((! c_time ) && (!(inode->i_mode & LINUX_S_IFMT)) ) {
							if(zero_flag) zero_flag++ ;
						continue;
						}
	
						d_time = ext2fs_le32_to_cpu(inode->i_dtime);
						if ( (! d_time) || d_time <= t_after){
							ext2fs_mark_generic_bitmap(imap,inode_nr);
						continue;
						}
					}
// 1. magical step 
					if (LINUX_S_ISDIR(mode) && ( flag & 0x01) && (pathname)){ 
						sprintf(pathname,"<%lu>",(long unsigned int)inode_nr);

	
						struct dir_list_head_t * dir = NULL;
						if (flag & 0x02){
							//disaster mode 
							//only search for undeleted entry 
							dir = get_dir3(NULL,0, inode_nr , "MAGIC-1",pathname, t_after,t_before, 0);
							if (dir) {
								lookup_local(des_dir, dir,t_after,t_before, RECOV_ALL | LOST_DIR_SEARCH );
								clear_dir_list(dir);
							}
						}
						else{   //search for all 
							dir = get_dir3(NULL,0, inode_nr , "MAGIC-1",pathname, t_after,t_before, DELETED_OPT);
							if (dir) {
								lookup_local(des_dir,dir,t_after,t_before,DELETED_OPT|RECOV_ALL|LOST_DIR_SEARCH);
								clear_dir_list(dir);
							}
						}

						
					}

// 2. magical step
					if (! (flag & 0x01) ){
						i_list = get_j_inode_list(current_fs->super, inode_nr);
						item = get_undel_inode(i_list,t_after,t_before);
						ext2fs_mark_generic_bitmap(imap,inode_nr);

						if (item) {
							if (! LINUX_S_ISDIR(item->inode->i_mode) ) {
								i_pathname = identify_filename(i_pathname, tmp_buf,
										(struct ext2_inode*)item->inode, inode_nr);
								sprintf(pathname,"<%lu>",(long unsigned int)inode_nr);
								recover_file(des_dir,"MAGIC-2", ((i_pathname)?i_pathname : pathname),
									     (struct ext2_inode*)item->inode, inode_nr, 0);
								if(i_pathname){
									free(i_pathname);
									i_pathname = NULL;
								}
							}
						}
						if (i_list) ring_del(i_list);
					}	
				}
			}
		}
	}
}
errout:
	if (pathname)
		 free(pathname);

	if(buf) {
		free(buf);
		buf = NULL;
	}

	if (tmp_buf){
		free(tmp_buf);
		tmp_buf = NULL;
	}
	if (cookie){
		magic_close(cookie);
		cookie = 0;
	}
return;
} 
Example #14
0
void addPath(const char *path, int squash_uids, int squash_perms)
{
	size_t len;
	char *full_name = NULL, *lnk = NULL;
	struct dirent *file = NULL;
	DIR *direc = NULL;
	struct stat st;
	int overWrite;
	__u16 inodeType;

	direc = opendir(path);

	if ( !direc )
		log_error("[Local fs opendir] Cannot open directory %s", path);

	while (( file = readdir(direc)) != NULL ) {

		if (( !strcmp(file->d_name, "." )) || ( !strcmp(file->d_name, ".." )))
			continue;

		len = strlen(path) + strlen( file->d_name ) + 3;

		if ( full_name ) {
			free( full_name );
			full_name = NULL;
		}

		full_name = (char*)malloc(len + 2);
		if ( !full_name )
			log_error("[Local fs stat] Memory allocation error ( full_name --> %s/%s )", path, file->d_name);

		memset(full_name, 0, len + 2);
		snprintf(full_name, len, "%s/%s", path, file->d_name);

		lstat(full_name, &st);
		mode_t fmt = st.st_mode & S_IFMT;

		if ( squash_uids )
			st.st_uid = st.st_gid = 0;

		if ( squash_perms )
			st.st_mode &= ~( LINUX_S_IRWXG | LINUX_S_IRWXO );

		overWrite = name_to_inode( file->d_name );

		if ( st.st_nlink > 1 ) {
			if (( lnk = linklist_add(st.st_dev, st.st_ino, full_name + modPath_path_len))) {

				if ( overWrite ) {
					log_action(ACT_RM, file->d_name, NULL, 0, 0, 0, 0, 0, 0, overWrite);
					if ( !do_rm(file->d_name))
						log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), file->d_name);
				}

				log_action(ACT_HARDLINK, file->d_name, lnk, 0, 0, 0, 0, 0, 0, overWrite);
				if (!do_hardlink(&st, lnk, file->d_name))
					log_error("[Filesystem error] cannot hardlink %s --> %s", file->d_name, lnk);
				continue;
			}
		}

		if ( overWrite )
			inodeType = inode_mode( file->d_name );

		if (( fmt == S_IFDIR ) && ( overWrite ) && ( !LINUX_S_ISDIR(inodeType)))
			log_error("[Remote fs mismatch] %s/%s exists but isn't a directory when it should be.", log_cwd(), file->d_name);
		else if (( fmt != S_IFDIR) && ( overWrite )) {
			if ( LINUX_S_ISDIR(inodeType))
				log_error("[Remote fs mismatch] %s/%s exists but is a directory when it shouldn't be.", log_cwd(), file->d_name);

			if ((!LINUX_S_ISREG(inodeType)) && (!LINUX_S_ISLNK(inodeType)) &&
			    (!LINUX_S_ISBLK(inodeType)) && (!LINUX_S_ISCHR(inodeType)) &&
			    (!LINUX_S_ISFIFO(inodeType)) && (!LINUX_S_ISSOCK(inodeType)))
				log_error("[Remote fs mismatch] Existing file %s/%s has unknown/unsupported type [0x%x].", log_cwd(), file->d_name);
		}

		switch ( fmt ) {
		case S_IFDIR:         // Directory
			log_action(ACT_MKDIR, file->d_name, NULL, 0, 0, 0, 0, 0, 0, overWrite);

			if ( !overWrite )
				if ( !do_mkdir( &st, file->d_name ))
					log_error("[Filesystem error] cannot mkdir %s/%s", log_cwd(), file->d_name);

			log_action(ACT_CHMODE, file->d_name, NULL, st.st_mode, 0, 0, 0, 0, 0, overWrite);
			if ( !do_chmode(file->d_name, st.st_mode))
				log_error("[Filesystem error] Failed to chmode 0x%x for directory %s/%s", st.st_mode, log_cwd(), file->d_name);
			log_action(ACT_CHOWN, file->d_name, NULL, 0, st.st_uid, st.st_gid, 0, 0, 0, 0);
			if ( !do_chown(file->d_name, st.st_uid, st.st_gid))
				log_error("[Filesystem error] Failed to chown %ld, %ld for directory %s/%s", st.st_uid, st.st_gid, log_cwd(), file->d_name);

			log_action(ACT_CHDIR, file->d_name, NULL, 0, 0, 0, 0, 0, 0, 0);
			if ( !do_chdir( file->d_name ))
				log_error("[Filesystem error] cannot chdir to newly created %s/%s", log_cwd(), file->d_name);

			addPath(full_name, squash_uids, squash_perms);

			log_action(ACT_CHDIR, "..", NULL, 0, 0, 0, 0, 0, 0, 0);
			if ( !do_chdir(".."))
				log_error("[Filesystem error] cannot chdir to parent directory");
			break;

		case S_IFREG:         // Regular file

			if ( overWrite ) {
				log_action(ACT_RM, file->d_name, NULL, 0, 0, 0, 0, 0, 0, overWrite);
				if ( !do_rm(file->d_name))
					log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), file->d_name);
			}

			log_action(ACT_WRITE, file->d_name, NULL, 0, 0, 0, 0, 0, 0, overWrite);
			if ( !do_write(full_name, file->d_name))
				log_error("[Filesystem error] cannot write %s/%s", log_cwd(), file->d_name);
			break;

		case S_IFLNK:         // Symbolic link

			lnk = (char*)malloc(MAX_PATHSIZE + 2);
			if ( !lnk )
				log_error("[symlink] Memory allocation error (lnk)");
			int len = readlink(full_name, lnk, MAX_PATHSIZE);
			if ( len == -1 ) {
				free(lnk);
				log_error("[Local filesystem error] Cannot read destination for link %s/%s", log_cwd(), file->d_name);
			} else lnk[len] = '\0';

			if ( overWrite ) {
				log_action(ACT_RM, file->d_name, NULL, 0, 0, 0, 0, 0, 0, overWrite);
				if ( !do_rm(file->d_name))
					log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), file->d_name);
			}

			log_action(ACT_SYMLINK, file->d_name, lnk, 0, 0, 0, 0, 0, 0, overWrite);
			if ( !do_symlink(&st, lnk, file->d_name))
				log_error("[Filesystem error] cannot symlink %s/%s --> %s", log_cwd(), file->d_name, lnk);

			free(lnk);
			break;

		case S_IFBLK:           // Block device node
		case S_IFCHR:           // Character device node
		case S_IFSOCK:          // socket
		case S_IFIFO:           // fifo

			if ( overWrite ) {
				log_action(ACT_RM, file->d_name, NULL, 0, 0, 0, 0, 0, 0, overWrite);
				if ( !do_rm(file->d_name))
					log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), file->d_name);
			}

			char nodetype = ( fmt == S_IFBLK ? 'b' : ( fmt == S_IFCHR ? 'c' : ( fmt == S_IFSOCK ? 's' : 'p' )));
			unsigned long major = 0, minor = 0;

			if (( nodetype == 'b' ) || ( nodetype == 'c' )) {
				major = (long)major(st.st_rdev);
				minor = (long)minor(st.st_rdev);
			}

			log_action(ACT_MKNOD, file->d_name, NULL, 0, 0, 0, nodetype, major, minor, overWrite);
			if ( !do_mknod(file->d_name, nodetype, major, minor))
				log_error("[Filesystem error] cannot mknod %c %ld,%ld %s/%s", log_cwd(), nodetype, major, minor, log_cwd(), file->d_name);
			break;
		}

		if ( fmt != S_IFDIR ) { // Not dir ?
			log_action(ACT_CHMODE, file->d_name, NULL, st.st_mode, 0, 0, 0, 0, 0, overWrite);
			if ( !do_chmode(file->d_name, st.st_mode))
				log_error("[Filesystem error] Failed to chmode 0x%x for file %s/%s", st.st_mode, log_cwd(), file->d_name);
			log_action(ACT_CHOWN, file->d_name, NULL, 0, st.st_uid, st.st_gid, 0, 0, 0, 0);
			if ( !do_chown(file->d_name, st.st_uid, st.st_gid))
				log_error("[Filesystem error] Failed to chown %ld, %ld for file %s/%s", st.st_uid, st.st_gid, log_cwd(), file->d_name);
		}

		if ( full_name ) {
			free( full_name );
			full_name = NULL;
		}
	}

	closedir(direc);

}
Example #15
0
int op_unlink (const char *path)
{
	int rt;
	errcode_t rc;

	char *p_path;
	char *r_path;

	ext2_ino_t p_ino;
	struct ext2_inode p_inode;
	ext2_ino_t r_ino;
	struct ext2_vnode *r_vnode;
	struct ext2_inode *r_inode;

	ext2_filsys e2fs;
	FUSE_EXT2_LOCK;
	e2fs	= current_ext2fs();

	debugf("enter");
	debugf("path = %s", path);

	rt=do_check_split(path, &p_path, &r_path);
	if (rt != 0) {
		debugf("do_check_split: failed");
		goto err;
	}

	debugf("parent: %s, child: %s", p_path, r_path);

	rt = do_readinode(e2fs, p_path, &p_ino, &p_inode);
	if (rt) {
		debugf("do_readinode(%s, &p_ino, &p_inode); failed", p_path);
		goto err_free_split;
	}
	rt = do_readvnode(e2fs, path, &r_ino, &r_vnode, DONT_OPEN_FILE);
	if (rt) {
		debugf("do_readvnode(%s, &r_ino, &r_vnode); failed", path);
		goto err_free_split;
	}
	r_inode = vnode2inode(r_vnode);

	if(LINUX_S_ISDIR(r_inode->i_mode)) {
		debugf("%s is a directory", path);
		vnode_put(r_vnode,0);
		rt = -EISDIR;
		goto err_free_split;
	}

	rc = ext2fs_unlink(e2fs, p_ino, r_path, r_ino, 0);
	if (rc) {
		debugf("ext2fs_unlink(e2fs, %d, %s, %d, 0); failed", p_ino, r_path, r_ino);
		vnode_put(r_vnode,0);
		rt = -EIO;
		goto err_free_split;
	}

	if (r_inode->i_links_count > 0) {
		r_inode->i_links_count -= 1;
	}

	p_inode.i_ctime = p_inode.i_mtime = e2fs->now ? e2fs->now : time(NULL);

	rc = ext2fs_write_inode(e2fs, p_ino, &p_inode);
	if (rc) {
		debugf("ext2fs_write_inode(e2fs, p_ino, &p_inode); failed");
		vnode_put(r_vnode,1);
		rt = -EIO;
		goto err_free_split;
	}

	r_inode->i_ctime = e2fs->now ? e2fs->now : time(NULL);
	rc = vnode_put(r_vnode,1);
	if (rc) {
		debugf("vnode_put(r_vnode,1); failed");
		rt = -EIO;
		goto err_free_split;
	}

	free_split(p_path, r_path);
	debugf("leave");
	FUSE_EXT2_UNLOCK;
	return 0;
err_free_split:
	free_split(p_path, r_path);
err:
	FUSE_EXT2_UNLOCK;
	return rt;
}
Example #16
0
// recover files from a "double quotes" listfile
void recover_list(char *des_dir, char *input_file,__u32 t_after, __u32 t_before, int flag){
	FILE  *f;
	char *lineptr = NULL ;
	char *filename = NULL ;
	char *p1 , *p2;
	size_t maxlen;
	size_t got;
	ext2_ino_t inode_nr;
	struct ring_buf *i_list;
	struct ext2_inode* r_inode;
	r_item *item = NULL;	
	
	f = fopen(input_file,"r");
	if (f) {
		rewind(f);
		maxlen = 512;
		lineptr = malloc(maxlen);
		filename = malloc(maxlen);
		if ((!lineptr) || (!filename))
			goto errout;
		while (! (feof(f))){
			got = getline (&lineptr, &maxlen, f);
		 	if (got != -1){
				p1 = strchr(lineptr,'"');
				p2 = strrchr(lineptr,'"');
				if ((p1) && (p2) && (p1 != p2)){
					p1++;
					*p2 = 0;
					strcpy(filename,p1);
					if (*filename == 0)
						continue;
					inode_nr = local_namei(NULL,filename,t_after,t_before,DELETED_OPT);
					if(! inode_nr){
#ifdef DEBUG
						printf("Filename %s not found\n",filename);
#endif
						continue;
					}
					i_list = get_j_inode_list(current_fs->super, inode_nr);
					item = get_undel_inode(i_list,t_after,t_before);

					if (item) {
						r_inode = (struct ext2_inode*)item->inode;
						if (! LINUX_S_ISDIR(r_inode->i_mode) ) 
							recover_file(des_dir,"", filename, r_inode, inode_nr ,flag);
						}
#ifdef DEBUG
						else
							printf("no Inode found for %s\n",filename);
#endif
					if (i_list) ring_del(i_list);
				}
#ifdef DEBUG
				else
					printf("Filename not found in : \"%s\"",lineptr);
#endif	
			}
		}

	}

errout:
	if (f) fclose(f);
	if (lineptr)
		free(lineptr);
	if (filename)
		free(filename); 
return ;
}
Example #17
0
void e2fsck_pass4(e2fsck_t ctx)
{
	ext2_filsys fs = ctx->fs;
	ext2_ino_t	i;
	struct ext2_inode	*inode;
#ifdef RESOURCE_TRACK
	struct resource_track	rtrack;
#endif
	struct problem_context	pctx;
	__u16	link_count, link_counted;
	char	*buf = 0;
	int	group, maxgroup;

	init_resource_track(&rtrack, ctx->fs->io);

#ifdef MTRACE
	mtrace_print("Pass 4");
#endif

	clear_problem_context(&pctx);

	if (!(ctx->options & E2F_OPT_PREEN))
		fix_problem(ctx, PR_4_PASS_HEADER, &pctx);

	group = 0;
	maxgroup = fs->group_desc_count;
	if (ctx->progress)
		if ((ctx->progress)(ctx, 4, 0, maxgroup))
			return;

	inode = e2fsck_allocate_memory(ctx, EXT2_INODE_SIZE(fs->super),
				       "scratch inode");

	/* Protect loop from wrap-around if s_inodes_count maxed */
	for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) {
		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
			goto errout;
		if ((i % fs->super->s_inodes_per_group) == 0) {
			group++;
			if (ctx->progress)
				if ((ctx->progress)(ctx, 4, group, maxgroup))
					goto errout;
		}
		if (i == EXT2_BAD_INO ||
		    (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
			continue;
		if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
		    (ctx->inode_imagic_map &&
		     ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
		    (ctx->inode_bb_map &&
		     ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
			continue;
		ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
		ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
		if (link_counted == 0) {
			if (!buf)
				buf = e2fsck_allocate_memory(ctx,
				     fs->blocksize, "bad_inode buffer");
			if (e2fsck_process_bad_inode(ctx, 0, i, buf))
				continue;
			if (disconnect_inode(ctx, i, inode))
				continue;
			ext2fs_icount_fetch(ctx->inode_link_info, i,
					    &link_count);
			ext2fs_icount_fetch(ctx->inode_count, i,
					    &link_counted);
		}
		if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i) &&
		    (link_counted > EXT2_LINK_MAX))
			link_counted = 1;
		if (link_counted != link_count) {
			e2fsck_read_inode(ctx, i, inode, "pass4");
			pctx.ino = i;
			pctx.inode = inode;
			if (link_count != inode->i_links_count) {
				pctx.num = link_count;
				fix_problem(ctx,
					    PR_4_INCONSISTENT_COUNT, &pctx);
			}
			pctx.num = link_counted;
			/* i_link_count was previously exceeded, but no longer
			 * is, fix this but don't consider it an error */
			if ((LINUX_S_ISDIR(inode->i_mode) && link_counted > 1 &&
			     (inode->i_flags & EXT2_INDEX_FL) &&
			     link_count == 1 && !(ctx->options & E2F_OPT_NO)) ||
			     (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx))) {
				inode->i_links_count = link_counted;
				e2fsck_write_inode(ctx, i, inode, "pass4");
			}
		}
	}
	ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
	ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
	ext2fs_free_inode_bitmap(ctx->inode_bb_map);
	ctx->inode_bb_map = 0;
	ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
	ctx->inode_imagic_map = 0;
errout:
	if (buf)
		ext2fs_free_mem(&buf);

	ext2fs_free_mem(&inode);
	print_resource_track(ctx, _("Pass 4"), &rtrack, ctx->fs->io);
}
Example #18
0
int
fstat(int fd, struct stat *st)
{
	int ret;
	struct linux_stat lst;
	struct ifreq ifr;

	ret = syscall(SYS_fstat, fd, &lst);
	if (ret == -1) {
		errno = EBADF;
		return -1;
	}

	st->st_size = lst.st_size;

	switch (lst.st_mode & LINUX_S_IFMT) {
	case LINUX_S_IFSOCK:
		__platform_socket_fd = fd;
		/* currently no support for raw socket networking */
		lst.st_mode = 0;
		break;
	case LINUX_S_IFBLK:
		syscall(SYS_ioctl, fd, BLKGETSIZE64, &st->st_size);
		break;
	case LINUX_S_IFCHR:
		/* macvtap has a dynamic major number, so hard to test */
		if (lst.st_rdev != makedev(10, 200) && major(lst.st_rdev) < 128)
			break;
		ret = syscall(SYS_ioctl, fd, TUNGETIFF, &ifr);
		if (ret == 0) {
			/* we do not yet support macvtap offload facilities */
			if (ifr.ifr_flags & IFF_VNET_HDR) {
				ifr.ifr_flags &= ~IFF_VNET_HDR;
				syscall(SYS_ioctl, fd, TUNSETIFF, &ifr);
			}
			/* use sock type to tell config we are network */
			lst.st_mode = LINUX_S_IFSOCK;
			/* find mac address */
			ret = syscall(SYS_ioctl, fd, SIOCGIFHWADDR, &ifr);
			if (ret == -1 && __platform_socket_fd != -1)
				ret = syscall(SYS_ioctl, __platform_socket_fd, SIOCGIFHWADDR, &ifr);
			if (ret == 0) {
				memcpy(st->st_hwaddr, ifr.ifr_addr.sa_data, 6);
			}
			__platform_pollfd[__platform_npoll].fd = fd;
			__platform_pollfd[__platform_npoll].events = POLLIN | POLLPRI;
			__platform_npoll++;
		}
		break;
	}
	st->st_mode = (LINUX_S_ISDIR (lst.st_mode) ? S_IFDIR  : 0) |
		      (LINUX_S_ISCHR (lst.st_mode) ? S_IFCHR  : 0) |
		      (LINUX_S_ISBLK (lst.st_mode) ? S_IFBLK  : 0) |
		      (LINUX_S_ISREG (lst.st_mode) ? S_IFREG  : 0) |
		      (LINUX_S_ISFIFO(lst.st_mode) ? S_IFIFO  : 0) |
		      (LINUX_S_ISLNK (lst.st_mode) ? S_IFLNK  : 0) |
		      (LINUX_S_ISSOCK(lst.st_mode) ? S_IFSOCK : 0);

	/* if we are passed in /dev/urandom use as a random source */
	if (LINUX_S_ISCHR(lst.st_mode) && lst.st_rdev == makedev(1, 9))
		__platform_random_fd = fd;

	return 0;
}
Example #19
0
errcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino)
{
    struct ext2_inode inode;
    struct ext2_inline_data data;
    errcode_t retval;
    size_t inline_size;
    char *inline_buf = 0;

    EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

    retval = ext2fs_read_inode(fs, ino, &inode);
    if (retval)
        return retval;

    if (!(inode.i_flags & EXT4_INLINE_DATA_FL))
        return EXT2_ET_NO_INLINE_DATA;

    data.fs = fs;
    data.ino = ino;
    retval = ext2fs_inline_data_ea_get(&data);
    if (retval)
        return retval;
    inline_size = data.ea_size + EXT4_MIN_INLINE_DATA_SIZE;
    retval = ext2fs_get_mem(inline_size, &inline_buf);
    if (retval)
        goto errout;

    memcpy(inline_buf, (void *)inode.i_block, EXT4_MIN_INLINE_DATA_SIZE);
    if (data.ea_size > 0) {
        memcpy(inline_buf + EXT4_MIN_INLINE_DATA_SIZE,
               data.ea_data, data.ea_size);
    }

    memset((void *)inode.i_block, 0, EXT4_MIN_INLINE_DATA_SIZE);
    /*
     * NOTE: We must do this write -> ea_remove -> read cycle here because
     * removing the inline data EA can free the EA block, which is a change
     * that our stack copy of the inode will never see.  If that happens,
     * we can end up with the EA block and lblk 0 pointing to the same
     * pblk, which is bad news.
     */
    retval = ext2fs_write_inode(fs, ino, &inode);
    if (retval)
        goto errout;
    retval = ext2fs_inline_data_ea_remove(fs, ino);
    if (retval)
        goto errout;
    retval = ext2fs_read_inode(fs, ino, &inode);
    if (retval)
        goto errout;

    if (LINUX_S_ISDIR(inode.i_mode)) {
        retval = ext2fs_inline_data_dir_expand(fs, ino, &inode,
                                               inline_buf, inline_size);
    } else {
        retval = ext2fs_inline_data_file_expand(fs, ino, &inode,
                                                inline_buf, inline_size);
    }

errout:
    if (inline_buf)
        ext2fs_free_mem(&inline_buf);
    ext2fs_free_mem(&data.ea_data);
    return retval;
}
Example #20
0
/*
 * This function expands '%IX' expressions
 */
static _INLINE_ void expand_inode_expression(FILE *f, ext2_filsys fs, char ch,
					     struct problem_context *ctx)
{
	struct ext2_inode	*inode;
	struct ext2_inode_large	*large_inode;

	if (!ctx || !ctx->inode)
		goto no_inode;

	inode = ctx->inode;
	large_inode = (struct ext2_inode_large *) inode;

	switch (ch) {
	case 's':
		if (LINUX_S_ISDIR(inode->i_mode))
			fprintf(f, "%u", inode->i_size);
		else {
#ifdef EXT2_NO_64_TYPE
			if (inode->i_size_high)
				fprintf(f, "0x%x%08x", inode->i_size_high,
					inode->i_size);
			else
				fprintf(f, "%u", inode->i_size);
#else
			fprintf(f, "%llu", EXT2_I_SIZE(inode));
#endif
		}
		break;
	case 'S':
		fprintf(f, "%u", large_inode->i_extra_isize);
		break;
	case 'b':
		if (ext2fs_has_feature_huge_file(fs->super))
			fprintf(f, "%llu", inode->i_blocks +
				(((long long) inode->osd2.linux2.l_i_blocks_hi)
				 << 32));
		else
			fprintf(f, "%u", inode->i_blocks);
		break;
	case 'l':
		fprintf(f, "%d", inode->i_links_count);
		break;
	case 'm':
		fprintf(f, "0%o", inode->i_mode);
		break;
	case 'M':
		print_time(f, inode->i_mtime);
		break;
	case 'F':
		fprintf(f, "%u", inode->i_faddr);
		break;
	case 'f':
		fprintf(f, "%llu", ext2fs_file_acl_block(fs, inode));
		break;
	case 'd':
		fprintf(f, "%u", (LINUX_S_ISDIR(inode->i_mode) ?
				  inode->i_dir_acl : 0));
		break;
	case 'u':
		fprintf(f, "%d", inode_uid(*inode));
		break;
	case 'g':
		fprintf(f, "%d", inode_gid(*inode));
		break;
	case 't':
		if (LINUX_S_ISREG(inode->i_mode))
			fputs(_("regular file"), f);
		else if (LINUX_S_ISDIR(inode->i_mode))
			fputs(_("directory"), f);
		else if (LINUX_S_ISCHR(inode->i_mode))
			fputs(_("character device"), f);
		else if (LINUX_S_ISBLK(inode->i_mode))
			fputs(_("block device"), f);
		else if (LINUX_S_ISFIFO(inode->i_mode))
			fputs(_("named pipe"), f);
		else if (LINUX_S_ISLNK(inode->i_mode))
			fputs(_("symbolic link"), f);
		else if (LINUX_S_ISSOCK(inode->i_mode))
			fputs(_("socket"), f);
		else
			fprintf(f, _("unknown file type with mode 0%o"),
				inode->i_mode);
		break;
	default:
	no_inode:
		fprintf(f, "%%I%c", ch);
		break;
	}
}
void do_htree_dump(int argc, char *argv[])
{
	ext2_ino_t	ino;
	struct ext2_inode inode;
	blk64_t		blk;
	char		*buf = NULL;
	struct 		ext2_dx_root_info  *rootnode;
	struct 		ext2_dx_entry *ent;
	errcode_t	errcode;

	if (check_fs_open(argv[0]))
		return;

	pager = open_pager();

	if (common_inode_args_process(argc, argv, &ino, 0))
		goto errout;

	if (debugfs_read_inode(ino, &inode, argv[1]))
		goto errout;

	if (!LINUX_S_ISDIR(inode.i_mode)) {
		com_err(argv[0], 0, "Not a directory");
		goto errout;
	}

	if ((inode.i_flags & EXT2_BTREE_FL) == 0) {
		com_err(argv[0], 0, "Not a hash-indexed directory");
		goto errout;
	}

	buf = malloc(2*current_fs->blocksize);
	if (!buf) {
		com_err(argv[0], 0, "Couldn't allocate htree buffer");
		goto errout;
	}

	errcode = ext2fs_bmap2(current_fs, ino, &inode, buf, 0, 0, 0, &blk);
	if (errcode) {
		com_err("do_htree_block", errcode,
			"while mapping logical block 0\n");
		goto errout;
	}

	errcode = io_channel_read_blk64(current_fs->io, blk,
					1, buf);
	if (errcode) {
		com_err(argv[0], errcode, "Error reading root node");
		goto errout;
	}

	rootnode = (struct ext2_dx_root_info *) (buf + 24);

	fprintf(pager, "Root node dump:\n");
	fprintf(pager, "\t Reserved zero: %u\n", rootnode->reserved_zero);
	fprintf(pager, "\t Hash Version: %d\n", rootnode->hash_version);
	fprintf(pager, "\t Info length: %d\n", rootnode->info_length);
	fprintf(pager, "\t Indirect levels: %d\n", rootnode->indirect_levels);
	fprintf(pager, "\t Flags: %d\n", rootnode->unused_flags);

	ent = (struct ext2_dx_entry *) (buf + 24 + rootnode->info_length);

	htree_dump_int_node(current_fs, ino, &inode, rootnode, ent,
			    buf + current_fs->blocksize,
			    rootnode->indirect_levels);

errout:
	free(buf);
	close_pager(pager);
}
Example #22
0
extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                                    ext2_ino_t ino)
{
    ext2_filsys fs = ctx->fs;
    struct ext2_inode	inode;
    int			inode_modified = 0;
    unsigned char		*frag, *fsize;
    struct problem_context	pctx;
    int	problem = 0;

    e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");

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

    if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
            !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
            !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
            !(LINUX_S_ISSOCK(inode.i_mode)))
        problem = PR_2_BAD_MODE;
    else if (LINUX_S_ISCHR(inode.i_mode)
             && !e2fsck_pass1_check_device_inode(&inode))
        problem = PR_2_BAD_CHAR_DEV;
    else if (LINUX_S_ISBLK(inode.i_mode)
             && !e2fsck_pass1_check_device_inode(&inode))
        problem = PR_2_BAD_BLOCK_DEV;
    else if (LINUX_S_ISFIFO(inode.i_mode)
             && !e2fsck_pass1_check_device_inode(&inode))
        problem = PR_2_BAD_FIFO;
    else if (LINUX_S_ISSOCK(inode.i_mode)
             && !e2fsck_pass1_check_device_inode(&inode))
        problem = PR_2_BAD_SOCKET;
    else if (LINUX_S_ISLNK(inode.i_mode)
             && !e2fsck_pass1_check_symlink(fs, &inode)) {
        problem = PR_2_SYMLINK_SIZE;
    }

    if (problem) {
        if (fix_problem(ctx, problem, &pctx)) {
            deallocate_inode(ctx, ino, 0);
            if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
                return 0;
            return 1;
        }
        problem = 0;
    }

    if (inode.i_faddr &&
            fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
        inode.i_faddr = 0;
        inode_modified++;
    }

    switch (fs->super->s_creator_os) {
    case EXT2_OS_LINUX:
        frag = &inode.osd2.linux2.l_i_frag;
        fsize = &inode.osd2.linux2.l_i_fsize;
        break;
    case EXT2_OS_HURD:
        frag = &inode.osd2.hurd2.h_i_frag;
        fsize = &inode.osd2.hurd2.h_i_fsize;
        break;
    case EXT2_OS_MASIX:
        frag = &inode.osd2.masix2.m_i_frag;
        fsize = &inode.osd2.masix2.m_i_fsize;
        break;
    default:
        frag = fsize = 0;
    }
    if (frag && *frag) {
        pctx.num = *frag;
        if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
            *frag = 0;
            inode_modified++;
        }
        pctx.num = 0;
    }
    if (fsize && *fsize) {
        pctx.num = *fsize;
        if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
            *fsize = 0;
            inode_modified++;
        }
        pctx.num = 0;
    }

    if (inode.i_file_acl &&
            !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
            fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
        inode.i_file_acl = 0;
        inode_modified++;
    }
    if (inode.i_file_acl &&
            ((inode.i_file_acl < fs->super->s_first_data_block) ||
             (inode.i_file_acl >= fs->super->s_blocks_count)) &&
            fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
        inode.i_file_acl = 0;
        inode_modified++;
    }
    if (inode.i_dir_acl &&
            LINUX_S_ISDIR(inode.i_mode) &&
            fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
        inode.i_dir_acl = 0;
        inode_modified++;
    }
    if (inode_modified)
        e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
    return 0;
}
Example #23
0
errcode_t ext2fs_move_blocks(ext2_filsys fs,
			     ext2fs_block_bitmap reserve,
			     ext2fs_block_bitmap alloc_map,
			     int flags)
{
	ext2_ino_t	ino;
	struct ext2_inode inode;
	errcode_t	retval;
	struct process_block_struct pb;
	ext2_inode_scan	scan;
	char		*block_buf;

	retval = ext2fs_open_inode_scan(fs, 0, &scan);
	if (retval)
		return retval;

	pb.reserve = reserve;
	pb.error = 0;
	pb.alloc_map = alloc_map ? alloc_map : fs->block_map;
	pb.flags = flags;

	retval = ext2fs_get_array(4, fs->blocksize, &block_buf);
	if (retval)
		return retval;
	pb.buf = block_buf + fs->blocksize * 3;

	/*
	 * If GET_DBLIST is set in the flags field, then we should
	 * gather directory block information while we're doing the
	 * block move.
	 */
	if (flags & EXT2_BMOVE_GET_DBLIST) {
		if (fs->dblist) {
			ext2fs_free_dblist(fs->dblist);
			fs->dblist = NULL;
		}
		retval = ext2fs_init_dblist(fs, 0);
		if (retval)
			return retval;
	}

	retval = ext2fs_get_next_inode(scan, &ino, &inode);
	if (retval)
		return retval;

	while (ino) {
		if ((inode.i_links_count == 0) ||
		    !ext2fs_inode_has_valid_blocks(&inode))
			goto next;

		pb.ino = ino;
		pb.inode = &inode;

		pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) &&
			      flags & EXT2_BMOVE_GET_DBLIST);

		retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
					      process_block, &pb);
		if (retval)
			return retval;
		if (pb.error)
			return pb.error;

	next:
		retval = ext2fs_get_next_inode(scan, &ino, &inode);
		if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
			goto next;
	}
	return 0;
}
Example #24
0
void addFilespec(FILE *fd, int squash_uids, int squash_perms)
{

	unsigned long rmode, mode, uid, gid, major, minor, i;
	unsigned long start, increment, count, octmode, decmode;
	char *c, *dir, *name, *dname = NULL, *path = NULL, *path2 = NULL, *line = NULL;
	char type;
	size_t len;
	int argv, i2, overWrite = 0, lineno = 0;
	__u16 inodeType;

	while ( getline(&line, &len, fd) >= 0 ) {
		rmode = mode = uid = gid = major = minor = start = count = overWrite = 0;
		increment = 1;
		lineno++;

		if (( c = strchr(line, '#'))) *c = 0;
		if ( path ) {
			free( path ); path = NULL;
		}
		if ( path2 ) {
			free( path2 ); path2 = NULL;
		}

		argv = sscanf(line, "%" SCANF_PREFIX "s %c %ld %lu %lu %lu %lu %lu %lu %lu",
			      SCANF_STRING(path), &type, &rmode, &uid, &gid, &major, &minor,
			      &start, &increment, &count);

		if ( argv < 3 ) {
			if ( argv > 0 )
				log_warning("device table[%d]: bad format for entry '%s' [skip]", lineno, path);
			continue;
		}

		i2 = 0;
		octmode = rmode;
		decmode = 0;
		while ( octmode != 0 ) {
			decmode = decmode + (octmode % 10) * pow(8, i2++);
			octmode = octmode / 10;
		}

		if ( squash_uids ) uid = gid = 0;

		mode = decmode;
		path2 = strdup( path );
		name = basename( path );
		dir = dirname( path2 );

		if (( !strcmp(name, ".")) || ( !strcmp(name, "..")) || ( !strcmp(name, "/"))) {
			log_warning("device table[%d]: [skip]", lineno);
			continue;
		}

		log_action(ACT_CHDIR, dir, NULL, 0, 0, 0, 0, 0, 0, 0);
		if ( !do_chdir(dir)) {
			log_warning("device table[%d]: target directory '%s' for entry '%s' does not exist [skip]", lineno, dir, name);
			log_action(ACT_CHDIR, "/", NULL, 0, 0, 0, 0, 0, 0, 0);
			if ( !do_chdir("/"))
				log_error("[Filesystem error] cannot chdir to root");
			continue;
		}

		if (( type != 'd' ) && ( type != 'f' ) && ( type != 'p' ) && ( type != 'c' ) && ( type != 'b' ) && ( type != 's')) {
			log_warning("device table[%d]: bad type '%c' for entry '%s' [skip]", lineno, type, name);
			continue;
		}

		if (squash_perms) {
			mode &= ~( LINUX_S_IRWXG | LINUX_S_IRWXO );
			rmode &= ~( LINUX_S_IRWXG | LINUX_S_IRWXO);
		}

		if ( count > 0 ) {

			if ( dname ) {
				free( dname );
				dname = NULL;
			}

			unsigned len;
			len = strlen(name) + 10;
			dname = malloc(len + 1);

			for ( i = start; i < count; i++ ) {
				snprintf(dname, len, "%s%lu", name, i);

				if (( overWrite = name_to_inode(dname)))
					inodeType = inode_mode(dname);

				if (( type == 'd' ) && ( overWrite ) && ( !LINUX_S_ISDIR(inodeType)))
					log_error("[Remote fs mismatch] %s/%s exists but isn't a directory when it should be.", log_cwd(), dname);
				else if (( type != 'd' ) && ( overWrite )) {

					if ( LINUX_S_ISDIR(inodeType))
						log_error("[Remote fs mismatch] %s/%s exists but is a directory when it shouldn't be.", log_cwd(), dname);

					if ((!LINUX_S_ISREG(inodeType)) && (!LINUX_S_ISLNK(inodeType)) &&
					    (!LINUX_S_ISBLK(inodeType)) && (!LINUX_S_ISCHR(inodeType)) &&
					    (!LINUX_S_ISFIFO(inodeType)) && (!LINUX_S_ISSOCK(inodeType)))
						log_error("[Remote fs mismatch] Existing file %s/%s has unknown/unsupported type [0x%x].", log_cwd(), dname, inodeType);
				}

				switch ( type ) {
				case 'd':
					mode |= LINUX_S_IFDIR;
					log_action(ACT_MKDIR, dname, NULL, 0, 0, 0, 0, 0, 0, overWrite);

					if ( !overWrite )
						if ( !do_mkdir(dname))
							log_error("[Filesystem error] cannot mkdir %s/%s", log_cwd(), dname);

					break;

				case 'c':
				case 'b':
					if ( type == 'c' )
						mode |= LINUX_S_IFCHR;
					else
						mode |= LINUX_S_IFBLK;

					if ( overWrite ) {
						log_action(ACT_RM, dname, NULL, 0, 0, 0, 0, 0, 0, overWrite);
						if ( !do_rm(dname))
							log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), dname);
					}

					log_action(ACT_MKNOD, dname, NULL, 0, 0, 0, type, major, minor + ((i * increment) - start), overWrite);
					if ( !do_mknod(dname, type, major, minor + ((i * increment) - start)))
						log_error("[Filesystem error] cannot mknod %s/%s", log_cwd(), dname);
					break;

				case 's':
				case 'p':
					if ( type == 's' )
						mode |= LINUX_S_IFSOCK;
					else mode |= LINUX_S_IFIFO;

					if ( overWrite ) {
						log_action(ACT_RM, dname, NULL, 0, 0, 0, 0, 0, 0, overWrite);
						if ( !do_rm(dname))
							log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), dname);
					}

					log_action(ACT_MKNOD, dname, NULL, 0, 0, 0, type, 0, 0, overWrite);
					if ( !do_mknod(dname, type, 0, 0))
						log_error("[Filesystem error] cannot mknod %s/%s", log_cwd(), dname);

					break;
				}

				log_action(ACT_CHMOD, dname, NULL, rmode, 0, 0, 0, 0, 0, 0);
				if ( !do_chmod(dname, rmode))
					log_error("[Filesystem error] cannot chmod %s/%s", log_cwd(), dname);
				log_action(ACT_CHOWN, dname, NULL, 0, uid, gid, 0, 0, 0, 0);
				if ( !do_chown(dname, uid, gid))
					log_error("[Filesystem error] cannot chown %s/%s", log_cwd(), dname);
			}

			log_action(ACT_CHDIR, "/", NULL, 0, 0, 0, 0, 0, 0, 0);
			if ( !do_chdir("/"))
				log_error("[Filesystem error] cannot chdir to root");
			free(dname);
			dname = NULL;

		} else {

			if (( overWrite = name_to_inode(name)))
				inodeType = inode_mode(name);

			if (( type == 'd' ) && ( overWrite ) && ( !LINUX_S_ISDIR(inodeType)))
				log_error("[Remote fs mismatch] %s/%s exists but isn't a directory when it should be.", log_cwd(), dname);
			else if ( type != 'd' ) {
				if (( overWrite ) && ( LINUX_S_ISDIR(inodeType)))
					log_error("[Remote fs mismatch] %s/%s exists but is a directory when it shouldn't be.", log_cwd(), dname);

				if (( overWrite ) && (!LINUX_S_ISREG(inodeType)) && (!LINUX_S_ISLNK(inodeType)) &&
				    (!LINUX_S_ISBLK(inodeType)) && (!LINUX_S_ISCHR(inodeType)) &&
				    (!LINUX_S_ISFIFO(inodeType)) && (!LINUX_S_ISSOCK(inodeType)))
					log_error("[Remote fs mismatch] Existing file %s/%s has unknown/unsupported type [0x%x].",  log_cwd(), dname, inodeType);
			}

			switch ( type ) {
			case 'd':
				mode |= LINUX_S_IFDIR;
				log_action(ACT_MKDIR, name, NULL, 0, 0, 0, 0, 0, 0, overWrite);

				if ( !overWrite )
					if ( !do_mkdir(name))
						log_error("[Filesystem error] cannot mkdir %s/%s", log_cwd(), name);
				break;

			case 'c':
			case 'b':
				if ( type == 'c' )
					mode |= LINUX_S_IFCHR;
				else
					mode |= LINUX_S_IFBLK;

				if ( overWrite ) {
					log_action(ACT_RM, name, NULL, 0, 0, 0, 0, 0, 0, overWrite);
					if ( !do_rm(name))
						log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), name);
				}

				log_action(ACT_MKNOD, name, NULL, 0, 0, 0, type, major, minor, overWrite);
				if ( !do_mknod(name, type, major, minor))
					log_error("[Filesystem error] cannot mknod %s/%s", log_cwd(), name);
				break;

			case 's':
			case 'p':
				if ( type == 's' )
					mode |= LINUX_S_IFSOCK;
				else mode |= LINUX_S_IFIFO;

				if ( overWrite ) {
					log_action(ACT_RM, name, NULL, 0, 0, 0, 0, 0, 0, overWrite);
					if ( !do_rm(name))
						log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), name);
				}

				log_action(ACT_MKNOD, name, NULL, 0, 0, 0, type, 0, 0, overWrite);
				if ( !do_mknod(name, type, 0, 0))
					log_error("[Filesystem error] cannot mknod %s/%s", log_cwd(), name);
				break;
			}

			log_action(ACT_CHMOD, name, NULL, rmode, 0, 0, 0, 0, 0, 0);
			if ( !do_chmod(name, rmode))
				log_error("[Filesystem error] cannot chmod %s/%s", log_cwd(), name);
			log_action(ACT_CHOWN, name, NULL, 0, uid, gid, 0, 0, 0, 0);
			if ( !do_chown(name, uid, gid))
				log_error("[Filesystem error] cannot chown %s/%s", log_cwd(), name);
			log_action(ACT_CHDIR, "/", NULL, 0, 0, 0, 0, 0, 0, 0);
			if ( !do_chdir("/"))
				log_error("[Filesystem error] cannot chdir to root");
		}

	}


	if ( line ) {
		free( line ); line = NULL;
	}
	if ( path ) {
		free( path ); path = NULL;
	}
	if ( path2 ) {
		free( path2 ); path2 = NULL;
	}

}
static int fat_unformat_aux(struct ph_param *params, const struct ph_options *options, const uint64_t start_offset, alloc_data_t *list_search_space)
{
  int ind_stop=0;
  uint64_t offset;
  uint64_t offset_end;
  unsigned char *buffer_start;
  unsigned char *buffer;
  time_t start_time;
  time_t previous_time;
  const unsigned int blocksize=params->blocksize;
  const unsigned int read_size=(blocksize>65536?blocksize:65536);
  alloc_data_t *current_search_space;
  file_recovery_t file_recovery;
  disk_t *disk=params->disk;
  const partition_t *partition=params->partition;

  reset_file_recovery(&file_recovery);
  file_recovery.blocksize=blocksize;
  buffer_start=(unsigned char *)MALLOC(READ_SIZE);
  buffer=buffer_start;
  start_time=time(NULL);
  previous_time=start_time;
  current_search_space=td_list_entry(list_search_space->list.prev, alloc_data_t, list);
  if(current_search_space==list_search_space)
  {
    free(buffer_start);
    return 0;
  }
  offset_end=current_search_space->end;
  current_search_space=td_list_entry(list_search_space->list.next, alloc_data_t, list);
  offset=set_search_start(params, &current_search_space, list_search_space);
  if(options->verbose>0)
    info_list_search_space(list_search_space, current_search_space, disk->sector_size, 0, options->verbose);
  disk->pread(disk, buffer, READ_SIZE, offset);
  for(;offset < offset_end; offset+=blocksize)
  {
    if(memcmp(buffer,         ".          ", 8+3)==0 &&
	memcmp(&buffer[0x20], "..         ", 8+3)==0)
    {
      file_data_t *dir_list;
      dir_list=dir_fat_aux(buffer,read_size,0,0);
      if(dir_list!=NULL)
      {
	const file_data_t *current_file;
	log_info("Sector %llu\n", (long long unsigned)offset/disk->sector_size);
	dir_aff_log(NULL, dir_list);
	del_search_space(list_search_space, offset, offset + blocksize -1);
	current_file=dir_list;
	while(current_file!=NULL)
	{
	  if(strcmp(current_file->name,".")==0 &&
	      LINUX_S_ISDIR(current_file->stat.st_mode)!=0 &&
	      current_file!=dir_list)
	    current_file=NULL;
	  else if(current_file->stat.st_ino>2 &&
	      LINUX_S_ISREG(current_file->stat.st_mode)!=0)
	  {
	    const uint64_t file_start=start_offset + (uint64_t)(current_file->stat.st_ino - 2) * blocksize;
#ifdef DJGPP
	    const uint64_t file_end=file_start+(current_file->file_size+blocksize-1)/blocksize*blocksize - 1;
#else
	    const uint64_t file_end=file_start+(current_file->stat.st_size+blocksize-1)/blocksize*blocksize - 1;
#endif
	    if(file_end < partition->part_offset + partition->part_size)
	    {
	      if(fat_copy_file(disk, partition, blocksize, start_offset, params->recup_dir, params->dir_num, current_file)==0)
	      {
		params->file_nbr++;
		del_search_space(list_search_space, file_start, file_end);
	      }
	      current_file=current_file->next;
	    }
	    else
	      current_file=NULL;
	  }
	  else
	    current_file=current_file->next;
	}
	delete_list_file(dir_list);
      }
    }
    buffer+=blocksize;
    if(buffer+read_size>buffer_start+READ_SIZE)
    {
      buffer=buffer_start;
      if(options->verbose>1)
      {
        log_verbose("Reading sector %10llu/%llu\n",
	    (unsigned long long)((offset-partition->part_offset)/disk->sector_size),
	    (unsigned long long)((partition->part_size-1)/disk->sector_size));
      }
      if(disk->pread(disk, buffer, READ_SIZE, offset) != READ_SIZE)
      {
#ifdef HAVE_NCURSES
	wmove(stdscr,11,0);
	wclrtoeol(stdscr);
	wprintw(stdscr,"Error reading sector %10lu\n",
	    (unsigned long)((offset-partition->part_offset)/disk->sector_size));
#endif
      }
#ifdef HAVE_NCURSES
      {
        time_t current_time;
        current_time=time(NULL);
        if(current_time>previous_time)
        {
	  const time_t elapsed_time=current_time - params->real_start_time;
          previous_time=current_time;
	  wmove(stdscr,9,0);
	  wclrtoeol(stdscr);
	  log_info("Reading sector %10llu/%llu, %u files found\n",
	      (unsigned long long)((offset-partition->part_offset)/disk->sector_size),
	      (unsigned long long)(partition->part_size/disk->sector_size), params->file_nbr);
	  wprintw(stdscr,"Reading sector %10llu/%llu, %u files found\n",
	      (unsigned long long)((offset-partition->part_offset)/disk->sector_size),
	      (unsigned long long)(partition->part_size/disk->sector_size), params->file_nbr);
	  wmove(stdscr,10,0);
	  wclrtoeol(stdscr);
	  wprintw(stdscr,"Elapsed time %uh%02um%02us",
	      (unsigned)(elapsed_time/60/60),
	      (unsigned)(elapsed_time/60%60),
	      (unsigned)(elapsed_time%60));
	  if(offset-partition->part_offset!=0)
	  {
	    wprintw(stdscr," - Estimated time to completion %uh%02um%02u\n",
		(unsigned)((partition->part_offset+partition->part_size-1-offset)*elapsed_time/(offset-partition->part_offset)/3600),
		(unsigned)(((partition->part_offset+partition->part_size-1-offset)*elapsed_time/(offset-partition->part_offset)/60)%60),
		(unsigned)((partition->part_offset+partition->part_size-1-offset)*elapsed_time/(offset-partition->part_offset))%60);
	  }
	  wrefresh(stdscr);
	  if(check_enter_key_or_s(stdscr))
	  {
	    log_info("PhotoRec has been stopped\n");
	    params->offset=offset;
	    offset = offset_end;
	    ind_stop=1;
	  }
	}
      }
#endif
    }
  }
  free(buffer_start);
  return ind_stop;
}
/*
 * This fuction deallocates an inode
 */
static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
{
	ext2_filsys fs = ctx->fs;
	struct ext2_inode	inode;
	struct problem_context	pctx;
	__u32			count;
	struct del_block	del_block;

	e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
	clear_problem_context(&pctx);
	pctx.ino = ino;

	/*
	 * Fix up the bitmaps...
	 */
	e2fsck_read_bitmaps(ctx);
	ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));

	if (ext2fs_file_acl_block(fs, &inode) &&
	    (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
		pctx.errcode = ext2fs_adjust_ea_refcount2(fs,
					ext2fs_file_acl_block(fs, &inode),
					block_buf, -1, &count);
		if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
			pctx.errcode = 0;
			count = 1;
		}
		if (pctx.errcode) {
			pctx.blk = ext2fs_file_acl_block(fs, &inode);
			fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
			ctx->flags |= E2F_FLAG_ABORT;
			return;
		}
		if (count == 0) {
			ext2fs_unmark_block_bitmap2(ctx->block_found_map,
					ext2fs_file_acl_block(fs, &inode));
			ext2fs_block_alloc_stats2(fs,
				  ext2fs_file_acl_block(fs, &inode), -1);
		}
		ext2fs_file_acl_block_set(fs, &inode, 0);
	}

	if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
		goto clear_inode;

	if (LINUX_S_ISREG(inode.i_mode) &&
	    ext2fs_needs_large_file_feature(EXT2_I_SIZE(&inode)))
		ctx->large_files--;

	del_block.ctx = ctx;
	del_block.num = 0;
	pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf,
					     deallocate_inode_block,
					     &del_block);
	if (pctx.errcode) {
		fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
		ctx->flags |= E2F_FLAG_ABORT;
		return;
	}
clear_inode:
	/* Inode may have changed by block_iterate, so reread it */
	e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
	e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode");
}
Example #27
0
void do_htree_dump(int argc, char *argv[])
{
	ext2_ino_t	ino;
	struct ext2_inode inode;
	int		c;
	int		long_opt = 0;
	blk_t		blk;
	char		*buf = NULL;
	struct 		ext2_dx_root_info  *rootnode;
	struct 		ext2_dx_entry *ent;
	struct		ext2_dx_countlimit *limit;
	errcode_t	errcode;

	if (check_fs_open(argv[0]))
		return;

	pager = open_pager();

	reset_getopt();
	while ((c = getopt (argc, argv, "l")) != EOF) {
		switch (c) {
		case 'l':
			long_opt++;
			break;
		default:
			goto print_usage;
		}
	}

	if (argc > optind+1) {
	print_usage:
		com_err(0, 0, "Usage: htree_dump [-l] file");
		goto errout;
	}

	if (argc == optind)
		ino = cwd;
	else
		ino = string_to_inode(argv[optind]);
	if (!ino)
		goto errout;

	if (debugfs_read_inode(ino, &inode, argv[1]))
		goto errout;

	if (!LINUX_S_ISDIR(inode.i_mode)) {
		com_err(argv[0], 0, "Not a directory");
		goto errout;
	}

	if ((inode.i_flags & EXT2_BTREE_FL) == 0) {
		com_err(argv[0], 0, "Not a hash-indexed directory");
		goto errout;
	}

	buf = malloc(2*current_fs->blocksize);
	if (!buf) {
		com_err(argv[0], 0, "Couldn't allocate htree buffer");
		goto errout;
	}

	errcode = ext2fs_bmap(current_fs, ino, &inode, buf, 0, 0, &blk);
	if (errcode) {
		com_err("do_htree_block", errcode,
			"while mapping logical block 0\n");
		goto errout;
	}

	errcode = io_channel_read_blk(current_fs->io, blk,
				      1, buf);
	if (errcode) {
		com_err(argv[0], errcode, "Error reading root node");
		goto errout;
	}

	rootnode = (struct ext2_dx_root_info *) (buf + 24);

	fprintf(pager, "Root node dump:\n");
	fprintf(pager, "\t Reserved zero: %u\n", rootnode->reserved_zero);
	fprintf(pager, "\t Hash Version: %d\n", rootnode->hash_version);
	fprintf(pager, "\t Info length: %d\n", rootnode->info_length);
	fprintf(pager, "\t Indirect levels: %d\n", rootnode->indirect_levels);
	fprintf(pager, "\t Flags: %d\n", rootnode->unused_flags);

	ent = (struct ext2_dx_entry *) (buf + 24 + rootnode->info_length);
	limit = (struct ext2_dx_countlimit *) ent;

	htree_dump_int_node(current_fs, ino, &inode, rootnode, ent,
			    buf + current_fs->blocksize,
			    rootnode->indirect_levels);

errout:
	free(buf);
	close_pager(pager);
}
Example #28
0
/*
 * This routine is called when an inode is not connected to the
 * directory tree.
 *
 * This subroutine returns 1 then the caller shouldn't bother with the
 * rest of the pass 4 tests.
 */
static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i,
			    struct ext2_inode *inode)
{
	ext2_filsys fs = ctx->fs;
	struct problem_context	pctx;
	__u32 eamagic = 0;
	int extra_size = 0;

	if (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE) {
		e2fsck_read_inode_full(ctx, i, inode,EXT2_INODE_SIZE(fs->super),
				       "pass4: disconnect_inode");
		extra_size = ((struct ext2_inode_large *)inode)->i_extra_isize;
	} else {
		e2fsck_read_inode(ctx, i, inode, "pass4: disconnect_inode");
	}
	clear_problem_context(&pctx);
	pctx.ino = i;
	pctx.inode = inode;

	if (EXT2_INODE_SIZE(fs->super) -EXT2_GOOD_OLD_INODE_SIZE -extra_size >0)
		eamagic = *(__u32 *)(((char *)inode) +EXT2_GOOD_OLD_INODE_SIZE +
				     extra_size);
	/*
	 * Offer to delete any zero-length files that does not have
	 * blocks.  If there is an EA block, it might have useful
	 * information, so we won't prompt to delete it, but let it be
	 * reconnected to lost+found.
	 */
	if (!inode->i_blocks && eamagic != EXT2_EXT_ATTR_MAGIC &&
	    (LINUX_S_ISREG(inode->i_mode) || LINUX_S_ISDIR(inode->i_mode))) {
		if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
			e2fsck_clear_inode(ctx, i, inode, 0,
					   "disconnect_inode");
			/*
			 * Fix up the bitmaps...
			 */
			e2fsck_read_bitmaps(ctx);
			ext2fs_inode_alloc_stats2(fs, i, -1,
						  LINUX_S_ISDIR(inode->i_mode));
			quota_data_inodes(ctx->qctx, inode, i, -1);
			return 0;
		}
	}

	/*
	 * Prompt to reconnect.
	 */
	if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
		if (e2fsck_reconnect_file(ctx, i))
			ext2fs_unmark_valid(fs);
	} else {
		/*
		 * If we don't attach the inode, then skip the
		 * i_links_test since there's no point in trying to
		 * force i_links_count to zero.
		 */
		ext2fs_unmark_valid(fs);
		return 1;
	}
	return 0;
}
Example #29
0
int ext2_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode)
{
    //ext2_log_trace("fileStruct %p, path %s, flags %i, mode %i\n", fileStruct, path, flags, mode);

    ext2_file_state* file = STATE(fileStruct);

    // Get the volume descriptor for this path
    file->vd = ext2GetVolume(path);
    if (!file->vd) {
        r->_errno = ENODEV;
        return -1;
    }

    // Lock
    ext2Lock(file->vd);

    // Determine which mode the file is opened for
    file->flags = flags;
    if ((flags & 0x03) == O_RDONLY) {
        file->read = true;
        file->write = false;
        file->append = false;
    } else if ((flags & 0x03) == O_WRONLY) {
        file->read = false;
        file->write = true;
        file->append = (flags & O_APPEND);
    } else if ((flags & 0x03) == O_RDWR) {
        file->read = true;
        file->write = true;
        file->append = (flags & O_APPEND);
    } else {
        r->_errno = EACCES;
        ext2Unlock(file->vd);
        return -1;
    }

    // Try and find the file and (if found) ensure that it is not a directory
    file->ni = ext2OpenEntry(file->vd, path);
    if (file->ni && LINUX_S_ISDIR(file->ni->ni.i_mode))
    {
        ext2CloseEntry(file->vd, file->ni);
        ext2Unlock(file->vd);
        r->_errno = EISDIR;
        return -1;
    }

    // Are we creating this file?
    if ((flags & O_CREAT) && !file->ni)
        // Create the file
        file->ni = ext2Create(file->vd, path, S_IFREG, NULL);
   // exit(0);
    // Sanity check, the file should be open by now
    if (!file->ni) {
        ext2Unlock(file->vd);
        r->_errno = ENOENT;
        return -1;
    }

    // Make sure we aren't trying to write to a read-only file
    if (!(file->vd->fs->flags & EXT2_FLAG_RW) && file->write)
    {
        ext2CloseEntry(file->vd, file->ni);
        ext2Unlock(file->vd);
        r->_errno = EROFS;
        return -1;
    }

    errcode_t err = ext2fs_file_open2(file->vd->fs, file->ni->ino, &file->ni->ni,
                                      file->write ? EXT2_FLAG_RW : 0, &file->fd);
    if(err != 0)
    {
        ext2CloseEntry(file->vd, file->ni);
        ext2Unlock(file->vd);
        r->_errno = ENOENT;
        return -1;
    }


    // Truncate the file if requested
    if ((flags & O_TRUNC) && file->write) {
        if (ext2fs_file_set_size2(file->fd, 0) != 0) {
            ext2CloseEntry(file->vd, file->ni);
            ext2Unlock(file->vd);
            r->_errno = errno;
            return -1;
        }
        file->ni->ni.i_size = file->ni->ni.i_size_high = 0;
    }

    // Set the files current position
	ext2fs_file_llseek(file->fd, file->append ? EXT2_I_SIZE(&file->ni->ni) : 0, SEEK_SET, 0);

    //ext2_log_trace("file->len %lld\n", EXT2_I_SIZE(&file->ni->ni));

    // Update file times
    ext2UpdateTimes(file->vd, file->ni, EXT2_UPDATE_ATIME);

    // Insert the file into the double-linked FILO list of open files
    if (file->vd->firstOpenFile) {
        file->nextOpenFile = file->vd->firstOpenFile;
        file->vd->firstOpenFile->prevOpenFile = file;
    } else {
        file->nextOpenFile = NULL;
    }
    file->prevOpenFile = NULL;
    file->vd->firstOpenFile = file;
    file->vd->openFileCount++;

    // Sync access time
    ext2Sync(file->vd, file->ni);

    file->is_ntfs = 0;

    // Unlock
    ext2Unlock(file->vd);

    return (int)(s64)fileStruct;
}
Example #30
0
static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, file_data_t*dir_list, const unsigned long int inode, const unsigned int depth)
{
  /* Return value
   * -1: quit
   *  1: back
   *  other: new inode
   * */
  int quit=0;
  WINDOW *window=(WINDOW*)dir_data->display;
  do
  {
    int offset=0;
    int pos_num=0;
    file_data_t *pos=dir_list;
    int old_LINES=LINES;
    unsigned int status=FILE_STATUS_MARKED;
    aff_copy(window);
    wmove(window,3,0);
    aff_part(window, AFF_PART_ORDER|AFF_PART_STATUS, disk, partition);
    wmove(window,4,0);
    wprintw(window,"Directory %s\n",dir_data->current_directory);
    do
    {
      int i;
      int car;
      const file_data_t *current_file;
      for(i=0,current_file=dir_list;(current_file!=NULL) && (i<offset);current_file=current_file->next,i++);
      for(i=offset;(current_file!=NULL) &&((i-offset)<INTER_DIR);i++,current_file=current_file->next)
      {
	char str[11];
	char		datestr[80];
	wmove(window, 6+i-offset, 0);
	wclrtoeol(window);	/* before addstr for BSD compatibility */
	if(current_file==pos)
	{
	  wattrset(window, A_REVERSE);
	  waddstr(window, ">");
	}
	else
	  waddstr(window, " ");
	if((current_file->status&FILE_STATUS_DELETED)!=0 && has_colors())
	  wbkgdset(window,' ' | COLOR_PAIR(1));
	else if((current_file->status&FILE_STATUS_MARKED)!=0 && has_colors())
	  wbkgdset(window,' ' | COLOR_PAIR(2));
	if(current_file->td_mtime!=0)
	{
	  struct tm		*tm_p;
	  tm_p = localtime(&current_file->td_mtime);
	  snprintf(datestr, sizeof(datestr),"%2d-%s-%4d %02d:%02d",
	      tm_p->tm_mday, monstr[tm_p->tm_mon],
	      1900 + tm_p->tm_year, tm_p->tm_hour,
	      tm_p->tm_min);
	  /* May have to use %d instead of %e */
	} else {
	  strncpy(datestr, "                 ",sizeof(datestr));
	}
	mode_string(current_file->st_mode, str);
	wprintw(window, "%s %5u %5u ", 
	    str, (unsigned int)current_file->st_uid, (unsigned int)current_file->st_gid);
	wprintw(window, "%9llu", (long long unsigned int)current_file->st_size);
	/* screen may overlap due to long filename */
	wprintw(window, " %s %s", datestr, current_file->name);
	if(((current_file->status&FILE_STATUS_DELETED)!=0 ||
	      (current_file->status&FILE_STATUS_MARKED)!=0) && has_colors())
	  wbkgdset(window,' ' | COLOR_PAIR(0));
	if(current_file==pos)
	  wattroff(window, A_REVERSE);
      }
      wmove(window, 6-1, 51);
      wclrtoeol(window);
      if(offset>0)
	wprintw(window, "Previous");
      /* Clear the last line, useful if overlapping */
      wmove(window,6+i-offset,0);
      wclrtoeol(window);
      wmove(window, 6+INTER_DIR, 51);
      wclrtoeol(window);
      if(current_file!=NULL)
	wprintw(window, "Next");
      if(dir_list==NULL)
      {
	wmove(window,6,0);
	wprintw(window,"No file found, filesystem may be damaged.");
      }
      /* Redraw the bottom of the screen everytime because very long filenames may have corrupt it*/
      mvwaddstr(window,LINES-3,0,"Use ");
      if(depth>0)
      {
	if(has_colors())
	  wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
	waddstr(window, "Left");
	if(has_colors())
	  wbkgdset(window,' ' | COLOR_PAIR(0));
	waddstr(window," arrow to go back, ");
      }
      if(has_colors())
	wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
      waddstr(window,"Right");
      if(has_colors())
	wbkgdset(window,' ' | COLOR_PAIR(0));
      waddstr(window," to change directory");
      if((dir_data->capabilities&CAPA_LIST_DELETED)!=0)
      {
	waddstr(window,", ");
	if(has_colors())
	  wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
	waddstr(window,"h");
	if(has_colors())
	  wbkgdset(window,' ' | COLOR_PAIR(0));
	if((dir_data->param&FLAG_LIST_DELETED)==0)
	  waddstr(window," to unhide deleted files");
	else
	  waddstr(window," to hide deleted files");
      }
      wmove(window,LINES-2,4);
      if(has_colors())
	wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
      waddstr(window,"q");
      if(has_colors())
	wbkgdset(window,' ' | COLOR_PAIR(0));
      waddstr(window," to quit");
      if(dir_data->copy_file!=NULL)
      {
	waddstr(window,", ");
	if(has_colors())
	  wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
	waddstr(window,":");
	if(has_colors())
	  wbkgdset(window,' ' | COLOR_PAIR(0));
	waddstr(window," to select the current file, ");
	if(has_colors())
	  wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
	waddstr(window,"a");
	if(has_colors())
	  wbkgdset(window,' ' | COLOR_PAIR(0));
	if((status&FILE_STATUS_MARKED)==FILE_STATUS_MARKED)
	  waddstr(window," to select all files  ");
	else
	  waddstr(window," to deselect all files");
	if(has_colors())
	  wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
	mvwaddstr(window,LINES-1,4,"C");
	if(has_colors())
	  wbkgdset(window,' ' | COLOR_PAIR(0));
	waddstr(window," to copy the selected files, ");
	if(has_colors())
	  wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
	waddstr(window,"c");
	if(has_colors())
	  wbkgdset(window,' ' | COLOR_PAIR(0));
	waddstr(window," to copy the current file");
      }
      wrefresh(window);
      /* Using gnome terminal under FC3, TERM=xterm, the screen is not always correct */
      wredrawln(window,0,getmaxy(window));	/* redrawwin def is boggus in pdcur24 */
      car=wgetch(window);
      wmove(window,5,0);
      wclrtoeol(window);
      switch(car)
      {
	case key_ESC:
	case 'q':
	case 'M':
	  quit=1;
	  break;
	case '-':
	case KEY_LEFT:
	case '4':
	  if(depth>0)
	    return 1;
	  break;
	case 'h':
	  if((dir_data->capabilities&CAPA_LIST_DELETED)!=0)
	    dir_data->param^=FLAG_LIST_DELETED;
	  return inode;
      }
      if(dir_list!=NULL)
      {
	switch(car)
	{
	  case KEY_UP:
	  case '8':
	    if(pos->prev!=NULL)
	    {
	      pos=pos->prev;
	      pos_num--;
	    }
	    break;
	  case KEY_DOWN:
	  case '2':
	    if(pos->next!=NULL)
	    {
	      pos=pos->next;
	      pos_num++;
	    }
	    break;
	  case ':':
	    if(!(pos->name[0]=='.' && pos->name[1]=='\0') &&
		!(pos->name[0]=='.' && pos->name[1]=='.' && pos->name[2]=='\0'))
	    pos->status^=FILE_STATUS_MARKED;
	    if(pos->next!=NULL)
	    {
	      pos=pos->next;
	      pos_num++;
	    }
	    break;
	  case 'a':
	    {
	      file_data_t *tmp;
	      for(tmp=dir_list; tmp!=NULL; tmp=tmp->next)
	      {
		if((tmp->name[0]=='.' && tmp->name[1]=='\0') ||
		    (tmp->name[0]=='.' && tmp->name[1]=='.' && tmp->name[2]=='\0'))
		{
		  tmp->status&=~FILE_STATUS_MARKED;
		}
		else
		{
		  if((tmp->status & FILE_STATUS_MARKED)!=status)
		    tmp->status^=FILE_STATUS_MARKED;
		}
	      }
	      status^=FILE_STATUS_MARKED;
	    }
	    break;
	  case 'p':
	  case 'P':
	  case '+':
	  case ' ':
	  case KEY_RIGHT:
	  case '\r':
	  case '\n':
	  case '6':
	  case KEY_ENTER:
#ifdef PADENTER
	  case PADENTER:
#endif
	    if((pos!=NULL) && (LINUX_S_ISDIR(pos->st_mode)!=0))
	    {
	      unsigned long int new_inode=pos->st_ino;
	      if((new_inode!=inode) &&(strcmp(pos->name,".")!=0))
	      {
		if(strcmp(pos->name,"..")==0)
		  return 1;
		if(strlen(dir_data->current_directory)+1+strlen(pos->name)+1<=sizeof(dir_data->current_directory))
		{
		  if(strcmp(dir_data->current_directory,"/"))
		    strcat(dir_data->current_directory,"/");
		  strcat(dir_data->current_directory,pos->name);
		  return (long int)new_inode;
		}
	      }
	    }
	    break;
	  case KEY_PPAGE:
	    for(i=0;(i<INTER_DIR-1)&&(pos->prev!=NULL);i++)
	    {
	      pos=pos->prev;
	      pos_num--;
	    }
	    break;
	  case KEY_NPAGE:
	    for(i=0;(i<INTER_DIR-1)&&(pos->next!=NULL);i++)
	    {
	      pos=pos->next;
	      pos_num++;
	    }
	    break;
	  case 'c':
	    if(dir_data->copy_file!=NULL)
	    {
	      const unsigned int current_directory_namelength=strlen(dir_data->current_directory);
	      if(strcmp(pos->name,"..")!=0 &&
		  current_directory_namelength+1+strlen(pos->name)<sizeof(dir_data->current_directory)-1)
	      {
		if(strcmp(dir_data->current_directory,"/"))
		  strcat(dir_data->current_directory,"/");
		if(strcmp(pos->name,".")!=0)
		  strcat(dir_data->current_directory,pos->name);
		if(dir_data->local_dir==NULL)
		{
		  if(LINUX_S_ISDIR(pos->st_mode)!=0)
		    dir_data->local_dir=ask_location("Please select a destination where %s and any files below will be copied.",
			dir_data->current_directory, NULL);
		  else
		    dir_data->local_dir=ask_location("Please select a destination where %s will be copied.",
			dir_data->current_directory, NULL);
		}
		if(dir_data->local_dir!=NULL)
		{
		  int res=-1;
		  wmove(window,5,0);
		  wclrtoeol(window);
		  if(has_colors())
		    wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1));
		  wprintw(window,"Copying, please wait...");
		  if(has_colors())
		    wbkgdset(window,' ' | COLOR_PAIR(0));
		  wrefresh(window);
		  if(LINUX_S_ISDIR(pos->st_mode)!=0)
		  {
		    res=copy_dir(disk, partition, dir_data, pos);
		  }
		  else if(LINUX_S_ISREG(pos->st_mode)!=0)
		  {
		    res=dir_data->copy_file(disk, partition, dir_data, pos);
		  }
		  wmove(window,5,0);
		  wclrtoeol(window);
		  if(res < -1)
		  {
		    if(has_colors())
		      wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1));
		    wprintw(window,"Copy failed!");
		  }
		  else
		  {
		    if(has_colors())
		      wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(2));
		    if(res < 0)
		      wprintw(window,"Copy done! (Failed to copy some files)");
		    else
		      wprintw(window,"Copy done!");
		  }
		  if(has_colors())
		    wbkgdset(window,' ' | COLOR_PAIR(0));
		}
		dir_data->current_directory[current_directory_namelength]='\0';
	      }
	    }
	    break;
	  case 'C':
	    if(dir_data->copy_file!=NULL)
	    {
	      if(dir_data->local_dir==NULL)
	      {
		dir_data->local_dir=ask_location("Please select a destination where the marked files will be copied.", NULL, NULL);
	      }
	      if(dir_data->local_dir!=NULL)
	      {
		file_data_t *tmp;
		int copy_bad=0;
		int copy_ok=0;
		const unsigned int current_directory_namelength=strlen(dir_data->current_directory);
		wmove(window,5,0);
		wclrtoeol(window);
		if(has_colors())
		  wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1));
		wprintw(window,"Copying, please wait...");
		if(has_colors())
		  wbkgdset(window,' ' | COLOR_PAIR(0));
		wrefresh(window);
		for(tmp=dir_list; tmp!=NULL; tmp=tmp->next)
		{
		  if((tmp->status&FILE_STATUS_MARKED)!=0 &&
		      current_directory_namelength + 1 + strlen(tmp->name) <
		      sizeof(dir_data->current_directory)-1)
		  {
		    if(strcmp(dir_data->current_directory,"/"))
		      strcat(dir_data->current_directory,"/");
		    if(strcmp(tmp->name,".")!=0)
		      strcat(dir_data->current_directory,tmp->name);
		    if(LINUX_S_ISDIR(tmp->st_mode)!=0)
		    {
		      const int res=copy_dir(disk, partition, dir_data, tmp);
		      if(res >=-1)
		      {
			tmp->status&=~FILE_STATUS_MARKED;
			copy_ok=1;
		      }
		      else if(res < 0)
			copy_bad=1;
		    }
		    else if(LINUX_S_ISREG(tmp->st_mode)!=0)
		    {
		      if(dir_data->copy_file(disk, partition, dir_data, tmp) == 0)
		      {
			tmp->status&=~FILE_STATUS_MARKED;
			copy_ok=1;
		      }
		      else
			copy_bad=1;
		    }
		  }
		  dir_data->current_directory[current_directory_namelength]='\0';
		}
		wmove(window,5,0);
		wclrtoeol(window);
		if(copy_bad > 0 && copy_ok==0)
		{
		  if(has_colors())
		    wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1));
		  wprintw(window,"Copy failed!");
		}
		else
		{
		  if(has_colors())
		    wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(2));
		  if(copy_bad > 0)
		    wprintw(window,"Copy done! (Failed to copy some files)");
		  else if(copy_ok == 0)
		    wprintw(window,"No file selected");
		  else
		    wprintw(window,"Copy done!");
		}
		if(has_colors())
		  wbkgdset(window,' ' | COLOR_PAIR(0));
	      }
	    }
	    break;	
	  case 'f':
	    {
	      const char *needle=ask_string_ncurses("Filename to find ? ");
	      if(needle!=NULL && needle[0]!='\0')
	      {
		file_data_t *pos_org=pos;
		const int pos_num_org=pos_num;
		while(strcmp(pos->name, needle)!=0 && pos->next!=NULL)
		{
		  pos=pos->next;
		  pos_num++;
		}
		if(strcmp(pos->name, needle)!=0)
		{
		  pos=pos_org;
		  pos_num=pos_num_org;
		}
	      }
	    }
	    break;
	}
	if(pos_num<offset)
	  offset=pos_num;
	if(pos_num>=offset+INTER_DIR)
	  offset=pos_num-INTER_DIR+1;
      }
    } while(quit==0 && old_LINES==LINES);
  } while(quit==0);
  return -1;
}