1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * namei.c |
4 | * |
5 | * PURPOSE |
6 | * Inode name handling routines for the OSTA-UDF(tm) filesystem. |
7 | * |
8 | * COPYRIGHT |
9 | * (C) 1998-2004 Ben Fennema |
10 | * (C) 1999-2000 Stelias Computing Inc |
11 | * |
12 | * HISTORY |
13 | * |
14 | * 12/12/98 blf Created. Split out the lookup code from dir.c |
15 | * 04/19/99 blf link, mknod, symlink support |
16 | */ |
17 | |
18 | #include "udfdecl.h" |
19 | |
20 | #include "udf_i.h" |
21 | #include "udf_sb.h" |
22 | #include <linux/string.h> |
23 | #include <linux/errno.h> |
24 | #include <linux/mm.h> |
25 | #include <linux/slab.h> |
26 | #include <linux/sched.h> |
27 | #include <linux/crc-itu-t.h> |
28 | #include <linux/exportfs.h> |
29 | #include <linux/iversion.h> |
30 | |
31 | static inline int udf_match(int len1, const unsigned char *name1, int len2, |
32 | const unsigned char *name2) |
33 | { |
34 | if (len1 != len2) |
35 | return 0; |
36 | |
37 | return !memcmp(p: name1, q: name2, size: len1); |
38 | } |
39 | |
40 | /** |
41 | * udf_fiiter_find_entry - find entry in given directory. |
42 | * |
43 | * @dir: directory inode to search in |
44 | * @child: qstr of the name |
45 | * @iter: iter to use for searching |
46 | * |
47 | * This function searches in the directory @dir for a file name @child. When |
48 | * found, @iter points to the position in the directory with given entry. |
49 | * |
50 | * Returns 0 on success, < 0 on error (including -ENOENT). |
51 | */ |
52 | static int udf_fiiter_find_entry(struct inode *dir, const struct qstr *child, |
53 | struct udf_fileident_iter *iter) |
54 | { |
55 | int flen; |
56 | unsigned char *fname = NULL; |
57 | struct super_block *sb = dir->i_sb; |
58 | int isdotdot = child->len == 2 && |
59 | child->name[0] == '.' && child->name[1] == '.'; |
60 | int ret; |
61 | |
62 | fname = kmalloc(UDF_NAME_LEN, GFP_KERNEL); |
63 | if (!fname) |
64 | return -ENOMEM; |
65 | |
66 | for (ret = udf_fiiter_init(iter, dir, pos: 0); |
67 | !ret && iter->pos < dir->i_size; |
68 | ret = udf_fiiter_advance(iter)) { |
69 | if (iter->fi.fileCharacteristics & FID_FILE_CHAR_DELETED) { |
70 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE)) |
71 | continue; |
72 | } |
73 | |
74 | if (iter->fi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) { |
75 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE)) |
76 | continue; |
77 | } |
78 | |
79 | if ((iter->fi.fileCharacteristics & FID_FILE_CHAR_PARENT) && |
80 | isdotdot) |
81 | goto out_ok; |
82 | |
83 | if (!iter->fi.lengthFileIdent) |
84 | continue; |
85 | |
86 | flen = udf_get_filename(sb, iter->name, |
87 | iter->fi.lengthFileIdent, fname, UDF_NAME_LEN); |
88 | if (flen < 0) { |
89 | ret = flen; |
90 | goto out_err; |
91 | } |
92 | |
93 | if (udf_match(len1: flen, name1: fname, len2: child->len, name2: child->name)) |
94 | goto out_ok; |
95 | } |
96 | if (!ret) |
97 | ret = -ENOENT; |
98 | |
99 | out_err: |
100 | udf_fiiter_release(iter); |
101 | out_ok: |
102 | kfree(objp: fname); |
103 | |
104 | return ret; |
105 | } |
106 | |
107 | static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, |
108 | unsigned int flags) |
109 | { |
110 | struct inode *inode = NULL; |
111 | struct udf_fileident_iter iter; |
112 | int err; |
113 | |
114 | if (dentry->d_name.len > UDF_NAME_LEN) |
115 | return ERR_PTR(error: -ENAMETOOLONG); |
116 | |
117 | err = udf_fiiter_find_entry(dir, child: &dentry->d_name, iter: &iter); |
118 | if (err < 0 && err != -ENOENT) |
119 | return ERR_PTR(error: err); |
120 | |
121 | if (err == 0) { |
122 | struct kernel_lb_addr loc; |
123 | |
124 | loc = lelb_to_cpu(in: iter.fi.icb.extLocation); |
125 | udf_fiiter_release(iter: &iter); |
126 | |
127 | inode = udf_iget(sb: dir->i_sb, ino: &loc); |
128 | } |
129 | |
130 | return d_splice_alias(inode, dentry); |
131 | } |
132 | |
133 | static int udf_expand_dir_adinicb(struct inode *inode, udf_pblk_t *block) |
134 | { |
135 | udf_pblk_t newblock; |
136 | struct buffer_head *dbh = NULL; |
137 | struct kernel_lb_addr eloc; |
138 | struct extent_position epos; |
139 | uint8_t alloctype; |
140 | struct udf_inode_info *iinfo = UDF_I(inode); |
141 | struct udf_fileident_iter iter; |
142 | uint8_t *impuse; |
143 | int ret; |
144 | |
145 | if (UDF_QUERY_FLAG(sb: inode->i_sb, UDF_FLAG_USE_SHORT_AD)) |
146 | alloctype = ICBTAG_FLAG_AD_SHORT; |
147 | else |
148 | alloctype = ICBTAG_FLAG_AD_LONG; |
149 | |
150 | if (!inode->i_size) { |
151 | iinfo->i_alloc_type = alloctype; |
152 | mark_inode_dirty(inode); |
153 | return 0; |
154 | } |
155 | |
156 | /* alloc block, and copy data to it */ |
157 | *block = udf_new_block(sb: inode->i_sb, inode, |
158 | partition: iinfo->i_location.partitionReferenceNum, |
159 | goal: iinfo->i_location.logicalBlockNum, err: &ret); |
160 | if (!(*block)) |
161 | return ret; |
162 | newblock = udf_get_pblock(inode->i_sb, *block, |
163 | iinfo->i_location.partitionReferenceNum, |
164 | 0); |
165 | if (newblock == 0xffffffff) |
166 | return -EFSCORRUPTED; |
167 | dbh = sb_getblk(sb: inode->i_sb, block: newblock); |
168 | if (!dbh) |
169 | return -ENOMEM; |
170 | lock_buffer(bh: dbh); |
171 | memcpy(dbh->b_data, iinfo->i_data, inode->i_size); |
172 | memset(dbh->b_data + inode->i_size, 0, |
173 | inode->i_sb->s_blocksize - inode->i_size); |
174 | set_buffer_uptodate(dbh); |
175 | unlock_buffer(bh: dbh); |
176 | |
177 | /* Drop inline data, add block instead */ |
178 | iinfo->i_alloc_type = alloctype; |
179 | memset(iinfo->i_data + iinfo->i_lenEAttr, 0, iinfo->i_lenAlloc); |
180 | iinfo->i_lenAlloc = 0; |
181 | eloc.logicalBlockNum = *block; |
182 | eloc.partitionReferenceNum = |
183 | iinfo->i_location.partitionReferenceNum; |
184 | iinfo->i_lenExtents = inode->i_size; |
185 | epos.bh = NULL; |
186 | epos.block = iinfo->i_location; |
187 | epos.offset = udf_file_entry_alloc_offset(inode); |
188 | ret = udf_add_aext(inode, &epos, &eloc, inode->i_size, 0); |
189 | brelse(bh: epos.bh); |
190 | if (ret < 0) { |
191 | brelse(bh: dbh); |
192 | udf_free_blocks(inode->i_sb, inode, &eloc, 0, 1); |
193 | return ret; |
194 | } |
195 | mark_inode_dirty(inode); |
196 | |
197 | /* Now fixup tags in moved directory entries */ |
198 | for (ret = udf_fiiter_init(iter: &iter, dir: inode, pos: 0); |
199 | !ret && iter.pos < inode->i_size; |
200 | ret = udf_fiiter_advance(iter: &iter)) { |
201 | iter.fi.descTag.tagLocation = cpu_to_le32(*block); |
202 | if (iter.fi.lengthOfImpUse != cpu_to_le16(0)) |
203 | impuse = dbh->b_data + iter.pos + |
204 | sizeof(struct fileIdentDesc); |
205 | else |
206 | impuse = NULL; |
207 | udf_fiiter_write_fi(iter: &iter, impuse); |
208 | } |
209 | brelse(bh: dbh); |
210 | /* |
211 | * We don't expect the iteration to fail as the directory has been |
212 | * already verified to be correct |
213 | */ |
214 | WARN_ON_ONCE(ret); |
215 | udf_fiiter_release(iter: &iter); |
216 | |
217 | return 0; |
218 | } |
219 | |
220 | static int udf_fiiter_add_entry(struct inode *dir, struct dentry *dentry, |
221 | struct udf_fileident_iter *iter) |
222 | { |
223 | struct udf_inode_info *dinfo = UDF_I(inode: dir); |
224 | int nfidlen, namelen = 0; |
225 | int ret; |
226 | int off, blksize = 1 << dir->i_blkbits; |
227 | udf_pblk_t block; |
228 | char name[UDF_NAME_LEN_CS0]; |
229 | |
230 | if (dentry) { |
231 | namelen = udf_put_filename(dir->i_sb, dentry->d_name.name, |
232 | dentry->d_name.len, |
233 | name, UDF_NAME_LEN_CS0); |
234 | if (!namelen) |
235 | return -ENAMETOOLONG; |
236 | } |
237 | nfidlen = ALIGN(sizeof(struct fileIdentDesc) + namelen, UDF_NAME_PAD); |
238 | |
239 | for (ret = udf_fiiter_init(iter, dir, pos: 0); |
240 | !ret && iter->pos < dir->i_size; |
241 | ret = udf_fiiter_advance(iter)) { |
242 | if (iter->fi.fileCharacteristics & FID_FILE_CHAR_DELETED) { |
243 | if (udf_dir_entry_len(cfi: &iter->fi) == nfidlen) { |
244 | iter->fi.descTag.tagSerialNum = cpu_to_le16(1); |
245 | iter->fi.fileVersionNum = cpu_to_le16(1); |
246 | iter->fi.fileCharacteristics = 0; |
247 | iter->fi.lengthFileIdent = namelen; |
248 | iter->fi.lengthOfImpUse = cpu_to_le16(0); |
249 | memcpy(iter->namebuf, name, namelen); |
250 | iter->name = iter->namebuf; |
251 | return 0; |
252 | } |
253 | } |
254 | } |
255 | if (ret) { |
256 | udf_fiiter_release(iter); |
257 | return ret; |
258 | } |
259 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB && |
260 | blksize - udf_ext0_offset(inode: dir) - iter->pos < nfidlen) { |
261 | udf_fiiter_release(iter); |
262 | ret = udf_expand_dir_adinicb(inode: dir, block: &block); |
263 | if (ret) |
264 | return ret; |
265 | ret = udf_fiiter_init(iter, dir, pos: dir->i_size); |
266 | if (ret < 0) |
267 | return ret; |
268 | } |
269 | |
270 | /* Get blocknumber to use for entry tag */ |
271 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { |
272 | block = dinfo->i_location.logicalBlockNum; |
273 | } else { |
274 | block = iter->eloc.logicalBlockNum + |
275 | ((iter->elen - 1) >> dir->i_blkbits); |
276 | } |
277 | off = iter->pos & (blksize - 1); |
278 | if (!off) |
279 | off = blksize; |
280 | /* Entry fits into current block? */ |
281 | if (blksize - udf_ext0_offset(inode: dir) - off >= nfidlen) |
282 | goto store_fi; |
283 | |
284 | ret = udf_fiiter_append_blk(iter); |
285 | if (ret) { |
286 | udf_fiiter_release(iter); |
287 | return ret; |
288 | } |
289 | |
290 | /* Entry will be completely in the new block? Update tag location... */ |
291 | if (!(iter->pos & (blksize - 1))) |
292 | block = iter->eloc.logicalBlockNum + |
293 | ((iter->elen - 1) >> dir->i_blkbits); |
294 | store_fi: |
295 | memset(&iter->fi, 0, sizeof(struct fileIdentDesc)); |
296 | if (UDF_SB(sb: dir->i_sb)->s_udfrev >= 0x0200) |
297 | udf_new_tag((char *)(&iter->fi), TAG_IDENT_FID, 3, 1, block, |
298 | sizeof(struct tag)); |
299 | else |
300 | udf_new_tag((char *)(&iter->fi), TAG_IDENT_FID, 2, 1, block, |
301 | sizeof(struct tag)); |
302 | iter->fi.fileVersionNum = cpu_to_le16(1); |
303 | iter->fi.lengthFileIdent = namelen; |
304 | iter->fi.lengthOfImpUse = cpu_to_le16(0); |
305 | memcpy(iter->namebuf, name, namelen); |
306 | iter->name = iter->namebuf; |
307 | |
308 | dir->i_size += nfidlen; |
309 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { |
310 | dinfo->i_lenAlloc += nfidlen; |
311 | } else { |
312 | /* Truncate last extent to proper size */ |
313 | udf_fiiter_update_elen(iter, new_elen: iter->elen - |
314 | (dinfo->i_lenExtents - dir->i_size)); |
315 | } |
316 | mark_inode_dirty(inode: dir); |
317 | |
318 | return 0; |
319 | } |
320 | |
321 | static void udf_fiiter_delete_entry(struct udf_fileident_iter *iter) |
322 | { |
323 | iter->fi.fileCharacteristics |= FID_FILE_CHAR_DELETED; |
324 | |
325 | if (UDF_QUERY_FLAG(sb: iter->dir->i_sb, UDF_FLAG_STRICT)) |
326 | memset(&iter->fi.icb, 0x00, sizeof(struct long_ad)); |
327 | |
328 | udf_fiiter_write_fi(iter, NULL); |
329 | } |
330 | |
331 | static void udf_add_fid_counter(struct super_block *sb, bool dir, int val) |
332 | { |
333 | struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb); |
334 | |
335 | if (!lvidiu) |
336 | return; |
337 | mutex_lock(&UDF_SB(sb)->s_alloc_mutex); |
338 | if (dir) |
339 | le32_add_cpu(var: &lvidiu->numDirs, val); |
340 | else |
341 | le32_add_cpu(var: &lvidiu->numFiles, val); |
342 | udf_updated_lvid(sb); |
343 | mutex_unlock(lock: &UDF_SB(sb)->s_alloc_mutex); |
344 | } |
345 | |
346 | static int udf_add_nondir(struct dentry *dentry, struct inode *inode) |
347 | { |
348 | struct udf_inode_info *iinfo = UDF_I(inode); |
349 | struct inode *dir = d_inode(dentry: dentry->d_parent); |
350 | struct udf_fileident_iter iter; |
351 | int err; |
352 | |
353 | err = udf_fiiter_add_entry(dir, dentry, iter: &iter); |
354 | if (err) { |
355 | inode_dec_link_count(inode); |
356 | discard_new_inode(inode); |
357 | return err; |
358 | } |
359 | iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); |
360 | iter.fi.icb.extLocation = cpu_to_lelb(in: iinfo->i_location); |
361 | *(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse = |
362 | cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL); |
363 | udf_fiiter_write_fi(iter: &iter, NULL); |
364 | inode_set_mtime_to_ts(inode: dir, ts: inode_set_ctime_current(inode: dir)); |
365 | mark_inode_dirty(inode: dir); |
366 | udf_fiiter_release(iter: &iter); |
367 | udf_add_fid_counter(sb: dir->i_sb, dir: false, val: 1); |
368 | d_instantiate_new(dentry, inode); |
369 | |
370 | return 0; |
371 | } |
372 | |
373 | static int udf_create(struct mnt_idmap *idmap, struct inode *dir, |
374 | struct dentry *dentry, umode_t mode, bool excl) |
375 | { |
376 | struct inode *inode = udf_new_inode(dir, mode); |
377 | |
378 | if (IS_ERR(ptr: inode)) |
379 | return PTR_ERR(ptr: inode); |
380 | |
381 | inode->i_data.a_ops = &udf_aops; |
382 | inode->i_op = &udf_file_inode_operations; |
383 | inode->i_fop = &udf_file_operations; |
384 | mark_inode_dirty(inode); |
385 | |
386 | return udf_add_nondir(dentry, inode); |
387 | } |
388 | |
389 | static int udf_tmpfile(struct mnt_idmap *idmap, struct inode *dir, |
390 | struct file *file, umode_t mode) |
391 | { |
392 | struct inode *inode = udf_new_inode(dir, mode); |
393 | |
394 | if (IS_ERR(ptr: inode)) |
395 | return PTR_ERR(ptr: inode); |
396 | |
397 | inode->i_data.a_ops = &udf_aops; |
398 | inode->i_op = &udf_file_inode_operations; |
399 | inode->i_fop = &udf_file_operations; |
400 | mark_inode_dirty(inode); |
401 | d_tmpfile(file, inode); |
402 | unlock_new_inode(inode); |
403 | return finish_open_simple(file, error: 0); |
404 | } |
405 | |
406 | static int udf_mknod(struct mnt_idmap *idmap, struct inode *dir, |
407 | struct dentry *dentry, umode_t mode, dev_t rdev) |
408 | { |
409 | struct inode *inode; |
410 | |
411 | if (!old_valid_dev(dev: rdev)) |
412 | return -EINVAL; |
413 | |
414 | inode = udf_new_inode(dir, mode); |
415 | if (IS_ERR(ptr: inode)) |
416 | return PTR_ERR(ptr: inode); |
417 | |
418 | init_special_inode(inode, mode, rdev); |
419 | return udf_add_nondir(dentry, inode); |
420 | } |
421 | |
422 | static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir, |
423 | struct dentry *dentry, umode_t mode) |
424 | { |
425 | struct inode *inode; |
426 | struct udf_fileident_iter iter; |
427 | int err; |
428 | struct udf_inode_info *dinfo = UDF_I(inode: dir); |
429 | struct udf_inode_info *iinfo; |
430 | |
431 | inode = udf_new_inode(dir, S_IFDIR | mode); |
432 | if (IS_ERR(ptr: inode)) |
433 | return PTR_ERR(ptr: inode); |
434 | |
435 | iinfo = UDF_I(inode); |
436 | inode->i_op = &udf_dir_inode_operations; |
437 | inode->i_fop = &udf_dir_operations; |
438 | err = udf_fiiter_add_entry(dir: inode, NULL, iter: &iter); |
439 | if (err) { |
440 | clear_nlink(inode); |
441 | discard_new_inode(inode); |
442 | return err; |
443 | } |
444 | set_nlink(inode, nlink: 2); |
445 | iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); |
446 | iter.fi.icb.extLocation = cpu_to_lelb(in: dinfo->i_location); |
447 | *(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse = |
448 | cpu_to_le32(dinfo->i_unique & 0x00000000FFFFFFFFUL); |
449 | iter.fi.fileCharacteristics = |
450 | FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT; |
451 | udf_fiiter_write_fi(iter: &iter, NULL); |
452 | udf_fiiter_release(iter: &iter); |
453 | mark_inode_dirty(inode); |
454 | |
455 | err = udf_fiiter_add_entry(dir, dentry, iter: &iter); |
456 | if (err) { |
457 | clear_nlink(inode); |
458 | discard_new_inode(inode); |
459 | return err; |
460 | } |
461 | iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); |
462 | iter.fi.icb.extLocation = cpu_to_lelb(in: iinfo->i_location); |
463 | *(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse = |
464 | cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL); |
465 | iter.fi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY; |
466 | udf_fiiter_write_fi(iter: &iter, NULL); |
467 | udf_fiiter_release(iter: &iter); |
468 | udf_add_fid_counter(sb: dir->i_sb, dir: true, val: 1); |
469 | inc_nlink(inode: dir); |
470 | inode_set_mtime_to_ts(inode: dir, ts: inode_set_ctime_current(inode: dir)); |
471 | mark_inode_dirty(inode: dir); |
472 | d_instantiate_new(dentry, inode); |
473 | |
474 | return 0; |
475 | } |
476 | |
477 | static int empty_dir(struct inode *dir) |
478 | { |
479 | struct udf_fileident_iter iter; |
480 | int ret; |
481 | |
482 | for (ret = udf_fiiter_init(iter: &iter, dir, pos: 0); |
483 | !ret && iter.pos < dir->i_size; |
484 | ret = udf_fiiter_advance(iter: &iter)) { |
485 | if (iter.fi.lengthFileIdent && |
486 | !(iter.fi.fileCharacteristics & FID_FILE_CHAR_DELETED)) { |
487 | udf_fiiter_release(iter: &iter); |
488 | return 0; |
489 | } |
490 | } |
491 | udf_fiiter_release(iter: &iter); |
492 | |
493 | return 1; |
494 | } |
495 | |
496 | static int udf_rmdir(struct inode *dir, struct dentry *dentry) |
497 | { |
498 | int ret; |
499 | struct inode *inode = d_inode(dentry); |
500 | struct udf_fileident_iter iter; |
501 | struct kernel_lb_addr tloc; |
502 | |
503 | ret = udf_fiiter_find_entry(dir, child: &dentry->d_name, iter: &iter); |
504 | if (ret) |
505 | goto out; |
506 | |
507 | ret = -EFSCORRUPTED; |
508 | tloc = lelb_to_cpu(in: iter.fi.icb.extLocation); |
509 | if (udf_get_lb_pblock(sb: dir->i_sb, loc: &tloc, offset: 0) != inode->i_ino) |
510 | goto end_rmdir; |
511 | ret = -ENOTEMPTY; |
512 | if (!empty_dir(dir: inode)) |
513 | goto end_rmdir; |
514 | udf_fiiter_delete_entry(iter: &iter); |
515 | if (inode->i_nlink != 2) |
516 | udf_warn(inode->i_sb, "empty directory has nlink != 2 (%u)\n" , |
517 | inode->i_nlink); |
518 | clear_nlink(inode); |
519 | inode->i_size = 0; |
520 | inode_dec_link_count(inode: dir); |
521 | udf_add_fid_counter(sb: dir->i_sb, dir: true, val: -1); |
522 | inode_set_mtime_to_ts(inode: dir, |
523 | ts: inode_set_ctime_to_ts(inode: dir, ts: inode_set_ctime_current(inode))); |
524 | mark_inode_dirty(inode: dir); |
525 | ret = 0; |
526 | end_rmdir: |
527 | udf_fiiter_release(iter: &iter); |
528 | out: |
529 | return ret; |
530 | } |
531 | |
532 | static int udf_unlink(struct inode *dir, struct dentry *dentry) |
533 | { |
534 | int ret; |
535 | struct inode *inode = d_inode(dentry); |
536 | struct udf_fileident_iter iter; |
537 | struct kernel_lb_addr tloc; |
538 | |
539 | ret = udf_fiiter_find_entry(dir, child: &dentry->d_name, iter: &iter); |
540 | if (ret) |
541 | goto out; |
542 | |
543 | ret = -EFSCORRUPTED; |
544 | tloc = lelb_to_cpu(in: iter.fi.icb.extLocation); |
545 | if (udf_get_lb_pblock(sb: dir->i_sb, loc: &tloc, offset: 0) != inode->i_ino) |
546 | goto end_unlink; |
547 | |
548 | if (!inode->i_nlink) { |
549 | udf_debug("Deleting nonexistent file (%lu), %u\n" , |
550 | inode->i_ino, inode->i_nlink); |
551 | set_nlink(inode, nlink: 1); |
552 | } |
553 | udf_fiiter_delete_entry(iter: &iter); |
554 | inode_set_mtime_to_ts(inode: dir, ts: inode_set_ctime_current(inode: dir)); |
555 | mark_inode_dirty(inode: dir); |
556 | inode_dec_link_count(inode); |
557 | udf_add_fid_counter(sb: dir->i_sb, dir: false, val: -1); |
558 | inode_set_ctime_to_ts(inode, ts: inode_get_ctime(inode: dir)); |
559 | ret = 0; |
560 | end_unlink: |
561 | udf_fiiter_release(iter: &iter); |
562 | out: |
563 | return ret; |
564 | } |
565 | |
566 | static int udf_symlink(struct mnt_idmap *idmap, struct inode *dir, |
567 | struct dentry *dentry, const char *symname) |
568 | { |
569 | struct inode *inode; |
570 | struct pathComponent *pc; |
571 | const char *compstart; |
572 | struct extent_position epos = {}; |
573 | int eoffset, elen = 0; |
574 | uint8_t *ea; |
575 | int err; |
576 | udf_pblk_t block; |
577 | unsigned char *name = NULL; |
578 | int namelen; |
579 | struct udf_inode_info *iinfo; |
580 | struct super_block *sb = dir->i_sb; |
581 | |
582 | name = kmalloc(UDF_NAME_LEN_CS0, GFP_KERNEL); |
583 | if (!name) { |
584 | err = -ENOMEM; |
585 | goto out; |
586 | } |
587 | |
588 | inode = udf_new_inode(dir, S_IFLNK | 0777); |
589 | if (IS_ERR(ptr: inode)) { |
590 | err = PTR_ERR(ptr: inode); |
591 | goto out; |
592 | } |
593 | |
594 | iinfo = UDF_I(inode); |
595 | down_write(sem: &iinfo->i_data_sem); |
596 | inode->i_data.a_ops = &udf_symlink_aops; |
597 | inode->i_op = &udf_symlink_inode_operations; |
598 | inode_nohighmem(inode); |
599 | |
600 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { |
601 | struct kernel_lb_addr eloc; |
602 | uint32_t bsize; |
603 | |
604 | block = udf_new_block(sb, inode, |
605 | partition: iinfo->i_location.partitionReferenceNum, |
606 | goal: iinfo->i_location.logicalBlockNum, err: &err); |
607 | if (!block) |
608 | goto out_no_entry; |
609 | epos.block = iinfo->i_location; |
610 | epos.offset = udf_file_entry_alloc_offset(inode); |
611 | epos.bh = NULL; |
612 | eloc.logicalBlockNum = block; |
613 | eloc.partitionReferenceNum = |
614 | iinfo->i_location.partitionReferenceNum; |
615 | bsize = sb->s_blocksize; |
616 | iinfo->i_lenExtents = bsize; |
617 | err = udf_add_aext(inode, &epos, &eloc, bsize, 0); |
618 | brelse(bh: epos.bh); |
619 | if (err < 0) { |
620 | udf_free_blocks(sb, inode, &eloc, 0, 1); |
621 | goto out_no_entry; |
622 | } |
623 | |
624 | block = udf_get_pblock(sb, block, |
625 | iinfo->i_location.partitionReferenceNum, |
626 | 0); |
627 | epos.bh = sb_getblk(sb, block); |
628 | if (unlikely(!epos.bh)) { |
629 | err = -ENOMEM; |
630 | udf_free_blocks(sb, inode, &eloc, 0, 1); |
631 | goto out_no_entry; |
632 | } |
633 | lock_buffer(bh: epos.bh); |
634 | memset(epos.bh->b_data, 0x00, bsize); |
635 | set_buffer_uptodate(epos.bh); |
636 | unlock_buffer(bh: epos.bh); |
637 | mark_buffer_dirty_inode(bh: epos.bh, inode); |
638 | ea = epos.bh->b_data + udf_ext0_offset(inode); |
639 | } else |
640 | ea = iinfo->i_data + iinfo->i_lenEAttr; |
641 | |
642 | eoffset = sb->s_blocksize - udf_ext0_offset(inode); |
643 | pc = (struct pathComponent *)ea; |
644 | |
645 | if (*symname == '/') { |
646 | do { |
647 | symname++; |
648 | } while (*symname == '/'); |
649 | |
650 | pc->componentType = 1; |
651 | pc->lengthComponentIdent = 0; |
652 | pc->componentFileVersionNum = 0; |
653 | elen += sizeof(struct pathComponent); |
654 | } |
655 | |
656 | err = -ENAMETOOLONG; |
657 | |
658 | while (*symname) { |
659 | if (elen + sizeof(struct pathComponent) > eoffset) |
660 | goto out_no_entry; |
661 | |
662 | pc = (struct pathComponent *)(ea + elen); |
663 | |
664 | compstart = symname; |
665 | |
666 | do { |
667 | symname++; |
668 | } while (*symname && *symname != '/'); |
669 | |
670 | pc->componentType = 5; |
671 | pc->lengthComponentIdent = 0; |
672 | pc->componentFileVersionNum = 0; |
673 | if (compstart[0] == '.') { |
674 | if ((symname - compstart) == 1) |
675 | pc->componentType = 4; |
676 | else if ((symname - compstart) == 2 && |
677 | compstart[1] == '.') |
678 | pc->componentType = 3; |
679 | } |
680 | |
681 | if (pc->componentType == 5) { |
682 | namelen = udf_put_filename(sb, compstart, |
683 | symname - compstart, |
684 | name, UDF_NAME_LEN_CS0); |
685 | if (!namelen) |
686 | goto out_no_entry; |
687 | |
688 | if (elen + sizeof(struct pathComponent) + namelen > |
689 | eoffset) |
690 | goto out_no_entry; |
691 | else |
692 | pc->lengthComponentIdent = namelen; |
693 | |
694 | memcpy(pc->componentIdent, name, namelen); |
695 | } |
696 | |
697 | elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; |
698 | |
699 | if (*symname) { |
700 | do { |
701 | symname++; |
702 | } while (*symname == '/'); |
703 | } |
704 | } |
705 | |
706 | brelse(bh: epos.bh); |
707 | inode->i_size = elen; |
708 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) |
709 | iinfo->i_lenAlloc = inode->i_size; |
710 | else |
711 | udf_truncate_tail_extent(inode); |
712 | mark_inode_dirty(inode); |
713 | up_write(sem: &iinfo->i_data_sem); |
714 | |
715 | err = udf_add_nondir(dentry, inode); |
716 | out: |
717 | kfree(objp: name); |
718 | return err; |
719 | |
720 | out_no_entry: |
721 | up_write(sem: &iinfo->i_data_sem); |
722 | inode_dec_link_count(inode); |
723 | discard_new_inode(inode); |
724 | goto out; |
725 | } |
726 | |
727 | static int udf_link(struct dentry *old_dentry, struct inode *dir, |
728 | struct dentry *dentry) |
729 | { |
730 | struct inode *inode = d_inode(dentry: old_dentry); |
731 | struct udf_fileident_iter iter; |
732 | int err; |
733 | |
734 | err = udf_fiiter_add_entry(dir, dentry, iter: &iter); |
735 | if (err) |
736 | return err; |
737 | iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); |
738 | iter.fi.icb.extLocation = cpu_to_lelb(in: UDF_I(inode)->i_location); |
739 | if (UDF_SB(sb: inode->i_sb)->s_lvid_bh) { |
740 | *(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse = |
741 | cpu_to_le32(lvid_get_unique_id(inode->i_sb)); |
742 | } |
743 | udf_fiiter_write_fi(iter: &iter, NULL); |
744 | udf_fiiter_release(iter: &iter); |
745 | |
746 | inc_nlink(inode); |
747 | udf_add_fid_counter(sb: dir->i_sb, dir: false, val: 1); |
748 | inode_set_ctime_current(inode); |
749 | mark_inode_dirty(inode); |
750 | inode_set_mtime_to_ts(inode: dir, ts: inode_set_ctime_current(inode: dir)); |
751 | mark_inode_dirty(inode: dir); |
752 | ihold(inode); |
753 | d_instantiate(dentry, inode); |
754 | |
755 | return 0; |
756 | } |
757 | |
758 | /* Anybody can rename anything with this: the permission checks are left to the |
759 | * higher-level routines. |
760 | */ |
761 | static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir, |
762 | struct dentry *old_dentry, struct inode *new_dir, |
763 | struct dentry *new_dentry, unsigned int flags) |
764 | { |
765 | struct inode *old_inode = d_inode(dentry: old_dentry); |
766 | struct inode *new_inode = d_inode(dentry: new_dentry); |
767 | struct udf_fileident_iter oiter, niter, diriter; |
768 | bool has_diriter = false, is_dir = false; |
769 | int retval; |
770 | struct kernel_lb_addr tloc; |
771 | |
772 | if (flags & ~RENAME_NOREPLACE) |
773 | return -EINVAL; |
774 | |
775 | retval = udf_fiiter_find_entry(dir: old_dir, child: &old_dentry->d_name, iter: &oiter); |
776 | if (retval) |
777 | return retval; |
778 | |
779 | tloc = lelb_to_cpu(in: oiter.fi.icb.extLocation); |
780 | if (udf_get_lb_pblock(sb: old_dir->i_sb, loc: &tloc, offset: 0) != old_inode->i_ino) { |
781 | retval = -ENOENT; |
782 | goto out_oiter; |
783 | } |
784 | |
785 | if (S_ISDIR(old_inode->i_mode)) { |
786 | if (new_inode) { |
787 | retval = -ENOTEMPTY; |
788 | if (!empty_dir(dir: new_inode)) |
789 | goto out_oiter; |
790 | } |
791 | is_dir = true; |
792 | } |
793 | if (is_dir && old_dir != new_dir) { |
794 | retval = udf_fiiter_find_entry(dir: old_inode, child: &dotdot_name, |
795 | iter: &diriter); |
796 | if (retval == -ENOENT) { |
797 | udf_err(old_inode->i_sb, |
798 | "directory (ino %lu) has no '..' entry\n" , |
799 | old_inode->i_ino); |
800 | retval = -EFSCORRUPTED; |
801 | } |
802 | if (retval) |
803 | goto out_oiter; |
804 | has_diriter = true; |
805 | tloc = lelb_to_cpu(in: diriter.fi.icb.extLocation); |
806 | if (udf_get_lb_pblock(sb: old_inode->i_sb, loc: &tloc, offset: 0) != |
807 | old_dir->i_ino) { |
808 | retval = -EFSCORRUPTED; |
809 | udf_err(old_inode->i_sb, |
810 | "directory (ino %lu) has parent entry pointing to another inode (%lu != %u)\n" , |
811 | old_inode->i_ino, old_dir->i_ino, |
812 | udf_get_lb_pblock(old_inode->i_sb, &tloc, 0)); |
813 | goto out_oiter; |
814 | } |
815 | } |
816 | |
817 | retval = udf_fiiter_find_entry(dir: new_dir, child: &new_dentry->d_name, iter: &niter); |
818 | if (retval && retval != -ENOENT) |
819 | goto out_oiter; |
820 | /* Entry found but not passed by VFS? */ |
821 | if (!retval && !new_inode) { |
822 | retval = -EFSCORRUPTED; |
823 | udf_fiiter_release(iter: &niter); |
824 | goto out_oiter; |
825 | } |
826 | /* Entry not found? Need to add one... */ |
827 | if (retval) { |
828 | udf_fiiter_release(iter: &niter); |
829 | retval = udf_fiiter_add_entry(dir: new_dir, dentry: new_dentry, iter: &niter); |
830 | if (retval) |
831 | goto out_oiter; |
832 | } |
833 | |
834 | /* |
835 | * Like most other Unix systems, set the ctime for inodes on a |
836 | * rename. |
837 | */ |
838 | inode_set_ctime_current(inode: old_inode); |
839 | mark_inode_dirty(inode: old_inode); |
840 | |
841 | /* |
842 | * ok, that's it |
843 | */ |
844 | niter.fi.fileVersionNum = oiter.fi.fileVersionNum; |
845 | niter.fi.fileCharacteristics = oiter.fi.fileCharacteristics; |
846 | memcpy(&(niter.fi.icb), &(oiter.fi.icb), sizeof(oiter.fi.icb)); |
847 | udf_fiiter_write_fi(iter: &niter, NULL); |
848 | udf_fiiter_release(iter: &niter); |
849 | |
850 | /* |
851 | * The old entry may have moved due to new entry allocation. Find it |
852 | * again. |
853 | */ |
854 | udf_fiiter_release(iter: &oiter); |
855 | retval = udf_fiiter_find_entry(dir: old_dir, child: &old_dentry->d_name, iter: &oiter); |
856 | if (retval) { |
857 | udf_err(old_dir->i_sb, |
858 | "failed to find renamed entry again in directory (ino %lu)\n" , |
859 | old_dir->i_ino); |
860 | } else { |
861 | udf_fiiter_delete_entry(iter: &oiter); |
862 | udf_fiiter_release(iter: &oiter); |
863 | } |
864 | |
865 | if (new_inode) { |
866 | inode_set_ctime_current(inode: new_inode); |
867 | inode_dec_link_count(inode: new_inode); |
868 | udf_add_fid_counter(sb: old_dir->i_sb, S_ISDIR(new_inode->i_mode), |
869 | val: -1); |
870 | } |
871 | inode_set_mtime_to_ts(inode: old_dir, ts: inode_set_ctime_current(inode: old_dir)); |
872 | inode_set_mtime_to_ts(inode: new_dir, ts: inode_set_ctime_current(inode: new_dir)); |
873 | mark_inode_dirty(inode: old_dir); |
874 | mark_inode_dirty(inode: new_dir); |
875 | |
876 | if (has_diriter) { |
877 | diriter.fi.icb.extLocation = |
878 | cpu_to_lelb(in: UDF_I(inode: new_dir)->i_location); |
879 | udf_update_tag((char *)&diriter.fi, |
880 | udf_dir_entry_len(cfi: &diriter.fi)); |
881 | udf_fiiter_write_fi(iter: &diriter, NULL); |
882 | udf_fiiter_release(iter: &diriter); |
883 | } |
884 | |
885 | if (is_dir) { |
886 | inode_dec_link_count(inode: old_dir); |
887 | if (new_inode) |
888 | inode_dec_link_count(inode: new_inode); |
889 | else { |
890 | inc_nlink(inode: new_dir); |
891 | mark_inode_dirty(inode: new_dir); |
892 | } |
893 | } |
894 | return 0; |
895 | out_oiter: |
896 | if (has_diriter) |
897 | udf_fiiter_release(iter: &diriter); |
898 | udf_fiiter_release(iter: &oiter); |
899 | |
900 | return retval; |
901 | } |
902 | |
903 | static struct dentry *udf_get_parent(struct dentry *child) |
904 | { |
905 | struct kernel_lb_addr tloc; |
906 | struct udf_fileident_iter iter; |
907 | int err; |
908 | |
909 | err = udf_fiiter_find_entry(dir: d_inode(dentry: child), child: &dotdot_name, iter: &iter); |
910 | if (err) |
911 | return ERR_PTR(error: err); |
912 | |
913 | tloc = lelb_to_cpu(in: iter.fi.icb.extLocation); |
914 | udf_fiiter_release(iter: &iter); |
915 | return d_obtain_alias(udf_iget(sb: child->d_sb, ino: &tloc)); |
916 | } |
917 | |
918 | |
919 | static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block, |
920 | u16 partref, __u32 generation) |
921 | { |
922 | struct inode *inode; |
923 | struct kernel_lb_addr loc; |
924 | |
925 | if (block == 0) |
926 | return ERR_PTR(error: -ESTALE); |
927 | |
928 | loc.logicalBlockNum = block; |
929 | loc.partitionReferenceNum = partref; |
930 | inode = udf_iget(sb, ino: &loc); |
931 | |
932 | if (IS_ERR(ptr: inode)) |
933 | return ERR_CAST(ptr: inode); |
934 | |
935 | if (generation && inode->i_generation != generation) { |
936 | iput(inode); |
937 | return ERR_PTR(error: -ESTALE); |
938 | } |
939 | return d_obtain_alias(inode); |
940 | } |
941 | |
942 | static struct dentry *udf_fh_to_dentry(struct super_block *sb, |
943 | struct fid *fid, int fh_len, int fh_type) |
944 | { |
945 | if (fh_len < 3 || |
946 | (fh_type != FILEID_UDF_WITH_PARENT && |
947 | fh_type != FILEID_UDF_WITHOUT_PARENT)) |
948 | return NULL; |
949 | |
950 | return udf_nfs_get_inode(sb, block: fid->udf.block, partref: fid->udf.partref, |
951 | generation: fid->udf.generation); |
952 | } |
953 | |
954 | static struct dentry *udf_fh_to_parent(struct super_block *sb, |
955 | struct fid *fid, int fh_len, int fh_type) |
956 | { |
957 | if (fh_len < 5 || fh_type != FILEID_UDF_WITH_PARENT) |
958 | return NULL; |
959 | |
960 | return udf_nfs_get_inode(sb, block: fid->udf.parent_block, |
961 | partref: fid->udf.parent_partref, |
962 | generation: fid->udf.parent_generation); |
963 | } |
964 | static int udf_encode_fh(struct inode *inode, __u32 *fh, int *lenp, |
965 | struct inode *parent) |
966 | { |
967 | int len = *lenp; |
968 | struct kernel_lb_addr location = UDF_I(inode)->i_location; |
969 | struct fid *fid = (struct fid *)fh; |
970 | int type = FILEID_UDF_WITHOUT_PARENT; |
971 | |
972 | if (parent && (len < 5)) { |
973 | *lenp = 5; |
974 | return FILEID_INVALID; |
975 | } else if (len < 3) { |
976 | *lenp = 3; |
977 | return FILEID_INVALID; |
978 | } |
979 | |
980 | *lenp = 3; |
981 | fid->udf.block = location.logicalBlockNum; |
982 | fid->udf.partref = location.partitionReferenceNum; |
983 | fid->udf.parent_partref = 0; |
984 | fid->udf.generation = inode->i_generation; |
985 | |
986 | if (parent) { |
987 | location = UDF_I(inode: parent)->i_location; |
988 | fid->udf.parent_block = location.logicalBlockNum; |
989 | fid->udf.parent_partref = location.partitionReferenceNum; |
990 | fid->udf.parent_generation = inode->i_generation; |
991 | *lenp = 5; |
992 | type = FILEID_UDF_WITH_PARENT; |
993 | } |
994 | |
995 | return type; |
996 | } |
997 | |
998 | const struct export_operations udf_export_ops = { |
999 | .encode_fh = udf_encode_fh, |
1000 | .fh_to_dentry = udf_fh_to_dentry, |
1001 | .fh_to_parent = udf_fh_to_parent, |
1002 | .get_parent = udf_get_parent, |
1003 | }; |
1004 | |
1005 | const struct inode_operations udf_dir_inode_operations = { |
1006 | .lookup = udf_lookup, |
1007 | .create = udf_create, |
1008 | .link = udf_link, |
1009 | .unlink = udf_unlink, |
1010 | .symlink = udf_symlink, |
1011 | .mkdir = udf_mkdir, |
1012 | .rmdir = udf_rmdir, |
1013 | .mknod = udf_mknod, |
1014 | .rename = udf_rename, |
1015 | .tmpfile = udf_tmpfile, |
1016 | }; |
1017 | |