diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
commit | 33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch) | |
tree | 2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /fs/hpfs/ea.c | |
parent | 216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff) |
Merge with Linux 2.3.32.
Diffstat (limited to 'fs/hpfs/ea.c')
-rw-r--r-- | fs/hpfs/ea.c | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c index d7abdc991..9632c054c 100644 --- a/fs/hpfs/ea.c +++ b/fs/hpfs/ea.c @@ -69,8 +69,64 @@ static void set_indirect_ea(struct super_block *s, int ano, secno a, char *data, hpfs_ea_write(s, a, ano, 0, size, data); } -/* Read an extended attribute named 'key' */ +/* Read an extended attribute named 'key' into the provided buffer */ +int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key, + char *buf, int size) +{ + unsigned pos; + int ano, len; + secno a; + struct extended_attribute *ea; + struct extended_attribute *ea_end = fnode_end_ea(fnode); + for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) + if (!strcmp(ea->name, key)) { + if (ea->indirect) + goto indirect; + if (ea->valuelen >= size) + return -EINVAL; + memcpy(buf, ea_data(ea), ea->valuelen); + buf[ea->valuelen] = 0; + return 0; + } + a = fnode->ea_secno; + len = fnode->ea_size_l; + ano = fnode->ea_anode; + pos = 0; + while (pos < len) { + char ex[4 + 255 + 1 + 8]; + ea = (struct extended_attribute *)ex; + if (pos + 4 > len) { + hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x", + ano ? "anode" : "sectors", a, len); + return -EIO; + } + if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO; + if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4)) + return -EIO; + if (!strcmp(ea->name, key)) { + if (ea->indirect) + goto indirect; + if (ea->valuelen >= size) + return -EINVAL; + if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, buf)) + return -EIO; + buf[ea->valuelen] = 0; + return 0; + } + pos += ea->namelen + ea->valuelen + 5; + } + return -ENOENT; +indirect: + if (ea_len(ea) >= size) + return -EINVAL; + if (hpfs_ea_read(s, ea_sec(ea), ea->anode, 0, ea_len(ea), buf)) + return -EIO; + buf[ea_len(ea)] = 0; + return 0; +} + +/* Read an extended attribute named 'key' */ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *size) { char *ret; |