OSDN Git Service

ext4_utils: Convert simg2img from stdio to fds
authorColin Cross <ccross@android.com>
Sat, 25 Dec 2010 09:55:26 +0000 (01:55 -0800)
committerColin Cross <ccross@android.com>
Wed, 5 Jan 2011 23:54:16 +0000 (15:54 -0800)
Bionic stdio does not support 64 bit file offsets

Change-Id: Ic7f2d12ea2007e55c9787e9c4bf2f4d4635f94f5

ext4_utils/simg2img.c

index 38b6191..88c9003 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include "ext4_utils.h"
-#include "output_file.h"
 #include "sparse_format.h"
 #include "sparse_crc32.h"
 
@@ -47,20 +46,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;
@@ -70,32 +117,26 @@ 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;
-       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.
-        */
-       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(FILE *in, u32 crc32)
+int process_crc32_chunk(int in, u32 crc32)
 {
        u32 file_crc32;
-       if (fread(&file_crc32, 4, 1, in) != 1) {
-               fprintf(stderr, "fread returned an error copying a crc32 chunk\n");
+       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);
        }
 
@@ -110,12 +151,14 @@ int process_crc32_chunk(FILE *in, u32 crc32)
 
 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();
@@ -127,17 +170,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)) == 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);
        }
@@ -156,7 +208,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) {
@@ -165,7 +217,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);
                }
@@ -174,7 +227,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) {
@@ -210,13 +263,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",