udf: Treat symlink component of type 2 as /
[pandora-kernel.git] / fs / udf / symlink.c
index b1d4488..d89f324 100644 (file)
@@ -41,10 +41,16 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from,
                pc = (struct pathComponent *)(from + elen);
                switch (pc->componentType) {
                case 1:
-                       if (pc->lengthComponentIdent == 0) {
-                               p = to;
-                               *p++ = '/';
-                       }
+                       /*
+                        * Symlink points to some place which should be agreed
+                        * upon between originator and receiver of the media. Ignore.
+                        */
+                       if (pc->lengthComponentIdent > 0)
+                               break;
+                       /* Fall through */
+               case 2:
+                       p = to;
+                       *p++ = '/';
                        break;
                case 3:
                        memcpy(p, "../", 3);
@@ -74,11 +80,17 @@ static int udf_symlink_filler(struct file *file, struct page *page)
        struct inode *inode = page->mapping->host;
        struct buffer_head *bh = NULL;
        unsigned char *symlink;
-       int err = -EIO;
+       int err;
        unsigned char *p = kmap(page);
        struct udf_inode_info *iinfo;
        uint32_t pos;
 
+       /* We don't support symlinks longer than one block */
+       if (inode->i_size > inode->i_sb->s_blocksize) {
+               err = -ENAMETOOLONG;
+               goto out_unmap;
+       }
+
        iinfo = UDF_I(inode);
        pos = udf_block_map(inode, 0);
 
@@ -88,8 +100,10 @@ static int udf_symlink_filler(struct file *file, struct page *page)
        } else {
                bh = sb_bread(inode->i_sb, pos);
 
-               if (!bh)
-                       goto out;
+               if (!bh) {
+                       err = -EIO;
+                       goto out_unlock_inode;
+               }
 
                symlink = bh->b_data;
        }
@@ -103,9 +117,10 @@ static int udf_symlink_filler(struct file *file, struct page *page)
        unlock_page(page);
        return 0;
 
-out:
+out_unlock_inode:
        up_read(&iinfo->i_data_sem);
        SetPageError(page);
+out_unmap:
        kunmap(page);
        unlock_page(page);
        return err;