|
@@ -66,21 +66,28 @@ again:
|
|
|
}
|
|
|
cnid = be32_to_cpu(entry.file.id);
|
|
|
if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) &&
|
|
|
- entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR)) {
|
|
|
+ entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
|
|
|
+ (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date ||
|
|
|
+ entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) &&
|
|
|
+ HFSPLUS_SB(sb).hidden_dir) {
|
|
|
struct qstr str;
|
|
|
char name[32];
|
|
|
|
|
|
if (dentry->d_fsdata) {
|
|
|
- err = -ENOENT;
|
|
|
- inode = NULL;
|
|
|
- goto out;
|
|
|
+ /*
|
|
|
+ * We found a link pointing to another link,
|
|
|
+ * so ignore it and treat it as regular file.
|
|
|
+ */
|
|
|
+ cnid = (unsigned long)dentry->d_fsdata;
|
|
|
+ linkid = 0;
|
|
|
+ } else {
|
|
|
+ dentry->d_fsdata = (void *)(unsigned long)cnid;
|
|
|
+ linkid = be32_to_cpu(entry.file.permissions.dev);
|
|
|
+ str.len = sprintf(name, "iNode%d", linkid);
|
|
|
+ str.name = name;
|
|
|
+ hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
|
|
|
+ goto again;
|
|
|
}
|
|
|
- dentry->d_fsdata = (void *)(unsigned long)cnid;
|
|
|
- linkid = be32_to_cpu(entry.file.permissions.dev);
|
|
|
- str.len = sprintf(name, "iNode%d", linkid);
|
|
|
- str.name = name;
|
|
|
- hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
|
|
|
- goto again;
|
|
|
} else if (!dentry->d_fsdata)
|
|
|
dentry->d_fsdata = (void *)(unsigned long)cnid;
|
|
|
} else {
|
|
@@ -330,7 +337,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
|
|
|
if (res)
|
|
|
return res;
|
|
|
|
|
|
- inode->i_nlink--;
|
|
|
+ if (inode->i_nlink > 0)
|
|
|
+ inode->i_nlink--;
|
|
|
hfsplus_delete_inode(inode);
|
|
|
if (inode->i_ino != cnid && !inode->i_nlink) {
|
|
|
if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
|
|
@@ -339,7 +347,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
|
|
|
hfsplus_delete_inode(inode);
|
|
|
} else
|
|
|
inode->i_flags |= S_DEAD;
|
|
|
- }
|
|
|
+ } else
|
|
|
+ inode->i_nlink = 0;
|
|
|
inode->i_ctime = CURRENT_TIME_SEC;
|
|
|
mark_inode_dirty(inode);
|
|
|
|