diff options
author | Sergei Antonov <saproj@gmail.com> | 2014-06-06 17:36:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-06 19:08:09 -0400 |
commit | 97a62eaefdc196969e9d3857f65fc8a90ee1fe3c (patch) | |
tree | 92977ff2afef8dc7e783f58e1402434dc18989fc /fs/hfsplus | |
parent | 7f2fc81ea26717245fa7e5493a080a9723d6d596 (diff) |
hfsplus: emit proper file type from readdir
hfsplus_readdir() incorrectly returned DT_REG for symbolic links and
special files. Return DT_REG, DT_LNK, DT_FIFO, DT_CHR, DT_BLK, DT_SOCK,
or DT_UNKNOWN according to mode field in catalog record. Programs
relying on information from readdir will now work correctly with HFS+.
Signed-off-by: Sergei Antonov <saproj@gmail.com>
Cc: Anton Altaparmakov <aia21@cam.ac.uk>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Vyacheslav Dubeyko <slava@dubeyko.com>
Cc: Hin-Tak Leung <htl10@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/hfsplus')
-rw-r--r-- | fs/hfsplus/dir.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index fb07d260e692..610a3260bef1 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
@@ -218,13 +218,31 @@ static int hfsplus_readdir(struct file *file, struct dir_context *ctx) | |||
218 | be32_to_cpu(entry.folder.id), DT_DIR)) | 218 | be32_to_cpu(entry.folder.id), DT_DIR)) |
219 | break; | 219 | break; |
220 | } else if (type == HFSPLUS_FILE) { | 220 | } else if (type == HFSPLUS_FILE) { |
221 | u16 mode; | ||
222 | unsigned type = DT_UNKNOWN; | ||
223 | |||
221 | if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { | 224 | if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { |
222 | pr_err("small file entry\n"); | 225 | pr_err("small file entry\n"); |
223 | err = -EIO; | 226 | err = -EIO; |
224 | goto out; | 227 | goto out; |
225 | } | 228 | } |
229 | |||
230 | mode = be16_to_cpu(entry.file.permissions.mode); | ||
231 | if (S_ISREG(mode)) | ||
232 | type = DT_REG; | ||
233 | else if (S_ISLNK(mode)) | ||
234 | type = DT_LNK; | ||
235 | else if (S_ISFIFO(mode)) | ||
236 | type = DT_FIFO; | ||
237 | else if (S_ISCHR(mode)) | ||
238 | type = DT_CHR; | ||
239 | else if (S_ISBLK(mode)) | ||
240 | type = DT_BLK; | ||
241 | else if (S_ISSOCK(mode)) | ||
242 | type = DT_SOCK; | ||
243 | |||
226 | if (!dir_emit(ctx, strbuf, len, | 244 | if (!dir_emit(ctx, strbuf, len, |
227 | be32_to_cpu(entry.file.id), DT_REG)) | 245 | be32_to_cpu(entry.file.id), type)) |
228 | break; | 246 | break; |
229 | } else { | 247 | } else { |
230 | pr_err("bad catalog entry type\n"); | 248 | pr_err("bad catalog entry type\n"); |