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