Whamcloud - gitweb
Try to use secure_getenv() in preference to __secure_getenv()
[tools/e2fsprogs.git] / lib / ext2fs / openfs.c
index 0b4df38..113b80e 100644 (file)
@@ -9,6 +9,7 @@
  * %End-Header%
  */
 
+#include "config.h"
 #include <stdio.h>
 #include <string.h>
 #if HAVE_UNISTD_H
@@ -22,6 +23,9 @@
 #if HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
 
 #include "ext2_fs.h"
 
@@ -82,6 +86,9 @@ errcode_t ext2fs_open(const char *name, int flags, int superblock,
  *     EXT2_FLAG_FORCE - Open the filesystem even if some of the
  *                             features aren't supported.
  *     EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device
+ *     EXT2_FLAG_SKIP_MMP - Open without multi-mount protection check.
+ *     EXT2_FLAG_64BITS - Allow 64-bit bitfields (needed for large
+ *                             filesystems)
  */
 errcode_t ext2fs_open2(const char *name, const char *io_options,
                       int flags, int superblock,
@@ -92,10 +99,11 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
        errcode_t       retval;
        unsigned long   i, first_meta_bg;
        __u32           features;
-       unsigned int    groups_per_block, blocks_per_group, io_flags;
+       unsigned int    blocks_per_group, io_flags;
        blk64_t         group_block, blk;
        char            *dest, *cp;
 #ifdef WORDS_BIGENDIAN
+       unsigned int    groups_per_block;
        struct ext2_group_desc *gdp;
        int             j;
 #endif
@@ -137,7 +145,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                goto cleanup;
        fs->image_io = fs->io;
        fs->io->app_data = fs;
-       retval = ext2fs_get_memalign(SUPERBLOCK_SIZE, 512, &fs->super);
+       retval = io_channel_alloc_buf(fs->io, -SUPERBLOCK_SIZE, &fs->super);
        if (retval)
                goto cleanup;
        if (flags & EXT2_FLAG_IMAGE_FILE) {
@@ -325,7 +333,9 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
        if (group_block == 0 && fs->blocksize == 1024)
                group_block = 1; /* Deal with 1024 blocksize && bigalloc */
        dest = (char *) fs->group_desc;
+#ifdef WORDS_BIGENDIAN
        groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
+#endif
        if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
                first_meta_bg = fs->super->s_first_meta_bg;
        else
@@ -351,8 +361,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                        goto cleanup;
 #ifdef WORDS_BIGENDIAN
                for (j=0; j < groups_per_block; j++) {
-                       /* The below happens to work... be careful. */
-                       gdp = ext2fs_group_desc(fs, fs->group_desc, j);
+                       gdp = ext2fs_group_desc(fs, fs->group_desc,
+                                               i * groups_per_block + j);
                        ext2fs_swap_group_desc2(fs, gdp);
                }
 #endif
@@ -373,12 +383,28 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                        ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
                        ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
                        ext2fs_bg_itable_unused_set(fs, group, 0);
+                       /* The checksum will be reset later, but fix it here
+                        * anyway to avoid printing a lot of spurious errors. */
+                       ext2fs_group_desc_csum_set(fs, group);
+               }
+               if (fs->flags & EXT2_FLAG_RW)
+                       ext2fs_mark_super_dirty(fs);
+       }
+
+       if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) &&
+           !(flags & EXT2_FLAG_SKIP_MMP) &&
+           (flags & (EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE))) {
+               retval = ext2fs_mmp_start(fs);
+               if (retval) {
+                       fs->flags |= EXT2_FLAG_SKIP_MMP; /* just do cleanup */
+                       ext2fs_mmp_stop(fs);
+                       goto cleanup;
                }
-               ext2fs_mark_super_dirty(fs);
        }
 
        fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR;
        *ret_fs = fs;
+
        return 0;
 cleanup:
        if (flags & EXT2_FLAG_NOFREE_ON_ERROR)