Upstream-Status: inappropriate From 0a7d5b11e62e54f88ce3a49d0c2327d537b3f531 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Sun, 5 Jun 2011 15:42:24 -0500 Subject: [PATCH 11/19] Copy files into the filesystem a piece at a time Instead of malloc-ing and entire files-worth of memory, reading it in, and writing it to the filesystem, do it a piece at a time. This allows very large files to be supported. Also, use off_t and make it 64-bits so it supports filesystems and files larger than 2GB. Full support for >2GB files is not quite here, that requires rev 1 filesystem support, which is coming later. --- genext2fs.c | 35 +++++++++++++++++++++++------------ 1 files changed, 23 insertions(+), 12 deletions(-) diff --git a/genext2fs.c b/genext2fs.c index f79438d..8a7f589 100644 --- a/genext2fs.c +++ b/genext2fs.c @@ -53,6 +53,12 @@ // along with -q, -P, -U +/* + * Allow fseeko/off_t to be 64-bit offsets to allow filesystems and + * individual files >2GB. + */ +#define _FILE_OFFSET_BITS 64 + #include #include @@ -603,7 +609,6 @@ struct hdlinks_s typedef struct { FILE *f; - uint8 *data; superblock *sb; groupdescriptor *gd; uint32 nheadblocks; @@ -1907,30 +1912,38 @@ mklink_fs(filesystem *fs, uint32 parent_nod, const char *name, size_t size, uint return nod; } +#define COPY_BLOCKS 16 +#define CB_SIZE (COPY_BLOCKS * BLOCKSIZE) + // make a file from a FILE* static uint32 -mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, size_t size, FILE *f, uid_t uid, gid_t gid, uint32 ctime, uint32 mtime) +mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, off_t size, FILE *f, uid_t uid, gid_t gid, uint32 ctime, uint32 mtime) { uint8 * b; uint32 nod = mknod_fs(fs, parent_nod, name, mode|FM_IFREG, uid, gid, 0, 0, ctime, mtime); nod_info *ni; inode *node = get_nod(fs, nod, &ni); + size_t readbytes; inode_pos ipos; + + b = malloc(CB_SIZE); + if (!b) + error_msg_and_die("mkfile_fs: out of memory"); inode_pos_init(fs, &ipos, nod, INODE_POS_TRUNCATE, NULL); node->i_size = size; - if (size) { - if(!(b = (uint8*)calloc(rndup(size, BLOCKSIZE), 1))) - error_msg_and_die("not enough mem to read file '%s'", name); - if(f) - if (fread(b, size, 1, f) != 1) // FIXME: ugly. use mmap() ... - error_msg_and_die("fread failed"); + while (size) { + readbytes = fread(b, 1, CB_SIZE, f); + if ((size < CB_SIZE && readbytes != size) + || (size >= CB_SIZE && readbytes != CB_SIZE)) + error_msg_and_die("fread failed"); extend_inode_blk(fs, &ipos, b, - rndup(size, BLOCKSIZE) / BLOCKSIZE); - free(b); + rndup(readbytes, BLOCKSIZE) / BLOCKSIZE); + size -= readbytes; } inode_pos_finish(fs, &ipos); put_nod(ni); + free(b); return nod; } @@ -2306,8 +2319,6 @@ alloc_fs(int swapit, char *fname, uint32 nbblocks, FILE *srcfile) if (!fs->hdlinks.hdl) error_msg_and_die("Not enough memory"); fs->hdlinks.count = 0 ; - fs->sb = (superblock *) (fs->data + BLOCKSIZE); - fs->gd = (groupdescriptor *) (fs->sb + 1); if (strcmp(fname, "-") == 0) fs->f = tmpfile(); -- 1.7.4.1