+1998-03-21 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2fs.h: Add new superblock fields (s_algorithm_usage_bitmap,
+ s_prealloc_blocks, s_prealloc_dir_blocks). Added
+ conditional defines of new features COMPAT_DIR_PREALLOC,
+ RO_COMPAT_LARGE_FILE RO_COMPAT_BTREE_DIR,
+ INCOMPAT_COMPRESSION, INCOMPAT_DIRNAME_SIZE. Changed
+ the library to declare that we support COMPAT_DIR_PREALLOC,
+ INCOMPAT_DIRNAME_SIZE, RO_COMPAT_LARGE_FILE.
+
+ * fileio.c: Rename function ext2fs_file_llseek to be
+ ext2fs_file_lseek, which is more accurate.
+
+ * block.c: Add new function ext2fs_block_iterate3 which calls
+ the iterator function with the blockcount argument of
+ type blkcnt_t. This version of the function is
+ allowed to handle large files; the other fucntions are
+ not.
+
+ * ext2fs.h: Add new type blkcnt_t
+
+ * ext2_err.et.in: Add error code EXT2_ET_FILE_TOO_BIG
+
+ * block.c (ext2fs_block_iterate2): Fix bug where the block count
+ field wasn't getting correctly incremented for sparse
+ files when the indirect or doubly-indirect block
+ specified in the inode was zero.
+
+Sun Mar 8 22:42:47 1998 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * unlink.c (unlink_proc):
+ * lookup.c (lookup_proc):
+ * link.c (link_proc):
+ * get_pathname.c (get_pathname_proc):
+ * dir_iterate.c (ext2fs_process_dir_block): Mask off high 8 bits
+ from dirent->name_len, so it can be used for other
+ purposes.
+
+ * ext2fs.h: Add definition of EXT2_FEATURE_INCOMPAT_DIRNAME_SIZE,
+ and indicate that we have support for this incompatible
+ option.
+
Mon Feb 23 08:46:33 1998 Theodore Ts'o <tytso@rsts-11.mit.edu>
* ext2_err.et.in: Added new error code, EXT2_ET_CANCEL_REQUESTED.
ext2_filsys fs;
int (*func)(ext2_filsys fs,
blk_t *blocknr,
- int bcount,
+ blkcnt_t bcount,
blk_t ref_blk,
int ref_offset,
void *priv_data);
- int bcount;
+ blkcnt_t bcount;
int bsize;
int flags;
errcode_t errcode;
return ret;
}
-errcode_t ext2fs_block_iterate2(ext2_filsys fs,
+errcode_t ext2fs_block_iterate3(ext2_filsys fs,
ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
blk_t *blocknr,
- int blockcnt,
+ blkcnt_t blockcnt,
blk_t ref_blk,
int ref_offset,
void *priv_data),
struct ext2_inode inode;
errcode_t retval;
struct block_context ctx;
+ int limit;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+ /*
+ * Check to see if we need to limit large files
+ */
+ if (flags & BLOCK_FLAG_NO_LARGE) {
+ ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
+ if (ctx.errcode)
+ goto abort;
+ got_inode = 1;
+ if (!LINUX_S_ISDIR(inode.i_mode) &&
+ (inode.i_size_high != 0))
+ return EXT2_ET_FILE_TOO_BIG;
+ }
+
retval = ext2fs_get_blocks(fs, ino, blocks);
if (retval)
return retval;
+ limit = fs->blocksize >> 2;
+
ctx.fs = fs;
ctx.func = func;
ctx.priv_data = priv_data;
0, 0, &ctx);
if (ret & BLOCK_ABORT)
goto abort;
- }
+ } else
+ ctx.bcount += limit;
if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK,
0, 0, &ctx);
if (ret & BLOCK_ABORT)
goto abort;
- }
+ } else
+ ctx.bcount += limit * limit;
if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK,
0, 0, &ctx);
return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
}
+/*
+ * Emulate the old ext2fs_block_iterate function!
+ */
+
struct xlate {
int (*func)(ext2_filsys fs,
blk_t *blocknr,
#ifdef __TURBOC__
#pragma argsused
#endif
-static int xlate_func(ext2_filsys fs, blk_t *blocknr, int blockcnt,
+static int xlate_func(ext2_filsys fs, blk_t *blocknr, blkcnt_t blockcnt,
blk_t ref_block, int ref_offset, void *priv_data)
{
struct xlate *xl = (struct xlate *) priv_data;
- return (*xl->func)(fs, blocknr, blockcnt, xl->real_private);
+ return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private);
}
errcode_t ext2fs_block_iterate(ext2_filsys fs,
xl.real_private = priv_data;
xl.func = func;
- return ext2fs_block_iterate2(fs, ino, flags, block_buf,
- xlate_func, &xl);
+ return ext2fs_block_iterate3(fs, ino, BLOCK_FLAG_NO_LARGE | flags,
+ block_buf, xlate_func, &xl);
+}
+
+/*
+ * Emulate the old ext2fs_block_iterate2 function!
+ */
+
+struct xlate2 {
+ int (*func)(ext2_filsys fs,
+ blk_t *blocknr,
+ int blockcnt,
+ blk_t ref_blk,
+ int ref_offset,
+ void *priv_data);
+ void *real_private;
+};
+
+#ifdef __TURBOC__
+#pragma argsused
+#endif
+static int xlate_func2(ext2_filsys fs, blk_t *blocknr, blkcnt_t blockcnt,
+ blk_t ref_block, int ref_offset, void *priv_data)
+{
+ struct xlate2 *xl = (struct xlate2 *) priv_data;
+
+ return (*xl->func)(fs, blocknr, (int) blockcnt, ref_block,
+ ref_offset, xl->real_private);
}
+errcode_t ext2fs_block_iterate2(ext2_filsys fs,
+ ino_t ino,
+ int flags,
+ char *block_buf,
+ int (*func)(ext2_filsys fs,
+ blk_t *blocknr,
+ int blockcnt,
+ blk_t ref_blk,
+ int ref_offset,
+ void *priv_data),
+ void *priv_data)
+{
+ struct xlate2 xl;
+
+ xl.real_private = priv_data;
+ xl.func = func;
+
+ return ext2fs_block_iterate3(fs, ino, BLOCK_FLAG_NO_LARGE | flags,
+ block_buf, xlate_func2, &xl);
+}
next:
if (((offset + dirent->rec_len) > fs->blocksize) ||
(dirent->rec_len < 8) ||
- ((dirent->name_len+8) > dirent->rec_len)) {
+ (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
ctx->errcode = EXT2_ET_DIR_CORRUPTED;
return BLOCK_ABORT;
}
00000000 T _ext2fs_file_close libext2fs fileio
00000000 T _ext2fs_file_read libext2fs fileio
00000000 T _ext2fs_file_write libext2fs fileio
-00000000 T _ext2fs_file_llseek libext2fs fileio
+00000000 T _ext2fs_file_lseek libext2fs fileio
00000000 T _ext2fs_file_get_size libext2fs fileio
00000000 T _ext2fs_file_set_size libext2fs fileio
00000000 T _ext2fs_get_mem libext2fs inline
00000000 T _ext2fs_free_mem libext2fs inline
00000000 T _ext2fs_resize_mem libext2fs inline
+00000000 T _ext2fs_block_iterate3 libext2fs block
ec EXT2_ET_CANCEL_REQUESTED,
"User cancel requested"
+ec EXT2_ET_FILE_TOO_BIG,
+ "Ext2 file too big"
+
end
typedef __u32 blk_t;
typedef unsigned int dgrp_t;
typedef __u32 ext2_off_t;
+typedef __s64 blkcnt_t;
#if EXT2_FLAT_INCLUDES
#include "com_err.h"
*
* BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be
* called for data blocks only.
+ *
+ * BLOCK_FLAG_NO_LARGE is for internal use only. It informs
+ * ext2fs_block_iterate3 that large files won't be accepted.
*/
#define BLOCK_FLAG_APPEND 1
#define BLOCK_FLAG_HOLE 1
#define BLOCK_FLAG_DEPTH_TRAVERSE 2
#define BLOCK_FLAG_DATA_ONLY 4
+#define BLOCK_FLAG_NO_LARGE 0x1000
+
/*
* Magic "block count" return values for the block iterator function.
*/
__u8 s_uuid[16]; /* 128-bit uuid for volume */
char s_volume_name[16]; /* volume name */
char s_last_mounted[64]; /* directory where last mounted */
- __u32 s_reserved[206]; /* Padding to the end of the block */
+ __u32 s_algorithm_usage_bitmap; /* For compression */
+ /*
+ * Performance hints. Directory preallocation should only
+ * happen if the EXT2_COMPAT_PREALLOC flag is on.
+ */
+ __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
+ __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
+ __u16 s_padding1;
+ __u32 s_reserved[204]; /* Padding to the end of the block */
};
/*
* Feature set definitions (that might not be in ext2_fs.h
* (was EXT2_COMPAT_SPARSE_SUPER)
*/
+
+#ifndef EXT2_FEATURE_COMPAT_DIR_PREALLOC
+#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
+#endif
+
#ifndef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#endif
-#define EXT2_LIB_FEATURE_COMPAT_SUPP 0
-#define EXT2_LIB_FEATURE_INCOMPAT_SUPP 0
-#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
+#ifndef EXT2_FEATURE_RO_COMPAT_LARGE_FILE
+#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
+#define i_size_high i_dir_acl
+#endif
+
+#ifndef EXT2_FEATURE_RO_COMPAT_BTREE_DIR
+#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
+#endif
+
+#ifndef EXT2_FEATURE_INCOMPAT_COMPRESSION
+#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
+#endif
+#ifndef EXT2_FEATURE_INCOMPAT_DIRNAME_SIZE
+#define EXT2_FEATURE_INCOMPAT_DIRNAME_SIZE 0x0002
+#endif
+
+#define EXT2_LIB_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_DIR_PREALLOC
+#define EXT2_LIB_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_DIRNAME_SIZE
+#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
+ EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
/*
* function prototypes
*/
int ref_offset,
void *priv_data),
void *priv_data);
+errcode_t ext2fs_block_iterate3(ext2_filsys fs,
+ ino_t ino,
+ int flags,
+ char *block_buf,
+ int (*func)(ext2_filsys fs,
+ blk_t *blocknr,
+ blkcnt_t blockcnt,
+ blk_t ref_blk,
+ int ref_offset,
+ void *priv_data),
+ void *priv_data);
/* bmap.c */
extern errcode_t ext2fs_bmap(ext2_filsys fs, ino_t ino,
unsigned int wanted, unsigned int *got);
extern errcode_t ext2fs_file_write(ext2_file_t file, void *buf,
unsigned int nbytes, unsigned int *written);
-extern errcode_t ext2fs_file_llseek(ext2_file_t file, ext2_off_t offset,
- int whence, ext2_off_t *ret_pos);
+extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
+ int whence, ext2_off_t *ret_pos);
extern ext2_off_t ext2fs_file_get_size(ext2_file_t file);
extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size);
}
-errcode_t ext2fs_file_llseek(ext2_file_t file, ext2_off_t offset,
- int whence, ext2_off_t *ret_pos)
+errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
+ int whence, ext2_off_t *ret_pos)
{
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
gp = (struct get_pathname_struct *) priv_data;
- if ((dirent->name_len == 2) &&
+ if (((dirent->name_len & 0xFF) == 2) &&
!strncmp(dirent->name, "..", 2))
gp->parent = dirent->inode;
if (dirent->inode == gp->search_ino) {
- retval = ext2fs_get_mem(dirent->name_len + 1,
+ retval = ext2fs_get_mem((dirent->name_len & 0xFF) + 1,
(void **) &gp->name);
if (!gp->name) {
gp->errcode = EXT2_ET_NO_MEMORY;
return DIRENT_ABORT;
}
- strncpy(gp->name, dirent->name, dirent->name_len);
- gp->name[dirent->name_len] = '\0';
+ strncpy(gp->name, dirent->name, (dirent->name_len & 0xFF));
+ gp->name[dirent->name_len & 0xFF] = '\0';
return DIRENT_ABORT;
}
return 0;
{
struct link_struct *ls = (struct link_struct *) priv_data;
struct ext2_dir_entry *next;
- int rec_len;
+ int rec_len, min_rec_len;
int ret = 0;
rec_len = EXT2_DIR_REC_LEN(ls->namelen);
* truncate it and return.
*/
if (dirent->inode) {
- if (dirent->rec_len < (EXT2_DIR_REC_LEN(dirent->name_len) +
- rec_len))
+ min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
+ if (dirent->rec_len < (min_rec_len + rec_len))
return ret;
- rec_len = dirent->rec_len - EXT2_DIR_REC_LEN(dirent->name_len);
- dirent->rec_len = EXT2_DIR_REC_LEN(dirent->name_len);
+ rec_len = dirent->rec_len - min_rec_len;
+ dirent->rec_len = min_rec_len;
next = (struct ext2_dir_entry *) (buf + offset +
dirent->rec_len);
next->inode = 0;
{
struct lookup_struct *ls = (struct lookup_struct *) priv_data;
- if (ls->len != dirent->name_len)
+ if (ls->len != (dirent->name_len & 0xFF))
return 0;
- if (strncmp(ls->name, dirent->name, dirent->name_len))
+ if (strncmp(ls->name, dirent->name, (dirent->name_len & 0xFF)))
return 0;
*ls->inode = dirent->inode;
ls->found++;
{
struct link_struct *ls = (struct link_struct *) priv_data;
- if (ls->name && (dirent->name_len != ls->namelen))
+ if (ls->name && ((dirent->name_len & 0xFF) != ls->namelen))
return 0;
- if (ls->name && strncmp(ls->name, dirent->name, dirent->name_len))
+ if (ls->name && strncmp(ls->name, dirent->name,
+ dirent->name_len & 0xFF))
return 0;
if (ls->inode && (dirent->inode != ls->inode))
return 0;