OSDN Git Service

Merge "Make inodes per group a multiple of inodes per block"
authorColin Cross <ccross@android.com>
Sun, 1 May 2011 02:08:09 +0000 (19:08 -0700)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Sun, 1 May 2011 02:08:09 +0000 (19:08 -0700)
38 files changed:
ext4_utils/Android.mk
ext4_utils/allocate.c
ext4_utils/allocate.h
ext4_utils/backed_block.c
ext4_utils/backed_block.h
ext4_utils/contents.c
ext4_utils/ext2simg.c [new file with mode: 0644]
ext4_utils/ext4_utils.c
ext4_utils/ext4_utils.h
ext4_utils/extent.c
ext4_utils/indirect.c
ext4_utils/make_ext4fs.c
ext4_utils/make_ext4fs.h
ext4_utils/make_ext4fs_main.c
ext4_utils/output_file.c
ext4_utils/output_file.h
ext4_utils/simg2img.c
ext4_utils/sparse_format.h
ext4_utils/wipe.c [new file with mode: 0644]
ext4_utils/wipe.h [new file with mode: 0644]
fatblock/fat.c
fatblock/fs.c
libublock/Android.mk
tests/Android.mk
tests/binder/benchmarks/binderAddInts.cpp
tests/bionic/libc/Android.mk
tests/bionic/libc/bionic/test_dlclose_destruction.c
tests/bionic/libc/common/test_clock.c [new file with mode: 0644]
tests/bionic/libc/common/test_strptime.c [new file with mode: 0644]
tests/bionic/libc/run-test.sh
tests/framebuffer/fb_test.c
tests/icachetest/Android.mk
tests/include/testUtil.h
tests/lib/testUtil/Android.mk
tests/lib/testUtil/testUtil.c
tests/memtest/Android.mk
tests/wifi/stress/Android.mk
tests/wifi/stress/wifiLoadScanAssoc.c [moved from tests/wifi/stress/wifiLoadScanAssoc_test.c with 86% similarity]

index c7934a3..417c839 100644 (file)
@@ -14,14 +14,15 @@ libext4_utils_src_files := \
         indirect.c \
         uuid.c \
         sha1.c \
-       sparse_crc32.c
+       sparse_crc32.c \
+       wipe.c
 
 LOCAL_SRC_FILES := $(libext4_utils_src_files)
 LOCAL_MODULE := libext4_utils
 LOCAL_MODULE_TAGS := optional
 LOCAL_C_INCLUDES += external/zlib
 LOCAL_SHARED_LIBRARIES := libz
-LOCAL_PRELINK_MODULE := false
+
 
 include $(BUILD_SHARED_LIBRARY)
 
@@ -32,7 +33,7 @@ LOCAL_MODULE := libext4_utils
 LOCAL_MODULE_TAGS := optional
 LOCAL_C_INCLUDES += external/zlib
 LOCAL_STATIC_LIBRARIES := libz
-LOCAL_PRELINK_MODULE := false
+
 
 include $(BUILD_STATIC_LIBRARY)
 
@@ -64,6 +65,24 @@ include $(BUILD_HOST_EXECUTABLE)
 
 include $(CLEAR_VARS)
 
