diff options
author | Tyler Hall <tylerwhall@gmail.com> | 2017-04-12 16:29:17 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2017-04-18 10:27:58 -0400 |
commit | d39a0d2c8413b33a5cd29466c1f6c4bda022ee58 (patch) | |
tree | be3fc94030d9aa9d71580e3ceeedcf06e8d6f4a9 /fs/cramfs | |
parent | a6ea791cb96f76fd600f6547a715e24ef66ba5e2 (diff) | |
download | u-boot-d39a0d2c8413b33a5cd29466c1f6c4bda022ee58.tar.gz u-boot-d39a0d2c8413b33a5cd29466c1f6c4bda022ee58.tar.bz2 u-boot-d39a0d2c8413b33a5cd29466c1f6c4bda022ee58.zip |
cramfs: basic symlink support
Handle symlinks to files in the current directory. Other cases could be
handled with additional code, but this is a start.
Add explicit errors for absolute paths and links found in the middle of
a path (directories). Other cases like '..' or '.' will result with the
file not being found as when those path components are explicitly
provided.
Add a helper to decompress a null-terminated link name which is shared
with cramfs_list_inode.
Signed-off-by: Tyler Hall <tylerwhall@gmail.com>
Diffstat (limited to 'fs/cramfs')
-rw-r--r-- | fs/cramfs/cramfs.c | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c index ca8bc5e12b..228f599d44 100644 --- a/fs/cramfs/cramfs.c +++ b/fs/cramfs/cramfs.c @@ -49,6 +49,9 @@ extern flash_info_t flash_info[]; #define PART_OFFSET(x) ((ulong)x->offset) #endif +static int cramfs_uncompress (unsigned long begin, unsigned long offset, + unsigned long loadoffset); + static int cramfs_read_super (struct part_info *info) { unsigned long root_offset; @@ -94,6 +97,22 @@ static int cramfs_read_super (struct part_info *info) return 0; } +/* Unpack to an allocated buffer, trusting in the inode's size field. */ +static char *cramfs_uncompress_link (unsigned long begin, unsigned long offset) +{ + struct cramfs_inode *inode = (struct cramfs_inode *)(begin + offset); + unsigned long size = CRAMFS_24 (inode->size); + char *link = malloc (size + 1); + + if (!link || cramfs_uncompress (begin, offset, (unsigned long)link) != size) { + free (link); + link = NULL; + } else { + link[size] = '\0'; + } + return link; +} + static unsigned long cramfs_resolve (unsigned long begin, unsigned long offset, unsigned long size, int raw, char *filename) @@ -143,6 +162,33 @@ static unsigned long cramfs_resolve (unsigned long begin, unsigned long offset, p); } else if (S_ISREG (CRAMFS_16 (inode->mode))) { return offset + inodeoffset; + } else if (S_ISLNK (CRAMFS_16 (inode->mode))) { + unsigned long ret; + char *link; + if (p && strlen(p)) { + printf ("unsupported symlink to \ + non-terminal path\n"); + return 0; + } + link = cramfs_uncompress_link (begin, + offset + inodeoffset); + if (!link) { + printf ("%*.*s: Error reading link\n", + namelen, namelen, name); + return 0; + } else if (link[0] == '/') { + printf ("unsupported symlink to \ + absolute path\n"); + free (link); + return 0; + } + ret = cramfs_resolve (begin, + offset, + size, + raw, + strtok(link, "/")); + free (link); + return ret; } else { printf ("%*.*s: unsupported file type (%x)\n", namelen, namelen, name, @@ -235,20 +281,12 @@ static int cramfs_list_inode (struct part_info *info, unsigned long offset) CRAMFS_24 (inode->size), namelen, namelen, name); if ((CRAMFS_16 (inode->mode) & S_IFMT) == S_IFLNK) { - /* symbolic link. - * Unpack the link target, trusting in the inode's size field. - */ - unsigned long size = CRAMFS_24 (inode->size); - char *link = malloc (size); - - if (link != NULL && cramfs_uncompress (PART_OFFSET(info), offset, - (unsigned long) link) - == size) - printf (" -> %*.*s\n", (int) size, (int) size, link); + char *link = cramfs_uncompress_link (PART_OFFSET(info), offset); + if (link) + printf (" -> %s\n", link); else printf (" [Error reading link]\n"); - if (link) - free (link); + free (link); } else printf ("\n"); |