From patchwork Mon Oct 27 19:48:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suriyan Ramasami X-Patchwork-Id: 403942 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 5103814003E for ; Tue, 28 Oct 2014 07:55:52 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 26D0AA7451; Mon, 27 Oct 2014 21:55:46 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Z9ZdAWyrL9zt; Mon, 27 Oct 2014 21:55:45 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id D6151A7584; Mon, 27 Oct 2014 21:55:41 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 3A297A7424 for ; Mon, 27 Oct 2014 20:48:57 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qnfUFX9NHMjH for ; Mon, 27 Oct 2014 20:48:57 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-ob0-f181.google.com (mail-ob0-f181.google.com [209.85.214.181]) by theia.denx.de (Postfix) with ESMTPS id 7D511A73E8 for ; Mon, 27 Oct 2014 20:48:52 +0100 (CET) Received: by mail-ob0-f181.google.com with SMTP id uy5so2685864obc.12 for ; Mon, 27 Oct 2014 12:48:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=MWvVpdy12a5ZzTHbdRSzM2MHJ4WGeoW/7Tvym/85SEo=; b=V1b3xPlgaNbi19A80e3ijw/DVU4emWpyzOPBv0yHs9wlguy+W2xQ2JClFBu6fMdJDr tF64rCdx14KM8w/P+v8qI3dRN4OIWfvm/GJ9zW8aYSwzS+8gQjsX/XB6MxRIImnvbiLs fIdHU+Yl6M0BEu8qYKsocHByiRGVMJKdtu0u2olRdzcUKtM33rb9MhudlmzNSFXlAb/g ERnYsRpcAKgPn4iGG8q/Vwa8WuqGGLfndi1ndc4eIInCvWCYXYEIMjVP1kQUfogOQzfp fqhp66zYI+wIX+uW+IEOxqhYwfjUuzZjTkQHwYcU5Ipt/1E8e6JvyaPuLKldlle7jYzh /99A== X-Received: by 10.202.81.15 with SMTP id f15mr1590210oib.77.1414439331266; Mon, 27 Oct 2014 12:48:51 -0700 (PDT) Received: from suriyanT430.us.oracle.com ([148.87.13.11]) by mx.google.com with ESMTPSA id d199sm1897261oih.11.2014.10.27.12.48.48 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 27 Oct 2014 12:48:50 -0700 (PDT) From: Suriyan Ramasami To: u-boot@lists.denx.de Date: Mon, 27 Oct 2014 12:48:44 -0700 Message-Id: <1414439325-28861-1-git-send-email-suriyan.r@gmail.com> X-Mailer: git-send-email 1.9.1 X-Mailman-Approved-At: Mon, 27 Oct 2014 21:55:28 +0100 Cc: srae@broadcom.com, fenghua@phytium.com.cn, p.wilczek@samsung.com, mahaijuns@gmail.com, sonic.zhang@analog.com, nobuhiro.iwamatsu.yj@renesas.com, marex@denx.de, swarren@nvidia.com, leirbag2311@gmail.com, siva.durga.paladugu@xilinx.com, ioan.nicu.ext@nsn.com, yoshiyuki.ito.ub@renesas.com, mathias.rulf@nsn.com, jeroen@myspectrum.nl, suriyan.r@gmail.com, pavel@denx.de, yorksun@freescale.com Subject: [U-Boot] [PATCH v4 1/1] fs: fat/ext4/sandbox: Deal with files greater than 2GB X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.13 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de The commands fatls/ext4ls give negative values when dealing with files greater than 2GB. The commands fatsize/ext4size do not update the variable filesize for these files. To deal with this, the fs functions have been modified to take an additional parameter of type "* loff_t" which is then populated. The return value of the fs functions are used only for error contitions. Signed-off-by: Suriyan Ramasami --- v4: * Support generic fs write commands * Sync up behavior of fs load vs fatload and ext4load * albert - change -ve to negative in commit message v3: * Added testcase to test writes * Correct function set_contents() in fs/fat/fat_write.c v2: * Added test case for fat/ext4 in test/fs/testfs.sh * md5sum: call map_sysmem() for buffer that md5_wd will work on v1: * First try. --- arch/sandbox/cpu/os.c | 11 +- arch/sandbox/cpu/state.c | 6 +- common/board_f.c | 6 +- common/cmd_ext4.c | 61 ++------- common/cmd_fat.c | 9 +- common/cmd_fs.c | 17 +++ common/cmd_md5sum.c | 12 +- common/env_fat.c | 4 +- fs/ext4/ext4_common.c | 24 ++-- fs/ext4/ext4_common.h | 4 +- fs/ext4/ext4_write.c | 32 +++++ fs/ext4/ext4fs.c | 37 ++--- fs/fat/fat.c | 124 +++++++++-------- fs/fat/fat_write.c | 59 ++++---- fs/fat/file.c | 7 +- fs/fs.c | 77 ++++++----- fs/sandbox/sandboxfs.c | 25 ++-- include/configs/sandbox.h | 2 + include/ext4fs.h | 13 +- include/fat.h | 19 +-- include/fs.h | 8 +- include/os.h | 2 +- include/sandboxfs.h | 8 +- test/fs/testfs.sh | 334 ++++++++++++++++++++++++++++++++++++++++++++++ 24 files changed, 655 insertions(+), 246 deletions(-) create mode 100755 test/fs/testfs.sh diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 1c4aa3f..43872e8 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -385,7 +385,7 @@ const char *os_dirent_get_typename(enum os_dirent_t type) return os_dirent_typename[OS_FILET_UNKNOWN]; } -ssize_t os_get_filesize(const char *fname) +int os_get_filesize(const char *fname, loff_t *size) { struct stat buf; int ret; @@ -393,7 +393,8 @@ ssize_t os_get_filesize(const char *fname) ret = stat(fname, &buf); if (ret) return ret; - return buf.st_size; + *size = buf.st_size; + return 0; } void os_putc(int ch) @@ -427,10 +428,10 @@ int os_read_ram_buf(const char *fname) { struct sandbox_state *state = state_get_current(); int fd, ret; - int size; + loff_t size; - size = os_get_filesize(fname); - if (size < 0) + ret = os_get_filesize(fname, &size); + if (ret < 0) return -ENOENT; if (size != state->ram_size) return -ENOSPC; diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c index 59adad6..07d2aea 100644 --- a/arch/sandbox/cpu/state.c +++ b/arch/sandbox/cpu/state.c @@ -49,12 +49,12 @@ static int state_ensure_space(int extra_size) static int state_read_file(struct sandbox_state *state, const char *fname) { - int size; + loff_t size; int ret; int fd; - size = os_get_filesize(fname); - if (size < 0) { + ret = os_get_filesize(fname, &size); + if (ret < 0) { printf("Cannot find sandbox state file '%s'\n", fname); return -ENOENT; } diff --git a/common/board_f.c b/common/board_f.c index b5bebc9..1fae112 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -285,7 +285,7 @@ static int read_fdt_from_file(void) struct sandbox_state *state = state_get_current(); const char *fname = state->fdt_fname; void *blob; - ssize_t size; + loff_t size; int err; int fd; @@ -298,8 +298,8 @@ static int read_fdt_from_file(void) return -EINVAL; } - size = os_get_filesize(fname); - if (size < 0) { + err = os_get_filesize(fname, &size); + if (err < 0) { printf("Failed to file FDT file '%s'\n", fname); return -ENOENT; } diff --git a/common/cmd_ext4.c b/common/cmd_ext4.c index ecfc6d3..19423d1 100644 --- a/common/cmd_ext4.c +++ b/common/cmd_ext4.c @@ -61,61 +61,16 @@ int do_ext4_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) #if defined(CONFIG_CMD_EXT4_WRITE) int do_ext4_write(cmd_tbl_t *cmdtp, int flag, int argc, - char *const argv[]) + char *const argv[]) { - const char *filename = "/"; - int dev, part; - unsigned long ram_address; - unsigned long file_size; - disk_partition_t info; - block_dev_desc_t *dev_desc; - - if (argc < 6) - return cmd_usage(cmdtp); - - part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); - if (part < 0) - return 1; - - dev = dev_desc->dev; - - /* get the filename */ - filename = argv[4]; - - /* get the address in hexadecimal format (string to int) */ - ram_address = simple_strtoul(argv[3], NULL, 16); - - /* get the filesize in hexadecimal format */ - file_size = simple_strtoul(argv[5], NULL, 16); - - /* set the device as block device */ - ext4fs_set_blk_dev(dev_desc, &info); - - /* mount the filesystem */ - if (!ext4fs_mount(info.size)) { - printf("Bad ext4 partition %s %d:%d\n", argv[1], dev, part); - goto fail; - } - - /* start write */ - if (ext4fs_write(filename, (unsigned char *)ram_address, file_size)) { - printf("** Error ext4fs_write() **\n"); - goto fail; - } - ext4fs_close(); - - return 0; - -fail: - ext4fs_close(); - - return 1; + return do_save(cmdtp, flag, argc, argv, FS_TYPE_EXT); } -U_BOOT_CMD(ext4write, 6, 1, do_ext4_write, - "create a file in the root directory", - " [sizebytes]\n" - " - create a file in / directory"); +U_BOOT_CMD(ext4write, 7, 1, do_ext4_write, + "create a file in the root directory", + " \n" + " [sizebytes] [file offset]\n" + " - create a file in / directory"); #endif @@ -132,7 +87,7 @@ U_BOOT_CMD(ext4ls, 4, 1, do_ext4_ls, " [directory]\n" " - list files from 'dev' on 'interface' in a 'directory'"); -U_BOOT_CMD(ext4load, 6, 0, do_ext4_load, +U_BOOT_CMD(ext4load, 7, 0, do_ext4_load, "load binary file from a Ext4 filesystem", " [ [addr [filename [bytes [pos]]]]]\n" " - load binary file 'filename' from 'dev' on 'interface'\n" diff --git a/common/cmd_fat.c b/common/cmd_fat.c index 633fbf1..186835a 100644 --- a/common/cmd_fat.c +++ b/common/cmd_fat.c @@ -100,7 +100,8 @@ U_BOOT_CMD( static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - long size; + loff_t size; + int ret; unsigned long addr; unsigned long count; block_dev_desc_t *dev_desc = NULL; @@ -127,15 +128,15 @@ static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag, count = simple_strtoul(argv[5], NULL, 16); buf = map_sysmem(addr, count); - size = file_fat_write(argv[4], buf, count); + ret = file_fat_write(argv[4], buf, 0, count, &size); unmap_sysmem(buf); - if (size == -1) { + if (ret == -1) { printf("\n** Unable to write \"%s\" from %s %d:%d **\n", argv[4], argv[1], dev, part); return 1; } - printf("%ld bytes written\n", size); + printf("%llu bytes written\n", size); return 0; } diff --git a/common/cmd_fs.c b/common/cmd_fs.c index 6754340..56e4b3c 100644 --- a/common/cmd_fs.c +++ b/common/cmd_fs.c @@ -51,6 +51,23 @@ U_BOOT_CMD( " If 'pos' is 0 or omitted, the file is read from the start." ) +static int do_save_wrapper(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return do_save(cmdtp, flag, argc, argv, FS_TYPE_ANY); +} + +U_BOOT_CMD( + write, 7, 0, do_save_wrapper, + "write file to a filesystem", + " [ [ [ [bytes [pos]]]]]\n" + " - Write binary file 'filename' to partition 'part' on device\n" + " type 'interface' instance 'dev' from addr 'addr' in memory.\n" + " 'bytes' gives the size to save in bytes and is mandatory.\n" + " 'pos' gives the file byte position to start writing to.\n" + " If 'pos' is 0 or omitted, the file is written from the start." +) + static int do_ls_wrapper(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { diff --git a/common/cmd_md5sum.c b/common/cmd_md5sum.c index 3ac8cc4..d22ace5 100644 --- a/common/cmd_md5sum.c +++ b/common/cmd_md5sum.c @@ -11,6 +11,7 @@ #include #include #include +#include /* * Store the resulting sum to an address or variable @@ -79,6 +80,7 @@ int do_md5sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int verify = 0; int ac; char * const *av; + void *buf; if (argc < 3) return CMD_RET_USAGE; @@ -96,7 +98,9 @@ int do_md5sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) addr = simple_strtoul(*av++, NULL, 16); len = simple_strtoul(*av++, NULL, 16); - md5_wd((unsigned char *) addr, len, output, CHUNKSZ_MD5); + buf = map_sysmem(addr, len); + md5_wd(buf, len, output, CHUNKSZ_MD5); + unmap_sysmem(buf); if (!verify) { printf("md5 for %08lx ... %08lx ==> ", addr, addr + len - 1); @@ -135,6 +139,7 @@ static int do_md5sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned long addr, len; unsigned int i; u8 output[16]; + void *buf; if (argc < 3) return CMD_RET_USAGE; @@ -142,7 +147,10 @@ static int do_md5sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) addr = simple_strtoul(argv[1], NULL, 16); len = simple_strtoul(argv[2], NULL, 16); - md5_wd((unsigned char *) addr, len, output, CHUNKSZ_MD5); + buf = map_sysmem(addr, len); + md5_wd(buf, len, output, CHUNKSZ_MD5); + unmap_sysmem(buf); + printf("md5 for %08lx ... %08lx ==> ", addr, addr + len - 1); for (i = 0; i < 16; i++) printf("%02x", output[i]); diff --git a/common/env_fat.c b/common/env_fat.c index 8db0160..9a6ce63 100644 --- a/common/env_fat.c +++ b/common/env_fat.c @@ -41,6 +41,7 @@ int saveenv(void) disk_partition_t info; int dev, part; int err; + loff_t size; err = env_export(&env_new); if (err) @@ -59,7 +60,8 @@ int saveenv(void) return 1; } - err = file_fat_write(FAT_ENV_FILE, (void *)&env_new, sizeof(env_t)); + err = file_fat_write(FAT_ENV_FILE, (void *)&env_new, sizeof(env_t), + &size); if (err == -1) { printf("\n** Unable to write \"%s\" from %s%d:%d **\n", FAT_ENV_FILE, FAT_ENV_INTERFACE, dev, part); diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 33d69c9..3b8df3f 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -1891,6 +1891,7 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, { unsigned int fpos = 0; int status; + loff_t actread; struct ext2fs_node *diro = (struct ext2fs_node *) dir; #ifdef DEBUG @@ -1908,8 +1909,8 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, status = ext4fs_read_file(diro, fpos, sizeof(struct ext2_dirent), - (char *) &dirent); - if (status < 1) + (char *)&dirent, &actread); + if (status < 0) return 0; if (dirent.namelen != 0) { @@ -1920,8 +1921,9 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, status = ext4fs_read_file(diro, fpos + sizeof(struct ext2_dirent), - dirent.namelen, filename); - if (status < 1) + dirent.namelen, filename, + &actread); + if (status < 0) return 0; fdiro = zalloc(sizeof(struct ext2fs_node)); @@ -2003,8 +2005,8 @@ int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, printf("< ? > "); break; } - printf("%10d %s\n", - __le32_to_cpu(fdiro->inode.size), + printf("%10u %s\n", + __le32_to_cpu(fdiro->inode.size), filename); } free(fdiro); @@ -2019,6 +2021,7 @@ static char *ext4fs_read_symlink(struct ext2fs_node *node) char *symlink; struct ext2fs_node *diro = node; int status; + loff_t actread; if (!diro->inode_read) { status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); @@ -2035,7 +2038,7 @@ static char *ext4fs_read_symlink(struct ext2fs_node *node) } else { status = ext4fs_read_file(diro, 0, __le32_to_cpu(diro->inode.size), - symlink); + symlink, &actread); if (status == 0) { free(symlink); return 0; @@ -2169,11 +2172,10 @@ int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode, return 1; } -int ext4fs_open(const char *filename) +int ext4fs_open(const char *filename, loff_t *len) { struct ext2fs_node *fdiro = NULL; int status; - int len; if (ext4fs_root == NULL) return -1; @@ -2190,10 +2192,10 @@ int ext4fs_open(const char *filename) if (status == 0) goto fail; } - len = __le32_to_cpu(fdiro->inode.size); + *len = __le32_to_cpu(fdiro->inode.size); ext4fs_file = fdiro; - return len; + return 0; fail: ext4fs_free_node(fdiro, &ext4fs_root->diropen); diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h index 5fa1719..48fd2ac 100644 --- a/fs/ext4/ext4_common.h +++ b/fs/ext4/ext4_common.h @@ -50,8 +50,8 @@ static inline void *zalloc(size_t size) int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode); -int ext4fs_read_file(struct ext2fs_node *node, int pos, - unsigned int len, char *buf); +int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, loff_t len, + char *buf, loff_t *actread); int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode, struct ext2fs_node **foundnode, int expecttype); int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c index 648a596..f7c52cc 100644 --- a/fs/ext4/ext4_write.c +++ b/fs/ext4/ext4_write.c @@ -975,3 +975,35 @@ fail: return -1; } + +int ext4_write_file(const char *filename, void *buf, loff_t offset, + loff_t len, loff_t *actwrite) +{ + int ret; + + if (offset != 0) { + printf("** Cannot support non-zero offset **\n"); + return -1; + } + + /* mount the filesystem */ + if (!ext4fs_mount(0)) { + printf("** Error Bad ext4 partition **\n"); + goto fail; + } + + ret = ext4fs_write(filename, buf, len); + + if (ret) { + printf("** Error ext4fs_write() **\n"); + goto fail; + } + ext4fs_close(); + + return 0; + +fail: + ext4fs_close(); + + return -1; +} diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c index cbdc220..ae1c47d 100644 --- a/fs/ext4/ext4fs.c +++ b/fs/ext4/ext4fs.c @@ -45,8 +45,8 @@ void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot) * Optimized read file API : collects and defers contiguous sector * reads into one potentially more efficient larger sequential read action */ -int ext4fs_read_file(struct ext2fs_node *node, int pos, - unsigned int len, char *buf) +int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, + loff_t len, char *buf, loff_t *actread) { struct ext_filesystem *fs = get_fs(); int i; @@ -150,7 +150,8 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos, previous_block_number = -1; } - return len; + *actread = len; + return 0; } int ext4fs_ls(const char *dirname) @@ -176,23 +177,24 @@ int ext4fs_ls(const char *dirname) int ext4fs_exists(const char *filename) { - int file_len; + loff_t file_len; + int ret; - file_len = ext4fs_open(filename); - return file_len >= 0; + ret = ext4fs_open(filename, &file_len); + return ret == 0; } -int ext4fs_size(const char *filename) +int ext4fs_size(const char *filename, loff_t *size) { - return ext4fs_open(filename); + return ext4fs_open(filename, size); } -int ext4fs_read(char *buf, unsigned len) +int ext4fs_read(char *buf, loff_t len, loff_t *actread) { if (ext4fs_root == NULL || ext4fs_file == NULL) return 0; - return ext4fs_read_file(ext4fs_file, 0, len, buf); + return ext4fs_read_file(ext4fs_file, 0, len, buf, actread); } int ext4fs_probe(block_dev_desc_t *fs_dev_desc, @@ -208,18 +210,19 @@ int ext4fs_probe(block_dev_desc_t *fs_dev_desc, return 0; } -int ext4_read_file(const char *filename, void *buf, int offset, int len) +int ext4_read_file(const char *filename, void *buf, loff_t offset, loff_t len, + loff_t *len_read) { - int file_len; - int len_read; + loff_t file_len; + int ret; if (offset != 0) { printf("** Cannot support non-zero offset **\n"); return -1; } - file_len = ext4fs_open(filename); - if (file_len < 0) { + ret = ext4fs_open(filename, &file_len); + if (ret < 0) { printf("** File not found %s **\n", filename); return -1; } @@ -227,7 +230,7 @@ int ext4_read_file(const char *filename, void *buf, int offset, int len) if (len == 0) len = file_len; - len_read = ext4fs_read(buf, len); + ret = ext4fs_read(buf, len, len_read); - return len_read; + return ret; } diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 561921f..df8705f 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -317,32 +317,33 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) /* * Read at most 'maxsize' bytes from 'pos' in the file associated with 'dentptr' * into 'buffer'. - * Return the number of bytes read or -1 on fatal errors. + * Update the number of bytes read in *gotsize or return -1 on fatal errors. */ __u8 get_contents_vfatname_block[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN); -static long -get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos, - __u8 *buffer, unsigned long maxsize) +static int +get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, + __u8 *buffer, loff_t maxsize, loff_t *gotsize) { - unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0; + loff_t filesize = FAT2CPU32(dentptr->size); unsigned int bytesperclust = mydata->clust_size * mydata->sect_size; __u32 curclust = START(dentptr); __u32 endclust, newclust; - unsigned long actsize; + loff_t actsize; - debug("Filesize: %ld bytes\n", filesize); + *gotsize = 0; + debug("Filesize: %llu bytes\n", filesize); if (pos >= filesize) { - debug("Read position past EOF: %lu\n", pos); - return gotsize; + debug("Read position past EOF: %llu\n", pos); + return 0; } if (maxsize > 0 && filesize > pos + maxsize) filesize = pos + maxsize; - debug("%ld bytes\n", filesize); + debug("%llu bytes\n", filesize); actsize = bytesperclust; @@ -352,7 +353,7 @@ get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos, if (CHECK_CLUST(curclust, mydata->fatsize)) { debug("curclust: 0x%x\n", curclust); debug("Invalid FAT entry\n"); - return gotsize; + return 0; } actsize += bytesperclust; } @@ -373,16 +374,16 @@ get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos, filesize -= actsize; actsize -= pos; memcpy(buffer, get_contents_vfatname_block + pos, actsize); - gotsize += actsize; + *gotsize += actsize; if (!filesize) - return gotsize; + return 0; buffer += actsize; curclust = get_fatent(mydata, curclust); if (CHECK_CLUST(curclust, mydata->fatsize)) { debug("curclust: 0x%x\n", curclust); debug("Invalid FAT entry\n"); - return gotsize; + return 0; } } @@ -398,7 +399,7 @@ get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos, if (CHECK_CLUST(newclust, mydata->fatsize)) { debug("curclust: 0x%x\n", newclust); debug("Invalid FAT entry\n"); - return gotsize; + return 0; } endclust = newclust; actsize += bytesperclust; @@ -410,14 +411,14 @@ get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos, printf("Error reading cluster\n"); return -1; } - gotsize += actsize; - return gotsize; + *gotsize += actsize; + return 0; getit: if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) { printf("Error reading cluster\n"); return -1; } - gotsize += (int)actsize; + *gotsize += (int)actsize; filesize -= actsize; buffer += actsize; @@ -425,7 +426,7 @@ getit: if (CHECK_CLUST(curclust, mydata->fatsize)) { debug("curclust: 0x%x\n", curclust); printf("Invalid FAT entry\n"); - return gotsize; + return 0; } actsize = bytesperclust; endclust = curclust; @@ -633,8 +634,8 @@ static dir_entry *get_dentfromdir(fsdata *mydata, int startsect, } if (doit) { if (dirc == ' ') { - printf(" %8ld %s%c\n", - (long)FAT2CPU32(dentptr->size), + printf(" %8u %s%c\n", + FAT2CPU32(dentptr->size), l_name, dirc); } else { @@ -690,8 +691,8 @@ static dir_entry *get_dentfromdir(fsdata *mydata, int startsect, if (doit) { if (dirc == ' ') { - printf(" %8ld %s%c\n", - (long)FAT2CPU32(dentptr->size), + printf(" %8u %s%c\n", + FAT2CPU32(dentptr->size), s_name, dirc); } else { printf(" %s%c\n", @@ -806,9 +807,9 @@ exit: __u8 do_fat_read_at_block[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN); -long -do_fat_read_at(const char *filename, unsigned long pos, void *buffer, - unsigned long maxsize, int dols, int dogetsize) +int +do_fat_read_at(const char *filename, loff_t pos, void *buffer, loff_t maxsize, + int dols, int dogetsize, loff_t *size) { char fnamecopy[2048]; boot_sector bs; @@ -821,7 +822,7 @@ do_fat_read_at(const char *filename, unsigned long pos, void *buffer, __u32 cursect; int idx, isdir = 0; int files = 0, dirs = 0; - long ret = -1; + int ret = -1; int firsttime; __u32 root_cluster = 0; int rootdir_size = 0; @@ -974,8 +975,8 @@ do_fat_read_at(const char *filename, unsigned long pos, void *buffer, } if (doit) { if (dirc == ' ') { - printf(" %8ld %s%c\n", - (long)FAT2CPU32(dentptr->size), + printf(" %8u %s%c\n", + FAT2CPU32(dentptr->size), l_name, dirc); } else { @@ -1032,8 +1033,8 @@ do_fat_read_at(const char *filename, unsigned long pos, void *buffer, } if (doit) { if (dirc == ' ') { - printf(" %8ld %s%c\n", - (long)FAT2CPU32(dentptr->size), + printf(" %8u %s%c\n", + FAT2CPU32(dentptr->size), s_name, dirc); } else { printf(" %s%c\n", @@ -1102,7 +1103,7 @@ do_fat_read_at(const char *filename, unsigned long pos, void *buffer, if (dols == LS_ROOT) { printf("\n%d file(s), %d dir(s)\n\n", files, dirs); - ret = 0; + *size = 0; } goto exit; } @@ -1141,7 +1142,7 @@ rootdir_done: if (get_dentfromdir(mydata, startsect, subname, dentptr, isdir ? 0 : dols) == NULL) { if (dols && !isdir) - ret = 0; + *size = 0; goto exit; } @@ -1152,21 +1153,24 @@ rootdir_done: subname = nextname; } - if (dogetsize) - ret = FAT2CPU32(dentptr->size); - else - ret = get_contents(mydata, dentptr, pos, buffer, maxsize); - debug("Size: %d, got: %ld\n", FAT2CPU32(dentptr->size), ret); + if (dogetsize) { + *size = FAT2CPU32(dentptr->size); + ret = 0; + } else { + ret = get_contents(mydata, dentptr, pos, buffer, maxsize, size); + } + debug("Size: %u, got: %llu\n", FAT2CPU32(dentptr->size), *size); exit: free(mydata->fatbuf); return ret; } -long -do_fat_read(const char *filename, void *buffer, unsigned long maxsize, int dols) +int +do_fat_read(const char *filename, void *buffer, loff_t maxsize, int dols, + loff_t *actread) { - return do_fat_read_at(filename, 0, buffer, maxsize, dols, 0); + return do_fat_read_at(filename, 0, buffer, maxsize, dols, 0, actread); } int file_fat_detectfs(void) @@ -1233,44 +1237,50 @@ int file_fat_detectfs(void) int file_fat_ls(const char *dir) { - return do_fat_read(dir, NULL, 0, LS_YES); + loff_t size; + + return do_fat_read(dir, NULL, 0, LS_YES, &size); } int fat_exists(const char *filename) { - int sz; - sz = do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1); - return sz >= 0; + int ret; + loff_t size; + ret = do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1, &size); + return ret == 0; } -int fat_size(const char *filename) +int fat_size(const char *filename, loff_t *size) { - return do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1); + return do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1, size); } -long file_fat_read_at(const char *filename, unsigned long pos, void *buffer, - unsigned long maxsize) +int file_fat_read_at(const char *filename, loff_t pos, void *buffer, + loff_t maxsize, loff_t *actread) { printf("reading %s\n", filename); - return do_fat_read_at(filename, pos, buffer, maxsize, LS_NO, 0); + return do_fat_read_at(filename, pos, buffer, maxsize, LS_NO, 0, + actread); } -long file_fat_read(const char *filename, void *buffer, unsigned long maxsize) +int file_fat_read(const char *filename, void *buffer, loff_t maxsize, + loff_t *actread) { - return file_fat_read_at(filename, 0, buffer, maxsize); + return file_fat_read_at(filename, 0, buffer, maxsize, actread); } -int fat_read_file(const char *filename, void *buf, int offset, int len) +int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len, + loff_t *actread) { - int len_read; + int ret; - len_read = file_fat_read_at(filename, offset, buf, len); - if (len_read == -1) { + ret = file_fat_read_at(filename, offset, buf, len, actread); + if (ret < 0) { printf("** Unable to read file %s **\n", filename); return -1; } - return len_read; + return 0; } void fat_close(void) diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 24ed5d3..b0c4611 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -660,24 +660,26 @@ static int clear_fatent(fsdata *mydata, __u32 entry) /* * Write at most 'maxsize' bytes from 'buffer' into * the file associated with 'dentptr' - * Return the number of bytes read or -1 on fatal errors. + * Update the number of bytes written in *gotsize and return 0 + * or return -1 on fatal errors. */ static int set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, - unsigned long maxsize) + loff_t maxsize, loff_t *gotsize) { - unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0; + loff_t filesize = FAT2CPU32(dentptr->size); unsigned int bytesperclust = mydata->clust_size * mydata->sect_size; __u32 curclust = START(dentptr); __u32 endclust = 0, newclust = 0; - unsigned long actsize; + loff_t actsize; - debug("Filesize: %ld bytes\n", filesize); + *gotsize = 0; + debug("Filesize: %llu bytes\n", filesize); if (maxsize > 0 && filesize > maxsize) filesize = maxsize; - debug("%ld bytes\n", filesize); + debug("%llu bytes\n", filesize); actsize = bytesperclust; endclust = curclust; @@ -692,7 +694,7 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, if (CHECK_CLUST(newclust, mydata->fatsize)) { debug("curclust: 0x%x\n", newclust); debug("Invalid FAT entry\n"); - return gotsize; + return 0; } endclust = newclust; actsize += bytesperclust; @@ -706,7 +708,7 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, } /* set remaining bytes */ - gotsize += (int)actsize; + *gotsize += actsize; filesize -= actsize; buffer += actsize; actsize = filesize; @@ -715,7 +717,7 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, debug("error: writing cluster\n"); return -1; } - gotsize += actsize; + *gotsize += actsize; /* Mark end of file in FAT */ if (mydata->fatsize == 16) @@ -724,20 +726,20 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, newclust = 0xfffffff; set_fatent_value(mydata, endclust, newclust); - return gotsize; + return 0; getit: if (set_cluster(mydata, curclust, buffer, (int)actsize) != 0) { debug("error: writing cluster\n"); return -1; } - gotsize += (int)actsize; + *gotsize += actsize; filesize -= actsize; buffer += actsize; if (CHECK_CLUST(curclust, mydata->fatsize)) { debug("curclust: 0x%x\n", curclust); debug("Invalid FAT entry\n"); - return gotsize; + return 0; } actsize = bytesperclust; curclust = endclust = newclust; @@ -766,7 +768,7 @@ static void fill_dentry(fsdata *mydata, dir_entry *dentptr, * exceed the size of the block device * Return -1 when overflow occurs, otherwise return 0 */ -static int check_overflow(fsdata *mydata, __u32 clustnum, unsigned long size) +static int check_overflow(fsdata *mydata, __u32 clustnum, loff_t size) { __u32 startsect, sect_num; @@ -924,7 +926,7 @@ static dir_entry *find_directory_entry(fsdata *mydata, int startsect, } static int do_fat_write(const char *filename, void *buffer, - unsigned long size) + loff_t size, loff_t *actwrite) { dir_entry *dentptr, *retdent; __u32 startsect; @@ -936,8 +938,8 @@ static int do_fat_write(const char *filename, void *buffer, int cursect; int ret = -1, name_len; char l_filename[VFAT_MAXLEN_BYTES]; - int write_size = size; + *actwrite = size; dir_curclust = 0; if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) { @@ -1015,7 +1017,7 @@ static int do_fat_write(const char *filename, void *buffer, ret = check_overflow(mydata, start_cluster, size); if (ret) { - printf("Error: %ld overflow\n", size); + printf("Error: %llu overflow\n", size); goto exit; } @@ -1025,13 +1027,12 @@ static int do_fat_write(const char *filename, void *buffer, goto exit; } - ret = set_contents(mydata, retdent, buffer, size); + ret = set_contents(mydata, retdent, buffer, size, actwrite); if (ret < 0) { printf("Error: writing contents\n"); goto exit; } - write_size = ret; - debug("attempt to write 0x%x bytes\n", write_size); + debug("attempt to write 0x%llx bytes\n", *actwrite); /* Flush fat buffer */ ret = flush_fat_buffer(mydata); @@ -1061,7 +1062,7 @@ static int do_fat_write(const char *filename, void *buffer, ret = check_overflow(mydata, start_cluster, size); if (ret) { - printf("Error: %ld overflow\n", size); + printf("Error: %llu overflow\n", size); goto exit; } @@ -1069,13 +1070,13 @@ static int do_fat_write(const char *filename, void *buffer, fill_dentry(mydata, empty_dentptr, filename, start_cluster, size, 0x20); - ret = set_contents(mydata, empty_dentptr, buffer, size); + ret = set_contents(mydata, empty_dentptr, buffer, size, + actwrite); if (ret < 0) { printf("Error: writing contents\n"); goto exit; } - write_size = ret; - debug("attempt to write 0x%x bytes\n", write_size); + debug("attempt to write 0x%llx bytes\n", *actwrite); /* Flush fat buffer */ ret = flush_fat_buffer(mydata); @@ -1096,11 +1097,17 @@ static int do_fat_write(const char *filename, void *buffer, exit: free(mydata->fatbuf); - return ret < 0 ? ret : write_size; + return ret; } -int file_fat_write(const char *filename, void *buffer, unsigned long maxsize) +int file_fat_write(const char *filename, void *buffer, loff_t offset, + loff_t maxsize, loff_t *actwrite) { + if (offset != 0) { + printf("Error: non zero offset is currently not suported.\n"); + return -1; + } + printf("writing %s\n", filename); - return do_fat_write(filename, buffer, maxsize); + return do_fat_write(filename, buffer, maxsize, actwrite); } diff --git a/fs/fat/file.c b/fs/fat/file.c index d910c46..b608883 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -162,8 +162,8 @@ file_ls(const char *dir) return filesystems[current_filesystem].ls(arg); } -long -file_read(const char *filename, void *buffer, unsigned long maxsize) +int +file_read(const char *filename, void *buffer, loff_t maxsize, loff_t *actread) { char fullpath[1024]; const char *arg; @@ -180,5 +180,6 @@ file_read(const char *filename, void *buffer, unsigned long maxsize) arg = fullpath; } - return filesystems[current_filesystem].read(arg, buffer, maxsize); + return filesystems[current_filesystem].read(arg, buffer, maxsize, + actread); } diff --git a/fs/fs.c b/fs/fs.c index dd680f3..0f5a1f4 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -46,19 +46,21 @@ static inline int fs_exists_unsupported(const char *filename) return 0; } -static inline int fs_size_unsupported(const char *filename) +static inline int fs_size_unsupported(const char *filename, loff_t *size) { return -1; } static inline int fs_read_unsupported(const char *filename, void *buf, - int offset, int len) + loff_t offset, loff_t len, + loff_t *actread) { return -1; } static inline int fs_write_unsupported(const char *filename, void *buf, - int offset, int len) + loff_t offset, loff_t len, + loff_t *actwrite) { return -1; } @@ -82,9 +84,11 @@ struct fstype_info { disk_partition_t *fs_partition); int (*ls)(const char *dirname); int (*exists)(const char *filename); - int (*size)(const char *filename); - int (*read)(const char *filename, void *buf, int offset, int len); - int (*write)(const char *filename, void *buf, int offset, int len); + int (*size)(const char *filename, loff_t *size); + int (*read)(const char *filename, void *buf, loff_t offset, + loff_t len, loff_t *actread); + int (*write)(const char *filename, void *buf, loff_t offset, + loff_t len, loff_t *actwrite); void (*close)(void); }; @@ -99,7 +103,11 @@ static struct fstype_info fstypes[] = { .exists = fat_exists, .size = fat_size, .read = fat_read_file, +#ifdef CONFIG_FAT_WRITE + .write = file_fat_write, +#else .write = fs_write_unsupported, +#endif }, #endif #ifdef CONFIG_FS_EXT4 @@ -112,7 +120,11 @@ static struct fstype_info fstypes[] = { .exists = ext4fs_exists, .size = ext4fs_size, .read = ext4_read_file, +#ifdef CONFIG_CMD_EXT4_WRITE + .write = ext4_write_file, +#else .write = fs_write_unsupported, +#endif }, #endif #ifdef CONFIG_SANDBOX @@ -233,20 +245,21 @@ int fs_exists(const char *filename) return ret; } -int fs_size(const char *filename) +int fs_size(const char *filename, loff_t *size) { int ret; struct fstype_info *info = fs_get_info(fs_type); - ret = info->size(filename); + ret = info->size(filename, size); fs_close(); return ret; } -int fs_read(const char *filename, ulong addr, int offset, int len) +int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, + loff_t *actread) { struct fstype_info *info = fs_get_info(fs_type); void *buf; @@ -257,11 +270,11 @@ int fs_read(const char *filename, ulong addr, int offset, int len) * means read the whole file. */ buf = map_sysmem(addr, len); - ret = info->read(filename, buf, offset, len); + ret = info->read(filename, buf, offset, len, actread); unmap_sysmem(buf); /* If we requested a specific number of bytes, check we got it */ - if (ret >= 0 && len && ret != len) { + if (ret == 0 && len && *actread != len) { printf("** Unable to read file %s **\n", filename); ret = -1; } @@ -270,17 +283,18 @@ int fs_read(const char *filename, ulong addr, int offset, int len) return ret; } -int fs_write(const char *filename, ulong addr, int offset, int len) +int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len, + loff_t *actwrite) { struct fstype_info *info = fs_get_info(fs_type); void *buf; int ret; buf = map_sysmem(addr, len); - ret = info->write(filename, buf, offset, len); + ret = info->write(filename, buf, offset, len, actwrite); unmap_sysmem(buf); - if (ret >= 0 && ret != len) { + if (ret < 0 && len != *actwrite) { printf("** Unable to write file %s **\n", filename); ret = -1; } @@ -292,7 +306,7 @@ int fs_write(const char *filename, ulong addr, int offset, int len) int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int fstype) { - int size; + loff_t size; if (argc != 4) return CMD_RET_USAGE; @@ -300,8 +314,7 @@ int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], if (fs_set_blk_dev(argv[1], argv[2], fstype)) return 1; - size = fs_size(argv[3]); - if (size < 0) + if (fs_size(argv[3], &size) < 0) return CMD_RET_FAILURE; setenv_hex("filesize", size); @@ -315,9 +328,10 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], unsigned long addr; const char *addr_str; const char *filename; - unsigned long bytes; - unsigned long pos; - int len_read; + loff_t bytes; + loff_t pos; + loff_t len_read; + int ret; unsigned long time; char *ep; @@ -359,12 +373,12 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], pos = 0; time = get_timer(0); - len_read = fs_read(filename, addr, pos, bytes); + ret = fs_read(filename, addr, pos, bytes, &len_read); time = get_timer(time); - if (len_read <= 0) + if (ret < 0) return 1; - printf("%d bytes read in %lu ms", len_read, time); + printf("%llu bytes read in %lu ms", len_read, time); if (time > 0) { puts(" ("); print_size(len_read / time * 1000, "/s"); @@ -408,9 +422,10 @@ int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], { unsigned long addr; const char *filename; - unsigned long bytes; - unsigned long pos; - int len; + loff_t bytes; + loff_t pos; + loff_t len; + int ret; unsigned long time; if (argc < 6 || argc > 7) @@ -419,8 +434,8 @@ int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], if (fs_set_blk_dev(argv[1], argv[2], fstype)) return 1; - filename = argv[3]; - addr = simple_strtoul(argv[4], NULL, 16); + addr = simple_strtoul(argv[3], NULL, 16); + filename = argv[4]; bytes = simple_strtoul(argv[5], NULL, 16); if (argc >= 7) pos = simple_strtoul(argv[6], NULL, 16); @@ -428,12 +443,12 @@ int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], pos = 0; time = get_timer(0); - len = fs_write(filename, addr, pos, bytes); + ret = fs_write(filename, addr, pos, bytes, &len); time = get_timer(time); - if (len <= 0) + if (ret < 0) return 1; - printf("%d bytes written in %lu ms", len, time); + printf("%llu bytes written in %lu ms", len, time); if (time > 0) { puts(" ("); print_size(len / time * 1000, "/s"); diff --git a/fs/sandbox/sandboxfs.c b/fs/sandbox/sandboxfs.c index ba6402c..d4d8378 100644 --- a/fs/sandbox/sandboxfs.c +++ b/fs/sandbox/sandboxfs.c @@ -16,7 +16,7 @@ int sandbox_fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info) long sandbox_fs_read_at(const char *filename, unsigned long pos, void *buffer, unsigned long maxsize) { - ssize_t size; + loff_t size; int fd, ret; fd = os_open(filename, OS_O_RDONLY); @@ -27,8 +27,16 @@ long sandbox_fs_read_at(const char *filename, unsigned long pos, os_close(fd); return ret; } - if (!maxsize) - maxsize = os_get_filesize(filename); + if (!maxsize) { + ret = os_get_filesize(filename, &size); + if (ret) { + os_close(fd); + return ret; + } + + maxsize = size; + } + size = os_read(fd, buffer, maxsize); os_close(fd); @@ -74,15 +82,16 @@ int sandbox_fs_ls(const char *dirname) int sandbox_fs_exists(const char *filename) { - ssize_t sz; + loff_t sz; + int ret; - sz = os_get_filesize(filename); - return sz >= 0; + ret = os_get_filesize(filename, &sz); + return ret == 0; } -int sandbox_fs_size(const char *filename) +int sandbox_fs_size(const char *filename, loff_t *size) { - return os_get_filesize(filename); + return os_get_filesize(filename, size); } void sandbox_fs_close(void) diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index ee4b244..2b03841 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -48,6 +48,7 @@ #define CONFIG_ANDROID_BOOT_IMAGE #define CONFIG_FS_FAT +#define CONFIG_FAT_WRITE #define CONFIG_FS_EXT4 #define CONFIG_EXT4_WRITE #define CONFIG_CMD_FAT @@ -57,6 +58,7 @@ #define CONFIG_DOS_PARTITION #define CONFIG_HOST_MAX_DEVICES 4 #define CONFIG_CMD_FS_GENERIC +#define CONFIG_CMD_MD5SUM #define CONFIG_SYS_VSNPRINTF diff --git a/include/ext4fs.h b/include/ext4fs.h index 6c419f3..7630057 100644 --- a/include/ext4fs.h +++ b/include/ext4fs.h @@ -125,24 +125,27 @@ int ext4fs_init(void); void ext4fs_deinit(void); int ext4fs_filename_check(char *filename); int ext4fs_write(const char *fname, unsigned char *buffer, - unsigned long sizebytes); + unsigned long sizebytes); +int ext4_write_file(const char *filename, void *buf, loff_t offset, loff_t len, + loff_t *actwrite); #endif struct ext_filesystem *get_fs(void); -int ext4fs_open(const char *filename); -int ext4fs_read(char *buf, unsigned len); +int ext4fs_open(const char *filename, loff_t *len); +int ext4fs_read(char *buf, loff_t len, loff_t *actread); int ext4fs_mount(unsigned part_length); void ext4fs_close(void); void ext4fs_reinit_global(void); int ext4fs_ls(const char *dirname); int ext4fs_exists(const char *filename); -int ext4fs_size(const char *filename); +int ext4fs_size(const char *filename, loff_t *size); void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot); int ext4fs_devread(lbaint_t sector, int byte_offset, int byte_len, char *buf); void ext4fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info); long int read_allocated_block(struct ext2_inode *inode, int fileblock); int ext4fs_probe(block_dev_desc_t *fs_dev_desc, disk_partition_t *fs_partition); -int ext4_read_file(const char *filename, void *buf, int offset, int len); +int ext4_read_file(const char *filename, void *buf, loff_t offset, loff_t len, + loff_t *actread); int ext4_read_superblock(char *buffer); #endif diff --git a/include/fat.h b/include/fat.h index 20ca3f3..7a57533 100644 --- a/include/fat.h +++ b/include/fat.h @@ -178,8 +178,8 @@ typedef struct { typedef int (file_detectfs_func)(void); typedef int (file_ls_func)(const char *dir); -typedef long (file_read_func)(const char *filename, void *buffer, - unsigned long maxsize); +typedef int (file_read_func)(const char *filename, void *buffer, + loff_t maxsize, loff_t *actread); struct filesystem { file_detectfs_func *detect; @@ -198,15 +198,18 @@ int file_cd(const char *path); int file_fat_detectfs(void); int file_fat_ls(const char *dir); int fat_exists(const char *filename); -int fat_size(const char *filename); -long file_fat_read_at(const char *filename, unsigned long pos, void *buffer, - unsigned long maxsize); -long file_fat_read(const char *filename, void *buffer, unsigned long maxsize); +int fat_size(const char *filename, loff_t *size); +int file_fat_read_at(const char *filename, loff_t pos, void *buffer, + loff_t maxsize, loff_t *actread); +int file_fat_read(const char *filename, void *buffer, loff_t maxsize, + loff_t *actread); const char *file_getfsname(int idx); int fat_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info); int fat_register_device(block_dev_desc_t *dev_desc, int part_no); -int file_fat_write(const char *filename, void *buffer, unsigned long maxsize); -int fat_read_file(const char *filename, void *buf, int offset, int len); +int file_fat_write(const char *filename, void *buf, loff_t offset, loff_t len, + loff_t *actwrite); +int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len, + loff_t *actread); void fat_close(void); #endif /* _FAT_H_ */ diff --git a/include/fs.h b/include/fs.h index 06a45f2..61ff572 100644 --- a/include/fs.h +++ b/include/fs.h @@ -55,7 +55,7 @@ int fs_exists(const char *filename); * * Returns the file's size in bytes, or a negative value if it doesn't exist. */ -int fs_size(const char *filename); +int fs_size(const char *filename, loff_t *size); /* * Read file "filename" from the partition previously set by fs_set_blk_dev(), @@ -66,7 +66,8 @@ int fs_size(const char *filename); * * Returns number of bytes read on success. Returns <= 0 on error. */ -int fs_read(const char *filename, ulong addr, int offset, int len); +int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, + loff_t *actread); /* * Write file "filename" to the partition previously set by fs_set_blk_dev(), @@ -76,7 +77,8 @@ int fs_read(const char *filename, ulong addr, int offset, int len); * * Returns number of bytes read on success. Returns <= 0 on error. */ -int fs_write(const char *filename, ulong addr, int offset, int len); +int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len, + loff_t *actwrite); /* * Common implementation for various filesystem commands, optionally limited diff --git a/include/os.h b/include/os.h index 0230a7f..cfefc8c 100644 --- a/include/os.h +++ b/include/os.h @@ -219,7 +219,7 @@ const char *os_dirent_get_typename(enum os_dirent_t type); * @param fname Filename to check * @return size of file, or -1 if an error ocurred */ -ssize_t os_get_filesize(const char *fname); +int os_get_filesize(const char *fname, loff_t *size); /** * Write a character to the controlling OS terminal diff --git a/include/sandboxfs.h b/include/sandboxfs.h index e7c3262..ea11168 100644 --- a/include/sandboxfs.h +++ b/include/sandboxfs.h @@ -26,8 +26,10 @@ long sandbox_fs_read_at(const char *filename, unsigned long pos, void sandbox_fs_close(void); int sandbox_fs_ls(const char *dirname); int sandbox_fs_exists(const char *filename); -int sandbox_fs_size(const char *filename); -int fs_read_sandbox(const char *filename, void *buf, int offset, int len); -int fs_write_sandbox(const char *filename, void *buf, int offset, int len); +int sandbox_fs_size(const char *filename, loff_t *size); +int fs_read_sandbox(const char *filename, void *buf, loff_t offset, loff_t len, + loff_t *size); +int fs_write_sandbox(const char *filename, void *buf, loff_t offset, + loff_t len, loff_t *actwrite); #endif diff --git a/test/fs/testfs.sh b/test/fs/testfs.sh new file mode 100755 index 0000000..140fa10 --- /dev/null +++ b/test/fs/testfs.sh @@ -0,0 +1,334 @@ +#!/bin/bash +# (C) Copyright 2014 Suriyan Ramasami +# +# SPDX-License-Identifier: GPL-2.0+ +# + +# Call with parameter clean to remove all its generated files and exit + +IMG=./3GB +TMPMOUNT=tmpmount +SFILE=1MB.file +BFILE=2.5GB.file +MD5FILE=./md5s.list + +# Output files +OUT=test.output + +# All out files will have the above prefix and a .out suffix +rm -f ${MD5FILE}.* ${OUT}.*.out + +if [ "$1" = "clean" ]; then + rm -f *.img + exit +fi + +MB1=${TMPMOUNT}/${SFILE} +GB2p5=${TMPMOUNT}/${BFILE} + +# 1st parameter is the prefix name of the image file +# 2nd parameter is the filesystem - vfat ext4 etc +# The final image file is $1.$2.img +# Returns the actual image created. +function CreateImg() { + THE_IMG=$1.$2.img + + # Create image if not already present - saves time, while debugging + + if [ ! -f ${THE_IMG} ]; then + fallocate -l 3G ${THE_IMG} &> /dev/null + if [ "$2" = "ext4" ]; then + mkfs.${2} ${THE_IMG} &> /dev/null < /dev/null + fi + fi + echo "${THE_IMG}" +} + +# First parameter is image file +# Second parameter which is prepended to the ls/load commands +# Example: load vs fatload +# Assumes SFILE and BFILE are set in env +function TestImg() { + THE_IMG="${1}" + PREFIX="${2}" + + # In u-boot commands, stands for host or hostfs + # hostfs maps to the host fs. + # host maps to the "sb bind" that we do + + # Set up the write file name + if [ "$PREFIX" = "fat" ]; then + WFILE=1MB.file.w + fi + if [ "$PREFIX" = "ext4" ]; then + WFILE="/1MB.file.w" + fi + + ../../u-boot << EOF + +sb bind 0 ${THE_IMG} +${PREFIX}ls host 0:0 / +# +# 1MB is 0x0010 0000 +${PREFIX}size host 0:0 ${SFILE} +printenv filesize +setenv filesize + +# 2.5GB (1024*1024*2500) is 0x9C40 0000 +${PREFIX}size host 0:0 ${BFILE} +printenv filesize +setenv filesize + +# Notes about load operation +# If I use 0x01000000 I get DMA misaligned error message +# Last two parameters are size and offset. + +# Read full 1MB of small file +${PREFIX}load host 0:0 0x01000008 ${SFILE} +printenv filesize +md5sum 0x01000008 \$filesize +setenv filesize + +# First 1MB of big file +${PREFIX}load host 0:0 0x01000008 ${BFILE} 0x00100000 0x0 +printenv filesize +md5sum 0x01000008 \$filesize +setenv filesize + +# Last 1MB of big file - fails for ext as no offset support +${PREFIX}load host 0:0 0x01000008 ${BFILE} 0x00100000 0x9C300000 +printenv filesize +md5sum 0x01000008 \$filesize +setenv filesize + +# One from the last 1MB chunk of 2GB - fails for ext +${PREFIX}load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF00000 +printenv filesize +md5sum 0x01000008 \$filesize +setenv filesize + +# One from the start 1MB chunk from 2GB - fails for ext +${PREFIX}load host 0:0 0x01000008 ${BFILE} 0x00100000 0x80000000 +printenv filesize +md5sum 0x01000008 \$filesize +setenv filesize + +# One 1MB chunk crossing the 2GB boundary - fails for ext +${PREFIX}load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF80000 +printenv filesize +md5sum 0x01000008 \$filesize +setenv filesize + +# 2MB chunk from the last 1MB of big file - Generic failure case +${PREFIX}load host 0:0 0x01000008 ${BFILE} 0x00200000 0x9C300000 +printenv filesize +# + +# Read 1MB from small file +${PREFIX}load host 0:0 0x01000008 ${SFILE} +# Write it back to test the writes +${PREFIX}write host 0:0 0x01000008 ${WFILE} \$filesize +mw.b 0x01000008 00 100 +${PREFIX}load host 0:0 0x01000008 ${WFILE} +md5sum 0x01000008 \$filesize +setenv filesize +# +reset + +EOF +} + +# Assume 1st argument is the name of the image file. +# Assume 2nd argument is the file where we generate the md5s of the +# files generated with the appropriate start and length that we use to test +function CreateFilesInImg() { + THE_IMG="$1" + MD5OUT="$2" + + # Create a big file in this image. + # Note that we work only on the start 1MB, couple MBs in the 2GB range + # and the last 1 MB of the huge 2.5GB file. + # So, just put random values only in those areas. + mkdir -p ${TMPMOUNT} + sudo mount -o loop ${THE_IMG} ${TMPMOUNT} + if [ ! -f ${GB2p5} ]; then + sudo dd if=/dev/urandom of=${GB2p5} bs=1M count=1 \ + 2> /dev/null + sudo dd if=/dev/urandom of=${GB2p5} bs=1M count=2 seek=2047 \ + 2> /dev/null + sudo dd if=/dev/urandom of=${GB2p5} bs=1M count=1 seek=2499 \ + 2> /dev/null + fi + + # Create a small file in this image. + if [ ! -f ${MB1} ]; then + sudo dd if=/dev/urandom of=${MB1} bs=1M count=1 2> /dev/null + fi + + # Delete the small file which possibly is written as part of a + # previous test. + sudo rm -f ${TMPMOUNT}/*.w + + # Generate the md5sums of reads that we will test against small file + dd if=${MB1} bs=1M skip=0 count=1 2> /dev/null | md5sum > ${MD5OUT} + + # Generate the md5sums of reads that we will test against big file + # One from beginning of file. + dd if=${GB2p5} bs=1M skip=0 count=1 2> /dev/null | md5sum >> ${MD5OUT} + + # One from end of file. + dd if=${GB2p5} bs=1M skip=2499 count=1 \ + 2> /dev/null | md5sum >> ${MD5OUT} + + # One from the last 1MB chunk of 2GB + dd if=${GB2p5} bs=1M skip=2047 count=1 \ + 2> /dev/null | md5sum >> ${MD5OUT} + + # One from the start 1MB chunk from 2GB + dd if=${GB2p5} bs=1M skip=2048 count=1 \ + 2> /dev/null | md5sum >> ${MD5OUT} + + # One 1MB chunk crossing the 2GB boundary + dd if=${GB2p5} bs=512K skip=4095 count=2 \ + 2> /dev/null | md5sum >> ${MD5OUT} + + sync + sudo umount tmpmount + rmdir tmpmount +} + +# First parameter is the text +# if $? is 0 its a pass, else a fail +function PassFail() { + + if [ $? -eq 0 ]; then + echo pass - "$1" + else + echo FAIL - "$1" + fi +} + +# Parameter 1 is the string which leads to an md5 generation +# Parameter 2 is the file we grep for that string +# Parameter 3 is the name of the file which has md5s in it +# Parameter 4 is the line # in the md5 file that we match it against +CheckMD5() { + + md5src=`grep -A6 "$1" "$2" | grep "md5 for"` + md5src=($md5src) + md5src=${md5src[6]} + md5dst=`sed -n $4p $3` + md5dst=($md5dst) + md5dst=${md5dst[0]} + [ "$md5src" = "$md5dst" ] + PassFail "$1" +} + +# First parameter is the name of the output file to check +# Second parameter is the name of the file containing the md5 expected +# Assume SFILE, BFILE and WFILE are set +function CheckResults() { + OUTFILE="$1" + MD5="$2" + + echo "------------------- Start $1 ---------------------" + # Check if the ls is showing correct results for 2.5 gb file + grep -A6 "ls host 0:0" $OUTFILE | grep 2621440000 | grep -iq 2.5gb.file + PassFail "ls host 0:0 of 2.5 GB file" + + # Check if the ls is showing correct results for 1 mb file + grep -A6 "ls host 0:0" $OUTFILE | grep 1048576 | grep -iq 1mb.file + PassFail "ls host 0:0 of 1 MB file" + + # Check size command on 1MB.file + grep -A3 "size host 0:0 ${SFILE}" $OUTFILE | grep -q "filesize=100000" + PassFail "size host 0:0 ${SFILE}" + + # Check size command on 2.5GB.file + grep -A3 "size host 0:0 ${BFILE}" $OUTFILE \ + | grep -q "filesize=9c400000" + PassFail "size host 0:0 ${BFILE}" + + # Check read full mb of 1MB.file + grep -A6 "load host 0:0 0x01000008 ${SFILE}" $OUTFILE | \ + grep -q "filesize=100000" + PassFail "load host 0:0 0x01000008 ${SFILE} sz" + CheckMD5 "load host 0:0 0x01000008 ${SFILE}" $OUTFILE $MD5 1 + + # Check first mb of 2.5GB.file + grep -A6 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x0" \ + $OUTFILE | grep -q "filesize=100000" + PassFail "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x0 sz" + CheckMD5 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x0" \ + $OUTFILE $MD5 2 + + # Check last mb of 2.5GB.file + grep -A6 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x9C300000" \ + $OUTFILE | grep -q "filesize=100000" + PassFail "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x9C300000 sz" + CheckMD5 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x9C300000" \ + $OUTFILE $MD5 3 + + # Check last 1mb chunk of 2gb from 2.5GB file + grep -A6 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF00000" \ + $OUTFILE | grep -q "filesize=100000" + PassFail "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF00000 sz" + CheckMD5 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF00000" \ + $OUTFILE $MD5 4 + + # Check first 1mb chunk after 2gb from 2.5GB file + grep -A6 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x80000000" \ + $OUTFILE | grep -q "filesize=100000" + PassFail "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x80000000 sz" + CheckMD5 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x80000000" \ + $OUTFILE $MD5 5 + + # Check 1mb chunk crossing the 2gb boundary from 2.5GB file + grep -A6 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF80000" \ + $OUTFILE | grep -q "filesize=100000" + PassFail "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF80000 sz" + CheckMD5 "load host 0:0 0x01000008 ${BFILE} 0x00100000 0x7FF80000" \ + $OUTFILE $MD5 6 + + # Check 2mb chunk from the last 1MB of 2.5GB file - generic failure case + grep -A6 "load host 0:0 0x01000008 ${BFILE} 0x00200000 0x9C300000" \ + $OUTFILE | grep -q 'Error: "filesize" not defined' + PassFail "load host 0:0 0x01000008 ${BFILE} 0x00200000 0x9C300000 sz" + + # Check 1mb chunk write + grep -A3 "write host 0:0 0x01000008 ${WFILE}" \ + $OUTFILE | egrep -q '1048576 bytes written|update journal' + PassFail "write host 0:0 0x01000008 ${WFILE}" + CheckMD5 "load host 0:0 0x01000008 ${WFILE}" \ + $OUTFILE $MD5 1 + echo "------------------- End $1 ---------------------" + echo "" +} + +for fs in ext4 fat; do + + if [ $fs = "fat" ]; then + FS=vfat + else + FS=$fs + fi + echo "Creating $FS image if not already present." + ACTIMG=`CreateImg ${IMG} ${FS}` + + echo "Creating files in $FS image if not already present." + CreateFilesInImg ${ACTIMG} ${MD5FILE}.${fs} + + TestImg ${ACTIMG} ${fs} > ${OUT}.${fs}.out + CheckResults ${OUT}.${fs}.out ${MD5FILE}.${fs} + + echo "Creating files in $FS image if not already present." + CreateFilesInImg ${ACTIMG} ${MD5FILE}.${fs} + + TestImg ${ACTIMG} "" > ${OUT}.fs.${fs}.out + CheckResults ${OUT}.fs.${fs}.out ${MD5FILE}.${fs} +done +