diff options
Diffstat (limited to 'fs/hfsplus/dir.c')
-rw-r--r-- | fs/hfsplus/dir.c | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 50c8f44b6c66..01a6fe3a395c 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
@@ -66,25 +66,32 @@ 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 { |
87 | printk("HFS+-fs: Illegal catalog entry type in lookup\n"); | 94 | printk(KERN_ERR "hfs: invalid catalog entry type in lookup\n"); |
88 | err = -EIO; | 95 | err = -EIO; |
89 | goto fail; | 96 | goto fail; |
90 | } | 97 | } |
@@ -132,12 +139,12 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
132 | case 1: | 139 | case 1: |
133 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); | 140 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); |
134 | if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) { | 141 | if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) { |
135 | printk("HFS+-fs: bad catalog folder thread\n"); | 142 | printk(KERN_ERR "hfs: bad catalog folder thread\n"); |
136 | err = -EIO; | 143 | err = -EIO; |
137 | goto out; | 144 | goto out; |
138 | } | 145 | } |
139 | if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) { | 146 | if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) { |
140 | printk("HFS+-fs: truncated catalog thread\n"); | 147 | printk(KERN_ERR "hfs: truncated catalog thread\n"); |
141 | err = -EIO; | 148 | err = -EIO; |
142 | goto out; | 149 | goto out; |
143 | } | 150 | } |
@@ -156,7 +163,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
156 | 163 | ||
157 | for (;;) { | 164 | for (;;) { |
158 | if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) { | 165 | if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) { |
159 | printk("HFS+-fs: walked past end of dir\n"); | 166 | printk(KERN_ERR "hfs: walked past end of dir\n"); |
160 | err = -EIO; | 167 | err = -EIO; |
161 | goto out; | 168 | goto out; |
162 | } | 169 | } |
@@ -168,7 +175,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
168 | goto out; | 175 | goto out; |
169 | if (type == HFSPLUS_FOLDER) { | 176 | if (type == HFSPLUS_FOLDER) { |
170 | if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) { | 177 | if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) { |
171 | printk("HFS+-fs: small dir entry\n"); | 178 | printk(KERN_ERR "hfs: small dir entry\n"); |
172 | err = -EIO; | 179 | err = -EIO; |
173 | goto out; | 180 | goto out; |
174 | } | 181 | } |
@@ -180,7 +187,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
180 | break; | 187 | break; |
181 | } else if (type == HFSPLUS_FILE) { | 188 | } else if (type == HFSPLUS_FILE) { |
182 | if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { | 189 | if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { |
183 | printk("HFS+-fs: small file entry\n"); | 190 | printk(KERN_ERR "hfs: small file entry\n"); |
184 | err = -EIO; | 191 | err = -EIO; |
185 | goto out; | 192 | goto out; |
186 | } | 193 | } |
@@ -188,7 +195,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
188 | be32_to_cpu(entry.file.id), DT_REG)) | 195 | be32_to_cpu(entry.file.id), DT_REG)) |
189 | break; | 196 | break; |
190 | } else { | 197 | } else { |
191 | printk("HFS+-fs: bad catalog entry type\n"); | 198 | printk(KERN_ERR "hfs: bad catalog entry type\n"); |
192 | err = -EIO; | 199 | err = -EIO; |
193 | goto out; | 200 | goto out; |
194 | } | 201 | } |
@@ -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 | ||