diff options
Diffstat (limited to 'fs/hfsplus/dir.c')
-rw-r--r-- | fs/hfsplus/dir.c | 33 |
1 files changed, 21 insertions, 12 deletions
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 | ||