diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-02 23:46:51 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-03 01:28:40 -0500 |
commit | 69102e9b4b61f56a26717659ec2e572a6b18458d (patch) | |
tree | 85f94fc81091e1f8014c9696359587884dceb3b8 /fs | |
parent | 810c1b2e48d32a8605928c3609262d94853c3a76 (diff) |
hfs: fix rename() over non-empty directory
merge hfs_unlink() and hfs_rmdir(), while we are at it.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/hfs/dir.c | 50 |
1 files changed, 13 insertions, 37 deletions
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index afa66aaa2237..b4d70b13be92 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c | |||
@@ -238,46 +238,22 @@ static int hfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
238 | } | 238 | } |
239 | 239 | ||
240 | /* | 240 | /* |
241 | * hfs_unlink() | 241 | * hfs_remove() |
242 | * | 242 | * |
243 | * This is the unlink() entry in the inode_operations structure for | 243 | * This serves as both unlink() and rmdir() in the inode_operations |
244 | * regular HFS directories. The purpose is to delete an existing | 244 | * structure for regular HFS directories. The purpose is to delete |
245 | * file, given the inode for the parent directory and the name | 245 | * an existing child, given the inode for the parent directory and |
246 | * (and its length) of the existing file. | 246 | * the name (and its length) of the existing directory. |
247 | */ | ||
248 | static int hfs_unlink(struct inode *dir, struct dentry *dentry) | ||
249 | { | ||
250 | struct inode *inode; | ||
251 | int res; | ||
252 | |||
253 | inode = dentry->d_inode; | ||
254 | res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name); | ||
255 | if (res) | ||
256 | return res; | ||
257 | |||
258 | drop_nlink(inode); | ||
259 | hfs_delete_inode(inode); | ||
260 | inode->i_ctime = CURRENT_TIME_SEC; | ||
261 | mark_inode_dirty(inode); | ||
262 | |||
263 | return res; | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * hfs_rmdir() | ||
268 | * | 247 | * |
269 | * This is the rmdir() entry in the inode_operations structure for | 248 | * HFS does not have hardlinks, so both rmdir and unlink set the |
270 | * regular HFS directories. The purpose is to delete an existing | 249 | * link count to 0. The only difference is the emptiness check. |
271 | * directory, given the inode for the parent directory and the name | ||
272 | * (and its length) of the existing directory. | ||
273 | */ | 250 | */ |
274 | static int hfs_rmdir(struct inode *dir, struct dentry *dentry) | 251 | static int hfs_remove(struct inode *dir, struct dentry *dentry) |
275 | { | 252 | { |
276 | struct inode *inode; | 253 | struct inode *inode = dentry->d_inode; |
277 | int res; | 254 | int res; |
278 | 255 | ||
279 | inode = dentry->d_inode; | 256 | if (S_ISDIR(inode->i_mode) && inode->i_size != 2) |
280 | if (inode->i_size != 2) | ||
281 | return -ENOTEMPTY; | 257 | return -ENOTEMPTY; |
282 | res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name); | 258 | res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name); |
283 | if (res) | 259 | if (res) |
@@ -307,7 +283,7 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
307 | 283 | ||
308 | /* Unlink destination if it already exists */ | 284 | /* Unlink destination if it already exists */ |
309 | if (new_dentry->d_inode) { | 285 | if (new_dentry->d_inode) { |
310 | res = hfs_unlink(new_dir, new_dentry); | 286 | res = hfs_remove(new_dir, new_dentry); |
311 | if (res) | 287 | if (res) |
312 | return res; | 288 | return res; |
313 | } | 289 | } |
@@ -332,9 +308,9 @@ const struct file_operations hfs_dir_operations = { | |||
332 | const struct inode_operations hfs_dir_inode_operations = { | 308 | const struct inode_operations hfs_dir_inode_operations = { |
333 | .create = hfs_create, | 309 | .create = hfs_create, |
334 | .lookup = hfs_lookup, | 310 | .lookup = hfs_lookup, |
335 | .unlink = hfs_unlink, | 311 | .unlink = hfs_remove, |
336 | .mkdir = hfs_mkdir, | 312 | .mkdir = hfs_mkdir, |
337 | .rmdir = hfs_rmdir, | 313 | .rmdir = hfs_remove, |
338 | .rename = hfs_rename, | 314 | .rename = hfs_rename, |
339 | .setattr = hfs_inode_setattr, | 315 | .setattr = hfs_inode_setattr, |
340 | }; | 316 | }; |