diff options
author | Roman Zippel <zippel@linux-m68k.org> | 2006-01-18 20:43:10 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-18 22:20:23 -0500 |
commit | af8c85bb6d4e5352551277edd8448c4dfb2328ab (patch) | |
tree | 1fb10ca9fb7890db706db358c944308dc0cf616c | |
parent | 9a4cad95c9338077487226e22d4e01bc9edebf21 (diff) |
[PATCH] hfs: set correct create date for links
HFS+ also requires the correct creation date so recent version of OS X
recognize it as link.
Improve link handling:
- if something is wrong with the link, ignore the link attribute and treat
it as regular file (this also fixes a missing unlock during lookup).
- check for incorrect link counts during unlink.
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/hfsplus/catalog.c | 1 | ||||
-rw-r--r-- | fs/hfsplus/dir.c | 33 |
2 files changed, 22 insertions, 12 deletions
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c index 04255af34709..04058c8096d1 100644 --- a/fs/hfsplus/catalog.c +++ b/fs/hfsplus/catalog.c | |||
@@ -127,6 +127,7 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i | |||
127 | file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); | 127 | file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); |
128 | file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); | 128 | file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); |
129 | file->user_info.fdFlags = cpu_to_be16(0x100); | 129 | file->user_info.fdFlags = cpu_to_be16(0x100); |
130 | file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date; | ||
130 | file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev); | 131 | file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev); |
131 | } | 132 | } |
132 | return sizeof(*file); | 133 | return sizeof(*file); |
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 82c223765478..01a6fe3a395c 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
@@ -66,21 +66,28 @@ again: | |||
66 | } | 66 | } |
67 | cnid = be32_to_cpu(entry.file.id); | 67 | cnid = be32_to_cpu(entry.file.id); |
68 | if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && | 68 | if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && |
69 | entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR)) { | 69 | entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) && |
70 | (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date || | ||
71 | entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) && | ||
72 | HFSPLUS_SB(sb).hidden_dir) { | ||
70 | struct qstr str; | 73 | struct qstr str; |
71 | char name[32]; | 74 | char name[32]; |
72 | 75 | ||
73 | if (dentry->d_fsdata) { | 76 | if (dentry->d_fsdata) { |
74 | err = -ENOENT; | 77 | /* |
75 | inode = NULL; | 78 | * We found a link pointing to another link, |
76 | goto out; | 79 | * so ignore it and treat it as regular file. |
80 | */ | ||
81 | cnid = (unsigned long)dentry->d_fsdata; | ||
82 | linkid = 0; | ||
83 | } else { | ||
84 | dentry->d_fsdata = (void *)(unsigned long)cnid; | ||
85 | linkid = be32_to_cpu(entry.file.permissions.dev); | ||
86 | str.len = sprintf(name, "iNode%d", linkid); | ||
87 | str.name = name; | ||
88 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str); | ||
89 | goto again; | ||
77 | } | 90 | } |
78 | dentry->d_fsdata = (void *)(unsigned long)cnid; | ||
79 | linkid = be32_to_cpu(entry.file.permissions.dev); | ||
80 | str.len = sprintf(name, "iNode%d", linkid); | ||
81 | str.name = name; | ||
82 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str); | ||
83 | goto again; | ||
84 | } else if (!dentry->d_fsdata) | 91 | } else if (!dentry->d_fsdata) |
85 | dentry->d_fsdata = (void *)(unsigned long)cnid; | 92 | dentry->d_fsdata = (void *)(unsigned long)cnid; |
86 | } else { | 93 | } else { |
@@ -330,7 +337,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
330 | if (res) | 337 | if (res) |
331 | return res; | 338 | return res; |
332 | 339 | ||
333 | inode->i_nlink--; | 340 | if (inode->i_nlink > 0) |
341 | inode->i_nlink--; | ||
334 | hfsplus_delete_inode(inode); | 342 | hfsplus_delete_inode(inode); |
335 | if (inode->i_ino != cnid && !inode->i_nlink) { | 343 | if (inode->i_ino != cnid && !inode->i_nlink) { |
336 | if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { | 344 | if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { |
@@ -339,7 +347,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
339 | hfsplus_delete_inode(inode); | 347 | hfsplus_delete_inode(inode); |
340 | } else | 348 | } else |
341 | inode->i_flags |= S_DEAD; | 349 | inode->i_flags |= S_DEAD; |
342 | } | 350 | } else |
351 | inode->i_nlink = 0; | ||
343 | inode->i_ctime = CURRENT_TIME_SEC; | 352 | inode->i_ctime = CURRENT_TIME_SEC; |
344 | mark_inode_dirty(inode); | 353 | mark_inode_dirty(inode); |
345 | 354 | ||