X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=fs%2Fcramfs%2Fcramfs.c;h=228f599d44bbca3e7c067ab5ae86ce9981e10a5e;hb=d39a0d2c8413b33a5cd29466c1f6c4bda022ee58;hp=ca8bc5e12b8499796746dc133e15d1c49f0649a7;hpb=a6ea791cb96f76fd600f6547a715e24ef66ba5e2;p=people%2Fms%2Fu-boot.git 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");