[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