diff options
Diffstat (limited to 'fs/ubifs/ubifs.c')
-rw-r--r-- | fs/ubifs/ubifs.c | 70 |
1 files changed, 56 insertions, 14 deletions
diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index f7a084747e6..0a7a7bff09f 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -570,7 +570,7 @@ static unsigned long ubifs_findfile(struct super_block *sb, char *filename) return 0; } -int ubifs_ls(char *filename) +int ubifs_ls(const char *filename) { struct ubifs_info *c = ubifs_sb->s_fs_info; struct file *file; @@ -581,7 +581,7 @@ int ubifs_ls(char *filename) int ret = 0; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); - inum = ubifs_findfile(ubifs_sb, filename); + inum = ubifs_findfile(ubifs_sb, (char *)filename); if (!inum) { ret = -1; goto out; @@ -787,7 +787,8 @@ error: return err; } -int ubifs_load(char *filename, u32 addr, u32 size) +int ubifs_read(const char *filename, void *buf, loff_t offset, + loff_t size, loff_t *actread) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; @@ -798,10 +799,18 @@ int ubifs_load(char *filename, u32 addr, u32 size) int count; int last_block_size = 0; + *actread = 0; + + if (offset & (PAGE_SIZE - 1)) { + printf("ubifs: Error offset must be a multple of %d\n", + PAGE_SIZE); + return -1; + } + c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); /* ubifs_findfile will resolve symlinks, so we know that we get * the real file here */ - inum = ubifs_findfile(ubifs_sb, filename); + inum = ubifs_findfile(ubifs_sb, (char *)filename); if (!inum) { err = -1; goto out; @@ -817,19 +826,24 @@ int ubifs_load(char *filename, u32 addr, u32 size) goto out; } + if (offset > inode->i_size) { + printf("ubifs: Error offset (%lld) > file-size (%lld)\n", + offset, size); + err = -1; + goto put_inode; + } + /* * If no size was specified or if size bigger than filesize * set size to filesize */ - if ((size == 0) || (size > inode->i_size)) - size = inode->i_size; + if ((size == 0) || (size > (inode->i_size - offset))) + size = inode->i_size - offset; count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; - printf("Loading file '%s' to addr 0x%08x with size %d (0x%08x)...\n", - filename, addr, size, size); - page.addr = (void *)addr; - page.index = 0; + page.addr = buf; + page.index = offset / PAGE_SIZE; page.inode = inode; for (i = 0; i < count; i++) { /* @@ -846,16 +860,44 @@ int ubifs_load(char *filename, u32 addr, u32 size) page.index++; } - if (err) + if (err) { printf("Error reading file '%s'\n", filename); - else { - setenv_hex("filesize", size); - printf("Done\n"); + *actread = i * PAGE_SIZE; + } else { + *actread = size; } +put_inode: ubifs_iput(inode); out: ubi_close_volume(c->ubi); return err; } + +/* Compat wrappers for common/cmd_ubifs.c */ +int ubifs_load(char *filename, u32 addr, u32 size) +{ + loff_t actread; + int err; + + printf("Loading file '%s' to addr 0x%08x...\n", filename, addr); + + err = ubifs_read(filename, (void *)addr, 0, size, &actread); + if (err == 0) { + setenv_hex("filesize", actread); + printf("Done\n"); + } + + return err; +} + +void uboot_ubifs_umount(void) +{ + if (ubifs_sb) { + printf("Unmounting UBIFS volume %s!\n", + ((struct ubifs_info *)(ubifs_sb->s_fs_info))->vi.name); + ubifs_umount(ubifs_sb->s_fs_info); + ubifs_sb = NULL; + } +} |