From: Theodore Ts'o Date: Tue, 12 Mar 2002 06:05:06 +0000 (-0500) Subject: dirblock.c (ext2fs_read_dir_block2, ext2fs_write_dir_block): New X-Git-Tag: E2FSPROGS-1.28-WIP-0626~34 X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=f9190c8a95c6b76eac567d5896b3ed06ed2a3ada;p=tools%2Fe2fsprogs.git 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. --- diff --git a/debugfs/ChangeLog b/debugfs/ChangeLog index 003b559..cde9e6d 100644 --- a/debugfs/ChangeLog +++ b/debugfs/ChangeLog @@ -1,5 +1,8 @@ 2002-03-11 Theodore Tso + * 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. diff --git a/debugfs/ls.c b/debugfs/ls.c index 7c5ae42..3064598 100644 --- a/debugfs/ls.c +++ b/debugfs/ls.c @@ -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 diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index bd58b99..634198a 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,5 +1,14 @@ 2002-03-11 Theodore Tso + * 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 diff --git a/lib/ext2fs/dirblock.c b/lib/ext2fs/dirblock.c index 9efbceb..185384b 100644 --- a/lib/ext2fs/dirblock.c +++ b/lib/ext2fs/dirblock.c @@ -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) @@ -45,56 +46,85 @@ errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block, 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); +} + diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index d55cd50..d6e9194 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -290,6 +290,11 @@ struct struct_ext2_filsys { #endif /* + * Flags for directory block reading and writing functions + */ +#define EXT2_DIRBLOCK_V2_STRUCT 0x0001 + +/* * Return flags for the directory iterator functions */ #define DIRENT_CHANGED 1 @@ -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,