[syslinux:pathbased] ext2: handle symlinks larger than a single block

syslinux-bot for H. Peter Anvin hpa at zytor.com
Tue Feb 16 14:12:03 PST 2010


Commit-ID:  eccb0be0701db563b21a18ccf29824ef5975df6f
Gitweb:     http://syslinux.zytor.com/commit/eccb0be0701db563b21a18ccf29824ef5975df6f
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Tue, 16 Feb 2010 14:09:03 -0800
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Tue, 16 Feb 2010 14:09:03 -0800

ext2: handle symlinks larger than a single block

There is no law that symlinks has to be a single block only.

Signed-off-by: H. Peter Anvin <hpa at zytor.com>


---
 core/fs/ext2/ext2.c |   38 +++++++++++++++++++++++++++++++++-----
 1 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/core/fs/ext2/ext2.c b/core/fs/ext2/ext2.c
index 5254340..060c3e4 100644
--- a/core/fs/ext2/ext2.c
+++ b/core/fs/ext2/ext2.c
@@ -287,26 +287,54 @@ static struct inode *ext2_iget(char *dname, struct inode *parent)
     return ext2_iget_by_inr(fs, de->d_inode);
 }
 
+/*
+ * Read the entire contents of an inode into a memory buffer
+ */
+static int cache_get_file(struct inode *inode, void *buf, size_t bytes)
+{
+    struct fs_info *fs = inode->fs;
+    struct device *dev = fs->fs_dev;
+    size_t block_size = BLOCK_SIZE(fs);
+    block_t block;
+    uint32_t index = 0;		/* Logical block number */
+    size_t chunk;
+    const char *data;
+    char *p = buf;
+
+    if (inode->size > bytes)
+	bytes = inode->size;
+
+    while (bytes) {
+	chunk = min(bytes, block_size);
+	block = ext2_bmap(inode, index++);
+	data = get_cache(dev, block);
+	memcpy(p, data, chunk);
+
+	bytes -= chunk;
+	p += chunk;
+    }
+
+    return 0;
+}
+	
 int ext2_readlink(struct inode *inode, char *buf)
 {
     struct fs_info *fs = inode->fs;
     int sec_per_block = 1 << (fs->block_shift - fs->sector_shift);
     bool fast_symlink;
     const char *data;
-    size_t bytes = inode->size;
 
     if (inode->size > BLOCK_SIZE(fs))
 	return -1;		/* Error! */
 
     fast_symlink = (inode->file_acl ? sec_per_block : 0) == inode->blocks;
     if (fast_symlink) {
-	memcpy(buf, inode->pvt, bytes);
+	memcpy(buf, inode->pvt, inode->size);
     } else {
-	data = get_cache(fs->fs_dev, *(uint32_t *)inode->pvt);
-	memcpy(buf, data, bytes);
+	cache_get_file(inode, buf, inode->size);
     }
 
-    return bytes;
+    return inode->size;
 }
 
 /*



More information about the Syslinux-commits mailing list