Whamcloud - gitweb
dirblock.c (ext2fs_read_dir_block2, ext2fs_write_dir_block): New
authorTheodore Ts'o <tytso@mit.edu>
Tue, 12 Mar 2002 06:05:06 +0000 (01:05 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 12 Mar 2002 06:05:06 +0000 (01:05 -0500)
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.

debugfs/ChangeLog
debugfs/ls.c
lib/ext2fs/ChangeLog
lib/ext2fs/dirblock.c
lib/ext2fs/ext2fs.h

index 003b559..cde9e6d 100644 (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.
 
index 7c5ae42..3064598 100644 (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
index bd58b99..634198a 100644 (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
index 9efbceb..185384b 100644 (file)
 #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);
+}
+
index d55cd50..d6e9194 100644 (file)
@@ -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,