blob: 1bb6ed948927fbe5a2d4176671b00d96fa63ddc3 [file] [log] [blame]
Bagas Sanjaya5ce34552023-05-22 07:54:34 +07001// SPDX-License-Identifier: GPL-2.0-only
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * namei.c
4 *
5 * PURPOSE
6 * Inode name handling routines for the OSTA-UDF(tm) filesystem.
7 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * COPYRIGHT
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 * (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>
Alexey Dobriyane8edc6e2007-05-21 01:22:52 +040026#include <linux/sched.h>
Bob Copelandf845fce2008-04-17 09:47:48 +020027#include <linux/crc-itu-t.h>
Rasmus Rohde221e5832008-04-30 17:22:06 +020028#include <linux/exportfs.h>
Jan Karaa48fc692021-11-04 15:22:35 +010029#include <linux/iversion.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
Al Viro391e8bb2010-01-31 21:28:48 -050031static inline int udf_match(int len1, const unsigned char *name1, int len2,
32 const unsigned char *name2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070033{
34 if (len1 != len2)
35 return 0;
Cyrill Gorcunov28de7942007-07-21 04:37:18 -070036
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 return !memcmp(name1, name2, len1);
38}
39
Fabian Frederick231473f2015-04-08 21:23:58 +020040/**
Jan Kara1c80afa2022-10-05 18:28:33 +020041 * udf_fiiter_find_entry - find entry in given directory.
Fabian Frederick231473f2015-04-08 21:23:58 +020042 *
43 * @dir: directory inode to search in
44 * @child: qstr of the name
Jan Kara1c80afa2022-10-05 18:28:33 +020045 * @iter: iter to use for searching
Fabian Frederick231473f2015-04-08 21:23:58 +020046 *
47 * This function searches in the directory @dir for a file name @child. When
Jan Kara1c80afa2022-10-05 18:28:33 +020048 * found, @iter points to the position in the directory with given entry.
Fabian Frederick231473f2015-04-08 21:23:58 +020049 *
Jan Kara1c80afa2022-10-05 18:28:33 +020050 * Returns 0 on success, < 0 on error (including -ENOENT).
Fabian Frederick231473f2015-04-08 21:23:58 +020051 */
Jan Kara1c80afa2022-10-05 18:28:33 +020052static int udf_fiiter_find_entry(struct inode *dir, const struct qstr *child,
53 struct udf_fileident_iter *iter)
Linus Torvalds1da177e2005-04-16 15:20:36 -070054{
Steve Magnanib490bdd2017-10-12 08:48:40 -050055 int flen;
Jan Kara1c80afa2022-10-05 18:28:33 +020056 unsigned char *fname = NULL;
57 struct super_block *sb = dir->i_sb;
Al Viro9fbb76c2008-10-12 00:15:17 -040058 int isdotdot = child->len == 2 &&
59 child->name[0] == '.' && child->name[1] == '.';
Jan Kara1c80afa2022-10-05 18:28:33 +020060 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
Jan Karab80697c2008-03-04 14:14:05 +010062 fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
Jan Kara1c80afa2022-10-05 18:28:33 +020063 if (!fname)
64 return -ENOMEM;
Jan Karab80697c2008-03-04 14:14:05 +010065
Jan Kara1c80afa2022-10-05 18:28:33 +020066 for (ret = udf_fiiter_init(iter, dir, 0);
67 !ret && iter->pos < dir->i_size;
68 ret = udf_fiiter_advance(iter)) {
69 if (iter->fi.fileCharacteristics & FID_FILE_CHAR_DELETED) {
Jan Kara3ee30392014-12-18 22:49:12 +010070 if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE))
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 continue;
72 }
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -070073
Jan Kara1c80afa2022-10-05 18:28:33 +020074 if (iter->fi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) {
Jan Kara3ee30392014-12-18 22:49:12 +010075 if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE))
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 continue;
77 }
78
Jan Kara1c80afa2022-10-05 18:28:33 +020079 if ((iter->fi.fileCharacteristics & FID_FILE_CHAR_PARENT) &&
Jesper Juhla4264b32010-12-12 23:18:15 +010080 isdotdot)
81 goto out_ok;
Rasmus Rohde221e5832008-04-30 17:22:06 +020082
Jan Kara1c80afa2022-10-05 18:28:33 +020083 if (!iter->fi.lengthFileIdent)
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 continue;
85
Jan Kara1c80afa2022-10-05 18:28:33 +020086 flen = udf_get_filename(sb, iter->name,
87 iter->fi.lengthFileIdent, fname, UDF_NAME_LEN);
Fabian Frederick231473f2015-04-08 21:23:58 +020088 if (flen < 0) {
Jan Kara1c80afa2022-10-05 18:28:33 +020089 ret = flen;
Fabian Frederick231473f2015-04-08 21:23:58 +020090 goto out_err;
91 }
92
93 if (udf_match(flen, fname, child->len, child->name))
Jan Karab80697c2008-03-04 14:14:05 +010094 goto out_ok;
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 }
Jan Kara1c80afa2022-10-05 18:28:33 +020096 if (!ret)
97 ret = -ENOENT;
Cyrill Gorcunov28de7942007-07-21 04:37:18 -070098
Fabian Frederick231473f2015-04-08 21:23:58 +020099out_err:
Jan Kara1c80afa2022-10-05 18:28:33 +0200100 udf_fiiter_release(iter);
Jan Karab80697c2008-03-04 14:14:05 +0100101out_ok:
Jan Karab80697c2008-03-04 14:14:05 +0100102 kfree(fname);
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700103
Jan Kara1c80afa2022-10-05 18:28:33 +0200104 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105}
106
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700107static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400108 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109{
110 struct inode *inode = NULL;
Jan Kara200918b2022-10-05 18:36:21 +0200111 struct udf_fileident_iter iter;
112 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
Andrew Gabbasov9fba7052016-01-15 02:44:21 -0600114 if (dentry->d_name.len > UDF_NAME_LEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 return ERR_PTR(-ENAMETOOLONG);
116
Jan Kara200918b2022-10-05 18:36:21 +0200117 err = udf_fiiter_find_entry(dir, &dentry->d_name, &iter);
118 if (err < 0 && err != -ENOENT)
119 return ERR_PTR(err);
Fabian Frederick231473f2015-04-08 21:23:58 +0200120
Jan Kara200918b2022-10-05 18:36:21 +0200121 if (err == 0) {
Pekka Enberg97e961f2008-10-15 12:29:03 +0200122 struct kernel_lb_addr loc;
123
Jan Kara200918b2022-10-05 18:36:21 +0200124 loc = lelb_to_cpu(iter.fi.icb.extLocation);
125 udf_fiiter_release(&iter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
Pekka Enberg97e961f2008-10-15 12:29:03 +0200127 inode = udf_iget(dir->i_sb, &loc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 }
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700129
Rasmus Rohde221e5832008-04-30 17:22:06 +0200130 return d_splice_alias(inode, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131}
132
Jan Karaf386c802023-01-24 14:49:52 +0100133static int udf_expand_dir_adinicb(struct inode *inode, udf_pblk_t *block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134{
Jan Karaa27b2922022-10-05 18:10:37 +0200135 udf_pblk_t newblock;
136 struct buffer_head *dbh = NULL;
Pekka Enberg5ca4e4b2008-10-15 12:28:03 +0200137 struct kernel_lb_addr eloc;
Jan Karaa27b2922022-10-05 18:10:37 +0200138 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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
Jan Karaa27b2922022-10-05 18:10:37 +0200145 if (UDF_QUERY_FLAG(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);
Jan Karaf386c802023-01-24 14:49:52 +0100153 return 0;
Jan Karab80697c2008-03-04 14:14:05 +0100154 }
155
Jan Karaa27b2922022-10-05 18:10:37 +0200156 /* alloc block, and copy data to it */
157 *block = udf_new_block(inode->i_sb, inode,
158 iinfo->i_location.partitionReferenceNum,
Jan Karaf386c802023-01-24 14:49:52 +0100159 iinfo->i_location.logicalBlockNum, &ret);
Jan Karaa27b2922022-10-05 18:10:37 +0200160 if (!(*block))
Jan Karaf386c802023-01-24 14:49:52 +0100161 return ret;
Jan Karaa27b2922022-10-05 18:10:37 +0200162 newblock = udf_get_pblock(inode->i_sb, *block,
163 iinfo->i_location.partitionReferenceNum,
164 0);
Jan Karaf386c802023-01-24 14:49:52 +0100165 if (newblock == 0xffffffff)
166 return -EFSCORRUPTED;
Jan Kara101ee132023-01-18 13:27:07 +0100167 dbh = sb_getblk(inode->i_sb, newblock);
Jan Karaa27b2922022-10-05 18:10:37 +0200168 if (!dbh)
Jan Karaf386c802023-01-24 14:49:52 +0100169 return -ENOMEM;
Jan Karaa27b2922022-10-05 18:10:37 +0200170 lock_buffer(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(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);
Jan Kara33e9a532022-12-19 19:50:14 +0100188 ret = udf_add_aext(inode, &epos, &eloc, inode->i_size, 0);
Jan Karaa27b2922022-10-05 18:10:37 +0200189 brelse(epos.bh);
Jan Kara33e9a532022-12-19 19:50:14 +0100190 if (ret < 0) {
Jan Karaf386c802023-01-24 14:49:52 +0100191 brelse(dbh);
Jan Kara33e9a532022-12-19 19:50:14 +0100192 udf_free_blocks(inode->i_sb, inode, &eloc, 0, 1);
Jan Karaf386c802023-01-24 14:49:52 +0100193 return ret;
Jan Kara33e9a532022-12-19 19:50:14 +0100194 }
Jan Karaa27b2922022-10-05 18:10:37 +0200195 mark_inode_dirty(inode);
196
197 /* Now fixup tags in moved directory entries */
198 for (ret = udf_fiiter_init(&iter, inode, 0);
199 !ret && iter.pos < inode->i_size;
200 ret = udf_fiiter_advance(&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, impuse);
208 }
Jan Karaf386c802023-01-24 14:49:52 +0100209 brelse(dbh);
Jan Karaa27b2922022-10-05 18:10:37 +0200210 /*
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);
216
Jan Karaf386c802023-01-24 14:49:52 +0100217 return 0;
Jan Karaa27b2922022-10-05 18:10:37 +0200218}
219
Jan Karaf2844802022-10-06 13:25:16 +0200220static 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(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
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700230 if (dentry) {
Jan Karaf2844802022-10-06 13:25:16 +0200231 namelen = udf_put_filename(dir->i_sb, dentry->d_name.name,
Andrew Gabbasov525e2c52016-01-15 02:44:19 -0600232 dentry->d_name.len,
Andrew Gabbasov9fba7052016-01-15 02:44:21 -0600233 name, UDF_NAME_LEN_CS0);
Jan Karaf2844802022-10-06 13:25:16 +0200234 if (!namelen)
235 return -ENAMETOOLONG;
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700236 }
Jan Karaf2e83342018-06-13 17:30:14 +0200237 nfidlen = ALIGN(sizeof(struct fileIdentDesc) + namelen, UDF_NAME_PAD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
Jan Karaf2844802022-10-06 13:25:16 +0200239 for (ret = udf_fiiter_init(iter, dir, 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(&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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 }
253 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 }
Jan Karaf2844802022-10-06 13:25:16 +0200255 if (ret) {
256 udf_fiiter_release(iter);
257 return ret;
258 }
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800259 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB &&
Jan Karaf2844802022-10-06 13:25:16 +0200260 blksize - udf_ext0_offset(dir) - iter->pos < nfidlen) {
Jan Karaf2844802022-10-06 13:25:16 +0200261 udf_fiiter_release(iter);
Jan Karaf386c802023-01-24 14:49:52 +0100262 ret = udf_expand_dir_adinicb(dir, &block);
263 if (ret)
Jan Karaf2844802022-10-06 13:25:16 +0200264 return ret;
Jan Karaf2844802022-10-06 13:25:16 +0200265 ret = udf_fiiter_init(iter, dir, dir->i_size);
266 if (ret < 0)
267 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 }
269
Jan Karaf2844802022-10-06 13:25:16 +0200270 /* Get blocknumber to use for entry tag */
271 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
272 block = dinfo->i_location.logicalBlockNum;
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700273 } else {
Jan Karaf2844802022-10-06 13:25:16 +0200274 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(dir) - off >= nfidlen)
282 goto store_fi;
Jan Kara2c948b32009-12-03 13:39:28 +0100283
Jan Karaf2844802022-10-06 13:25:16 +0200284 ret = udf_fiiter_append_blk(iter);
285 if (ret) {
286 udf_fiiter_release(iter);
287 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 }
289
Jan Karaf2844802022-10-06 13:25:16 +0200290 /* 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);
294store_fi:
295 memset(&iter->fi, 0, sizeof(struct fileIdentDesc));
296 if (UDF_SB(dir->i_sb)->s_udfrev >= 0x0200)
297 udf_new_tag((char *)(&iter->fi), TAG_IDENT_FID, 3, 1, block,
Pekka Enberg5ca4e4b2008-10-15 12:28:03 +0200298 sizeof(struct tag));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 else
Jan Karaf2844802022-10-06 13:25:16 +0200300 udf_new_tag((char *)(&iter->fi), TAG_IDENT_FID, 2, 1, block,
Pekka Enberg5ca4e4b2008-10-15 12:28:03 +0200301 sizeof(struct tag));
Jan Karaf2844802022-10-06 13:25:16 +0200302 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;
Jan Kara2c948b32009-12-03 13:39:28 +0100307
Jan Karaf2844802022-10-06 13:25:16 +0200308 dir->i_size += nfidlen;
309 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
310 dinfo->i_lenAlloc += nfidlen;
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700311 } else {
Jan Karaf2844802022-10-06 13:25:16 +0200312 /* Truncate last extent to proper size */
313 udf_fiiter_update_elen(iter, iter->elen -
314 (dinfo->i_lenExtents - dir->i_size));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 }
Jan Karaf2844802022-10-06 13:25:16 +0200316 mark_inode_dirty(dir);
Jan Karab80697c2008-03-04 14:14:05 +0100317
Jan Karaf2844802022-10-06 13:25:16 +0200318 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319}
320
Jan Kara4cca7e32022-10-05 19:26:59 +0200321static void udf_fiiter_delete_entry(struct udf_fileident_iter *iter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322{
Jan Kara4cca7e32022-10-05 19:26:59 +0200323 iter->fi.fileCharacteristics |= FID_FILE_CHAR_DELETED;
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700324
Jan Kara4cca7e32022-10-05 19:26:59 +0200325 if (UDF_QUERY_FLAG(iter->dir->i_sb, UDF_FLAG_STRICT))
326 memset(&iter->fi.icb, 0x00, sizeof(struct long_ad));
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700327
Jan Kara4cca7e32022-10-05 19:26:59 +0200328 udf_fiiter_write_fi(iter, NULL);
329}
330
Jan Kara085cf7b2023-01-25 19:31:38 +0100331static 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(&lvidiu->numDirs, val);
340 else
341 le32_add_cpu(&lvidiu->numFiles, val);
342 udf_updated_lvid(sb);
343 mutex_unlock(&UDF_SB(sb)->s_alloc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344}
345
Al Virod2be51c2014-09-04 09:34:14 -0400346static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
Al Virod2be51c2014-09-04 09:34:14 -0400348 struct udf_inode_info *iinfo = UDF_I(inode);
David Howells2b0143b2015-03-17 22:25:59 +0000349 struct inode *dir = d_inode(dentry->d_parent);
Jan Karaef91f992022-10-06 14:08:59 +0200350 struct udf_fileident_iter iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352
Jan Karaef91f992022-10-06 14:08:59 +0200353 err = udf_fiiter_add_entry(dir, dentry, &iter);
354 if (err) {
Miklos Szeredi6d6b77f2011-10-28 14:13:28 +0200355 inode_dec_link_count(inode);
Al Viro5c1a68a32018-05-16 12:25:39 -0400356 discard_new_inode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 return err;
358 }
Jan Karaef91f992022-10-06 14:08:59 +0200359 iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
360 iter.fi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
361 *(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse =
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800362 cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
Jan Karaef91f992022-10-06 14:08:59 +0200363 udf_fiiter_write_fi(&iter, NULL);
Jeff Laytonf972fed2023-10-04 14:52:59 -0400364 inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
Jan Kara3adc12e2015-03-24 16:47:25 -0400365 mark_inode_dirty(dir);
Jan Karaef91f992022-10-06 14:08:59 +0200366 udf_fiiter_release(&iter);
Jan Kara085cf7b2023-01-25 19:31:38 +0100367 udf_add_fid_counter(dir->i_sb, false, 1);
Al Viro1e2e5472018-05-04 08:23:01 -0400368 d_instantiate_new(dentry, inode);
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700369
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 return 0;
371}
372
Christian Brauner6c960e62023-01-13 12:49:13 +0100373static int udf_create(struct mnt_idmap *idmap, struct inode *dir,
Christian Brauner549c7292021-01-21 14:19:43 +0100374 struct dentry *dentry, umode_t mode, bool excl)
Al Virod2be51c2014-09-04 09:34:14 -0400375{
Al Viro0b93a922014-09-04 09:47:41 -0400376 struct inode *inode = udf_new_inode(dir, mode);
Al Virod2be51c2014-09-04 09:34:14 -0400377
Al Viro0b93a922014-09-04 09:47:41 -0400378 if (IS_ERR(inode))
379 return PTR_ERR(inode);
Al Virod2be51c2014-09-04 09:34:14 -0400380
Jan Kara37a8a392023-01-24 12:23:04 +0100381 inode->i_data.a_ops = &udf_aops;
Al Virod2be51c2014-09-04 09:34:14 -0400382 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
Christian Brauner011e2b72023-01-13 12:49:18 +0100389static int udf_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
Miklos Szeredi863f1442022-09-24 07:00:00 +0200390 struct file *file, umode_t mode)
Al Viro656d09d2013-06-12 09:35:33 +0400391{
Al Viro0b93a922014-09-04 09:47:41 -0400392 struct inode *inode = udf_new_inode(dir, mode);
Al Viro656d09d2013-06-12 09:35:33 +0400393
Al Viro0b93a922014-09-04 09:47:41 -0400394 if (IS_ERR(inode))
395 return PTR_ERR(inode);
Al Viro656d09d2013-06-12 09:35:33 +0400396
Jan Kara37a8a392023-01-24 12:23:04 +0100397 inode->i_data.a_ops = &udf_aops;
Al Viro656d09d2013-06-12 09:35:33 +0400398 inode->i_op = &udf_file_inode_operations;
399 inode->i_fop = &udf_file_operations;
400 mark_inode_dirty(inode);
Miklos Szeredi863f1442022-09-24 07:00:00 +0200401 d_tmpfile(file, inode);
Al Virob2315092014-09-04 09:38:11 -0400402 unlock_new_inode(inode);
Miklos Szeredi863f1442022-09-24 07:00:00 +0200403 return finish_open_simple(file, 0);
Al Viro656d09d2013-06-12 09:35:33 +0400404}
405
Christian Brauner5ebb29b2023-01-13 12:49:16 +0100406static int udf_mknod(struct mnt_idmap *idmap, struct inode *dir,
Christian Brauner549c7292021-01-21 14:19:43 +0100407 struct dentry *dentry, umode_t mode, dev_t rdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408{
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700409 struct inode *inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
411 if (!old_valid_dev(rdev))
412 return -EINVAL;
413
Al Viro0b93a922014-09-04 09:47:41 -0400414 inode = udf_new_inode(dir, mode);
415 if (IS_ERR(inode))
416 return PTR_ERR(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
Al Virod2be51c2014-09-04 09:34:14 -0400418 init_special_inode(inode, mode, rdev);
419 return udf_add_nondir(dentry, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420}
421
Christian Braunerc54bd912023-01-13 12:49:15 +0100422static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
Christian Brauner549c7292021-01-21 14:19:43 +0100423 struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424{
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700425 struct inode *inode;
Jan Kara00bce6f2022-10-06 14:22:33 +0200426 struct udf_fileident_iter iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 int err;
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800428 struct udf_inode_info *dinfo = UDF_I(dir);
429 struct udf_inode_info *iinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Al Viro0b93a922014-09-04 09:47:41 -0400431 inode = udf_new_inode(dir, S_IFDIR | mode);
432 if (IS_ERR(inode))
433 return PTR_ERR(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800435 iinfo = UDF_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 inode->i_op = &udf_dir_inode_operations;
437 inode->i_fop = &udf_dir_operations;
Jan Kara00bce6f2022-10-06 14:22:33 +0200438 err = udf_fiiter_add_entry(inode, NULL, &iter);
439 if (err) {
440 clear_nlink(inode);
Al Viro5c1a68a32018-05-16 12:25:39 -0400441 discard_new_inode(inode);
Jan Kara00bce6f2022-10-06 14:22:33 +0200442 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 }
Miklos Szeredibfe86842011-10-28 14:13:29 +0200444 set_nlink(inode, 2);
Jan Kara00bce6f2022-10-06 14:22:33 +0200445 iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
446 iter.fi.icb.extLocation = cpu_to_lelb(dinfo->i_location);
447 *(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse =
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800448 cpu_to_le32(dinfo->i_unique & 0x00000000FFFFFFFFUL);
Jan Kara00bce6f2022-10-06 14:22:33 +0200449 iter.fi.fileCharacteristics =
Marcin Slusarz4b111112008-02-08 04:20:36 -0800450 FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT;
Jan Kara00bce6f2022-10-06 14:22:33 +0200451 udf_fiiter_write_fi(&iter, NULL);
452 udf_fiiter_release(&iter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 mark_inode_dirty(inode);
454
Jan Kara00bce6f2022-10-06 14:22:33 +0200455 err = udf_fiiter_add_entry(dir, dentry, &iter);
456 if (err) {
Miklos Szeredi6d6b77f2011-10-28 14:13:28 +0200457 clear_nlink(inode);
Al Viro5c1a68a32018-05-16 12:25:39 -0400458 discard_new_inode(inode);
Jan Kara00bce6f2022-10-06 14:22:33 +0200459 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 }
Jan Kara00bce6f2022-10-06 14:22:33 +0200461 iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
462 iter.fi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
463 *(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse =
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800464 cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
Jan Kara00bce6f2022-10-06 14:22:33 +0200465 iter.fi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
466 udf_fiiter_write_fi(&iter, NULL);
467 udf_fiiter_release(&iter);
Jan Kara085cf7b2023-01-25 19:31:38 +0100468 udf_add_fid_counter(dir->i_sb, true, 1);
Dave Hansend8c76e62006-09-30 23:29:04 -0700469 inc_nlink(dir);
Jeff Laytonf972fed2023-10-04 14:52:59 -0400470 inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 mark_inode_dirty(dir);
Al Viro1e2e5472018-05-04 08:23:01 -0400472 d_instantiate_new(dentry, inode);
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700473
Jan Kara00bce6f2022-10-06 14:22:33 +0200474 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475}
476
477static int empty_dir(struct inode *dir)
478{
Jan Karaafb525f2022-10-05 19:10:02 +0200479 struct udf_fileident_iter iter;
480 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
Jan Karaafb525f2022-10-05 19:10:02 +0200482 for (ret = udf_fiiter_init(&iter, dir, 0);
483 !ret && iter.pos < dir->i_size;
484 ret = udf_fiiter_advance(&iter)) {
485 if (iter.fi.lengthFileIdent &&
486 !(iter.fi.fileCharacteristics & FID_FILE_CHAR_DELETED)) {
487 udf_fiiter_release(&iter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 return 0;
489 }
490 }
Jan Karaafb525f2022-10-05 19:10:02 +0200491 udf_fiiter_release(&iter);
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700492
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 return 1;
494}
495
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700496static int udf_rmdir(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497{
Jan Karad11ffa82022-10-05 19:33:23 +0200498 int ret;
David Howells2b0143b2015-03-17 22:25:59 +0000499 struct inode *inode = d_inode(dentry);
Jan Karad11ffa82022-10-05 19:33:23 +0200500 struct udf_fileident_iter iter;
Pekka Enberg5ca4e4b2008-10-15 12:28:03 +0200501 struct kernel_lb_addr tloc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Jan Karad11ffa82022-10-05 19:33:23 +0200503 ret = udf_fiiter_find_entry(dir, &dentry->d_name, &iter);
504 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 goto out;
506
Jan Karad11ffa82022-10-05 19:33:23 +0200507 ret = -EFSCORRUPTED;
508 tloc = lelb_to_cpu(iter.fi.icb.extLocation);
Pekka Enberg97e961f2008-10-15 12:29:03 +0200509 if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 goto end_rmdir;
Jan Karad11ffa82022-10-05 19:33:23 +0200511 ret = -ENOTEMPTY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 if (!empty_dir(inode))
513 goto end_rmdir;
Jan Karad11ffa82022-10-05 19:33:23 +0200514 udf_fiiter_delete_entry(&iter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 if (inode->i_nlink != 2)
Steve Magnanifcbf7632017-10-12 08:48:41 -0500516 udf_warn(inode->i_sb, "empty directory has nlink != 2 (%u)\n",
Joe Perchesa40ecd72011-10-10 01:08:04 -0700517 inode->i_nlink);
Dave Hansence71ec32006-09-30 23:29:06 -0700518 clear_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 inode->i_size = 0;
Stephen Mollettc007c062007-05-08 00:31:31 -0700520 inode_dec_link_count(dir);
Jan Kara085cf7b2023-01-25 19:31:38 +0100521 udf_add_fid_counter(dir->i_sb, true, -1);
Jeff Laytonf972fed2023-10-04 14:52:59 -0400522 inode_set_mtime_to_ts(dir,
523 inode_set_ctime_to_ts(dir, inode_set_ctime_current(inode)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 mark_inode_dirty(dir);
Jan Karad11ffa82022-10-05 19:33:23 +0200525 ret = 0;
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700526end_rmdir:
Jan Karad11ffa82022-10-05 19:33:23 +0200527 udf_fiiter_release(&iter);
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700528out:
Jan Karad11ffa82022-10-05 19:33:23 +0200529 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530}
531
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700532static int udf_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533{
Jan Kara6ec01a82022-10-05 19:36:49 +0200534 int ret;
David Howells2b0143b2015-03-17 22:25:59 +0000535 struct inode *inode = d_inode(dentry);
Jan Kara6ec01a82022-10-05 19:36:49 +0200536 struct udf_fileident_iter iter;
Pekka Enberg5ca4e4b2008-10-15 12:28:03 +0200537 struct kernel_lb_addr tloc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Jan Kara6ec01a82022-10-05 19:36:49 +0200539 ret = udf_fiiter_find_entry(dir, &dentry->d_name, &iter);
540 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 goto out;
542
Jan Kara6ec01a82022-10-05 19:36:49 +0200543 ret = -EFSCORRUPTED;
544 tloc = lelb_to_cpu(iter.fi.icb.extLocation);
Pekka Enberg97e961f2008-10-15 12:29:03 +0200545 if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 goto end_unlink;
547
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700548 if (!inode->i_nlink) {
Steve Magnanifcbf7632017-10-12 08:48:41 -0500549 udf_debug("Deleting nonexistent file (%lu), %u\n",
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700550 inode->i_ino, inode->i_nlink);
Miklos Szeredibfe86842011-10-28 14:13:29 +0200551 set_nlink(inode, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 }
Jan Kara6ec01a82022-10-05 19:36:49 +0200553 udf_fiiter_delete_entry(&iter);
Jeff Laytonf972fed2023-10-04 14:52:59 -0400554 inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 mark_inode_dirty(dir);
Dave Hansen9a53c3a2006-09-30 23:29:03 -0700556 inode_dec_link_count(inode);
Jan Kara085cf7b2023-01-25 19:31:38 +0100557 udf_add_fid_counter(dir->i_sb, false, -1);
Jeff Layton59ad88f2023-07-05 15:01:44 -0400558 inode_set_ctime_to_ts(inode, inode_get_ctime(dir));
Jan Kara6ec01a82022-10-05 19:36:49 +0200559 ret = 0;
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700560end_unlink:
Jan Kara6ec01a82022-10-05 19:36:49 +0200561 udf_fiiter_release(&iter);
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700562out:
Jan Kara6ec01a82022-10-05 19:36:49 +0200563 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564}
565
Christian Brauner7a77db92023-01-13 12:49:14 +0100566static int udf_symlink(struct mnt_idmap *idmap, struct inode *dir,
Christian Brauner549c7292021-01-21 14:19:43 +0100567 struct dentry *dentry, const char *symname)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568{
Fabian Frederick6ff6b2b2017-04-23 20:58:15 +0200569 struct inode *inode = udf_new_inode(dir, S_IFLNK | 0777);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 struct pathComponent *pc;
Al Viro391e8bb2010-01-31 21:28:48 -0500571 const char *compstart;
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700572 struct extent_position epos = {};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 int eoffset, elen = 0;
Al Viro391e8bb2010-01-31 21:28:48 -0500574 uint8_t *ea;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 int err;
Steve Magnanib490bdd2017-10-12 08:48:40 -0500576 udf_pblk_t block;
Al Viro391e8bb2010-01-31 21:28:48 -0500577 unsigned char *name = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 int namelen;
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800579 struct udf_inode_info *iinfo;
Jan Karad664b6a2010-10-20 18:28:46 +0200580 struct super_block *sb = dir->i_sb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
Al Viro0b93a922014-09-04 09:47:41 -0400582 if (IS_ERR(inode))
583 return PTR_ERR(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
Alessio Igor Bogani4d0fb622010-11-16 18:40:47 +0100585 iinfo = UDF_I(inode);
586 down_write(&iinfo->i_data_sem);
Andrew Gabbasov9fba7052016-01-15 02:44:21 -0600587 name = kmalloc(UDF_NAME_LEN_CS0, GFP_NOFS);
Jan Karab80697c2008-03-04 14:14:05 +0100588 if (!name) {
589 err = -ENOMEM;
590 goto out_no_entry;
591 }
592
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 inode->i_data.a_ops = &udf_symlink_aops;
Jan Karaad4d0532017-01-02 14:30:31 +0100594 inode->i_op = &udf_symlink_inode_operations;
Al Viro21fc61c2015-11-17 01:07:57 -0500595 inode_nohighmem(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800597 if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
Pekka Enberg5ca4e4b2008-10-15 12:28:03 +0200598 struct kernel_lb_addr eloc;
Harvey Harrison78e917d2008-04-28 02:16:19 -0700599 uint32_t bsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Jan Karad664b6a2010-10-20 18:28:46 +0200601 block = udf_new_block(sb, inode,
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800602 iinfo->i_location.partitionReferenceNum,
603 iinfo->i_location.logicalBlockNum, &err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 if (!block)
605 goto out_no_entry;
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800606 epos.block = iinfo->i_location;
Jan Karaff116fc2007-05-08 00:35:14 -0700607 epos.offset = udf_file_entry_alloc_offset(inode);
608 epos.bh = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 eloc.logicalBlockNum = block;
Marcin Slusarz4b111112008-02-08 04:20:36 -0800610 eloc.partitionReferenceNum =
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800611 iinfo->i_location.partitionReferenceNum;
Jan Karad664b6a2010-10-20 18:28:46 +0200612 bsize = sb->s_blocksize;
Harvey Harrison78e917d2008-04-28 02:16:19 -0700613 iinfo->i_lenExtents = bsize;
Jan Kara2b100742022-12-19 19:54:12 +0100614 err = udf_add_aext(inode, &epos, &eloc, bsize, 0);
Jan Kara3bf25cb2007-05-08 00:35:16 -0700615 brelse(epos.bh);
Jan Kara2b100742022-12-19 19:54:12 +0100616 if (err < 0) {
617 udf_free_blocks(sb, inode, &eloc, 0, 1);
618 goto out_no_entry;
619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
Jan Karad664b6a2010-10-20 18:28:46 +0200621 block = udf_get_pblock(sb, block,
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800622 iinfo->i_location.partitionReferenceNum,
Marcin Slusarz4b111112008-02-08 04:20:36 -0800623 0);
Jan Kara101ee132023-01-18 13:27:07 +0100624 epos.bh = sb_getblk(sb, block);
Arturo Giustifa236c22021-05-18 12:34:57 +0200625 if (unlikely(!epos.bh)) {
626 err = -ENOMEM;
Jan Kara2b100742022-12-19 19:54:12 +0100627 udf_free_blocks(sb, inode, &eloc, 0, 1);
Arturo Giustifa236c22021-05-18 12:34:57 +0200628 goto out_no_entry;
629 }
Jan Karaff116fc2007-05-08 00:35:14 -0700630 lock_buffer(epos.bh);
Jan Karad664b6a2010-10-20 18:28:46 +0200631 memset(epos.bh->b_data, 0x00, bsize);
Jan Karaff116fc2007-05-08 00:35:14 -0700632 set_buffer_uptodate(epos.bh);
633 unlock_buffer(epos.bh);
634 mark_buffer_dirty_inode(epos.bh, inode);
635 ea = epos.bh->b_data + udf_ext0_offset(inode);
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800636 } else
Jan Kara382a2282020-09-25 12:29:54 +0200637 ea = iinfo->i_data + iinfo->i_lenEAttr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
Jan Karad664b6a2010-10-20 18:28:46 +0200639 eoffset = sb->s_blocksize - udf_ext0_offset(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 pc = (struct pathComponent *)ea;
641
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700642 if (*symname == '/') {
643 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 symname++;
645 } while (*symname == '/');
646
647 pc->componentType = 1;
648 pc->lengthComponentIdent = 0;
649 pc->componentFileVersionNum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 elen += sizeof(struct pathComponent);
651 }
652
653 err = -ENAMETOOLONG;
654
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700655 while (*symname) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 if (elen + sizeof(struct pathComponent) > eoffset)
657 goto out_no_entry;
658
659 pc = (struct pathComponent *)(ea + elen);
660
Al Viro391e8bb2010-01-31 21:28:48 -0500661 compstart = symname;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700663 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 symname++;
665 } while (*symname && *symname != '/');
666
667 pc->componentType = 5;
668 pc->lengthComponentIdent = 0;
669 pc->componentFileVersionNum = 0;
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700670 if (compstart[0] == '.') {
671 if ((symname - compstart) == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 pc->componentType = 4;
Marcin Slusarz4b111112008-02-08 04:20:36 -0800673 else if ((symname - compstart) == 2 &&
674 compstart[1] == '.')
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 pc->componentType = 3;
676 }
677
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700678 if (pc->componentType == 5) {
Andrew Gabbasov525e2c52016-01-15 02:44:19 -0600679 namelen = udf_put_filename(sb, compstart,
680 symname - compstart,
Andrew Gabbasov9fba7052016-01-15 02:44:21 -0600681 name, UDF_NAME_LEN_CS0);
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700682 if (!namelen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 goto out_no_entry;
684
Marcin Slusarz4b111112008-02-08 04:20:36 -0800685 if (elen + sizeof(struct pathComponent) + namelen >
686 eoffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 goto out_no_entry;
688 else
689 pc->lengthComponentIdent = namelen;
690
691 memcpy(pc->componentIdent, name, namelen);
692 }
693
694 elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
695
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700696 if (*symname) {
697 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 symname++;
699 } while (*symname == '/');
700 }
701 }
702
Jan Kara3bf25cb2007-05-08 00:35:16 -0700703 brelse(epos.bh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 inode->i_size = elen;
Marcin Slusarz48d6d8ff2008-02-08 04:20:44 -0800705 if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
706 iinfo->i_lenAlloc = inode->i_size;
Jan Kara2c948b32009-12-03 13:39:28 +0100707 else
708 udf_truncate_tail_extent(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 mark_inode_dirty(inode);
Jan Kara4ea77722013-12-23 22:02:16 +0100710 up_write(&iinfo->i_data_sem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Al Virod2be51c2014-09-04 09:34:14 -0400712 err = udf_add_nondir(dentry, inode);
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700713out:
Jan Karab80697c2008-03-04 14:14:05 +0100714 kfree(name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 return err;
716
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700717out_no_entry:
Alessio Igor Bogani4d0fb622010-11-16 18:40:47 +0100718 up_write(&iinfo->i_data_sem);
Dave Hansen9a53c3a2006-09-30 23:29:03 -0700719 inode_dec_link_count(inode);
Al Viro5c1a68a32018-05-16 12:25:39 -0400720 discard_new_inode(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 goto out;
722}
723
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700724static int udf_link(struct dentry *old_dentry, struct inode *dir,
725 struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726{
David Howells2b0143b2015-03-17 22:25:59 +0000727 struct inode *inode = d_inode(old_dentry);
Jan Karadbfb1022022-10-06 14:59:11 +0200728 struct udf_fileident_iter iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 int err;
730
Jan Karadbfb1022022-10-06 14:59:11 +0200731 err = udf_fiiter_add_entry(dir, dentry, &iter);
732 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 return err;
Jan Karadbfb1022022-10-06 14:59:11 +0200734 iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
735 iter.fi.icb.extLocation = cpu_to_lelb(UDF_I(inode)->i_location);
Jan Karad664b6a2010-10-20 18:28:46 +0200736 if (UDF_SB(inode->i_sb)->s_lvid_bh) {
Jan Karadbfb1022022-10-06 14:59:11 +0200737 *(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse =
Jan Karad664b6a2010-10-20 18:28:46 +0200738 cpu_to_le32(lvid_get_unique_id(inode->i_sb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 }
Jan Karadbfb1022022-10-06 14:59:11 +0200740 udf_fiiter_write_fi(&iter, NULL);
741 udf_fiiter_release(&iter);
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700742
Dave Hansend8c76e62006-09-30 23:29:04 -0700743 inc_nlink(inode);
Jan Kara085cf7b2023-01-25 19:31:38 +0100744 udf_add_fid_counter(dir->i_sb, false, 1);
Jeff Layton59ad88f2023-07-05 15:01:44 -0400745 inode_set_ctime_current(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 mark_inode_dirty(inode);
Jeff Laytonf972fed2023-10-04 14:52:59 -0400747 inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
Jan Kara3adc12e2015-03-24 16:47:25 -0400748 mark_inode_dirty(dir);
Al Viro7de9c6ee2010-10-23 11:11:40 -0400749 ihold(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 d_instantiate(dentry, inode);
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 return 0;
753}
754
755/* Anybody can rename anything with this: the permission checks are left to the
756 * higher-level routines.
757 */
Christian Braunere18275a2023-01-13 12:49:17 +0100758static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir,
Christian Brauner549c7292021-01-21 14:19:43 +0100759 struct dentry *old_dentry, struct inode *new_dir,
760 struct dentry *new_dentry, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761{
David Howells2b0143b2015-03-17 22:25:59 +0000762 struct inode *old_inode = d_inode(old_dentry);
763 struct inode *new_inode = d_inode(new_dentry);
Jan Karae9109a92022-10-06 16:41:23 +0200764 struct udf_fileident_iter oiter, niter, diriter;
Al Viro9d35ceb2023-10-17 14:44:23 -0400765 bool has_diriter = false, is_dir = false;
Jan Karae9109a92022-10-06 16:41:23 +0200766 int retval;
Pekka Enberg5ca4e4b2008-10-15 12:28:03 +0200767 struct kernel_lb_addr tloc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
Miklos Szeredif03b8ad2016-09-27 11:03:57 +0200769 if (flags & ~RENAME_NOREPLACE)
770 return -EINVAL;
771
Jan Karae9109a92022-10-06 16:41:23 +0200772 retval = udf_fiiter_find_entry(old_dir, &old_dentry->d_name, &oiter);
773 if (retval)
774 return retval;
775
776 tloc = lelb_to_cpu(oiter.fi.icb.extLocation);
777 if (udf_get_lb_pblock(old_dir->i_sb, &tloc, 0) != old_inode->i_ino) {
778 retval = -ENOENT;
779 goto out_oiter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 }
Fabian Frederick231473f2015-04-08 21:23:58 +0200781
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700782 if (S_ISDIR(old_inode->i_mode)) {
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700783 if (new_inode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 retval = -ENOTEMPTY;
785 if (!empty_dir(new_inode))
Jan Karae9109a92022-10-06 16:41:23 +0200786 goto out_oiter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 }
Al Viro9d35ceb2023-10-17 14:44:23 -0400788 is_dir = true;
789 }
790 if (is_dir && old_dir != new_dir) {
Jan Karae9109a92022-10-06 16:41:23 +0200791 retval = udf_fiiter_find_entry(old_inode, &dotdot_name,
792 &diriter);
793 if (retval == -ENOENT) {
794 udf_err(old_inode->i_sb,
795 "directory (ino %lu) has no '..' entry\n",
796 old_inode->i_ino);
797 retval = -EFSCORRUPTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 }
Jan Kara7517ce5d2023-06-01 12:58:22 +0200799 if (retval)
Jan Karae9109a92022-10-06 16:41:23 +0200800 goto out_oiter;
801 has_diriter = true;
802 tloc = lelb_to_cpu(diriter.fi.icb.extLocation);
Pekka Enberg97e961f2008-10-15 12:29:03 +0200803 if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) !=
Jan Karae9109a92022-10-06 16:41:23 +0200804 old_dir->i_ino) {
805 retval = -EFSCORRUPTED;
806 udf_err(old_inode->i_sb,
807 "directory (ino %lu) has parent entry pointing to another inode (%lu != %u)\n",
808 old_inode->i_ino, old_dir->i_ino,
809 udf_get_lb_pblock(old_inode->i_sb, &tloc, 0));
810 goto out_oiter;
811 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 }
Jan Karae9109a92022-10-06 16:41:23 +0200813
814 retval = udf_fiiter_find_entry(new_dir, &new_dentry->d_name, &niter);
815 if (retval && retval != -ENOENT)
816 goto out_oiter;
817 /* Entry found but not passed by VFS? */
818 if (!retval && !new_inode) {
819 retval = -EFSCORRUPTED;
820 udf_fiiter_release(&niter);
821 goto out_oiter;
822 }
823 /* Entry not found? Need to add one... */
824 if (retval) {
825 udf_fiiter_release(&niter);
826 retval = udf_fiiter_add_entry(new_dir, new_dentry, &niter);
827 if (retval)
828 goto out_oiter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 }
830
831 /*
832 * Like most other Unix systems, set the ctime for inodes on a
833 * rename.
834 */
Jeff Layton59ad88f2023-07-05 15:01:44 -0400835 inode_set_ctime_current(old_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 mark_inode_dirty(old_inode);
837
838 /*
839 * ok, that's it
840 */
Jan Karae9109a92022-10-06 16:41:23 +0200841 niter.fi.fileVersionNum = oiter.fi.fileVersionNum;
842 niter.fi.fileCharacteristics = oiter.fi.fileCharacteristics;
843 memcpy(&(niter.fi.icb), &(oiter.fi.icb), sizeof(oiter.fi.icb));
844 udf_fiiter_write_fi(&niter, NULL);
845 udf_fiiter_release(&niter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Jan Karae9109a92022-10-06 16:41:23 +0200847 /*
848 * The old entry may have moved due to new entry allocation. Find it
849 * again.
850 */
851 udf_fiiter_release(&oiter);
852 retval = udf_fiiter_find_entry(old_dir, &old_dentry->d_name, &oiter);
853 if (retval) {
854 udf_err(old_dir->i_sb,
855 "failed to find renamed entry again in directory (ino %lu)\n",
856 old_dir->i_ino);
857 } else {
858 udf_fiiter_delete_entry(&oiter);
859 udf_fiiter_release(&oiter);
860 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861
Cyrill Gorcunovcb00ea32007-07-19 01:47:43 -0700862 if (new_inode) {
Jeff Layton59ad88f2023-07-05 15:01:44 -0400863 inode_set_ctime_current(new_inode);
Dave Hansen9a53c3a2006-09-30 23:29:03 -0700864 inode_dec_link_count(new_inode);
Jan Kara085cf7b2023-01-25 19:31:38 +0100865 udf_add_fid_counter(old_dir->i_sb, S_ISDIR(new_inode->i_mode),
866 -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 }
Jeff Laytonf972fed2023-10-04 14:52:59 -0400868 inode_set_mtime_to_ts(old_dir, inode_set_ctime_current(old_dir));
869 inode_set_mtime_to_ts(new_dir, inode_set_ctime_current(new_dir));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 mark_inode_dirty(old_dir);
Jan Kara3adc12e2015-03-24 16:47:25 -0400871 mark_inode_dirty(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872
Jan Karae9109a92022-10-06 16:41:23 +0200873 if (has_diriter) {
874 diriter.fi.icb.extLocation =
875 cpu_to_lelb(UDF_I(new_dir)->i_location);
876 udf_update_tag((char *)&diriter.fi,
877 udf_dir_entry_len(&diriter.fi));
878 udf_fiiter_write_fi(&diriter, NULL);
879 udf_fiiter_release(&diriter);
Al Viro9d35ceb2023-10-17 14:44:23 -0400880 }
Marcin Slusarz4b111112008-02-08 04:20:36 -0800881
Al Viro9d35ceb2023-10-17 14:44:23 -0400882 if (is_dir) {
Dave Hansen9a53c3a2006-09-30 23:29:03 -0700883 inode_dec_link_count(old_dir);
Marcin Slusarz4b111112008-02-08 04:20:36 -0800884 if (new_inode)
Dave Hansen9a53c3a2006-09-30 23:29:03 -0700885 inode_dec_link_count(new_inode);
Marcin Slusarz4b111112008-02-08 04:20:36 -0800886 else {
Dave Hansend8c76e62006-09-30 23:29:04 -0700887 inc_nlink(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 mark_inode_dirty(new_dir);
889 }
890 }
Jan Karae9109a92022-10-06 16:41:23 +0200891 return 0;
892out_oiter:
Jan Kara7517ce5d2023-06-01 12:58:22 +0200893 if (has_diriter)
Jan Karae9109a92022-10-06 16:41:23 +0200894 udf_fiiter_release(&diriter);
895 udf_fiiter_release(&oiter);
Cyrill Gorcunov28de7942007-07-21 04:37:18 -0700896
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 return retval;
898}
899
Rasmus Rohde221e5832008-04-30 17:22:06 +0200900static struct dentry *udf_get_parent(struct dentry *child)
901{
Pekka Enberg97e961f2008-10-15 12:29:03 +0200902 struct kernel_lb_addr tloc;
Jan Kara9b06fbe2022-10-05 18:48:45 +0200903 struct udf_fileident_iter iter;
904 int err;
Rasmus Rohde221e5832008-04-30 17:22:06 +0200905
Jan Kara9b06fbe2022-10-05 18:48:45 +0200906 err = udf_fiiter_find_entry(d_inode(child), &dotdot_name, &iter);
907 if (err)
908 return ERR_PTR(err);
Rasmus Rohde221e5832008-04-30 17:22:06 +0200909
Jan Kara9b06fbe2022-10-05 18:48:45 +0200910 tloc = lelb_to_cpu(iter.fi.icb.extLocation);
911 udf_fiiter_release(&iter);
Al Virof58b8c3e2023-11-11 01:55:30 -0500912 return d_obtain_alias(udf_iget(child->d_sb, &tloc));
Rasmus Rohde221e5832008-04-30 17:22:06 +0200913}
914
915
916static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block,
917 u16 partref, __u32 generation)
918{
919 struct inode *inode;
Pekka Enberg5ca4e4b2008-10-15 12:28:03 +0200920 struct kernel_lb_addr loc;
Rasmus Rohde221e5832008-04-30 17:22:06 +0200921
922 if (block == 0)
923 return ERR_PTR(-ESTALE);
924
925 loc.logicalBlockNum = block;
926 loc.partitionReferenceNum = partref;
Pekka Enberg97e961f2008-10-15 12:29:03 +0200927 inode = udf_iget(sb, &loc);
Rasmus Rohde221e5832008-04-30 17:22:06 +0200928
Jan Kara6d3d5e82014-09-04 16:15:51 +0200929 if (IS_ERR(inode))
930 return ERR_CAST(inode);
Rasmus Rohde221e5832008-04-30 17:22:06 +0200931
932 if (generation && inode->i_generation != generation) {
933 iput(inode);
934 return ERR_PTR(-ESTALE);
935 }
Christoph Hellwig44003722008-08-11 15:49:04 +0200936 return d_obtain_alias(inode);
Rasmus Rohde221e5832008-04-30 17:22:06 +0200937}
938
939static struct dentry *udf_fh_to_dentry(struct super_block *sb,
940 struct fid *fid, int fh_len, int fh_type)
941{
NeilBrown92acca42015-05-08 10:16:23 +1000942 if (fh_len < 3 ||
Rasmus Rohde221e5832008-04-30 17:22:06 +0200943 (fh_type != FILEID_UDF_WITH_PARENT &&
944 fh_type != FILEID_UDF_WITHOUT_PARENT))
945 return NULL;
946
947 return udf_nfs_get_inode(sb, fid->udf.block, fid->udf.partref,
948 fid->udf.generation);
949}
950
951static struct dentry *udf_fh_to_parent(struct super_block *sb,
952 struct fid *fid, int fh_len, int fh_type)
953{
NeilBrown92acca42015-05-08 10:16:23 +1000954 if (fh_len < 5 || fh_type != FILEID_UDF_WITH_PARENT)
Rasmus Rohde221e5832008-04-30 17:22:06 +0200955 return NULL;
956
957 return udf_nfs_get_inode(sb, fid->udf.parent_block,
958 fid->udf.parent_partref,
959 fid->udf.parent_generation);
960}
Al Virob0b03822012-04-02 14:34:06 -0400961static int udf_encode_fh(struct inode *inode, __u32 *fh, int *lenp,
962 struct inode *parent)
Rasmus Rohde221e5832008-04-30 17:22:06 +0200963{
964 int len = *lenp;
Pekka Enberg5ca4e4b2008-10-15 12:28:03 +0200965 struct kernel_lb_addr location = UDF_I(inode)->i_location;
Rasmus Rohde221e5832008-04-30 17:22:06 +0200966 struct fid *fid = (struct fid *)fh;
967 int type = FILEID_UDF_WITHOUT_PARENT;
968
Al Virob0b03822012-04-02 14:34:06 -0400969 if (parent && (len < 5)) {
Aneesh Kumar K.V5fe0c232011-01-29 18:43:25 +0530970 *lenp = 5;
Namjae Jeon94e07a752013-02-17 15:48:11 +0900971 return FILEID_INVALID;
Aneesh Kumar K.V5fe0c232011-01-29 18:43:25 +0530972 } else if (len < 3) {
973 *lenp = 3;
Namjae Jeon94e07a752013-02-17 15:48:11 +0900974 return FILEID_INVALID;
Aneesh Kumar K.V5fe0c232011-01-29 18:43:25 +0530975 }
Rasmus Rohde221e5832008-04-30 17:22:06 +0200976
977 *lenp = 3;
978 fid->udf.block = location.logicalBlockNum;
979 fid->udf.partref = location.partitionReferenceNum;
Mathias Krause0143fc52012-07-12 08:46:55 +0200980 fid->udf.parent_partref = 0;
Rasmus Rohde221e5832008-04-30 17:22:06 +0200981 fid->udf.generation = inode->i_generation;
982
Al Virob0b03822012-04-02 14:34:06 -0400983 if (parent) {
984 location = UDF_I(parent)->i_location;
Rasmus Rohde221e5832008-04-30 17:22:06 +0200985 fid->udf.parent_block = location.logicalBlockNum;
986 fid->udf.parent_partref = location.partitionReferenceNum;
987 fid->udf.parent_generation = inode->i_generation;
Rasmus Rohde221e5832008-04-30 17:22:06 +0200988 *lenp = 5;
989 type = FILEID_UDF_WITH_PARENT;
990 }
991
992 return type;
993}
994
995const struct export_operations udf_export_ops = {
996 .encode_fh = udf_encode_fh,
997 .fh_to_dentry = udf_fh_to_dentry,
998 .fh_to_parent = udf_fh_to_parent,
999 .get_parent = udf_get_parent,
1000};
1001
Arjan van de Venc5ef1c42007-02-12 00:55:40 -08001002const struct inode_operations udf_dir_inode_operations = {
Cyrill Gorcunov28de7942007-07-21 04:37:18 -07001003 .lookup = udf_lookup,
1004 .create = udf_create,
1005 .link = udf_link,
1006 .unlink = udf_unlink,
1007 .symlink = udf_symlink,
1008 .mkdir = udf_mkdir,
1009 .rmdir = udf_rmdir,
1010 .mknod = udf_mknod,
1011 .rename = udf_rename,
Al Viro656d09d2013-06-12 09:35:33 +04001012 .tmpfile = udf_tmpfile,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013};