+LOCAL_SRC_FILES := ext2simg.c
+LOCAL_MODULE := ext2simg
+LOCAL_MODULE_TAGS := optional
+LOCAL_SHARED_LIBRARIES += libext4_utils libz
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := ext2simg.c
+LOCAL_MODULE := ext2simg
+LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_LIBRARIES += libext4_utils libz
+
+include $(BUILD_HOST_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
 LOCAL_SRC_FILES := simg2img.c \
        sparse_crc32.c
 LOCAL_MODULE := simg2img
@@ -72,6 +91,14 @@ include $(BUILD_HOST_EXECUTABLE)
 
 include $(CLEAR_VARS)
 
+LOCAL_SRC_FILES := simg2img.c \
+       sparse_crc32.c
+LOCAL_MODULE := simg2img
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
 LOCAL_MODULE := mkuserimg.sh
 LOCAL_SRC_FILES := mkuserimg.sh
 LOCAL_MODULE_CLASS := EXECUTABLES
index 20ba154..9377e3c 100644 (file)
  * limitations under the License.
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-
 #include "ext4_utils.h"
 #include "allocate.h"
 #include "backed_block.h"
 #include "ext4.h"
 
+#include <stdio.h>
+#include <stdlib.h>
+
 struct region_list {
        struct region *first;
        struct region *last;
@@ -148,7 +148,7 @@ static void allocate_bg_inode_table(struct block_group_info *bg)
        u32 block = bg->first_block + 2;
 
        if (bg->has_superblock)
-               block += aux_info.bg_desc_blocks + aux_info.bg_desc_reserve_blocks + 1;
+               block += aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks + 1;
 
        bg->inode_table = calloc(aux_info.inode_table_blocks, info.block_size);
        if (bg->inode_table == NULL)
@@ -258,7 +258,7 @@ static void init_bg(struct block_group_info *bg, unsigned int i)
        bg->has_superblock = ext4_bg_has_super_block(i);
 
        if (bg->has_superblock)
-               header_blocks += 1 + aux_info.bg_desc_blocks + aux_info.bg_desc_reserve_blocks;
+               header_blocks += 1 + aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks;
 
        bg->bitmaps = calloc(info.block_size, 2);
        bg->block_bitmap = bg->bitmaps;
@@ -269,7 +269,7 @@ static void init_bg(struct block_group_info *bg, unsigned int i)
 
        u32 block = bg->first_block;
        if (bg->has_superblock)
-               block += 1 + aux_info.bg_desc_blocks +  aux_info.bg_desc_reserve_blocks;
+               block += 1 + aux_info.bg_desc_blocks +  info.bg_desc_reserve_blocks;
        queue_data_block(bg->bitmaps, 2 * info.block_size, block);
 
        bg->data_blocks_used = 0;
index f4bed41..16dc33c 100644 (file)
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#ifndef _ALLOCATE_H_
+#define _ALLOCATE_H_
+
 #define EXT4_ALLOCATE_FAILED (u32)(~0)
 
 #include "ext4_utils.h"
@@ -49,3 +52,5 @@ void append_region(struct block_allocation *alloc,
        u32 block, u32 len, int bg);
 struct block_allocation *create_allocation();
 int append_oob_allocation(struct block_allocation *alloc, u32 len);
+
+#endif
index c1a2f20..473cce2 100644 (file)
  * limitations under the License.
  */
 
-#include <stdlib.h>
-
 #include "ext4_utils.h"
 #include "backed_block.h"
 
+#include <stdlib.h>
+
 struct data_block {
        u32 block;
        u32 len;
        u8 *data;
        const char *filename;
-       off_t offset;
+       off64_t offset;
        struct data_block *next;
 };
 
@@ -83,7 +83,7 @@ void queue_data_block(u8 *data, u32 len, u32 block)
 }
 
 /* Queues a chunk of a file on disk to be written to the specified data blocks */
-void queue_data_file(const char *filename, off_t offset, u32 len,
+void queue_data_file(const char *filename, off64_t offset, u32 len,
        u32 block)
 {
        struct data_block *db = malloc(sizeof(struct data_block));
@@ -102,7 +102,7 @@ void queue_data_file(const char *filename, off_t offset, u32 len,
 /* Iterates over the queued data blocks, calling data_func for each contiguous
    data block, and file_func for each contiguous file block */
 void for_each_data_block(data_block_callback_t data_func,
-       data_block_file_callback_t file_func, struct output_file *out)
+       data_block_file_callback_t file_func, void *priv)
 {
        struct data_block *db;
        u32 last_block = 0;
@@ -113,9 +113,9 @@ void for_each_data_block(data_block_callback_t data_func,
                last_block = db->block + DIV_ROUND_UP(db->len, info.block_size) - 1;
 
                if (db->filename)
-                       file_func(out, (u64)db->block * info.block_size, db->filename, db->offset, db->len);
+                       file_func(priv, (u64)db->block * info.block_size, db->filename, db->offset, db->len);
                else
-                       data_func(out, (u64)db->block * info.block_size, db->data, db->len);
+                       data_func(priv, (u64)db->block * info.block_size, db->data, db->len);
        }
 }
 
index 5304f00..d131dc6 100644 (file)
 #ifndef _BACKED_BLOCK_H_
 #define _BACKED_BLOCK_H_
 
-#include <sys/types.h>
-#include <unistd.h>
 #include "ext4_utils.h"
 #include "output_file.h"
 
-typedef void (*data_block_callback_t)(struct output_file *out, u64 off,
-       u8 *data, int len);
-typedef void (*data_block_file_callback_t)(struct output_file *out, u64 off,
-                                          const char *file, off_t offset,
+typedef void (*data_block_callback_t)(void *priv, u64 off, u8 *data, int len);
+typedef void (*data_block_file_callback_t)(void *priv, u64 off,
+                                          const char *file, off64_t offset,
                                           int len);
 
 void queue_data_block(u8 *data, u32 len, u32 block);
-void queue_data_file(const char *filename, off_t offset, u32 len,
+void queue_data_file(const char *filename, off64_t offset, u32 len,
        u32 block);
 void for_each_data_block(data_block_callback_t data_func,
-       data_block_file_callback_t file_func, struct output_file *out);
+       data_block_file_callback_t file_func, void *priv);
 void free_data_blocks();
 
 #endif
index 0ecdfd4..c7607ab 100644 (file)
@@ -39,6 +39,11 @@ static u32 dentry_size(u32 entries, struct dentry *dentries)
                len += dentry_len;
        }
 
+       /* include size of the dentry used to pad until the end of the block */
+       if (len % info.block_size + 8 > info.block_size)
+               len += info.block_size - (len % info.block_size);
+       len += 8;
+
        return len;
 }
 
@@ -51,7 +56,7 @@ static struct ext4_dir_entry_2 *add_dentry(u8 *data, u32 *offset,
        struct ext4_dir_entry_2 *dentry;
 
        u32 start_block = *offset / info.block_size;
-       u32 end_block = (*offset + rec_len) / info.block_size;
+       u32 end_block = (*offset + rec_len - 1) / info.block_size;
        if (start_block != end_block) {
                /* Adding this dentry will cross a block boundary, so pad the previous
                   dentry to the block boundary */
@@ -115,7 +120,7 @@ u32 make_directory(u32 dir_inode_num, u32 entries, struct dentry *dentries,
 
        data = inode_allocate_data_extents(inode, len, len);
        if (data == NULL) {
-               error("failed to allocate %llu extents", len);
+               error("failed to allocate %u extents", len);
                return EXT4_ALLOCATE_FAILED;
        }
 
diff --git a/ext4_utils/ext2simg.c b/ext4_utils/ext2simg.c
new file mode 100644 (file)
index 0000000..9332bad
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ext4_utils.h"
+#include "make_ext4fs.h"
+#include "output_file.h"
+#include "backed_block.h"
+#include "allocate.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <unistd.h>
+
+extern struct fs_info info;
+
+static int verbose = 0;
+
+static void usage(char *path)
+{
+       fprintf(stderr, "%s [ options ] <image or block device> <output image>\n", path);
+       fprintf(stderr, "\n");
+       fprintf(stderr, "  -c include CRC block\n");
+       fprintf(stderr, "  -v verbose output\n");
+       fprintf(stderr, "  -z gzip output\n");
+       fprintf(stderr, "  -S don't use sparse output format\n");
+}
+
+static int read_ext(int fd)
+{
+       off64_t ret;
+       struct ext4_super_block sb;
+       unsigned int i;
+
+       ret = lseek64(fd, 1024, SEEK_SET);
+       if (ret < 0)
+               critical_error_errno("failed to seek to superblock");
+
+       ret = read(fd, &sb, sizeof(sb));
+       if (ret < 0)
+               critical_error_errno("failed to read superblock");
+       if (ret != sizeof(sb))
+               critical_error("failed to read all of superblock");
+
+       ext4_parse_sb(&sb);
+
+       ret = lseek64(fd, info.len, SEEK_SET);
+       if (ret < 0)
+               critical_error_errno("failed to seek to end of input image");
+
+       ret = lseek64(fd, info.block_size * (aux_info.first_data_block + 1), SEEK_SET);
+       if (ret < 0)
+               critical_error_errno("failed to seek to block group descriptors");
+
+       ret = read(fd, aux_info.bg_desc, info.block_size * aux_info.bg_desc_blocks);
+       if (ret < 0)
+               critical_error_errno("failed to read block group descriptors");
+       if (ret != (int)info.block_size * (int)aux_info.bg_desc_blocks)
+               critical_error("failed to read all of block group descriptors");
+
+       if (verbose) {
+               printf("Found filesystem with parameters:\n");
+               printf("    Size: %llu\n", info.len);
+               printf("    Block size: %d\n", info.block_size);
+               printf("    Blocks per group: %d\n", info.blocks_per_group);
+               printf("    Inodes per group: %d\n", info.inodes_per_group);
+               printf("    Inode size: %d\n", info.inode_size);
+               printf("    Label: %s\n", info.label);
+               printf("    Blocks: %llu\n", aux_info.len_blocks);
+               printf("    Block groups: %d\n", aux_info.groups);
+               printf("    Reserved block group size: %d\n", info.bg_desc_reserve_blocks);
+               printf("    Used %d/%d inodes and %d/%d blocks\n",
+                               aux_info.sb->s_inodes_count - aux_info.sb->s_free_inodes_count,
+                               aux_info.sb->s_inodes_count,
+                               aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo,
+                               aux_info.sb->s_blocks_count_lo);
+       }
+
+       return 0;
+}
+
+static int bitmap_get_bit(u8 *bitmap, u32 bit)
+{
+       if (bitmap[bit / 8] & 1 << (bit % 8))
+               return 1;
+
+       return 0;
+}
+
+static int build_sparse_ext(int fd, const char *filename)
+{
+       unsigned int i;
+       unsigned int block;
+       int start_contiguous_block;
+       u8 *block_bitmap;
+       off64_t ret;
+
+       block_bitmap = malloc(info.block_size);
+       if (!block_bitmap)
+               critical_error("failed to allocate block bitmap");
+
+       if (aux_info.first_data_block > 0)
+               queue_data_file(filename, 0,
+                               info.block_size * aux_info.first_data_block, 0);
+
+       for (i = 0; i < aux_info.groups; i++) {
+               u32 first_block = aux_info.first_data_block + i * info.blocks_per_group;
+               u32 last_block = min(info.blocks_per_group, aux_info.len_blocks - first_block);
+
+               ret = lseek64(fd, (u64)info.block_size * aux_info.bg_desc[i].bg_block_bitmap,
+                               SEEK_SET);
+               if (ret < 0)
+                       critical_error_errno("failed to seek to block group bitmap %d", i);
+
+               ret = read(fd, block_bitmap, info.block_size);
+               if (ret < 0)
+                       critical_error_errno("failed to read block group bitmap %d", i);
+               if (ret != (int)info.block_size)
+                       critical_error("failed to read all of block group bitmap %d", i);
+
+               start_contiguous_block = -1;
+               for (block = 0; block < last_block; block++) {
+                       if (start_contiguous_block >= 0) {
+                               if (!bitmap_get_bit(block_bitmap, block)) {
+                                       u32 start_block = first_block + start_contiguous_block;
+                                       u32 len_blocks = block - start_contiguous_block;
+
+                                       queue_data_file(filename, (u64)info.block_size * start_block,
+                                                       info.block_size * len_blocks, start_block);
+                                       start_contiguous_block = -1;
+                               }
+                       } else {
+                               if (bitmap_get_bit(block_bitmap, block))
+                                       start_contiguous_block = block;
+                       }
+               }
+
+               if (start_contiguous_block >= 0) {
+                       u32 start_block = first_block + start_contiguous_block;
+                       u32 len_blocks = last_block - start_contiguous_block;
+                       queue_data_file(filename, (u64)info.block_size * start_block,
+                                       info.block_size * len_blocks, start_block);
+               }
+       }
+
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       int opt;
+       const char *in = NULL;
+       const char *out = NULL;
+       int gzip = 0;
+       int sparse = 1;
+       int fd;
+       int crc = 0;
+
+       while ((opt = getopt(argc, argv, "cvzS")) != -1) {
+               switch (opt) {
+               case 'c':
+                       crc = 1;
+                       break;
+               case 'v':
+                       verbose = 1;
+                       break;
+               case 'z':
+                       gzip = 1;
+                       break;
+               case 'S':
+                       sparse = 0;
+                       break;
+               }
+       }
+
+       if (optind >= argc) {
+               fprintf(stderr, "Expected image or block device after options\n");
+               usage(argv[0]);
+               exit(EXIT_FAILURE);
+       }
+
+       in = argv[optind++];
+
+       if (optind >= argc) {
+               fprintf(stderr, "Expected output image after input image\n");
+               usage(argv[0]);
+               exit(EXIT_FAILURE);
+       }
+
+       out = argv[optind++];
+
+       if (optind < argc) {
+               fprintf(stderr, "Unexpected argument: %s\n", argv[optind]);
+               usage(argv[0]);
+               exit(EXIT_FAILURE);
+       }
+
+       fd = open(in, O_RDONLY);
+
+       if (fd < 0)
+               critical_error_errno("failed to open input image");
+
+       read_ext(fd);
+
+       build_sparse_ext(fd, in);
+
+       close(fd);
+
+       write_ext4_image(out, gzip, sparse, crc, 0);
+
+       return 0;
+}
index 60a4da3..f4f04d9 100644 (file)
  * limitations under the License.
  */
 
+#include "ext4_utils.h"
+#include "output_file.h"
+#include "backed_block.h"
+#include "uuid.h"
+#include "allocate.h"
+#include "indirect.h"
+#include "extent.h"
+
 #include <fcntl.h>
 #include <arpa/inet.h>
 #include <sys/ioctl.h>
 #include <sys/disk.h>
 #endif
 
-#include "ext4_utils.h"
-#include "output_file.h"
-#include "backed_block.h"
-#include "uuid.h"
-#include "allocate.h"
-#include "indirect.h"
-#include "extent.h"
-
 #include "ext4.h"
 #include "jbd2.h"
 
@@ -42,6 +42,8 @@ int force = 0;
 struct fs_info info;
 struct fs_aux_info aux_info;
 
+jmp_buf setjmp_env;
+
 /* returns 1 if a is a power of b */
 static int is_power_of(int a, int b)
 {
@@ -73,35 +75,64 @@ int ext4_bg_has_super_block(int bg)
        return 0;
 }
 
+struct count_chunks {
+       u32 chunks;
+       u64 cur_ptr;
+};
+
+void count_data_block(void *priv, u64 off, u8 *data, int len)
+{
+       struct count_chunks *count_chunks = priv;
+       if (off > count_chunks->cur_ptr)
+               count_chunks->chunks++;
+       count_chunks->cur_ptr = off + ALIGN(len, info.block_size);
+       count_chunks->chunks++;
+}
+
+void count_file_block(void *priv, u64 off, const char *file,
+               off64_t offset, int len)
+{
+       struct count_chunks *count_chunks = priv;
+       if (off > count_chunks->cur_ptr)
+               count_chunks->chunks++;
+       count_chunks->cur_ptr = off + ALIGN(len, info.block_size);
+       count_chunks->chunks++;
+}
+
+int count_sparse_chunks()
+{
+       struct count_chunks count_chunks = {0, 0};
+
+       for_each_data_block(count_data_block, count_file_block, &count_chunks);
+
+       if (count_chunks.cur_ptr != (u64) info.len)
+               count_chunks.chunks++;
+
+       return count_chunks.chunks;
+}
+
+static void ext4_write_data_block(void *priv, u64 off, u8 *data, int len)
+{
+       write_data_block(priv, off, data, len);
+}
+static void ext4_write_data_file(void *priv, u64 off, const char *file,
+               off64_t offset, int len)
+{
+       write_data_file(priv, off, file, offset, len);
+}
+
 /* Write the filesystem image to a file */
-void write_ext4_image(const char *filename, int gz, int sparse)
+void write_ext4_image(const char *filename, int gz, int sparse, int crc,
+               int wipe)
 {
        int ret = 0;
-       struct output_file *out = open_output_file(filename, gz, sparse);
-       off_t off;
+       struct output_file *out = open_output_file(filename, gz, sparse,
+               count_sparse_chunks(), crc, wipe);
 
        if (!out)
                return;
 
-       /* The write_data* functions expect only block aligned calls.
-        * This is not an issue, except when we write out the super
-        * block on a system with a block size > 1K.  So, we need to
-        * deal with that here.
-        */
-       if (info.block_size > 1024) {
-               u8 buf[4096] = { 0 };   /* The larget supported ext4 block size */
-               memcpy(buf + 1024, (u8*)aux_info.sb, 1024);
-               write_data_block(out, 0, buf, info.block_size);
-
-       } else {
-               write_data_block(out, 1024, (u8*)aux_info.sb, 1024);
-       }
-
-       write_data_block(out, (u64)(aux_info.first_data_block + 1) * info.block_size,
-                        (u8*)aux_info.bg_desc,
-                        aux_info.bg_desc_blocks * info.block_size);
-
-       for_each_data_block(write_data_block, write_data_file, out);
+       for_each_data_block(ext4_write_data_block, ext4_write_data_file, out);
 
        pad_output_file(out, info.len);
 
@@ -125,20 +156,13 @@ void ext4_create_fs_aux_info()
                DIV_ROUND_UP(aux_info.groups * sizeof(struct ext2_group_desc),
                        info.block_size);
 
-       aux_info.bg_desc_reserve_blocks =
-               DIV_ROUND_UP(aux_info.groups * 1024 * sizeof(struct ext2_group_desc),
-                       info.block_size) - aux_info.bg_desc_blocks;
-
-       if (aux_info.bg_desc_reserve_blocks > aux_info.blocks_per_ind)
-               aux_info.bg_desc_reserve_blocks = aux_info.blocks_per_ind;
-
        aux_info.default_i_flags = EXT4_NOATIME_FL;
 
        u32 last_group_size = aux_info.len_blocks % info.blocks_per_group;
        u32 last_header_size = 2 + aux_info.inode_table_blocks;
        if (ext4_bg_has_super_block(aux_info.groups - 1))
                last_header_size += 1 + aux_info.bg_desc_blocks +
-                       aux_info.bg_desc_reserve_blocks;
+                       info.bg_desc_reserve_blocks;
        if (last_group_size > 0 && last_group_size < last_header_size) {
                aux_info.groups--;
                aux_info.len_blocks -= last_group_size;
@@ -203,7 +227,7 @@ void ext4_fill_in_sb()
        memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
        sb->s_algorithm_usage_bitmap = 0;
 
-       sb->s_reserved_gdt_blocks = aux_info.bg_desc_reserve_blocks;
+       sb->s_reserved_gdt_blocks = info.bg_desc_reserve_blocks;
        sb->s_prealloc_blocks = 0;
        sb->s_prealloc_dir_blocks = 0;
 
@@ -241,13 +265,12 @@ void ext4_fill_in_sb()
                        info.blocks_per_group;
                u32 header_size = 0;
                if (ext4_bg_has_super_block(i)) {
-                       if (i != 0) {
+                       if (i != 0)
                                queue_data_block((u8 *)sb, info.block_size, group_start_block);
-                               queue_data_block((u8 *)aux_info.bg_desc,
-                                       aux_info.bg_desc_blocks * info.block_size,
-                                       group_start_block + 1);
-                       }
-                       header_size = 1 + aux_info.bg_desc_blocks + aux_info.bg_desc_reserve_blocks;
+                       queue_data_block((u8 *)aux_info.bg_desc,
+                               aux_info.bg_desc_blocks * info.block_size,
+                               group_start_block + 1);
+                       header_size = 1 + aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks;
                }
 
                aux_info.bg_desc[i].bg_block_bitmap = group_start_block + header_size;
@@ -260,6 +283,53 @@ void ext4_fill_in_sb()
        }
 }
 
+void ext4_queue_sb(void)
+{
+       /* The write_data* functions expect only block aligned calls.
+        * This is not an issue, except when we write out the super
+        * block on a system with a block size > 1K.  So, we need to
+        * deal with that here.
+        */
+       if (info.block_size > 1024) {
+               u8 *buf = calloc(info.block_size, 1);
+               memcpy(buf + 1024, (u8*)aux_info.sb, 1024);
+               queue_data_block(buf, info.block_size, 0);
+       } else {
+               queue_data_block((u8*)aux_info.sb, 1024, 1);
+       }
+}
+
+void ext4_parse_sb(struct ext4_super_block *sb)
+{
+       if (sb->s_magic != EXT4_SUPER_MAGIC)
+               error("superblock magic incorrect");
+
+       if (sb->s_state != EXT4_VALID_FS)
+               error("filesystem state not valid");
+
+       info.block_size = 1024 << sb->s_log_block_size;
+       info.blocks_per_group = sb->s_blocks_per_group;
+       info.inodes_per_group = sb->s_inodes_per_group;
+       info.inode_size = sb->s_inode_size;
+       info.inodes = sb->s_inodes_count;
+       info.feat_ro_compat = sb->s_feature_ro_compat;
+       info.feat_compat = sb->s_feature_compat;
+       info.feat_incompat = sb->s_feature_incompat;
+       info.bg_desc_reserve_blocks = sb->s_reserved_gdt_blocks;
+       info.label = sb->s_volume_name;
+
+       aux_info.len_blocks = ((u64)sb->s_blocks_count_hi << 32) +
+                       sb->s_blocks_count_lo;
+       info.len = (u64)info.block_size * aux_info.len_blocks;
+
+       ext4_create_fs_aux_info();
+
+       memcpy(aux_info.sb, sb, sizeof(*sb));
+
+       if (aux_info.first_data_block != sb->s_first_data_block)
+               critical_error("first data block does not match");
+}
+
 void ext4_create_resize_inode()
 {
        struct block_allocation *reserve_inode_alloc = create_allocation();
@@ -278,7 +348,7 @@ void ext4_create_resize_inode()
                                info.blocks_per_group;
                        u32 reserved_block_start = group_start_block + 1 +
                                aux_info.bg_desc_blocks;
-                       u32 reserved_block_len = aux_info.bg_desc_reserve_blocks;
+                       u32 reserved_block_len = info.bg_desc_reserve_blocks;
                        append_region(reserve_inode_alloc, reserved_block_start,
                                reserved_block_len, i);
                        reserve_inode_len += reserved_block_len;
@@ -375,17 +445,29 @@ u64 get_file_size(const char *filename)
 {
        struct stat buf;
        int ret;
+       u64 reserve_len = 0;
+       s64 computed_size;
 
        ret = stat(filename, &buf);
        if (ret)
                return 0;
 
+       if (info.len < 0)
+               reserve_len = -info.len;
+
        if (S_ISREG(buf.st_mode))
-               return buf.st_size;
+               computed_size = buf.st_size - reserve_len;
        else if (S_ISBLK(buf.st_mode))
-               return get_block_device_size(filename);
+               computed_size = get_block_device_size(filename) - reserve_len;
        else
-               return 0;
+               computed_size = 0;
+
+       if (computed_size < 0) {
+               warn("Computed filesystem size less than 0");
+               computed_size = 0;
+       }
+
+       return computed_size;
 }
 
 u64 parse_num(const char *arg)
index 697c8d9..4518b98 100644 (file)
 #ifndef _EXT4_UTILS_H_
 #define _EXT4_UTILS_H_
 
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE64_SOURCE
+#include <sys/types.h>
+#include <unistd.h>
+
 #include <sys/types.h>
 #include <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <setjmp.h>
+
+#if defined(__APPLE__) && defined(__MACH__)
+#define lseek64 lseek
+#define ftruncate64 ftruncate
+#define mmap64 mmap
+#define off64_t off_t
+#endif
+
+#ifdef __BIONIC__
+extern void*  __mmap2(void *, size_t, int, int, int, off_t);
+static inline void *mmap64(void *addr, size_t length, int prot, int flags,
+        int fd, off64_t offset)
+{
+    return __mmap2(addr, length, prot, flags, fd, offset >> 12);
+}
+#endif
 
 extern int force;
 
 #define warn(fmt, args...) do { fprintf(stderr, "warning: %s: " fmt "\n", __func__, ## args); } while (0)
-#define error(fmt, args...) do { fprintf(stderr, "error: %s: " fmt "\n", __func__, ## args); if (!force) exit(EXIT_FAILURE); } while (0)
-#define error_errno(s) error(s ": %s", strerror(errno))
-#define critical_error(fmt, args...) do { fprintf(stderr, "critical error: %s: " fmt "\n", __func__, ## args); exit(EXIT_FAILURE); } while (0)
-#define critical_error_errno(s) critical_error(s ": %s", strerror(errno))
+#define error(fmt, args...) do { fprintf(stderr, "error: %s: " fmt "\n", __func__, ## args); if (!force) longjmp(setjmp_env, EXIT_FAILURE); } while (0)
+#define error_errno(s, args...) error(s ": %s", ##args, strerror(errno))
+#define critical_error(fmt, args...) do { fprintf(stderr, "critical error: %s: " fmt "\n", __func__, ## args); longjmp(setjmp_env, EXIT_FAILURE); } while (0)
+#define critical_error_errno(s, args...) critical_error(s ": %s", ##args, strerror(errno))
 
 #define EXT4_SUPER_MAGIC 0xEF53
 #define EXT4_JNL_BACKUP_BLOCKS 1
@@ -54,6 +77,7 @@ extern int force;
 #define __u8 u8
 
 typedef unsigned long long u64;
+typedef signed long long s64;
 typedef unsigned int u32;
 typedef unsigned short int u16;
 typedef unsigned char u8;
@@ -72,7 +96,9 @@ struct ext2_group_desc {
 };
 
 struct fs_info {
-       u64 len;
+       s64 len;        /* If set to 0, ask the block device for the size,
+                        * if less than 0, reserve that much space at the
+                        * end of the partition, else use the size given. */
        u32 block_size;
        u32 blocks_per_group;
        u32 inodes_per_group;
@@ -82,6 +108,7 @@ struct fs_info {
        u16 feat_ro_compat;
        u16 feat_compat;
        u16 feat_incompat;
+       u32 bg_desc_reserve_blocks;
        const char *label;
        u8 no_journal;
 };
@@ -95,7 +122,6 @@ struct fs_aux_info {
        u32 inode_table_blocks;
        u32 groups;
        u32 bg_desc_blocks;
-       u32 bg_desc_reserve_blocks;
        u32 default_i_flags;
        u32 blocks_per_ind;
        u32 blocks_per_dind;
@@ -105,6 +131,8 @@ struct fs_aux_info {
 extern struct fs_info info;
 extern struct fs_aux_info aux_info;
 
+extern jmp_buf setjmp_env;
+
 static inline int log_2(int j)
 {
        int i;
@@ -116,14 +144,17 @@ static inline int log_2(int j)
 }
 
 int ext4_bg_has_super_block(int bg);
-void write_ext4_image(const char *filename, int gz, int sparse);
+void write_ext4_image(const char *filename, int gz, int sparse, int crc,
+               int wipe);
 void ext4_create_fs_aux_info(void);
 void ext4_free_fs_aux_info(void);
 void ext4_fill_in_sb(void);
 void ext4_create_resize_inode(void);
 void ext4_create_journal_inode(void);
 void ext4_update_free(void);
+void ext4_queue_sb(void);
 u64 get_file_size(const char *filename);
 u64 parse_num(const char *arg);
+void ext4_parse_sb(struct ext4_super_block *sb);
 
 #endif
index 1d2581d..daa2541 100644 (file)
  * limitations under the License.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-
 #include "ext4_utils.h"
 #include "ext4.h"
 #include "ext4_extents.h"
 #include "backed_block.h"
-
 #include "extent.h"
 
+#include <stdlib.h>
+#include <stdio.h>
+
+
 /* Creates data buffers for the first backing_len bytes of a block allocation
    and queues them to be written */
 static u8 *extent_create_backing(struct block_allocation *alloc,
@@ -55,7 +55,7 @@ static u8 *extent_create_backing(struct block_allocation *alloc,
 static void extent_create_backing_file(struct block_allocation *alloc,
        u64 backing_len, const char *filename)
 {
-       off_t offset = 0;
+       off64_t offset = 0;
        for (; alloc != NULL && backing_len > 0; get_next_region(alloc)) {
                u32 region_block;
                u32 region_len;
index 2d9d710..4e768a1 100644 (file)
@@ -14,9 +14,6 @@
  * limitations under the License.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-
 #include "ext4_utils.h"
 #include "ext4.h"
 #include "ext4_extents.h"
@@ -24,6 +21,9 @@
 #include "indirect.h"
 #include "allocate.h"
 
+#include <stdlib.h>
+#include <stdio.h>
+
 /* Creates data buffers for the first backing_len bytes of a block allocation
    and queues them to be written */
 static u8 *create_backing(struct block_allocation *alloc,
@@ -425,14 +425,14 @@ void inode_attach_resize(struct ext4_inode *inode,
                struct block_allocation *alloc)
 {
        u32 block_len = block_allocation_len(alloc);
-       u32 superblocks = block_len / aux_info.bg_desc_reserve_blocks;
+       u32 superblocks = block_len / info.bg_desc_reserve_blocks;
        u32 i, j;
        u64 blocks;
        u64 size;
 
-       if (block_len % aux_info.bg_desc_reserve_blocks)
+       if (block_len % info.bg_desc_reserve_blocks)
                critical_error("reserved blocks not a multiple of %d",
-                               aux_info.bg_desc_reserve_blocks);
+                               info.bg_desc_reserve_blocks);
 
        append_oob_allocation(alloc, 1);
        u32 dind_block = get_oob_block(alloc, 0);
@@ -442,28 +442,28 @@ void inode_attach_resize(struct ext4_inode *inode,
                critical_error_errno("calloc");
        queue_data_block((u8 *)dind_block_data, info.block_size, dind_block);
 
-       u32 *ind_block_data = calloc(info.block_size, aux_info.bg_desc_reserve_blocks);
+       u32 *ind_block_data = calloc(info.block_size, info.bg_desc_reserve_blocks);
        if (!ind_block_data)
                critical_error_errno("calloc");
        queue_data_block((u8 *)ind_block_data,
-                       info.block_size * aux_info.bg_desc_reserve_blocks,
+                       info.block_size * info.bg_desc_reserve_blocks,
                        get_block(alloc, 0));
 
-       for (i = 0; i < aux_info.bg_desc_reserve_blocks; i++) {
-               int r = (i - aux_info.bg_desc_blocks) % aux_info.bg_desc_reserve_blocks;
+       for (i = 0; i < info.bg_desc_reserve_blocks; i++) {
+               int r = (i - aux_info.bg_desc_blocks) % info.bg_desc_reserve_blocks;
                if (r < 0)
-                       r += aux_info.bg_desc_reserve_blocks;
+                       r += info.bg_desc_reserve_blocks;
 
                dind_block_data[i] = get_block(alloc, r);
 
                for (j = 1; j < superblocks; j++) {
-                       u32 b = j * aux_info.bg_desc_reserve_blocks + r;
+                       u32 b = j * info.bg_desc_reserve_blocks + r;
                        ind_block_data[r * aux_info.blocks_per_ind + j - 1] = get_block(alloc, b);
                }
        }
 
        u32 last_block = EXT4_NDIR_BLOCKS + aux_info.blocks_per_ind +
-                       aux_info.blocks_per_ind * (aux_info.bg_desc_reserve_blocks - 1) +
+                       aux_info.blocks_per_ind * (info.bg_desc_reserve_blocks - 1) +
                        superblocks - 2;
 
        blocks = ((u64)block_len + 1) * info.block_size / 512;
index e37d617..22c9424 100644 (file)
  * limitations under the License.
  */
 
-#define _GNU_SOURCE
+#include "make_ext4fs.h"
+#include "output_file.h"
+#include "ext4_utils.h"
+#include "allocate.h"
+#include "contents.h"
+#include "uuid.h"
+#include "backed_block.h"
 
 #include <dirent.h>
 #include <libgen.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include "make_ext4fs.h"
-#include "output_file.h"
-#include "ext4_utils.h"
-#include "allocate.h"
-#include "contents.h"
-#include "uuid.h"
-
 #ifdef ANDROID
 #include <private/android_filesystem_config.h>
 #endif
@@ -219,6 +218,23 @@ static u32 compute_inodes_per_group()
        return ALIGN(inodes, (info.block_size / info.inode_size));
 }
 
+static u32 compute_bg_desc_reserve_blocks()
+{
+       u32 blocks = DIV_ROUND_UP(info.len, info.block_size);
+       u32 block_groups = DIV_ROUND_UP(blocks, info.blocks_per_group);
+       u32 bg_desc_blocks = DIV_ROUND_UP(block_groups * sizeof(struct ext2_group_desc),
+                       info.block_size);
+
+       u32 bg_desc_reserve_blocks =
+                       DIV_ROUND_UP(block_groups * 1024 * sizeof(struct ext2_group_desc),
+                                       info.block_size) - bg_desc_blocks;
+
+       if (bg_desc_reserve_blocks > info.block_size / sizeof(u32))
+               bg_desc_reserve_blocks = info.block_size / sizeof(u32);
+
+       return bg_desc_reserve_blocks;
+}
+
 void reset_ext4fs_info() {
     // Reset all the global data structures used by make_ext4fs so it
     // can be called again.
@@ -227,13 +243,24 @@ void reset_ext4fs_info() {
     free_data_blocks();
 }
 
-int make_ext4fs(const char *filename, const char *directory,
-                char *mountpoint, int android, int gzip, int sparse)
+int make_ext4fs(const char *filename, s64 len)
+{
+    reset_ext4fs_info();
+    info.len = len;
+    return make_ext4fs_internal(filename, NULL, NULL, 0, 0, 0, 0, 1);
+}
+
+int make_ext4fs_internal(const char *filename, const char *directory,
+                         char *mountpoint, int android, int gzip, int sparse,
+                         int crc, int wipe)
 {
         u32 root_inode_num;
         u16 root_mode;
 
-       if (info.len == 0)
+       if (setjmp(setjmp_env))
+               return EXIT_FAILURE; /* Handle a call to longjmp() */
+
+       if (info.len <= 0)
                info.len = get_file_size(filename);
 
        if (info.len <= 0) {
@@ -278,6 +305,8 @@ int make_ext4fs(const char *filename, const char *directory,
                        EXT4_FEATURE_INCOMPAT_FILETYPE;
 
 
+       info.bg_desc_reserve_blocks = compute_bg_desc_reserve_blocks();
+
        printf("Creating filesystem with parameters:\n");
        printf("    Size: %llu\n", info.len);
        printf("    Block size: %d\n", info.block_size);
@@ -291,7 +320,7 @@ int make_ext4fs(const char *filename, const char *directory,
 
        printf("    Blocks: %llu\n", aux_info.len_blocks);
        printf("    Block groups: %d\n", aux_info.groups);
-       printf("    Reserved block group size: %d\n", aux_info.bg_desc_reserve_blocks);
+       printf("    Reserved block group size: %d\n", info.bg_desc_reserve_blocks);
 
        block_allocator_init();
 
@@ -316,13 +345,15 @@ int make_ext4fs(const char *filename, const char *directory,
 
        ext4_update_free();
 
+       ext4_queue_sb();
+
        printf("Created filesystem with %d/%d inodes and %d/%d blocks\n",
                        aux_info.sb->s_inodes_count - aux_info.sb->s_free_inodes_count,
                        aux_info.sb->s_inodes_count,
                        aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo,
                        aux_info.sb->s_blocks_count_lo);
 
-       write_ext4_image(filename, gzip, sparse);
+       write_ext4_image(filename, gzip, sparse, crc, wipe);
 
        return 0;
 }
index 8c6b259..3a26c3f 100644 (file)
@@ -21,7 +21,9 @@
 #include "ext4.h"
 
 void reset_ext4fs_info();
-int make_ext4fs(const char *filename, const char *directory,
-                char *mountpoint, int android, int gzip, int sparse);
+int make_ext4fs(const char *filename, s64 len);
+int make_ext4fs_internal(const char *filename, const char *directory,
+                         char *mountpoint, int android, int gzip, int sparse,
+                         int crc, int wipe);
 
 #endif
index 66d7aac..8742e61 100644 (file)
@@ -46,8 +46,10 @@ int main(int argc, char **argv)
         int android = 0;
         int gzip = 0;
         int sparse = 0;
+        int crc = 0;
+        int wipe = 0;
 
-        while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:fzJs")) != -1) {
+        while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:fwzJsc")) != -1) {
                 switch (opt) {
                 case 'l':
                         info.len = parse_num(optarg);
@@ -77,12 +79,18 @@ int main(int argc, char **argv)
                         android = 1;
                         mountpoint = optarg;
                         break;
+                case 'w':
+                        wipe = 1;
+                        break;
                 case 'z':
                         gzip = 1;
                         break;
                case 'J':
                        info.no_journal = 1;
                        break;
+               case 'c':
+                       crc = 1;
+                       break;
                 case 's':
                         sparse = 1;
                         break;
@@ -98,6 +106,18 @@ int main(int argc, char **argv)
                 exit(EXIT_FAILURE);
        }
 
+        if (wipe && sparse) {
+                fprintf(stderr, "Cannot specifiy both wipe and sparse\n");
+                usage(argv[0]);
+                exit(EXIT_FAILURE);
+        }
+
+        if (wipe && gzip) {
+                fprintf(stderr, "Cannot specifiy both wipe and gzip\n");
+                usage(argv[0]);
+                exit(EXIT_FAILURE);
+        }
+
         if (optind >= argc) {
                 fprintf(stderr, "Expected filename after options\n");
                 usage(argv[0]);
@@ -115,5 +135,6 @@ int main(int argc, char **argv)
                 exit(EXIT_FAILURE);
         }
 
-        return make_ext4fs(filename, directory, mountpoint, android, gzip, sparse);
+        return make_ext4fs_internal(filename, directory, mountpoint, android, gzip,
+                       sparse, crc, wipe);
 }
index 3785b06..abe8414 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define _LARGEFILE64_SOURCE
+
+#include "ext4_utils.h"
+#include "output_file.h"
+#include "sparse_format.h"
+#include "sparse_crc32.h"
+#include "wipe.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include <zlib.h>
 
-#include "ext4_utils.h"
-#include "output_file.h"
-#include "sparse_format.h"
-#include "sparse_crc32.h"
-
 #if defined(__APPLE__) && defined(__MACH__)
 #define lseek64 lseek
 #define off64_t off_t
@@ -50,9 +50,10 @@ struct output_file {
        gzFile gz_fd;
        int sparse;
        u64 cur_out_ptr;
-       int chunk_cnt;
+       u32 chunk_cnt;
        u32 crc32;
        struct output_file_ops *ops;
+       int use_crc;
 };
 
 static int file_seek(struct output_file *out, off64_t off)
@@ -171,13 +172,6 @@ static int emit_skip_chunk(struct output_file *out, u64 skip_len)
        out->cur_out_ptr += skip_len;
        out->chunk_cnt++;
 
-       /* Compute the CRC for all those zeroes.  Do it block_size bytes at a time. */
-       while (skip_len) {
-               chunk = (skip_len > info.block_size) ? info.block_size : skip_len;
-               out->crc32 = sparse_crc32(out->crc32, zero_buf, chunk);
-               skip_len -= chunk;
-       }
-
        return 0;
 }
 
@@ -239,9 +233,12 @@ static int write_chunk_raw(struct output_file *out, u64 off, u8 *data, int len)
                        return -1;
        }
 
-       out->crc32 = sparse_crc32(out->crc32, data, len);
-       if (zero_len)
-               out->crc32 = sparse_crc32(out->crc32, zero_buf, zero_len);
+       if (out->use_crc) {
+               out->crc32 = sparse_crc32(out->crc32, data, len);
+               if (zero_len)
+                       out->crc32 = sparse_crc32(out->crc32, zero_buf, zero_len);
+       }
+
        out->cur_out_ptr += rnd_up_len;
        out->chunk_cnt++;
 
@@ -251,24 +248,30 @@ static int write_chunk_raw(struct output_file *out, u64 off, u8 *data, int len)
 void close_output_file(struct output_file *out)
 {
        int ret;
+       chunk_header_t chunk_header;
 
        if (out->sparse) {
-               /* we need to seek back to the beginning and update the file header */
-               sparse_header.total_chunks = out->chunk_cnt;
-               sparse_header.image_checksum = out->crc32;
+               if (out->use_crc) {
+                       chunk_header.chunk_type = CHUNK_TYPE_CRC32;
+                       chunk_header.reserved1 = 0;
+                       chunk_header.chunk_sz = 0;
+                       chunk_header.total_sz = CHUNK_HEADER_LEN + 4;
 
-               ret = out->ops->seek(out, 0);
-               if (ret < 0)
-                       error("failure seeking to start of sparse file");
+                       out->ops->write(out, (u8 *)&chunk_header, sizeof(chunk_header));
+                       out->ops->write(out, (u8 *)&out->crc32, 4);
 
-               ret = out->ops->write(out, (u8 *)&sparse_header, sizeof(sparse_header));
-               if (ret < 0)
-                       error("failure updating sparse file header");
+                       out->chunk_cnt++;
+               }
+
+               if (out->chunk_cnt != sparse_header.total_chunks)
+                       error("sparse chunk count did not match: %d %d", out->chunk_cnt,
+                                       sparse_header.total_chunks);
        }
        out->ops->close(out);
 }
 
-struct output_file *open_output_file(const char *filename, int gz, int sparse)
+struct output_file *open_output_file(const char *filename, int gz, int sparse,
+        int chunks, int crc, int wipe)
 {
        int ret;
        struct output_file *out = malloc(sizeof(struct output_file));
@@ -292,13 +295,17 @@ struct output_file *open_output_file(const char *filename, int gz, int sparse)
                        return NULL;
                }
        } else {
-               out->ops = &file_ops;
-               out->fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-               if (out->fd < 0) {
-                       error_errno("open");
-                       free(out);
-                       return NULL;
+               if (strcmp(filename, "-")) {
+                       out->fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+                       if (out->fd < 0) {
+                               error_errno("open");
+                               free(out);
+                               return NULL;
+                       }
+               } else {
+                       out->fd = STDOUT_FILENO;
                }
+               out->ops = &file_ops;
        }
        out->sparse = sparse;
        out->cur_out_ptr = 0ll;
@@ -306,13 +313,18 @@ struct output_file *open_output_file(const char *filename, int gz, int sparse)
 
        /* Initialize the crc32 value */
        out->crc32 = 0;
+       out->use_crc = crc;
+
+       if (wipe)
+               wipe_block_device(out->fd, info.len);
 
        if (out->sparse) {
-               /* Write out the file header.  We'll update the unknown fields
-                * when we close the file.
-                */
                sparse_header.blk_sz = info.block_size,
                sparse_header.total_blks = info.len / info.block_size,
+               sparse_header.total_chunks = chunks;
+               if (out->use_crc)
+                       sparse_header.total_chunks++;
+
                ret = out->ops->write(out, (u8 *)&sparse_header, sizeof(sparse_header));
                if (ret < 0)
                        return NULL;
@@ -325,7 +337,7 @@ void pad_output_file(struct output_file *out, u64 len)
 {
        int ret;
 
-       if (len > info.len) {
+       if (len > (u64) info.len) {
                error("attempted to pad file %llu bytes past end of filesystem",
                                len - info.len);
                return;
@@ -333,7 +345,6 @@ void pad_output_file(struct output_file *out, u64 len)
        if (out->sparse) {
                /* We need to emit a DONT_CARE chunk to pad out the file if the
                 * cur_out_ptr is not already at the end of the filesystem.
-                * We also need to compute the CRC for it.
                 */
                if (len < out->cur_out_ptr) {
                        error("attempted to pad file %llu bytes less than the current output pointer",
@@ -363,7 +374,7 @@ void write_data_block(struct output_file *out, u64 off, u8 *data, int len)
 {
        int ret;
        
-       if (off + len > info.len) {
+       if (off + len > (u64) info.len) {
                error("attempted to write block %llu past end of filesystem",
                                off + len - info.len);
                return;
@@ -384,11 +395,13 @@ void write_data_block(struct output_file *out, u64 off, u8 *data, int len)
 
 /* Write a contiguous region of data blocks from a file */
 void write_data_file(struct output_file *out, u64 off, const char *file,
-                    off_t offset, int len)
+                    off64_t offset, int len)
 {
        int ret;
+       off64_t aligned_offset;
+       int aligned_diff;
 
-       if (off + len >= info.len) {
+       if (off + len >= (u64) info.len) {
                error("attempted to write block %llu past end of filesystem",
                                off + len - info.len);
                return;
@@ -400,21 +413,25 @@ void write_data_file(struct output_file *out, u64 off, const char *file,
                return;
        }
 
-       u8 *data = mmap(NULL, len, PROT_READ, MAP_SHARED, file_fd, offset);
+       aligned_offset = offset & ~(4096 - 1);
+       aligned_diff = offset - aligned_offset;
+
+       u8 *data = mmap64(NULL, len + aligned_diff, PROT_READ, MAP_SHARED, file_fd,
+                       aligned_offset);
        if (data == MAP_FAILED) {
-               error_errno("mmap");
+               error_errno("mmap64");
                close(file_fd);
                return;
        }
 
        if (out->sparse) {
-               write_chunk_raw(out, off, data, len);
+               write_chunk_raw(out, off, data + aligned_diff, len);
        } else {
                ret = out->ops->seek(out, off);
                if (ret < 0)
                        goto err;
 
-               ret = out->ops->write(out, data, len);
+               ret = out->ops->write(out, data + aligned_diff, len);
                if (ret < 0)
                        goto err;
        }
@@ -427,4 +444,3 @@ err:
        munmap(data, len);
        close(file_fd);
 }
-
index 82b0952..7866c6a 100644 (file)
  * limitations under the License.
  */
 
+#ifndef _OUTPUT_FILE_H_
+#define _OUTPUT_FILE_H_
+
 struct output_file;
 
-struct output_file *open_output_file(const char *filename, int gz, int sparse);
+struct output_file *open_output_file(const char *filename, int gz, int sparse,
+        int chunks, int crc, int wipe);
 void write_data_block(struct output_file *out, u64 off, u8 *data, int len);
 void write_data_file(struct output_file *out, u64 off, const char *file,
-                    off_t offset, int len);
+                    off64_t offset, int len);
 void pad_output_file(struct output_file *out, u64 len);
 void close_output_file(struct output_file *out);
+
+#endif
index 88c67b4..a074b28 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define _LARGEFILE64_SOURCE
-#define _FILE_OFFSET_BITS 64
+
+#include "ext4_utils.h"
+#include "sparse_format.h"
+#include "sparse_crc32.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdio.h>
 
-#include "ext4_utils.h"
-#include "output_file.h"
-#include "sparse_format.h"
-#include "sparse_crc32.h"
-
-#if defined(__APPLE__) && defined(__MACH__)
-#define lseek64 lseek
-#define off64_t off_t
-#endif
-
 #define COPY_BUF_SIZE (1024*1024)
 u8 *copybuf;
 
@@ -49,20 +41,68 @@ void usage()
   fprintf(stderr, "Usage: simg2img <sparse_image_file> <raw_image_file>\n");
 }
 
-int process_raw_chunk(FILE *in, FILE *out, u32 blocks, u32 blk_sz, u32 *crc32)
+static int read_all(int fd, void *buf, size_t len)
+{
+       size_t total = 0;
+       int ret;
+       char *ptr = buf;
+
+       while (total < len) {
+               ret = read(fd, ptr, len - total);
+
+               if (ret < 0)
+                       return ret;
+
+               if (ret == 0)
+                       return total;
+
+               ptr += ret;
+               total += ret;
+       }
+
+       return total;
+}
+
+static int write_all(int fd, void *buf, size_t len)
+{
+       size_t total = 0;
+       int ret;
+       char *ptr = buf;
+
+       while (total < len) {
+               ret = write(fd, ptr, len - total);
+
+               if (ret < 0)
+                       return ret;
+
+               if (ret == 0)
+                       return total;
+
+               ptr += ret;
+               total += ret;
+       }
+
+       return total;
+}
+
+int process_raw_chunk(int in, int out, u32 blocks, u32 blk_sz, u32 *crc32)
 {
        u64 len = (u64)blocks * blk_sz;
+       int ret;
        int chunk;
 
        while (len) {
                chunk = (len > COPY_BUF_SIZE) ? COPY_BUF_SIZE : len;
-               if (fread(copybuf, chunk, 1, in) != 1) {
-                       fprintf(stderr, "fread returned an error copying a raw chunk\n");
+               ret = read_all(in, copybuf, chunk);
+               if (ret != chunk) {
+                       fprintf(stderr, "read returned an error copying a raw chunk: %d %d\n",
+                                       ret, chunk);
                        exit(-1);
                }
                *crc32 = sparse_crc32(*crc32, copybuf, chunk);
-               if (fwrite(copybuf, chunk, 1, out) != 1) {
-                       fprintf(stderr, "fwrite returned an error copying a raw chunk\n");
+               ret = write_all(out, copybuf, chunk);
+               if (ret != chunk) {
+                       fprintf(stderr, "write returned an error copying a raw chunk\n");
                        exit(-1);
                }
                len -= chunk;
@@ -72,44 +112,48 @@ int process_raw_chunk(FILE *in, FILE *out, u32 blocks, u32 blk_sz, u32 *crc32)
 }
 
 
-int process_skip_chunk(FILE *out, u32 blocks, u32 blk_sz, u32 *crc32)
+int process_skip_chunk(int out, u32 blocks, u32 blk_sz, u32 *crc32)
 {
        /* len needs to be 64 bits, as the sparse file specifies the skip amount
         * as a 32 bit value of blocks.
         */
        u64 len = (u64)blocks * blk_sz;
-       u64 len_save;
-       u32 skip_chunk;
 
-       /* Fseek takes the offset as a long, which may be 32 bits on some systems.
-        * So, lets do a sequence of fseeks() with SEEK_CUR to get the file pointer
-        * where we want it.
-        */
-       len_save = len;
-       while (len) {
-               skip_chunk = (len > 0x80000000) ? 0x80000000 : len;
-               fseek(out, skip_chunk, SEEK_CUR);
-               len -= skip_chunk;
+       lseek64(out, len, SEEK_CUR);
+
+       return blocks;
+}
+
+int process_crc32_chunk(int in, u32 crc32)
+{
+       u32 file_crc32;
+       int ret;
+
+       ret = read_all(in, &file_crc32, 4);
+       if (ret != 4) {
+               fprintf(stderr, "read returned an error copying a crc32 chunk\n");
+               exit(-1);
        }
-       /* And compute the CRC of the skipped region a chunk at a time */
-       len = len_save;
-       while (len) {
-               skip_chunk = (skip_chunk > blk_sz) ? blk_sz : skip_chunk;
-               *crc32 = sparse_crc32(*crc32, zerobuf, skip_chunk);
-               len -= skip_chunk;
+
+       if (file_crc32 != crc32) {
+               fprintf(stderr, "computed crc32 of 0x%8.8x, expected 0x%8.8x\n",
+                        crc32, file_crc32);
+               exit(-1);
        }
 
-       return blocks;
+       return 0;
 }
 
 int main(int argc, char *argv[])
 {
-       FILE *in, *out;
+       int in;
+       int out;
        unsigned int i;
        sparse_header_t sparse_header;
        chunk_header_t chunk_header;
        u32 crc32 = 0;
        u32 total_blocks = 0;
+       int ret;
 
        if (argc != 3) {
                usage();
@@ -121,17 +165,26 @@ int main(int argc, char *argv[])
                exit(-1);
        }
 
-       if ((in = fopen(argv[1], "rb")) == 0) {
-               fprintf(stderr, "Cannot open input file %s\n", argv[1]);
-               exit(-1);
+       if (strcmp(argv[1], "-") == 0) {
+               in = STDIN_FILENO;
+       } else {
+               if ((in = open(argv[1], O_RDONLY)) == 0) {
+                       fprintf(stderr, "Cannot open input file %s\n", argv[1]);
+                       exit(-1);
+               }
        }
 
-       if ((out = fopen(argv[2], "wb")) == 0) {
-               fprintf(stderr, "Cannot open output file %s\n", argv[2]);
-               exit(-1);
+       if (strcmp(argv[2], "-") == 0) {
+               out = STDOUT_FILENO;
+       } else {
+               if ((out = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666)) == 0) {
+                       fprintf(stderr, "Cannot open output file %s\n", argv[2]);
+                       exit(-1);
+               }
        }
 
-       if (fread(&sparse_header, sizeof(sparse_header), 1, in) != 1) {
+       ret = read_all(in, &sparse_header, sizeof(sparse_header));
+       if (ret != sizeof(sparse_header)) {
                fprintf(stderr, "Error reading sparse file header\n");
                exit(-1);
        }
@@ -150,7 +203,7 @@ int main(int argc, char *argv[])
                /* Skip the remaining bytes in a header that is longer than
                 * we expected.
                 */
-               fseek(in, sparse_header.file_hdr_sz - SPARSE_HEADER_LEN, SEEK_CUR);
+               lseek64(in, sparse_header.file_hdr_sz - SPARSE_HEADER_LEN, SEEK_CUR);
        }
 
        if ( (zerobuf = malloc(sparse_header.blk_sz)) == 0) {
@@ -159,7 +212,8 @@ int main(int argc, char *argv[])
        }
 
        for (i=0; i<sparse_header.total_chunks; i++) {
-               if (fread(&chunk_header, sizeof(chunk_header), 1, in) != 1) {
+               ret = read_all(in, &chunk_header, sizeof(chunk_header));
+               if (ret != sizeof(chunk_header)) {
                        fprintf(stderr, "Error reading chunk header\n");
                        exit(-1);
                }
@@ -168,7 +222,7 @@ int main(int argc, char *argv[])
                        /* Skip the remaining bytes in a header that is longer than
                         * we expected.
                         */
-                       fseek(in, sparse_header.chunk_hdr_sz - CHUNK_HEADER_LEN, SEEK_CUR);
+                       lseek64(in, sparse_header.chunk_hdr_sz - CHUNK_HEADER_LEN, SEEK_CUR);
                }
 
                switch (chunk_header.chunk_type) {
@@ -189,9 +243,11 @@ int main(int argc, char *argv[])
                        total_blocks += process_skip_chunk(out,
                                         chunk_header.chunk_sz, sparse_header.blk_sz, &crc32);
                        break;
+                   case CHUNK_TYPE_CRC32:
+                       process_crc32_chunk(in, crc32);
+                       break;
                    default:
                        fprintf(stderr, "Unknown chunk type 0x%4.4x\n", chunk_header.chunk_type);
-                       exit(-1);
                }
 
        }
@@ -201,13 +257,13 @@ int main(int argc, char *argv[])
         * will make the file the correct size.  Make sure the offset is
         * computed in 64 bits, and the function called can handle 64 bits.
         */
-       if (ftruncate(fileno(out), (u64)total_blocks * sparse_header.blk_sz)) {
+       if (ftruncate64(out, (u64)total_blocks * sparse_header.blk_sz)) {
                fprintf(stderr, "Error calling ftruncate() to set the image size\n");
                exit(-1);
        }
 
-       fclose(in);
-       fclose(out);
+       close(in);
+       close(out);
 
        if (sparse_header.total_blks != total_blocks) {
                fprintf(stderr, "Wrote %d blocks, expected to write %d blocks\n",
@@ -215,12 +271,6 @@ int main(int argc, char *argv[])
                exit(-1);
        }
 
-       if (sparse_header.image_checksum != crc32) {
-               fprintf(stderr, "computed crc32 of 0x%8.8x, expected 0x%8.8x\n",
-                        crc32, sparse_header.image_checksum);
-               exit(-1);
-       }
-
        exit(0);
 }
 
index ba13214..6c62c34 100644 (file)
@@ -33,6 +33,7 @@ typedef struct sparse_header {
 #define CHUNK_TYPE_RAW         0xCAC1
 #define CHUNK_TYPE_FILL                0xCAC2
 #define CHUNK_TYPE_DONT_CARE   0xCAC3
+#define CHUNK_TYPE_CRC32    0xCAC4
 
 typedef struct chunk_header {
   __le16       chunk_type;     /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */
@@ -41,7 +42,9 @@ typedef struct chunk_header {
   __le32       total_sz;       /* in bytes of chunk input file including chunk header and data */
 } chunk_header_t;
 
-/* Following a Raw or Fill chunk is data.  For a Raw chunk, it's the data in chunk_sz * blk_sz.
+/* Following a Raw or Fill or CRC32 chunk is data.
+ *  For a Raw chunk, it's the data in chunk_sz * blk_sz.
  *  For a Fill chunk, it's 4 bytes of the fill data.
+ *  For a CRC32 chunk, it's 4 bytes of CRC32
  */
 
diff --git a/ext4_utils/wipe.c b/ext4_utils/wipe.c
new file mode 100644 (file)
index 0000000..3bd33e5
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ext4_utils.h"
+#include "wipe.h"
+
+#if defined(__linux__)
+
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+
+#ifndef BLKDISCARD
+#define BLKDISCARD _IO(0x12,119)
+#endif
+
+#ifndef BLKSECDISCARD
+#define BLKSECDISCARD _IO(0x12,125)
+#endif
+
+int wipe_block_device(int fd, s64 len)
+{
+       u64 range[2];
+       int ret;
+
+       range[0] = 0;
+       range[1] = len;
+       ret = ioctl(fd, BLKSECDISCARD, &range);
+       if (ret < 0) {
+               range[0] = 0;
+               range[1] = len;
+               ret = ioctl(fd, BLKDISCARD, &range);
+               if (ret < 0) {
+                       warn("Discard failed\n");
+                       return 1;
+               } else {
+                       warn("Wipe via secure discard failed, used discard instead\n");
+                       return 0;
+               }
+       }
+
+       return 0;
+}
+#else
+int wipe_block_device(int fd, s64 len)
+{
+       error("wipe not supported on non-linux platforms");
+       return 1;
+}
+#endif
+
diff --git a/ext4_utils/wipe.h b/ext4_utils/wipe.h
new file mode 100644 (file)
index 0000000..814877d
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WIPE_H_
+#define _WIPE_H_
+
+int wipe_block_device(int fd, s64 len);
+
+#endif
index 02e3292..c549bc1 100644 (file)
@@ -16,7 +16,7 @@
 
 #include <assert.h>
 #include <string.h>
-#include <sys/endian.h>
+#include <endian.h>
 
 #include "fat.h"
 
index 5ab33d7..fb19a70 100644 (file)
@@ -16,7 +16,7 @@
 
 #include <assert.h>
 #include <string.h>
-#include <sys/endian.h>
+#include <endian.h>
 
 #include "fatblock.h"
 #include "fat.h"
index 50663ec..690c5e8 100644 (file)
@@ -19,5 +19,5 @@ LOCAL_MODULE := libublock
 LOCAL_MODULE_TAGS := optional
 LOCAL_SRC_FILES := ublock.c
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_PRELINK_MODULE := false
+
 include $(BUILD_SHARED_LIBRARY)
index 582ddc9..5053e7d 100644 (file)
@@ -1,3 +1 @@
-ifeq ($(TARGET_ARCH),arm)
 include $(call all-subdir-makefiles)
-endif
index 5b75c3d..21b76bf 100644 (file)
@@ -88,23 +88,6 @@ class AddIntsService : public BBinder
     int cpu_;
 };
 
-// Workaround for missing sched_setaffinity(2) and getcpu(2)
-#ifndef CPU_SETSIZE
-#define HAVE_CUSTOM_CPU_SETSIZE 1
-#define CPU_SETSIZE 1024
-struct getcpu_cache;
-typedef struct { uint64_t bits[CPU_SETSIZE / 64]; } cpu_set_t;
-static int sched_getaffinity(pid_t pid, unsigned int cpusetsize,
-                             cpu_set_t *set);
-static int sched_setaffinity(pid_t pid, unsigned int cpusetsize,
-                             cpu_set_t *mask);
-//static int getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache);
-static int sched_getcpu(void);
-static int CPU_ISSET(int cpu, const cpu_set_t *set);
-static void CPU_SET(int cpu, cpu_set_t *set);
-static void CPU_ZERO(cpu_set_t *set);
-#endif /* !CPU_SETSIZE */
-
 // File scope function prototypes
 static void server(void);
 static void client(void);
@@ -311,7 +294,7 @@ static void client(void)
             cerr << "expected: " << expected << endl;
         }
 
-        if (options.iterDelay > 0.0) { testDelay(options.iterDelay); }
+        if (options.iterDelay > 0.0) { testDelaySpin(options.iterDelay); }
     }
 
     // Display the results
@@ -399,74 +382,3 @@ static ostream &operator<<(ostream &stream, const cpu_set_t& set)
 
     return stream;
 }
-
-#ifdef HAVE_CUSTOM_CPU_SETSIZE
-// ======== Local implementation of system calls with missing bionic call stubs
-static int sched_getaffinity(pid_t pid, unsigned int cpusetsize,
-                             cpu_set_t *set)
-{
-    int rv;
-
-    rv = syscall(__NR_sched_getaffinity, pid, cpusetsize, set);
-    if (rv < 0) { return rv; }
-
-    // Kernel implementation of sched_getaffinity() returns the number
-    // of bytes in the set that it set.  Set the rest of our set bits
-    // to 0.
-    memset(((char *) set) + rv, 0x00, sizeof(cpu_set_t) - rv);
-
-    return 0;
-}
-
-static int sched_setaffinity(pid_t pid, unsigned int cpusetsize,
-                             cpu_set_t *mask)
-{
-    int rv;
-
-    rv = syscall(__NR_sched_setaffinity, pid, cpusetsize, mask);
-
-    return rv;
-}
-
-static int getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
-{
-    int rv;
-
-    rv = syscall(345, cpu, node, tcache);
-
-    return rv;
-}
-
-static int sched_getcpu(void)
-{
-    unsigned cpu;
-    int ret = getcpu(&cpu, NULL, NULL);
-    if (ret == 0)
-        ret = (int)cpu;
-}
-
-static int CPU_ISSET(int cpu, const cpu_set_t *set)
-{
-    if (cpu < 0) { return 0; }
-    if ((unsigned) cpu >= (sizeof(cpu_set_t) * CHAR_BIT)) { return 0; }
-
-    if ((*((uint64_t *)set + (cpu / 64))) & (1ULL << (cpu % 64))) {
-        return true;
-    }
-
-    return false;
-}
-
-static void CPU_SET(int cpu, cpu_set_t *set)
-{
-    if (cpu < 0) { return; }
-    if ((unsigned) cpu > (sizeof(cpu_set_t) * CHAR_BIT)) { return; }
-
-    *((uint64_t *)set + (cpu / 64)) |= 1ULL << (cpu % 64);
-}
-
-static void CPU_ZERO(cpu_set_t *set)
-{
-    memset(set, 0x00, sizeof(cpu_set_t));
-}
-#endif /* HAVE_CUSTOM_CPU_SETSIZE */
index 594565d..5dcf130 100644 (file)
@@ -61,6 +61,7 @@ endef
 # First, the tests in 'common'
 
 sources := \
+    common/test_clock.c \
     common/test_cpu_set.c \
     common/test_drand48.c \
     common/test_executable_destructor.c \
@@ -78,6 +79,7 @@ sources := \
     common/test_seteuid.c \
     common/test_static_cpp_mutex.cpp \
     common/test_strftime_2039.c \
+    common/test_strptime.c \
     common/test_tm_zone.c \
     common/test_udp.c \
 
@@ -169,7 +171,7 @@ $(call device-test, $(sources))
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := bionic/lib_relocs.c
 LOCAL_MODULE    := libtest_relocs
-LOCAL_PRELINK_MODULE := false
+
 LOCAL_MODULE_TAGS := tests
 include $(BUILD_SHARED_LIBRARY)
 
@@ -188,7 +190,7 @@ include $(BUILD_EXECUTABLE)
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := bionic/lib_static_init.cpp
 LOCAL_MODULE    := libtest_static_init
-LOCAL_PRELINK_MODULE := false
+
 LOCAL_MODULE_TAGS := tests
 include $(BUILD_SHARED_LIBRARY)
 
@@ -204,7 +206,7 @@ include $(BUILD_EXECUTABLE)
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := bionic/libdlclosetest1.cpp
 LOCAL_MODULE := libdlclosetest1
-LOCAL_PRELINK_MODULE := false
+
 LOCAL_MODULE_TAGS := tests
 include $(BUILD_SHARED_LIBRARY)
 
@@ -213,7 +215,7 @@ include $(BUILD_SHARED_LIBRARY)
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := bionic/libdlclosetest2.c
 LOCAL_MODULE := libdlclosetest2
-LOCAL_PRELINK_MODULE := false
+
 LOCAL_MODULE_TAGS := tests
 include $(BUILD_SHARED_LIBRARY)
 
index 928057a..348df17 100644 (file)
@@ -76,6 +76,10 @@ check_library(const char*  libname)
     }
 
     fprintf(stderr, "%s unloaded.\n", libname);
+    if (y != 2) {
+        fprintf(stderr, "Static destructors was not called on dlclose()!\n");
+        return 2;
+    }
     return 0;
 }
 
diff --git a/tests/bionic/libc/common/test_clock.c b/tests/bionic/libc/common/test_clock.c
new file mode 100644 (file)
index 0000000..6d3752e
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Minimal test program for clock
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+// this thread soaks the CPU so that clock() function will advance
+void *cpu_hog(void *arg)
+{
+    for (;;) {
+        // the system call should not be optimized away by the compiler
+        (void) getpid();
+    }
+}
+
+int main(int argc, char **argv)
+{
+    pthread_t thread;
+    clock_t ticks10, ticks15;
+
+    // do not call clock() here so we can test initialization
+
+    // soak the CPU for 10 seconds, then read clock
+    pthread_create(&thread, NULL, cpu_hog, NULL);
+    sleep(10);
+    ticks10 = clock();
+
+    // soak the CPU for 5 more seconds, then read clock
+    sleep(5);
+    ticks15 = clock();
+
+    // print the results
+    printf("CLOCKS_PER_SEC = %ld ticks/sec\n", (clock_t) CLOCKS_PER_SEC);
+    printf("At 10 secs clock=%lu, at 15 secs clock=%lu\n", ticks10, ticks15);
+
+    // exit could wait for the other thread to complete
+    _exit(EXIT_SUCCESS);
+}
diff --git a/tests/bionic/libc/common/test_strptime.c b/tests/bionic/libc/common/test_strptime.c
new file mode 100644 (file)
index 0000000..3cfc03b
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Minimal test program for strptime
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+int main(int argc, char **argv)
+{
+    struct tm tm;
+    char buf[255];
+
+    // For now, only test a couple of formats that use recursion
+
+    memset(&tm, 0, sizeof(tm));
+    strptime("11:14", "%R", &tm);
+    strftime(buf, sizeof(buf), "%H:%M", &tm);
+    puts(buf);
+    puts(!strcmp(buf, "11:14") ? "OK" : "FAILED");
+
+    memset(&tm, 0, sizeof(tm));
+    strptime("09:41:53", "%T", &tm);
+    strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
+    puts(buf);
+    puts(!strcmp(buf, "09:41:53") ? "OK" : "FAILED");
+
+    return EXIT_SUCCESS;
+}
index bd9b25e..c88c6fe 100755 (executable)
@@ -165,7 +165,7 @@ set_adb_cmd_log $TMPDIR/adb.log.txt
 
 DEVICE_TEST_DIR=/data/local/bionic-test
 DEVICE_TEST=$DEVICE_TEST_DIR/$TESTNAME
-adb_cmd mkdir -p $DEVICE_TEST_DIR
+adb_cmd mkdir $DEVICE_TEST_DIR
 $ADB_CMD push $TESTEXE $DEVICE_TEST_DIR/
 if [ $? != 0 ] ; then
     echo "ERROR: Can't push test to device!"
index 3943506..0b8bc68 100644 (file)
 #include <linux/fb.h>
 #include <linux/kd.h>
 
-#include <pixelflinger/pixelflinger.h>
-
-#include "minui.h"
-
-typedef struct {
-    GGLSurface texture;
-    unsigned cwidth;
-    unsigned cheight;
-    unsigned ascent;
-} GRFont;
-
-static GGLContext *gr_context = 0;
-static GGLSurface gr_framebuffer[2];
+struct simple_fb {
+    void *data;
+    int width;
+    int height;
+    int stride;
+    int bpp;
+};
+
+static struct simple_fb gr_fbs[2];
 static unsigned gr_active_fb = 0;
 
 static int gr_fb_fd = -1;
@@ -53,10 +49,11 @@ struct timespec tv, tv2;
 static void dumpinfo(struct fb_fix_screeninfo *fi,
                      struct fb_var_screeninfo *vi);
 
-static int get_framebuffer(GGLSurface *fb)
+static int get_framebuffer(struct simple_fb *fb, unsigned bpp)
 {
     int fd;
     void *bits;
+    int bytes_per_pixel;
 
     fd = open("/dev/graphics/fb0", O_RDWR);
     if (fd < 0) {
@@ -67,12 +64,21 @@ static int get_framebuffer(GGLSurface *fb)
         }
     }
 
-    if(ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
+    if(ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
         perror("failed to get fb0 info");
         return -1;
     }
 
-    if(ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
+    if (bpp && vi.bits_per_pixel != bpp) {
+        printf("bpp != %d, forcing...\n", bpp);
+        vi.bits_per_pixel = bpp;
+        if(ioctl(fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
+            perror("failed to force bpp");
+            return -1;
+        }
+    }
+
+    if(ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
         perror("failed to get fb0 info");
         return -1;
     }
@@ -85,21 +91,22 @@ static int get_framebuffer(GGLSurface *fb)
         return -1;
     }
 
-    fb->version = sizeof(*fb);
+    bytes_per_pixel = vi.bits_per_pixel >> 3;
+
     fb->width = vi.xres;
     fb->height = vi.yres;
-    fb->stride = fi.line_length / (vi.bits_per_pixel >> 3);
+    fb->stride = fi.line_length / bytes_per_pixel;
     fb->data = bits;
-    fb->format = GGL_PIXEL_FORMAT_RGB_565;
+    fb->bpp = vi.bits_per_pixel;
 
     fb++;
 
-    fb->version = sizeof(*fb);
     fb->width = vi.xres;
     fb->height = vi.yres;
-    fb->stride = fi.line_length / (vi.bits_per_pixel >> 3);
-    fb->data = (void*) (((unsigned) bits) + vi.yres * vi.xres * 2);
-    fb->format = GGL_PIXEL_FORMAT_RGB_565;
+    fb->stride = fi.line_length / bytes_per_pixel;
+    fb->data = (void *)((unsigned long)bits +
+                        vi.yres * vi.xres * bytes_per_pixel);
+    fb->bpp = vi.bits_per_pixel;
 
     return fd;
 }
@@ -129,7 +136,7 @@ static void dumpinfo(struct fb_fix_screeninfo *fi, struct fb_var_screeninfo *vi)
 
 }
 
-int gr_init(void)
+int gr_init(int bpp, int id)
 {
     int fd = -1;
 
@@ -144,7 +151,7 @@ int gr_init(void)
         }
     }
 
-    gr_fb_fd = get_framebuffer(gr_framebuffer);
+    gr_fb_fd = get_framebuffer(gr_fbs, bpp);
 
     if(gr_fb_fd < 0) {
         if (fd >= 0) {
@@ -157,8 +164,8 @@ int gr_init(void)
     gr_vt_fd = fd;
 
         /* start with 0 as front (displayed) and 1 as back (drawing) */
-    gr_active_fb = 0;
-    set_active_framebuffer(0);
+    gr_active_fb = id;
+    set_active_framebuffer(id);
 
     return 0;
 }
@@ -177,67 +184,103 @@ void gr_exit(void)
 
 int gr_fb_width(void)
 {
-    return gr_framebuffer[0].width;
+    return gr_fbs[0].width;
 }
 
 int gr_fb_height(void)
 {
-    return gr_framebuffer[0].height;
+    return gr_fbs[0].height;
 }
 
 uint16_t red = 0xf800;
 uint16_t green = 0x07e0;
 uint16_t blue = 0x001f;
+uint16_t white = 0xffff;
+uint16_t black = 0x0;
+
+uint32_t red32 = 0x00ff0000;
+uint32_t green32 = 0x0000ff00;
+uint32_t blue32 = 0x000000ff;
+uint32_t white32 = 0x00ffffff;
+uint32_t black32 = 0x0;
+
+void draw_grid(int w, int h, void* _loc) {
+    int i, j;
+    int v;
+    int stride = fi.line_length / (vi.bits_per_pixel >> 3);
+    uint16_t *loc = _loc;
+    uint32_t *loc32 = _loc;
+
+    for (j = 0; j < h/2; j++) {
+        for (i = 0; i < w/2; i++)
+            if (vi.bits_per_pixel == 16)
+                loc[i + j*(stride)] = red;
+            else
+                loc32[i + j*(stride)] = red32;
+        for (; i < w; i++)
+            if (vi.bits_per_pixel == 16)
+                loc[i + j*(stride)] = green;
+            else
+                loc32[i + j*(stride)] = green32;
+    }
 
-void draw_grid(int w, int h, uint16_t* loc) {
-  int i, j;
-  int v;
-  int stride = fi.line_length / (vi.bits_per_pixel >> 3);
-
-  for (j = 0; j < h/2; j++) {
-    for (i = 0; i < w/2; i++)
-      loc[i + j*(stride)] = red;
-    for (; i < w; i++)
-      loc[i + j*(stride)] = green;
-  }
-  for (; j < h; j++) {
-    for (i = 0; i < w/2; i++)
-      loc[i + j*(stride)] = blue;
-    for (; i < w; i++)
-      loc[i + j*(stride)] = 0xffff;
-  }
+    for (; j < h; j++) {
+        for (i = 0; i < w/2; i++)
+            if (vi.bits_per_pixel == 16)
+                loc[i + j*(stride)] = blue;
+            else
+                loc32[i + j*(stride)] = blue32;
+        for (; i < w; i++)
+            if (vi.bits_per_pixel == 16)
+                loc[i + j*(stride)] = white;
+            else
+                loc32[i + j*(stride)] = white32;
+    }
 
 }
 
-void clear_screen(int w, int h, uint16_t* loc)
+void clear_screen(int w, int h, void* _loc)
 {
     int i,j;
     int stride = fi.line_length / (vi.bits_per_pixel >> 3);
-
-  for (j = 0; j < h; j++)
-    for (i = 0; i < w; i++)
-      loc[i + j*(stride)] = 0x0000;
+    uint16_t *loc = _loc;
+    uint32_t *loc32 = _loc;
+
+    for (j = 0; j < h; j++)
+        for (i = 0; i < w; i++)
+            if (vi.bits_per_pixel == 16)
+                loc[i + j*(stride)] = black;
+            else
+                loc32[i + j*(stride)] = black32;
 }
 
 int main(int argc, char **argv) {
   int w;
   int h;
   int id = 0;
-  gr_init();
-  w = vi.xres;
-  h = vi.yres;
-  clear_screen(w, h, (uint16_t *)gr_framebuffer[0].data);
-  clear_screen(w, h, (uint16_t *)gr_framebuffer[1].data);
-
-  if (argc > 2) {
-    w = atoi(argv[1]);
-    h = atoi(argv[2]);
+  int bpp = 0;
+
+  if (argc > 1)
+      bpp = atoi(argv[1]);
+
+  if (argc > 4)
+      id = !!atoi(argv[4]);
+
+  gr_init(bpp, id);
+
+  if (argc > 3) {
+      w = atoi(argv[2]);
+      h = atoi(argv[3]);
+  } else {
+      w = vi.xres;
+      h = vi.yres;
   }
 
-  if (argc > 3)
-      id = !!atoi(argv[3]);
+  clear_screen(vi.xres, vi.yres, gr_fbs[0].data);
+  clear_screen(vi.xres, vi.yres, gr_fbs[1].data);
+
+  draw_grid(w, h, gr_fbs[id].data);
 
-  draw_grid(w, h, (uint16_t *)gr_framebuffer[id].data);
   set_active_framebuffer(!id);
   set_active_framebuffer(id);
 
index 39d0016..f50f790 100644 (file)
@@ -1,5 +1,5 @@
 # Copyright 2006 The Android Open Source Project
-
+ifeq ($(TARGET_ARCH),arm)
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -12,3 +12,4 @@ LOCAL_MODULE:= icache
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
+endif
index 7e04742..3b75914 100644 (file)
@@ -35,6 +35,7 @@ struct timeval tvDelta(const struct timeval *first,
     const struct timeval *second);
 
 void testDelay(float amt);
+void testDelaySpin(float amt);
 
 // Pseudo Random Utilities
 int testRandBool(void);
index 42758ae..f814dac 100644 (file)
@@ -23,6 +23,6 @@ LOCAL_SRC_FILES:= testUtil.c
 LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../include
 LOCAL_CFLAGS += -std=c99
 LOCAL_SHARED_LIBRARIES += libcutils libutils
-LOCAL_PRELINK_MODULE := false
+
 
 include $(BUILD_STATIC_LIBRARY)
index abe57d1..d63fbba 100644 (file)
@@ -282,6 +282,27 @@ void testDelay(float amt)
     } while (true);
 }
 
+// Delay spins for the number of seconds specified by amt or a greater
+// amount.  The amt variable is of type float and thus non-integer amounts
+// of time can be specified.  Differs from testDelay() in that
+// testDelaySpin() performs a spin loop, instead of using nanosleep().
+void testDelaySpin(float amt)
+{
+    struct timespec   start, current, delta;
+
+    // Get the time at which we started
+    clock_gettime(CLOCK_MONOTONIC, &start);
+
+    do {
+        // Get current time
+        clock_gettime(CLOCK_MONOTONIC, &current);
+
+        // How much time is left
+        delta = tsDelta(&start, &current);
+        if (ts2double(&delta) > amt) { break; }
+    } while (true);
+}
+
 /*
  * Hex Dump
  *
index 7fc6c0a..3b893f6 100644 (file)
@@ -1,5 +1,5 @@
 # Copyright 2006 The Android Open Source Project
-
+ifeq ($(TARGET_ARCH),arm)
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -18,3 +18,4 @@ LOCAL_MODULE_TAGS := optional
 LOCAL_CFLAGS += -fomit-frame-pointer
 
 include $(BUILD_EXECUTABLE)
+endif
index dd78e4f..e9a7cc4 100644 (file)
@@ -18,9 +18,9 @@ LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
 LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := wifiLoadScanAssoc_test
+LOCAL_MODULE := wifiLoadScanAssoc
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativestresstest
-LOCAL_SRC_FILES := wifiLoadScanAssoc_test.c
+LOCAL_SRC_FILES := wifiLoadScanAssoc.c
 LOCAL_SHARED_LIBRARIES += libcutils libutils libhardware_legacy
 LOCAL_STATIC_LIBRARIES += libtestUtil
 LOCAL_C_INCLUDES += system/extras/tests/include \
similarity index 86%
rename from tests/wifi/stress/wifiLoadScanAssoc_test.c
rename to tests/wifi/stress/wifiLoadScanAssoc.c
index 250cdd6..62b179c 100644 (file)
@@ -101,7 +101,6 @@ bool_t eFlag, sFlag, pFlag;
 
 // File scope prototypes
 static void init(void);
-static void execCmd(const char *cmd);
 static void randDelay(void);
 static void randBind(const cpu_set_t *availSet, int *chosenCPU);
 
@@ -307,7 +306,7 @@ main(int argc, char *argv[])
                 testPrintE("Command too long for: %s\n", CMD_STATUS);
                 exit(22);
             }
-            execCmd(cmd);
+            testExecCmd(cmd);
         }
 
         // Stop Supplicant
@@ -353,7 +352,7 @@ main(int argc, char *argv[])
             testPrintE("Command too long for: %s\n", CMD_STATUS);
             exit(22);
         }
-        execCmd(cmd);
+        testExecCmd(cmd);
     }
 
     // Start framework
@@ -362,7 +361,7 @@ main(int argc, char *argv[])
         testPrintE("Command too long for: %s\n", CMD_START_FRAMEWORK);
         exit(27);
     }
-    execCmd(cmd);
+    testExecCmd(cmd);
 
     testPrintI("Successfully completed %u passes", pass - startPass);
 
@@ -411,7 +410,7 @@ init(void)
         testPrintE("Command too long for: %s\n", CMD_STOP_FRAMEWORK);
         exit(41);
     }
-    execCmd(cmd);
+    testExecCmd(cmd);
 
     // Is WiFi driver loaded?
     // If so stop the wpa_supplicant and unload the driver.
@@ -437,65 +436,6 @@ init(void)
 }
 
 /*
- * Execute Command
- *
- * Executes the command pointed to by cmd.  Which CPU executes the
- * command is randomly selected from the set of CPUs that were
- * available during testcase initialization.  Output from the
- * executed command is captured and sent to LogCat Info.  Once
- * the command has finished execution, it's exit status is captured
- * and checked for an exit status of zero.  Any other exit status
- * causes diagnostic information to be printed and an immediate
- * testcase failure.
- */
-void
-execCmd(const char *cmd)
-{
-    FILE *fp;
-    int rv;
-    int status;
-    char str[MAXSTR];
-    int cpu;
-
-    // Randomly bind to one of the available CPUs
-    randBind(&availCPU, &cpu);
-
-    // Display CPU executing on and command to be executed
-    testPrintI("CPU: %u cmd: %s", cpu, cmd);
-
-    // Execute the command
-    fflush(stdout);
-    if ((fp = popen(cmd, "r")) == NULL) {
-        testPrintE("execCmd popen failed, errno: %i", errno);
-        exit(61);
-    }
-
-    // Obtain and display each line of output from the executed command
-    while (fgets(str, sizeof(str), fp) != NULL) {
-        if ((strlen(str) > 1) && (str[strlen(str) - 1] == '\n')) {
-            str[strlen(str) - 1] = '\0';
-        }
-        testPrintI(" out: %s", str);
-        testDelay(0.1);
-    }
-
-    // Obtain and check return status of executed command.
-    // Fail on non-zero exit status
-    status = pclose(fp);
-    if (!(WIFEXITED(status) && (WEXITSTATUS(status) == 0))) {
-        testPrintE("Unexpected command failure");
-        testPrintE("  status: %#x", status);
-        if (WIFEXITED(status)) {
-            testPrintE("WEXITSTATUS: %i", WEXITSTATUS(status));
-        }
-        if (WIFSIGNALED(status)) {
-            testPrintE("WTERMSIG: %i", WTERMSIG(status));
-        }
-        exit(62);
-    }
-}
-
-/*
  * Random Delay
  *
  * Delays for a random amount of time within the range given
@@ -511,11 +451,10 @@ void randDelay(void)
 {
     const unsigned long nanosecspersec = 1000000000;
     float            fract, biasedFract, amt;
-    struct timespec  remaining;
-    struct timeval   start, current, delta;
+    struct timeval   startTime, endTime;
 
     // Obtain start time
-    gettimeofday(&start, NULL);
+    gettimeofday(&startTime, NULL);
 
     // Determine random amount to sleep.
     // Values closer to delayMin are prefered by an amount
@@ -524,21 +463,13 @@ void randDelay(void)
     biasedFract = pow(DELAY_EXP, fract) / pow(DELAY_EXP, 1.0);
     amt = delayMin + ((delayMax - delayMin) * biasedFract);
 
-    do {
-        // Get current time
-        gettimeofday(&current, NULL);
-
-        // How much time is left
-        delta = tvDelta(&start, &current);
-        if (tv2double(&delta) > amt) { break; }
-
-        // Request to sleep for the remaining time
-        remaining = double2ts(amt - tv2double(&delta));
-        (void) nanosleep(&remaining, NULL);
-    } while (true);
+    // Delay
+    testDelay(amt);
 
+    // Obtain end time and display delta
+    gettimeofday(&endTime, NULL);
     testPrintI("delay: %.2f",
-        (float) (tv2double(&current) - tv2double(&start)));
+        (float) (tv2double(&endTime) - tv2double(&startTime)));
 }
 
 static void