Blame view
fs/hfsplus/dir.c
13.9 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 8 9 10 11 12 13 |
/* * linux/fs/hfsplus/dir.c * * Copyright (C) 2001 * Brad Boyer (flar@allandria.com) * (C) 2003 Ardis Technologies <roman@ardistech.com> * * Handling of directories */ #include <linux/errno.h> #include <linux/fs.h> |
1da177e4c Linux-2.6.12-rc2 |
14 15 |
#include <linux/slab.h> #include <linux/random.h> |
017f8da43 hfsplus: fix wors... |
16 |
#include <linux/nls.h> |
1da177e4c Linux-2.6.12-rc2 |
17 18 19 |
#include "hfsplus_fs.h" #include "hfsplus_raw.h" |
324ef39a8 hfsplus: add supp... |
20 |
#include "xattr.h" |
b4c1107cc hfsplus: integrat... |
21 |
#include "acl.h" |
1da177e4c Linux-2.6.12-rc2 |
22 23 24 25 26 27 28 29 30 31 |
static inline void hfsplus_instantiate(struct dentry *dentry, struct inode *inode, u32 cnid) { dentry->d_fsdata = (void *)(unsigned long)cnid; d_instantiate(dentry, inode); } /* Find the entry inside dir named dentry->d_name */ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry, |
00cd8dd3b stop passing name... |
32 |
unsigned int flags) |
1da177e4c Linux-2.6.12-rc2 |
33 34 35 36 37 38 39 40 41 42 |
{ struct inode *inode = NULL; struct hfs_find_data fd; struct super_block *sb; hfsplus_cat_entry entry; int err; u32 cnid, linkid = 0; u16 type; sb = dir->i_sb; |
d45bce8fa HFS+: add custom ... |
43 |
|
1da177e4c Linux-2.6.12-rc2 |
44 |
dentry->d_fsdata = NULL; |
5bd9d99d1 hfsplus: add erro... |
45 46 47 |
err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); if (err) return ERR_PTR(err); |
89ac9b4d3 hfsplus: fix long... |
48 49 50 51 |
err = hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name); if (unlikely(err < 0)) goto fail; |
1da177e4c Linux-2.6.12-rc2 |
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
again: err = hfs_brec_read(&fd, &entry, sizeof(entry)); if (err) { if (err == -ENOENT) { hfs_find_exit(&fd); /* No such entry */ inode = NULL; goto out; } goto fail; } type = be16_to_cpu(entry.type); if (type == HFSPLUS_FOLDER) { if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) { err = -EIO; goto fail; } cnid = be32_to_cpu(entry.folder.id); dentry->d_fsdata = (void *)(unsigned long)cnid; } else if (type == HFSPLUS_FILE) { if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { err = -EIO; goto fail; } cnid = be32_to_cpu(entry.file.id); |
2753cc281 hfsplus: over 80 ... |
77 78 79 80 |
if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) && |
68e787c3c hfsplus: fix NULL... |
81 |
HFSPLUS_SB(sb)->hidden_dir && |
2753cc281 hfsplus: over 80 ... |
82 83 84 85 |
(entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir)-> create_date || entry.file.create_date == |
2b0143b5c VFS: normal files... |
86 |
HFSPLUS_I(d_inode(sb->s_root))-> |
68e787c3c hfsplus: fix NULL... |
87 |
create_date)) { |
1da177e4c Linux-2.6.12-rc2 |
88 89 90 91 |
struct qstr str; char name[32]; if (dentry->d_fsdata) { |
af8c85bb6 [PATCH] hfs: set ... |
92 93 94 95 96 97 98 99 |
/* * 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; |
2753cc281 hfsplus: over 80 ... |
100 101 |
linkid = be32_to_cpu(entry.file.permissions.dev); |
af8c85bb6 [PATCH] hfs: set ... |
102 103 |
str.len = sprintf(name, "iNode%d", linkid); str.name = name; |
89ac9b4d3 hfsplus: fix long... |
104 |
err = hfsplus_cat_build_key(sb, fd.search_key, |
2753cc281 hfsplus: over 80 ... |
105 106 |
HFSPLUS_SB(sb)->hidden_dir->i_ino, &str); |
89ac9b4d3 hfsplus: fix long... |
107 108 |
if (unlikely(err < 0)) goto fail; |
af8c85bb6 [PATCH] hfs: set ... |
109 |
goto again; |
1da177e4c Linux-2.6.12-rc2 |
110 |
} |
1da177e4c Linux-2.6.12-rc2 |
111 112 113 |
} else if (!dentry->d_fsdata) dentry->d_fsdata = (void *)(unsigned long)cnid; } else { |
d61426732 hfs/hfsplus: conv... |
114 115 |
pr_err("invalid catalog entry type in lookup "); |
1da177e4c Linux-2.6.12-rc2 |
116 117 118 119 |
err = -EIO; goto fail; } hfs_find_exit(&fd); |
635253915 iget: stop HFSPLU... |
120 121 122 |
inode = hfsplus_iget(dir->i_sb, cnid); if (IS_ERR(inode)) return ERR_CAST(inode); |
1da177e4c Linux-2.6.12-rc2 |
123 |
if (S_ISREG(inode->i_mode)) |
f6089ff87 hfsplus: fix link... |
124 |
HFSPLUS_I(inode)->linkid = linkid; |
1da177e4c Linux-2.6.12-rc2 |
125 126 127 128 129 130 131 |
out: d_add(dentry, inode); return NULL; fail: hfs_find_exit(&fd); return ERR_PTR(err); } |
e72514e7a [readdir] convert... |
132 |
static int hfsplus_readdir(struct file *file, struct dir_context *ctx) |
1da177e4c Linux-2.6.12-rc2 |
133 |
{ |
e72514e7a [readdir] convert... |
134 |
struct inode *inode = file_inode(file); |
1da177e4c Linux-2.6.12-rc2 |
135 136 |
struct super_block *sb = inode->i_sb; int len, err; |
017f8da43 hfsplus: fix wors... |
137 |
char *strbuf; |
1da177e4c Linux-2.6.12-rc2 |
138 139 140 141 |
hfsplus_cat_entry entry; struct hfs_find_data fd; struct hfsplus_readdir_data *rd; u16 type; |
e72514e7a [readdir] convert... |
142 |
if (file->f_pos >= inode->i_size) |
1da177e4c Linux-2.6.12-rc2 |
143 |
return 0; |
5bd9d99d1 hfsplus: add erro... |
144 145 146 |
err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); if (err) return err; |
017f8da43 hfsplus: fix wors... |
147 148 149 150 151 |
strbuf = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_MAX_STRLEN + 1, GFP_KERNEL); if (!strbuf) { err = -ENOMEM; goto out; } |
89ac9b4d3 hfsplus: fix long... |
152 |
hfsplus_cat_build_key_with_cnid(sb, fd.search_key, inode->i_ino); |
324ef39a8 hfsplus: add supp... |
153 |
err = hfs_brec_find(&fd, hfs_find_rec_by_key); |
1da177e4c Linux-2.6.12-rc2 |
154 155 |
if (err) goto out; |
e72514e7a [readdir] convert... |
156 |
if (ctx->pos == 0) { |
1da177e4c Linux-2.6.12-rc2 |
157 |
/* This is completely artificial... */ |
e72514e7a [readdir] convert... |
158 |
if (!dir_emit_dot(file, ctx)) |
1da177e4c Linux-2.6.12-rc2 |
159 |
goto out; |
e72514e7a [readdir] convert... |
160 161 162 |
ctx->pos = 1; } if (ctx->pos == 1) { |
6f24f8928 hfsplus: Fix pote... |
163 164 165 166 |
if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { err = -EIO; goto out; } |
2753cc281 hfsplus: over 80 ... |
167 168 |
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); |
1da177e4c Linux-2.6.12-rc2 |
169 |
if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) { |
d61426732 hfs/hfsplus: conv... |
170 171 |
pr_err("bad catalog folder thread "); |
1da177e4c Linux-2.6.12-rc2 |
172 173 174 175 |
err = -EIO; goto out; } if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) { |
d61426732 hfs/hfsplus: conv... |
176 177 |
pr_err("truncated catalog thread "); |
1da177e4c Linux-2.6.12-rc2 |
178 179 180 |
err = -EIO; goto out; } |
e72514e7a [readdir] convert... |
181 |
if (!dir_emit(ctx, "..", 2, |
1da177e4c Linux-2.6.12-rc2 |
182 183 |
be32_to_cpu(entry.thread.parentID), DT_DIR)) goto out; |
e72514e7a [readdir] convert... |
184 |
ctx->pos = 2; |
1da177e4c Linux-2.6.12-rc2 |
185 |
} |
e72514e7a [readdir] convert... |
186 187 188 189 190 |
if (ctx->pos >= inode->i_size) goto out; err = hfs_brec_goto(&fd, ctx->pos - 1); if (err) goto out; |
1da177e4c Linux-2.6.12-rc2 |
191 192 |
for (;;) { if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) { |
d61426732 hfs/hfsplus: conv... |
193 194 |
pr_err("walked past end of dir "); |
1da177e4c Linux-2.6.12-rc2 |
195 196 197 |
err = -EIO; goto out; } |
6f24f8928 hfsplus: Fix pote... |
198 199 200 201 202 |
if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { err = -EIO; goto out; } |
2753cc281 hfsplus: over 80 ... |
203 204 |
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); |
1da177e4c Linux-2.6.12-rc2 |
205 |
type = be16_to_cpu(entry.type); |
017f8da43 hfsplus: fix wors... |
206 |
len = NLS_MAX_CHARSET_SIZE * HFSPLUS_MAX_STRLEN; |
1da177e4c Linux-2.6.12-rc2 |
207 208 209 210 |
err = hfsplus_uni2asc(sb, &fd.key->cat.name, strbuf, &len); if (err) goto out; if (type == HFSPLUS_FOLDER) { |
2753cc281 hfsplus: over 80 ... |
211 212 |
if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) { |
d61426732 hfs/hfsplus: conv... |
213 214 |
pr_err("small dir entry "); |
1da177e4c Linux-2.6.12-rc2 |
215 216 217 |
err = -EIO; goto out; } |
dd73a01a3 hfsplus: fix HFSP... |
218 219 220 |
if (HFSPLUS_SB(sb)->hidden_dir && HFSPLUS_SB(sb)->hidden_dir->i_ino == be32_to_cpu(entry.folder.id)) |
1da177e4c Linux-2.6.12-rc2 |
221 |
goto next; |
e72514e7a [readdir] convert... |
222 |
if (!dir_emit(ctx, strbuf, len, |
1da177e4c Linux-2.6.12-rc2 |
223 224 225 |
be32_to_cpu(entry.folder.id), DT_DIR)) break; } else if (type == HFSPLUS_FILE) { |
97a62eaef hfsplus: emit pro... |
226 227 |
u16 mode; unsigned type = DT_UNKNOWN; |
1da177e4c Linux-2.6.12-rc2 |
228 |
if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { |
d61426732 hfs/hfsplus: conv... |
229 230 |
pr_err("small file entry "); |
1da177e4c Linux-2.6.12-rc2 |
231 232 233 |
err = -EIO; goto out; } |
97a62eaef hfsplus: emit pro... |
234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
mode = be16_to_cpu(entry.file.permissions.mode); if (S_ISREG(mode)) type = DT_REG; else if (S_ISLNK(mode)) type = DT_LNK; else if (S_ISFIFO(mode)) type = DT_FIFO; else if (S_ISCHR(mode)) type = DT_CHR; else if (S_ISBLK(mode)) type = DT_BLK; else if (S_ISSOCK(mode)) type = DT_SOCK; |
e72514e7a [readdir] convert... |
248 |
if (!dir_emit(ctx, strbuf, len, |
97a62eaef hfsplus: emit pro... |
249 |
be32_to_cpu(entry.file.id), type)) |
1da177e4c Linux-2.6.12-rc2 |
250 251 |
break; } else { |
d61426732 hfs/hfsplus: conv... |
252 253 |
pr_err("bad catalog entry type "); |
1da177e4c Linux-2.6.12-rc2 |
254 255 256 |
err = -EIO; goto out; } |
20b7643d8 hfsplus: spaces/i... |
257 |
next: |
e72514e7a [readdir] convert... |
258 259 |
ctx->pos++; if (ctx->pos >= inode->i_size) |
1da177e4c Linux-2.6.12-rc2 |
260 261 262 263 264 |
goto out; err = hfs_brec_goto(&fd, 1); if (err) goto out; } |
e72514e7a [readdir] convert... |
265 |
rd = file->private_data; |
1da177e4c Linux-2.6.12-rc2 |
266 267 268 269 270 271 |
if (!rd) { rd = kmalloc(sizeof(struct hfsplus_readdir_data), GFP_KERNEL); if (!rd) { err = -ENOMEM; goto out; } |
e72514e7a [readdir] convert... |
272 273 |
file->private_data = rd; rd->file = file; |
323ee8fc5 hfsplus: switch t... |
274 |
spin_lock(&HFSPLUS_I(inode)->open_dir_lock); |
6af502de2 hfsplus: fix HFSP... |
275 |
list_add(&rd->list, &HFSPLUS_I(inode)->open_dir_list); |
323ee8fc5 hfsplus: switch t... |
276 |
spin_unlock(&HFSPLUS_I(inode)->open_dir_lock); |
1da177e4c Linux-2.6.12-rc2 |
277 |
} |
323ee8fc5 hfsplus: switch t... |
278 279 280 281 |
/* * Can be done after the list insertion; exclusion with * hfsplus_delete_cat() is provided by directory lock. */ |
1da177e4c Linux-2.6.12-rc2 |
282 283 |
memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key)); out: |
017f8da43 hfsplus: fix wors... |
284 |
kfree(strbuf); |
1da177e4c Linux-2.6.12-rc2 |
285 286 287 288 289 290 291 292 |
hfs_find_exit(&fd); return err; } static int hfsplus_dir_release(struct inode *inode, struct file *file) { struct hfsplus_readdir_data *rd = file->private_data; if (rd) { |
323ee8fc5 hfsplus: switch t... |
293 |
spin_lock(&HFSPLUS_I(inode)->open_dir_lock); |
1da177e4c Linux-2.6.12-rc2 |
294 |
list_del(&rd->list); |
323ee8fc5 hfsplus: switch t... |
295 |
spin_unlock(&HFSPLUS_I(inode)->open_dir_lock); |
1da177e4c Linux-2.6.12-rc2 |
296 297 298 299 |
kfree(rd); } return 0; } |
1da177e4c Linux-2.6.12-rc2 |
300 301 302 |
static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, struct dentry *dst_dentry) { |
dd73a01a3 hfsplus: fix HFSP... |
303 |
struct hfsplus_sb_info *sbi = HFSPLUS_SB(dst_dir->i_sb); |
2b0143b5c VFS: normal files... |
304 305 |
struct inode *inode = d_inode(src_dentry); struct inode *src_dir = d_inode(src_dentry->d_parent); |
1da177e4c Linux-2.6.12-rc2 |
306 307 308 309 310 311 312 |
struct qstr str; char name[32]; u32 cnid, id; int res; if (HFSPLUS_IS_RSRC(inode)) return -EPERM; |
f6089ff87 hfsplus: fix link... |
313 314 |
if (!S_ISREG(inode->i_mode)) return -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
315 |
|
7ac9fb9c2 hfsplus: add per-... |
316 |
mutex_lock(&sbi->vh_mutex); |
1da177e4c Linux-2.6.12-rc2 |
317 318 319 320 321 322 323 324 |
if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) { for (;;) { get_random_bytes(&id, sizeof(cnid)); id &= 0x3fffffff; str.name = name; str.len = sprintf(name, "iNode%d", id); res = hfsplus_rename_cat(inode->i_ino, src_dir, &src_dentry->d_name, |
dd73a01a3 hfsplus: fix HFSP... |
325 |
sbi->hidden_dir, &str); |
1da177e4c Linux-2.6.12-rc2 |
326 327 328 |
if (!res) break; if (res != -EEXIST) |
7ac9fb9c2 hfsplus: add per-... |
329 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
330 |
} |
f6089ff87 hfsplus: fix link... |
331 |
HFSPLUS_I(inode)->linkid = id; |
dd73a01a3 hfsplus: fix HFSP... |
332 |
cnid = sbi->next_cnid++; |
1da177e4c Linux-2.6.12-rc2 |
333 |
src_dentry->d_fsdata = (void *)(unsigned long)cnid; |
2753cc281 hfsplus: over 80 ... |
334 335 |
res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode); |
1da177e4c Linux-2.6.12-rc2 |
336 337 |
if (res) /* panic? */ |
7ac9fb9c2 hfsplus: add per-... |
338 |
goto out; |
dd73a01a3 hfsplus: fix HFSP... |
339 |
sbi->file_count++; |
1da177e4c Linux-2.6.12-rc2 |
340 |
} |
dd73a01a3 hfsplus: fix HFSP... |
341 |
cnid = sbi->next_cnid++; |
1da177e4c Linux-2.6.12-rc2 |
342 343 |
res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode); if (res) |
7ac9fb9c2 hfsplus: add per-... |
344 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
345 |
|
d8c76e6f4 [PATCH] r/o bind ... |
346 |
inc_nlink(inode); |
1da177e4c Linux-2.6.12-rc2 |
347 |
hfsplus_instantiate(dst_dentry, inode, cnid); |
7de9c6ee3 new helper: ihold() |
348 |
ihold(inode); |
02027d42c fs: Replace CURRE... |
349 |
inode->i_ctime = current_time(inode); |
1da177e4c Linux-2.6.12-rc2 |
350 |
mark_inode_dirty(inode); |
dd73a01a3 hfsplus: fix HFSP... |
351 |
sbi->file_count++; |
9e6c5829b hfsplus: get rid ... |
352 |
hfsplus_mark_mdb_dirty(dst_dir->i_sb); |
7ac9fb9c2 hfsplus: add per-... |
353 354 355 |
out: mutex_unlock(&sbi->vh_mutex); return res; |
1da177e4c Linux-2.6.12-rc2 |
356 357 358 359 |
} static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) { |
dd73a01a3 hfsplus: fix HFSP... |
360 |
struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
2b0143b5c VFS: normal files... |
361 |
struct inode *inode = d_inode(dentry); |
1da177e4c Linux-2.6.12-rc2 |
362 363 364 365 366 367 368 |
struct qstr str; char name[32]; u32 cnid; int res; if (HFSPLUS_IS_RSRC(inode)) return -EPERM; |
7ac9fb9c2 hfsplus: add per-... |
369 |
mutex_lock(&sbi->vh_mutex); |
1da177e4c Linux-2.6.12-rc2 |
370 371 |
cnid = (u32)(unsigned long)dentry->d_fsdata; if (inode->i_ino == cnid && |
6af502de2 hfsplus: fix HFSP... |
372 |
atomic_read(&HFSPLUS_I(inode)->opencnt)) { |
1da177e4c Linux-2.6.12-rc2 |
373 374 375 376 |
str.name = name; str.len = sprintf(name, "temp%lu", inode->i_ino); res = hfsplus_rename_cat(inode->i_ino, dir, &dentry->d_name, |
dd73a01a3 hfsplus: fix HFSP... |
377 |
sbi->hidden_dir, &str); |
85b8fe8cc hfsplus: free spa... |
378 |
if (!res) { |
1da177e4c Linux-2.6.12-rc2 |
379 |
inode->i_flags |= S_DEAD; |
85b8fe8cc hfsplus: free spa... |
380 381 |
drop_nlink(inode); } |
7ac9fb9c2 hfsplus: add per-... |
382 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
383 384 385 |
} res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); if (res) |
7ac9fb9c2 hfsplus: add per-... |
386 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
387 |
|
af8c85bb6 [PATCH] hfs: set ... |
388 |
if (inode->i_nlink > 0) |
9a53c3a78 [PATCH] r/o bind ... |
389 |
drop_nlink(inode); |
76b0c26af HFS+: fix unlink ... |
390 391 392 393 |
if (inode->i_ino == cnid) clear_nlink(inode); if (!inode->i_nlink) { if (inode->i_ino != cnid) { |
dd73a01a3 hfsplus: fix HFSP... |
394 |
sbi->file_count--; |
6af502de2 hfsplus: fix HFSP... |
395 |
if (!atomic_read(&HFSPLUS_I(inode)->opencnt)) { |
76b0c26af HFS+: fix unlink ... |
396 |
res = hfsplus_delete_cat(inode->i_ino, |
dd73a01a3 hfsplus: fix HFSP... |
397 |
sbi->hidden_dir, |
76b0c26af HFS+: fix unlink ... |
398 399 400 401 402 |
NULL); if (!res) hfsplus_delete_inode(inode); } else inode->i_flags |= S_DEAD; |
1da177e4c Linux-2.6.12-rc2 |
403 |
} else |
76b0c26af HFS+: fix unlink ... |
404 |
hfsplus_delete_inode(inode); |
af8c85bb6 [PATCH] hfs: set ... |
405 |
} else |
dd73a01a3 hfsplus: fix HFSP... |
406 |
sbi->file_count--; |
02027d42c fs: Replace CURRE... |
407 |
inode->i_ctime = current_time(inode); |
1da177e4c Linux-2.6.12-rc2 |
408 |
mark_inode_dirty(inode); |
7ac9fb9c2 hfsplus: add per-... |
409 410 |
out: mutex_unlock(&sbi->vh_mutex); |
1da177e4c Linux-2.6.12-rc2 |
411 412 |
return res; } |
1da177e4c Linux-2.6.12-rc2 |
413 414 |
static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) { |
7ac9fb9c2 hfsplus: add per-... |
415 |
struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
2b0143b5c VFS: normal files... |
416 |
struct inode *inode = d_inode(dentry); |
1da177e4c Linux-2.6.12-rc2 |
417 |
int res; |
1da177e4c Linux-2.6.12-rc2 |
418 419 |
if (inode->i_size != 2) return -ENOTEMPTY; |
7ac9fb9c2 hfsplus: add per-... |
420 421 |
mutex_lock(&sbi->vh_mutex); |
1da177e4c Linux-2.6.12-rc2 |
422 423 |
res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); if (res) |
7ac9fb9c2 hfsplus: add per-... |
424 |
goto out; |
ce71ec368 [PATCH] r/o bind ... |
425 |
clear_nlink(inode); |
02027d42c fs: Replace CURRE... |
426 |
inode->i_ctime = current_time(inode); |
1da177e4c Linux-2.6.12-rc2 |
427 428 |
hfsplus_delete_inode(inode); mark_inode_dirty(inode); |
7ac9fb9c2 hfsplus: add per-... |
429 430 431 |
out: mutex_unlock(&sbi->vh_mutex); return res; |
1da177e4c Linux-2.6.12-rc2 |
432 433 434 435 436 |
} static int hfsplus_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { |
7ac9fb9c2 hfsplus: add per-... |
437 |
struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
1da177e4c Linux-2.6.12-rc2 |
438 |
struct inode *inode; |
27a4e3884 hfsplus: incorrec... |
439 |
int res = -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
440 |
|
7ac9fb9c2 hfsplus: add per-... |
441 |
mutex_lock(&sbi->vh_mutex); |
f17c89bfc hfsplus: fix erro... |
442 |
inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO); |
1da177e4c Linux-2.6.12-rc2 |
443 |
if (!inode) |
7ac9fb9c2 hfsplus: add per-... |
444 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
445 446 |
res = page_symlink(inode, symname, strlen(symname) + 1); |
f17c89bfc hfsplus: fix erro... |
447 448 |
if (res) goto out_err; |
1da177e4c Linux-2.6.12-rc2 |
449 |
|
1da177e4c Linux-2.6.12-rc2 |
450 |
res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); |
f17c89bfc hfsplus: fix erro... |
451 452 |
if (res) goto out_err; |
1da177e4c Linux-2.6.12-rc2 |
453 |
|
324ef39a8 hfsplus: add supp... |
454 455 456 457 458 459 460 461 |
res = hfsplus_init_inode_security(inode, dir, &dentry->d_name); if (res == -EOPNOTSUPP) res = 0; /* Operation is not supported. */ else if (res) { /* Try to delete anyway without error analysis. */ hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); goto out_err; } |
f17c89bfc hfsplus: fix erro... |
462 463 |
hfsplus_instantiate(dentry, inode, inode->i_ino); mark_inode_dirty(inode); |
7ac9fb9c2 hfsplus: add per-... |
464 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
465 |
|
f17c89bfc hfsplus: fix erro... |
466 |
out_err: |
6d6b77f16 filesystems: add ... |
467 |
clear_nlink(inode); |
f17c89bfc hfsplus: fix erro... |
468 469 |
hfsplus_delete_inode(inode); iput(inode); |
7ac9fb9c2 hfsplus: add per-... |
470 471 |
out: mutex_unlock(&sbi->vh_mutex); |
1da177e4c Linux-2.6.12-rc2 |
472 473 474 475 |
return res; } static int hfsplus_mknod(struct inode *dir, struct dentry *dentry, |
1a67aafb5 switch ->mknod() ... |
476 |
umode_t mode, dev_t rdev) |
1da177e4c Linux-2.6.12-rc2 |
477 |
{ |
7ac9fb9c2 hfsplus: add per-... |
478 |
struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
1da177e4c Linux-2.6.12-rc2 |
479 |
struct inode *inode; |
27a4e3884 hfsplus: incorrec... |
480 |
int res = -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
481 |
|
7ac9fb9c2 hfsplus: add per-... |
482 |
mutex_lock(&sbi->vh_mutex); |
30d3abbec hfsplus: merge mk... |
483 |
inode = hfsplus_new_inode(dir->i_sb, mode); |
1da177e4c Linux-2.6.12-rc2 |
484 |
if (!inode) |
7ac9fb9c2 hfsplus: add per-... |
485 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
486 |
|
90e616905 hfsplus: create c... |
487 488 |
if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) init_special_inode(inode, mode, rdev); |
1da177e4c Linux-2.6.12-rc2 |
489 |
res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); |
324ef39a8 hfsplus: add supp... |
490 491 492 493 494 495 496 497 498 499 |
if (res) goto failed_mknod; res = hfsplus_init_inode_security(inode, dir, &dentry->d_name); if (res == -EOPNOTSUPP) res = 0; /* Operation is not supported. */ else if (res) { /* Try to delete anyway without error analysis. */ hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); goto failed_mknod; |
1da177e4c Linux-2.6.12-rc2 |
500 |
} |
30d3abbec hfsplus: merge mk... |
501 |
|
1da177e4c Linux-2.6.12-rc2 |
502 503 |
hfsplus_instantiate(dentry, inode, inode->i_ino); mark_inode_dirty(inode); |
324ef39a8 hfsplus: add supp... |
504 505 506 507 508 509 |
goto out; failed_mknod: clear_nlink(inode); hfsplus_delete_inode(inode); iput(inode); |
7ac9fb9c2 hfsplus: add per-... |
510 511 512 |
out: mutex_unlock(&sbi->vh_mutex); return res; |
1da177e4c Linux-2.6.12-rc2 |
513 |
} |
4acdaf27e switch ->create()... |
514 |
static int hfsplus_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
ebfc3b49a don't pass nameid... |
515 |
bool excl) |
30d3abbec hfsplus: merge mk... |
516 517 518 |
{ return hfsplus_mknod(dir, dentry, mode, 0); } |
18bb1db3e switch vfs_mkdir(... |
519 |
static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |
30d3abbec hfsplus: merge mk... |
520 521 522 |
{ return hfsplus_mknod(dir, dentry, mode | S_IFDIR, 0); } |
1da177e4c Linux-2.6.12-rc2 |
523 |
static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, |
f03b8ad8d fs: support RENAM... |
524 525 |
struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) |
1da177e4c Linux-2.6.12-rc2 |
526 527 |
{ int res; |
f03b8ad8d fs: support RENAM... |
528 529 |
if (flags & ~RENAME_NOREPLACE) return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
530 |
/* Unlink destination if it already exists */ |
2b0143b5c VFS: normal files... |
531 |
if (d_really_is_positive(new_dentry)) { |
e36cb0b89 VFS: (Scripted) C... |
532 |
if (d_is_dir(new_dentry)) |
40de9a7ce hfsplus: fix rena... |
533 |
res = hfsplus_rmdir(new_dir, new_dentry); |
e3911785b hfsplus: remove u... |
534 |
else |
40de9a7ce hfsplus: fix rena... |
535 |
res = hfsplus_unlink(new_dir, new_dentry); |
1da177e4c Linux-2.6.12-rc2 |
536 537 538 539 540 541 542 543 544 545 546 |
if (res) return res; } res = hfsplus_rename_cat((u32)(unsigned long)old_dentry->d_fsdata, old_dir, &old_dentry->d_name, new_dir, &new_dentry->d_name); if (!res) new_dentry->d_fsdata = old_dentry->d_fsdata; return res; } |
92e1d5be9 [PATCH] mark stru... |
547 |
const struct inode_operations hfsplus_dir_inode_operations = { |
324ef39a8 hfsplus: add supp... |
548 549 550 551 552 553 554 555 556 |
.lookup = hfsplus_lookup, .create = hfsplus_create, .link = hfsplus_link, .unlink = hfsplus_unlink, .mkdir = hfsplus_mkdir, .rmdir = hfsplus_rmdir, .symlink = hfsplus_symlink, .mknod = hfsplus_mknod, .rename = hfsplus_rename, |
324ef39a8 hfsplus: add supp... |
557 |
.listxattr = hfsplus_listxattr, |
b4c1107cc hfsplus: integrat... |
558 559 |
#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL .get_acl = hfsplus_get_posix_acl, |
b0a7ab570 hfsplus: use gene... |
560 |
.set_acl = hfsplus_set_posix_acl, |
b4c1107cc hfsplus: integrat... |
561 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
562 |
}; |
4b6f5d20b [PATCH] Make most... |
563 |
const struct file_operations hfsplus_dir_operations = { |
eb29d66d4 hfsplus: write up... |
564 |
.fsync = hfsplus_file_fsync, |
1da177e4c Linux-2.6.12-rc2 |
565 |
.read = generic_read_dir, |
323ee8fc5 hfsplus: switch t... |
566 |
.iterate_shared = hfsplus_readdir, |
7cc4bcc6f hfsplus: Push dow... |
567 |
.unlocked_ioctl = hfsplus_ioctl, |
1da177e4c Linux-2.6.12-rc2 |
568 569 570 |
.llseek = generic_file_llseek, .release = hfsplus_dir_release, }; |