mirror of https://github.com/vitalif/e2fsprogs
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
parent
52783e0ca7
commit
f9190c8a95
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue