dirblock.c (ext2fs_read_dir_block2, ext2fs_write_dir_block): New

functions which take an extra flags argument.  The flag
	EXT2_DIRBLOCK_V2_STRUCT will reverse when the name_len
	field is byte swampped on big-endian machines, since in
	the V2 structure, name_len is a char field which is
	doesn't need to be byte swapped --- except if an
	old-style kernel had byte-swapped the name_len field
	as part of the V1 structure.

Also fixed a bug in debugfs which used ext2_dir_entry_2 without 
worrying about the above issue, with the net result that "ls -l"
would print an incorrect file type on big-endian systems.
bitmap-optimize
Theodore Ts'o 2002-03-12 01:05:06 -05:00
parent 52783e0ca7
commit f9190c8a95
5 changed files with 83 additions and 33 deletions

View File

@ -1,5 +1,8 @@
2002-03-11 Theodore Tso <tytso@mit.edu>
* ls.c (list_dir_proc): Fix bug: ls -l fails to print the file
type correctly if running on big-endian systems.
* htree.c (htree_dump_leaf_node): Use the ext2_dirhash function
instead of a local static function.

View File

@ -51,7 +51,6 @@ static int list_dir_proc(ext2_ino_t dir,
char *buf,
void *private)
{
struct ext2_dir_entry_2 *d2;
struct ext2_inode inode;
ext2_ino_t ino;
struct tm *tm_p;
@ -90,9 +89,9 @@ static int list_dir_proc(ext2_ino_t dir,
strcpy(datestr, " ");
memset(&inode, 0, sizeof(struct ext2_inode));
}
d2 = (struct ext2_dir_entry_2 *) dirent;
fprintf(ls->f, "%c%6u%c %6o (%d) %5d %5d ", lbr, ino, rbr,
inode.i_mode, d2->file_type, inode.i_uid, inode.i_gid);
inode.i_mode, dirent->name_len >> 8,
inode.i_uid, inode.i_gid);
if (LINUX_S_ISDIR(inode.i_mode))
fprintf(ls->f, "%5d", inode.i_size);
else

View File

@ -1,5 +1,14 @@
2002-03-11 Theodore Tso <tytso@mit.edu>
* dirblock.c (ext2fs_read_dir_block2, ext2fs_write_dir_block): New
functions which take an extra flags argument. The flag
EXT2_DIRBLOCK_V2_STRUCT will reverse when the name_len
field is byte swampped on big-endian machines, since in
the V2 structure, name_len is a char field which is
doesn't need to be byte swapped --- except if an
old-style kernel had byte-swapped the name_len field
as part of the V1 structure.
* ext2_err.et.in (EXT2_ET_DIRHASH_UNSUPP): New error code
* dirhash.c (ext2fs_dirhash): New function which calculates the

View File

@ -19,13 +19,14 @@
#include "ext2_fs.h"
#include "ext2fs.h"
errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
void *buf)
errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
void *buf, int flags)
{
errcode_t retval;
char *p, *end;
struct ext2_dir_entry *dirent;
unsigned int rec_len, do_swap;
unsigned int name_len, rec_len, do_swap;
retval = io_channel_read_blk(fs->io, block, 1, buf);
if (retval)
@ -44,57 +45,86 @@ errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
dirent->rec_len = ext2fs_swab16(dirent->rec_len);
dirent->name_len = ext2fs_swab16(dirent->name_len);
}
#endif
name_len = dirent->name_len;
#ifdef WORDS_BIGENDIAN
if (flags & EXT2_DIRBLOCK_V2_STRUCT)
dirent->name_len = ext2fs_swab16(dirent->name_len);
#endif
rec_len = dirent->rec_len;
if ((rec_len < 8) || (rec_len % 4)) {
rec_len = 8;
retval = EXT2_ET_DIR_CORRUPTED;
}
if (((dirent->name_len & 0xFF) + 8) > dirent->rec_len)
if (((name_len & 0xFF) + 8) > dirent->rec_len)
retval = EXT2_ET_DIR_CORRUPTED;
p += rec_len;
}
return retval;
}
errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
void *inbuf)
errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
void *buf)
{
return ext2fs_read_dir_block2(fs, block, buf, 0);
}
errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
void *inbuf, int flags)
{
#ifdef EXT2FS_ENABLE_SWAPFS
int do_swap = 0;
errcode_t retval;
char *p, *end, *write_buf;
char *p, *end;
char *buf = 0;
struct ext2_dir_entry *dirent;
#ifdef EXT2FS_ENABLE_SWAPFS
if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) {
retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
if (retval)
return retval;
write_buf = buf;
memcpy(buf, inbuf, fs->blocksize);
p = buf;
end = buf + fs->blocksize;
while (p < end) {
dirent = (struct ext2_dir_entry *) p;
if ((dirent->rec_len < 8) ||
(dirent->rec_len % 4)) {
retval = EXT2_ET_DIR_CORRUPTED;
goto errout;
}
p += dirent->rec_len;
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
do_swap = 1;
#ifndef WORDS_BIGENDIAN
if (!do_swap)
return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
#endif
retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
if (retval)
return retval;
memcpy(buf, inbuf, fs->blocksize);
p = buf;
end = buf + fs->blocksize;
while (p < end) {
dirent = (struct ext2_dir_entry *) p;
if ((dirent->rec_len < 8) ||
(dirent->rec_len % 4)) {
ext2fs_free_mem((void **) &buf);
return (EXT2_ET_DIR_CORRUPTED);
}
p += dirent->rec_len;
if (do_swap) {
dirent->inode = ext2fs_swab32(dirent->inode);
dirent->rec_len = ext2fs_swab16(dirent->rec_len);
dirent->name_len = ext2fs_swab16(dirent->name_len);
}
} else
#ifdef WORDS_BIGENDIAN
if (flags & EXT2_DIRBLOCK_V2_STRUCT)
dirent->name_len = ext2fs_swab16(dirent->name_len);
#endif
write_buf = (char *) inbuf;
retval = io_channel_write_blk(fs->io, block, 1, write_buf);
errout:
if (buf)
ext2fs_free_mem((void **) &buf);
}
retval = io_channel_write_blk(fs->io, block, 1, buf);
ext2fs_free_mem((void **) &buf);
return retval;
#else
return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
#endif
}
errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
void *inbuf)
{
return ext2fs_write_dir_block2(fs, block, inbuf, 0);
}

View File

@ -289,6 +289,11 @@ struct struct_ext2_filsys {
#define EXT2_BMOVE_DEBUG 0x0002
#endif
/*
* Flags for directory block reading and writing functions
*/
#define EXT2_DIRBLOCK_V2_STRUCT 0x0001
/*
* Return flags for the directory iterator functions
*/
@ -598,8 +603,12 @@ extern errcode_t
/* dirblock.c */
extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
void *buf);
extern errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
void *buf, int flags);
extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
void *buf);
extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
void *buf, int flags);
/* dirhash.c */
extern errcode_t ext2fs_dirhash(int version, const char *name, int len,