[U-Boot] [PATCH v4 1/1] fs: fat/ext4/sandbox: Deal with files greater than 2GB
Suriyan Ramasami
suriyan.r at gmail.com
Mon Oct 27 20:48:44 CET 2014
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 <suriyan.r at gmail.com>
---
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",
- "<interface> <dev[:part]> <addr> <absolute filename path> [sizebytes]\n"
- " - create a file in / directory");
+U_BOOT_CMD(ext4write, 7, 1, do_ext4_write,
+ "create a file in the root directory",
+ "<interface> <dev[:part]> <addr> <absolute filename path>\n"
+ " [sizebytes] [file offset]\n"
+ " - create a file in / directory");
#endif
@@ -132,7 +87,7 @@ U_BOOT_CMD(ext4ls, 4, 1, do_ext4_ls,
"<interface> <dev[:part]> [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",
"<interface> [<dev[:part]> [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",
+ "<interface> [<dev[:part]> [<addr> [<filename> [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 <common.h>
#include <command.h>
#include <u-boot/md5.h>
+#include <asm/io.h>
/*
* 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 <<EOF
+y
+EOF
+ else
+ mkfs.${2} ${THE_IMG} &> /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, <interface> 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
+
--
1.9.1
More information about the U-Boot
mailing list