15ce34554SBagas Sanjaya // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * namei.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * PURPOSE
61da177e4SLinus Torvalds * Inode name handling routines for the OSTA-UDF(tm) filesystem.
71da177e4SLinus Torvalds *
81da177e4SLinus Torvalds * COPYRIGHT
91da177e4SLinus Torvalds * (C) 1998-2004 Ben Fennema
101da177e4SLinus Torvalds * (C) 1999-2000 Stelias Computing Inc
111da177e4SLinus Torvalds *
121da177e4SLinus Torvalds * HISTORY
131da177e4SLinus Torvalds *
141da177e4SLinus Torvalds * 12/12/98 blf Created. Split out the lookup code from dir.c
151da177e4SLinus Torvalds * 04/19/99 blf link, mknod, symlink support
161da177e4SLinus Torvalds */
171da177e4SLinus Torvalds
181da177e4SLinus Torvalds #include "udfdecl.h"
191da177e4SLinus Torvalds
201da177e4SLinus Torvalds #include "udf_i.h"
211da177e4SLinus Torvalds #include "udf_sb.h"
221da177e4SLinus Torvalds #include <linux/string.h>
231da177e4SLinus Torvalds #include <linux/errno.h>
241da177e4SLinus Torvalds #include <linux/mm.h>
251da177e4SLinus Torvalds #include <linux/slab.h>
26e8edc6e0SAlexey Dobriyan #include <linux/sched.h>
27f845fcedSBob Copeland #include <linux/crc-itu-t.h>
28221e583aSRasmus Rohde #include <linux/exportfs.h>
29a48fc69fSJan Kara #include <linux/iversion.h>
301da177e4SLinus Torvalds
udf_match(int len1,const unsigned char * name1,int len2,const unsigned char * name2)31391e8bbdSAl Viro static inline int udf_match(int len1, const unsigned char *name1, int len2,
32391e8bbdSAl Viro const unsigned char *name2)
331da177e4SLinus Torvalds {
341da177e4SLinus Torvalds if (len1 != len2)
351da177e4SLinus Torvalds return 0;
3628de7948SCyrill Gorcunov
371da177e4SLinus Torvalds return !memcmp(name1, name2, len1);
381da177e4SLinus Torvalds }
391da177e4SLinus Torvalds
40231473f6SFabian Frederick /**
411c80afa0SJan Kara * udf_fiiter_find_entry - find entry in given directory.
42231473f6SFabian Frederick *
43231473f6SFabian Frederick * @dir: directory inode to search in
44231473f6SFabian Frederick * @child: qstr of the name
451c80afa0SJan Kara * @iter: iter to use for searching
46231473f6SFabian Frederick *
47231473f6SFabian Frederick * This function searches in the directory @dir for a file name @child. When
481c80afa0SJan Kara * found, @iter points to the position in the directory with given entry.
49231473f6SFabian Frederick *
501c80afa0SJan Kara * Returns 0 on success, < 0 on error (including -ENOENT).
51231473f6SFabian Frederick */
udf_fiiter_find_entry(struct inode * dir,const struct qstr * child,struct udf_fileident_iter * iter)521c80afa0SJan Kara static int udf_fiiter_find_entry(struct inode *dir, const struct qstr *child,
531c80afa0SJan Kara struct udf_fileident_iter *iter)
541da177e4SLinus Torvalds {
55b490bdd6SSteve Magnani int flen;
561c80afa0SJan Kara unsigned char *fname = NULL;
571c80afa0SJan Kara struct super_block *sb = dir->i_sb;
589fbb76ceSAl Viro int isdotdot = child->len == 2 &&
599fbb76ceSAl Viro child->name[0] == '.' && child->name[1] == '.';
601c80afa0SJan Kara int ret;
61b80697c1SJan Kara
62b80697c1SJan Kara fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
631c80afa0SJan Kara if (!fname)
641c80afa0SJan Kara return -ENOMEM;
651da177e4SLinus Torvalds
661c80afa0SJan Kara for (ret = udf_fiiter_init(iter, dir, 0);
671c80afa0SJan Kara !ret && iter->pos < dir->i_size;
681c80afa0SJan Kara ret = udf_fiiter_advance(iter)) {
691c80afa0SJan Kara if (iter->fi.fileCharacteristics & FID_FILE_CHAR_DELETED) {
703ee3039cSJan Kara if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE))
711da177e4SLinus Torvalds continue;
721da177e4SLinus Torvalds }
731da177e4SLinus Torvalds
741c80afa0SJan Kara if (iter->fi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) {
753ee3039cSJan Kara if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE))
761da177e4SLinus Torvalds continue;
771da177e4SLinus Torvalds }
781da177e4SLinus Torvalds
791c80afa0SJan Kara if ((iter->fi.fileCharacteristics & FID_FILE_CHAR_PARENT) &&
80a4264b3fSJesper Juhl isdotdot)
81a4264b3fSJesper Juhl goto out_ok;
82221e583aSRasmus Rohde
831c80afa0SJan Kara if (!iter->fi.lengthFileIdent)
841da177e4SLinus Torvalds continue;
851da177e4SLinus Torvalds
861c80afa0SJan Kara flen = udf_get_filename(sb, iter->name,
871c80afa0SJan Kara iter->fi.lengthFileIdent, fname, UDF_NAME_LEN);
88231473f6SFabian Frederick if (flen < 0) {
891c80afa0SJan Kara ret = flen;
90231473f6SFabian Frederick goto out_err;
91231473f6SFabian Frederick }
92231473f6SFabian Frederick
93231473f6SFabian Frederick if (udf_match(flen, fname, child->len, child->name))
94b80697c1SJan Kara goto out_ok;
951da177e4SLinus Torvalds }
961c80afa0SJan Kara if (!ret)
971c80afa0SJan Kara ret = -ENOENT;
9828de7948SCyrill Gorcunov
99231473f6SFabian Frederick out_err:
1001c80afa0SJan Kara udf_fiiter_release(iter);
101b80697c1SJan Kara out_ok:
102b80697c1SJan Kara kfree(fname);
10328de7948SCyrill Gorcunov
1041c80afa0SJan Kara return ret;
1051da177e4SLinus Torvalds }
1061da177e4SLinus Torvalds
udf_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)107cb00ea35SCyrill Gorcunov static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
10800cd8dd3SAl Viro unsigned int flags)
1091da177e4SLinus Torvalds {
1101da177e4SLinus Torvalds struct inode *inode = NULL;
111200918b3SJan Kara struct udf_fileident_iter iter;
112200918b3SJan Kara int err;
1131da177e4SLinus Torvalds
1149fba7056SAndrew Gabbasov if (dentry->d_name.len > UDF_NAME_LEN)
1151da177e4SLinus Torvalds return ERR_PTR(-ENAMETOOLONG);
1161da177e4SLinus Torvalds
117200918b3SJan Kara err = udf_fiiter_find_entry(dir, &dentry->d_name, &iter);
118200918b3SJan Kara if (err < 0 && err != -ENOENT)
119200918b3SJan Kara return ERR_PTR(err);
120231473f6SFabian Frederick
121200918b3SJan Kara if (err == 0) {
12297e961fdSPekka Enberg struct kernel_lb_addr loc;
12397e961fdSPekka Enberg
124200918b3SJan Kara loc = lelb_to_cpu(iter.fi.icb.extLocation);
125200918b3SJan Kara udf_fiiter_release(&iter);
1261da177e4SLinus Torvalds
12797e961fdSPekka Enberg inode = udf_iget(dir->i_sb, &loc);
1286d3d5e86SJan Kara if (IS_ERR(inode))
1296d3d5e86SJan Kara return ERR_CAST(inode);
1301da177e4SLinus Torvalds }
13128de7948SCyrill Gorcunov
132221e583aSRasmus Rohde return d_splice_alias(inode, dentry);
1331da177e4SLinus Torvalds }
1341da177e4SLinus Torvalds
udf_expand_dir_adinicb(struct inode * inode,udf_pblk_t * block)135f386c802SJan Kara static int udf_expand_dir_adinicb(struct inode *inode, udf_pblk_t *block)
1361da177e4SLinus Torvalds {
137a27b2923SJan Kara udf_pblk_t newblock;
138a27b2923SJan Kara struct buffer_head *dbh = NULL;
1395ca4e4beSPekka Enberg struct kernel_lb_addr eloc;
140a27b2923SJan Kara struct extent_position epos;
141a27b2923SJan Kara uint8_t alloctype;
142a27b2923SJan Kara struct udf_inode_info *iinfo = UDF_I(inode);
143a27b2923SJan Kara struct udf_fileident_iter iter;
144a27b2923SJan Kara uint8_t *impuse;
145a27b2923SJan Kara int ret;
1461da177e4SLinus Torvalds
147a27b2923SJan Kara if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
148a27b2923SJan Kara alloctype = ICBTAG_FLAG_AD_SHORT;
149a27b2923SJan Kara else
150a27b2923SJan Kara alloctype = ICBTAG_FLAG_AD_LONG;
151a27b2923SJan Kara
152a27b2923SJan Kara if (!inode->i_size) {
153a27b2923SJan Kara iinfo->i_alloc_type = alloctype;
154a27b2923SJan Kara mark_inode_dirty(inode);
155f386c802SJan Kara return 0;
156b80697c1SJan Kara }
157b80697c1SJan Kara
158a27b2923SJan Kara /* alloc block, and copy data to it */
159a27b2923SJan Kara *block = udf_new_block(inode->i_sb, inode,
160a27b2923SJan Kara iinfo->i_location.partitionReferenceNum,
161f386c802SJan Kara iinfo->i_location.logicalBlockNum, &ret);
162a27b2923SJan Kara if (!(*block))
163f386c802SJan Kara return ret;
164a27b2923SJan Kara newblock = udf_get_pblock(inode->i_sb, *block,
165a27b2923SJan Kara iinfo->i_location.partitionReferenceNum,
166a27b2923SJan Kara 0);
167f386c802SJan Kara if (newblock == 0xffffffff)
168f386c802SJan Kara return -EFSCORRUPTED;
169101ee137SJan Kara dbh = sb_getblk(inode->i_sb, newblock);
170a27b2923SJan Kara if (!dbh)
171f386c802SJan Kara return -ENOMEM;
172a27b2923SJan Kara lock_buffer(dbh);
173a27b2923SJan Kara memcpy(dbh->b_data, iinfo->i_data, inode->i_size);
174a27b2923SJan Kara memset(dbh->b_data + inode->i_size, 0,
175a27b2923SJan Kara inode->i_sb->s_blocksize - inode->i_size);
176a27b2923SJan Kara set_buffer_uptodate(dbh);
177a27b2923SJan Kara unlock_buffer(dbh);
178a27b2923SJan Kara
179a27b2923SJan Kara /* Drop inline data, add block instead */
180a27b2923SJan Kara iinfo->i_alloc_type = alloctype;
181a27b2923SJan Kara memset(iinfo->i_data + iinfo->i_lenEAttr, 0, iinfo->i_lenAlloc);
182a27b2923SJan Kara iinfo->i_lenAlloc = 0;
183a27b2923SJan Kara eloc.logicalBlockNum = *block;
184a27b2923SJan Kara eloc.partitionReferenceNum =
185a27b2923SJan Kara iinfo->i_location.partitionReferenceNum;
186a27b2923SJan Kara iinfo->i_lenExtents = inode->i_size;
187a27b2923SJan Kara epos.bh = NULL;
188a27b2923SJan Kara epos.block = iinfo->i_location;
189a27b2923SJan Kara epos.offset = udf_file_entry_alloc_offset(inode);
19033e9a53cSJan Kara ret = udf_add_aext(inode, &epos, &eloc, inode->i_size, 0);
191a27b2923SJan Kara brelse(epos.bh);
19233e9a53cSJan Kara if (ret < 0) {
193f386c802SJan Kara brelse(dbh);
19433e9a53cSJan Kara udf_free_blocks(inode->i_sb, inode, &eloc, 0, 1);
195f386c802SJan Kara return ret;
19633e9a53cSJan Kara }
197a27b2923SJan Kara mark_inode_dirty(inode);
198a27b2923SJan Kara
199a27b2923SJan Kara /* Now fixup tags in moved directory entries */
200a27b2923SJan Kara for (ret = udf_fiiter_init(&iter, inode, 0);
201a27b2923SJan Kara !ret && iter.pos < inode->i_size;
202a27b2923SJan Kara ret = udf_fiiter_advance(&iter)) {
203a27b2923SJan Kara iter.fi.descTag.tagLocation = cpu_to_le32(*block);
204a27b2923SJan Kara if (iter.fi.lengthOfImpUse != cpu_to_le16(0))
205a27b2923SJan Kara impuse = dbh->b_data + iter.pos +
206a27b2923SJan Kara sizeof(struct fileIdentDesc);
207a27b2923SJan Kara else
208a27b2923SJan Kara impuse = NULL;
209a27b2923SJan Kara udf_fiiter_write_fi(&iter, impuse);
210a27b2923SJan Kara }
211f386c802SJan Kara brelse(dbh);
212a27b2923SJan Kara /*
213a27b2923SJan Kara * We don't expect the iteration to fail as the directory has been
214a27b2923SJan Kara * already verified to be correct
215a27b2923SJan Kara */
216a27b2923SJan Kara WARN_ON_ONCE(ret);
217a27b2923SJan Kara udf_fiiter_release(&iter);
218a27b2923SJan Kara
219f386c802SJan Kara return 0;
220a27b2923SJan Kara }
221a27b2923SJan Kara
udf_fiiter_add_entry(struct inode * dir,struct dentry * dentry,struct udf_fileident_iter * iter)222f2844803SJan Kara static int udf_fiiter_add_entry(struct inode *dir, struct dentry *dentry,
223f2844803SJan Kara struct udf_fileident_iter *iter)
224f2844803SJan Kara {
225f2844803SJan Kara struct udf_inode_info *dinfo = UDF_I(dir);
226f2844803SJan Kara int nfidlen, namelen = 0;
227f2844803SJan Kara int ret;
228f2844803SJan Kara int off, blksize = 1 << dir->i_blkbits;
229f2844803SJan Kara udf_pblk_t block;
230f2844803SJan Kara char name[UDF_NAME_LEN_CS0];
231f2844803SJan Kara
232cb00ea35SCyrill Gorcunov if (dentry) {
233f2844803SJan Kara if (!dentry->d_name.len)
234f2844803SJan Kara return -EINVAL;
235f2844803SJan Kara namelen = udf_put_filename(dir->i_sb, dentry->d_name.name,
236525e2c56SAndrew Gabbasov dentry->d_name.len,
2379fba7056SAndrew Gabbasov name, UDF_NAME_LEN_CS0);
238f2844803SJan Kara if (!namelen)
239f2844803SJan Kara return -ENAMETOOLONG;
2401da177e4SLinus Torvalds }
241f2e83347SJan Kara nfidlen = ALIGN(sizeof(struct fileIdentDesc) + namelen, UDF_NAME_PAD);
2421da177e4SLinus Torvalds
243f2844803SJan Kara for (ret = udf_fiiter_init(iter, dir, 0);
244f2844803SJan Kara !ret && iter->pos < dir->i_size;
245f2844803SJan Kara ret = udf_fiiter_advance(iter)) {
246f2844803SJan Kara if (iter->fi.fileCharacteristics & FID_FILE_CHAR_DELETED) {
247f2844803SJan Kara if (udf_dir_entry_len(&iter->fi) == nfidlen) {
248f2844803SJan Kara iter->fi.descTag.tagSerialNum = cpu_to_le16(1);
249f2844803SJan Kara iter->fi.fileVersionNum = cpu_to_le16(1);
250f2844803SJan Kara iter->fi.fileCharacteristics = 0;
251f2844803SJan Kara iter->fi.lengthFileIdent = namelen;
252f2844803SJan Kara iter->fi.lengthOfImpUse = cpu_to_le16(0);
253f2844803SJan Kara memcpy(iter->namebuf, name, namelen);
254f2844803SJan Kara iter->name = iter->namebuf;
255f2844803SJan Kara return 0;
2561da177e4SLinus Torvalds }
2571da177e4SLinus Torvalds }
2581da177e4SLinus Torvalds }
259f2844803SJan Kara if (ret) {
260f2844803SJan Kara udf_fiiter_release(iter);
261f2844803SJan Kara return ret;
2621da177e4SLinus Torvalds }
26348d6d8ffSMarcin Slusarz if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB &&
264f2844803SJan Kara blksize - udf_ext0_offset(dir) - iter->pos < nfidlen) {
265f2844803SJan Kara udf_fiiter_release(iter);
266f386c802SJan Kara ret = udf_expand_dir_adinicb(dir, &block);
267f386c802SJan Kara if (ret)
268f2844803SJan Kara return ret;
269f2844803SJan Kara ret = udf_fiiter_init(iter, dir, dir->i_size);
270f2844803SJan Kara if (ret < 0)
271f2844803SJan Kara return ret;
2721da177e4SLinus Torvalds }
2731da177e4SLinus Torvalds
274f2844803SJan Kara /* Get blocknumber to use for entry tag */
27548d6d8ffSMarcin Slusarz if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
27648d6d8ffSMarcin Slusarz block = dinfo->i_location.logicalBlockNum;
277cb00ea35SCyrill Gorcunov } else {
278f2844803SJan Kara block = iter->eloc.logicalBlockNum +
279f2844803SJan Kara ((iter->elen - 1) >> dir->i_blkbits);
2801da177e4SLinus Torvalds }
281f2844803SJan Kara off = iter->pos & (blksize - 1);
282f2844803SJan Kara if (!off)
283f2844803SJan Kara off = blksize;
284f2844803SJan Kara /* Entry fits into current block? */
285f2844803SJan Kara if (blksize - udf_ext0_offset(dir) - off >= nfidlen)
286f2844803SJan Kara goto store_fi;
2872c948b3fSJan Kara
288f2844803SJan Kara ret = udf_fiiter_append_blk(iter);
289f2844803SJan Kara if (ret) {
290f2844803SJan Kara udf_fiiter_release(iter);
291f2844803SJan Kara return ret;
2921da177e4SLinus Torvalds }
2931da177e4SLinus Torvalds
294f2844803SJan Kara /* Entry will be completely in the new block? Update tag location... */
295f2844803SJan Kara if (!(iter->pos & (blksize - 1)))
296f2844803SJan Kara block = iter->eloc.logicalBlockNum +
297f2844803SJan Kara ((iter->elen - 1) >> dir->i_blkbits);
298f2844803SJan Kara store_fi:
299f2844803SJan Kara memset(&iter->fi, 0, sizeof(struct fileIdentDesc));
300f2844803SJan Kara if (UDF_SB(dir->i_sb)->s_udfrev >= 0x0200)
301f2844803SJan Kara udf_new_tag((char *)(&iter->fi), TAG_IDENT_FID, 3, 1, block,
3025ca4e4beSPekka Enberg sizeof(struct tag));
3031da177e4SLinus Torvalds else
304f2844803SJan Kara udf_new_tag((char *)(&iter->fi), TAG_IDENT_FID, 2, 1, block,
3055ca4e4beSPekka Enberg sizeof(struct tag));
306f2844803SJan Kara iter->fi.fileVersionNum = cpu_to_le16(1);
307f2844803SJan Kara iter->fi.lengthFileIdent = namelen;
308f2844803SJan Kara iter->fi.lengthOfImpUse = cpu_to_le16(0);
309f2844803SJan Kara memcpy(iter->namebuf, name, namelen);
310f2844803SJan Kara iter->name = iter->namebuf;
311f2844803SJan Kara
3121da177e4SLinus Torvalds dir->i_size += nfidlen;
313f2844803SJan Kara if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
31448d6d8ffSMarcin Slusarz dinfo->i_lenAlloc += nfidlen;
315cb00ea35SCyrill Gorcunov } else {
316f2844803SJan Kara /* Truncate last extent to proper size */
317f2844803SJan Kara udf_fiiter_update_elen(iter, iter->elen -
318f2844803SJan Kara (dinfo->i_lenExtents - dir->i_size));
319f2844803SJan Kara }
320f2844803SJan Kara mark_inode_dirty(dir);
321f2844803SJan Kara
322f2844803SJan Kara return 0;
323b80697c1SJan Kara }
324b80697c1SJan Kara
udf_fiiter_delete_entry(struct udf_fileident_iter * iter)3254cca7e3dSJan Kara static void udf_fiiter_delete_entry(struct udf_fileident_iter *iter)
3261da177e4SLinus Torvalds {
3274cca7e3dSJan Kara iter->fi.fileCharacteristics |= FID_FILE_CHAR_DELETED;
32828de7948SCyrill Gorcunov
3294cca7e3dSJan Kara if (UDF_QUERY_FLAG(iter->dir->i_sb, UDF_FLAG_STRICT))
3304cca7e3dSJan Kara memset(&iter->fi.icb, 0x00, sizeof(struct long_ad));
33128de7948SCyrill Gorcunov
3324cca7e3dSJan Kara udf_fiiter_write_fi(iter, NULL);
3334cca7e3dSJan Kara }
3344cca7e3dSJan Kara
udf_add_fid_counter(struct super_block * sb,bool dir,int val)335085cf7b7SJan Kara static void udf_add_fid_counter(struct super_block *sb, bool dir, int val)
336085cf7b7SJan Kara {
337085cf7b7SJan Kara struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb);
338085cf7b7SJan Kara
339085cf7b7SJan Kara if (!lvidiu)
340085cf7b7SJan Kara return;
341085cf7b7SJan Kara mutex_lock(&UDF_SB(sb)->s_alloc_mutex);
342085cf7b7SJan Kara if (dir)
343085cf7b7SJan Kara le32_add_cpu(&lvidiu->numDirs, val);
344085cf7b7SJan Kara else
345085cf7b7SJan Kara le32_add_cpu(&lvidiu->numFiles, val);
346085cf7b7SJan Kara udf_updated_lvid(sb);
347085cf7b7SJan Kara mutex_unlock(&UDF_SB(sb)->s_alloc_mutex);
3481da177e4SLinus Torvalds }
3491da177e4SLinus Torvalds
udf_add_nondir(struct dentry * dentry,struct inode * inode)350d2be51cbSAl Viro static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
3511da177e4SLinus Torvalds {
352d2be51cbSAl Viro struct udf_inode_info *iinfo = UDF_I(inode);
3532b0143b5SDavid Howells struct inode *dir = d_inode(dentry->d_parent);
354ef91f999SJan Kara struct udf_fileident_iter iter;
3551da177e4SLinus Torvalds int err;
3561da177e4SLinus Torvalds
357ef91f999SJan Kara err = udf_fiiter_add_entry(dir, dentry, &iter);
358ef91f999SJan Kara if (err) {
3596d6b77f1SMiklos Szeredi inode_dec_link_count(inode);
3605c1a68a3SAl Viro discard_new_inode(inode);
3611da177e4SLinus Torvalds return err;
3621da177e4SLinus Torvalds }
363ef91f999SJan Kara iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
364ef91f999SJan Kara iter.fi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
365ef91f999SJan Kara *(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse =
36648d6d8ffSMarcin Slusarz cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
367ef91f999SJan Kara udf_fiiter_write_fi(&iter, NULL);
36859ad88f2SJeff Layton dir->i_mtime = inode_set_ctime_current(dir);
3691da177e4SLinus Torvalds mark_inode_dirty(dir);
370ef91f999SJan Kara udf_fiiter_release(&iter);
371085cf7b7SJan Kara udf_add_fid_counter(dir->i_sb, false, 1);
3721e2e547aSAl Viro d_instantiate_new(dentry, inode);
37328de7948SCyrill Gorcunov
3741da177e4SLinus Torvalds return 0;
3751da177e4SLinus Torvalds }
3761da177e4SLinus Torvalds
udf_create(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode,bool excl)3776c960e68SChristian Brauner static int udf_create(struct mnt_idmap *idmap, struct inode *dir,
378549c7297SChristian Brauner struct dentry *dentry, umode_t mode, bool excl)
379d2be51cbSAl Viro {
3800b93a92bSAl Viro struct inode *inode = udf_new_inode(dir, mode);
381d2be51cbSAl Viro
3820b93a92bSAl Viro if (IS_ERR(inode))
3830b93a92bSAl Viro return PTR_ERR(inode);
384d2be51cbSAl Viro
385d2be51cbSAl Viro inode->i_data.a_ops = &udf_aops;
386d2be51cbSAl Viro inode->i_op = &udf_file_inode_operations;
387d2be51cbSAl Viro inode->i_fop = &udf_file_operations;
388d2be51cbSAl Viro mark_inode_dirty(inode);
389d2be51cbSAl Viro
390d2be51cbSAl Viro return udf_add_nondir(dentry, inode);
391d2be51cbSAl Viro }
392d2be51cbSAl Viro
udf_tmpfile(struct mnt_idmap * idmap,struct inode * dir,struct file * file,umode_t mode)393011e2b71SChristian Brauner static int udf_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
394863f144fSMiklos Szeredi struct file *file, umode_t mode)
395656d09dfSAl Viro {
3960b93a92bSAl Viro struct inode *inode = udf_new_inode(dir, mode);
397656d09dfSAl Viro
3980b93a92bSAl Viro if (IS_ERR(inode))
3990b93a92bSAl Viro return PTR_ERR(inode);
400656d09dfSAl Viro
401656d09dfSAl Viro inode->i_data.a_ops = &udf_aops;
402656d09dfSAl Viro inode->i_op = &udf_file_inode_operations;
403656d09dfSAl Viro inode->i_fop = &udf_file_operations;
404656d09dfSAl Viro mark_inode_dirty(inode);
405863f144fSMiklos Szeredi d_tmpfile(file, inode);
406b2315096SAl Viro unlock_new_inode(inode);
407863f144fSMiklos Szeredi return finish_open_simple(file, 0);
408656d09dfSAl Viro }
409656d09dfSAl Viro
udf_mknod(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode,dev_t rdev)4105ebb29beSChristian Brauner static int udf_mknod(struct mnt_idmap *idmap, struct inode *dir,
411549c7297SChristian Brauner struct dentry *dentry, umode_t mode, dev_t rdev)
4121da177e4SLinus Torvalds {
4131da177e4SLinus Torvalds struct inode *inode;
4141da177e4SLinus Torvalds
4151da177e4SLinus Torvalds if (!old_valid_dev(rdev))
4161da177e4SLinus Torvalds return -EINVAL;
4171da177e4SLinus Torvalds
4180b93a92bSAl Viro inode = udf_new_inode(dir, mode);
4190b93a92bSAl Viro if (IS_ERR(inode))
4200b93a92bSAl Viro return PTR_ERR(inode);
4211da177e4SLinus Torvalds
4221da177e4SLinus Torvalds init_special_inode(inode, mode, rdev);
423d2be51cbSAl Viro return udf_add_nondir(dentry, inode);
4241da177e4SLinus Torvalds }
4251da177e4SLinus Torvalds
udf_mkdir(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode)426c54bd91eSChristian Brauner static int udf_mkdir(struct mnt_idmap *idmap, struct inode *dir,
427549c7297SChristian Brauner struct dentry *dentry, umode_t mode)
4281da177e4SLinus Torvalds {
4291da177e4SLinus Torvalds struct inode *inode;
43000bce6f7SJan Kara struct udf_fileident_iter iter;
4311da177e4SLinus Torvalds int err;
43248d6d8ffSMarcin Slusarz struct udf_inode_info *dinfo = UDF_I(dir);
43348d6d8ffSMarcin Slusarz struct udf_inode_info *iinfo;
4341da177e4SLinus Torvalds
4350b93a92bSAl Viro inode = udf_new_inode(dir, S_IFDIR | mode);
4360b93a92bSAl Viro if (IS_ERR(inode))
4370b93a92bSAl Viro return PTR_ERR(inode);
4381da177e4SLinus Torvalds
43948d6d8ffSMarcin Slusarz iinfo = UDF_I(inode);
4401da177e4SLinus Torvalds inode->i_op = &udf_dir_inode_operations;
4411da177e4SLinus Torvalds inode->i_fop = &udf_dir_operations;
44200bce6f7SJan Kara err = udf_fiiter_add_entry(inode, NULL, &iter);
44300bce6f7SJan Kara if (err) {
44400bce6f7SJan Kara clear_nlink(inode);
4455c1a68a3SAl Viro discard_new_inode(inode);
44600bce6f7SJan Kara return err;
4471da177e4SLinus Torvalds }
448bfe86848SMiklos Szeredi set_nlink(inode, 2);
44900bce6f7SJan Kara iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
45000bce6f7SJan Kara iter.fi.icb.extLocation = cpu_to_lelb(dinfo->i_location);
45100bce6f7SJan Kara *(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse =
45248d6d8ffSMarcin Slusarz cpu_to_le32(dinfo->i_unique & 0x00000000FFFFFFFFUL);
45300bce6f7SJan Kara iter.fi.fileCharacteristics =
4544b11111aSMarcin Slusarz FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT;
45500bce6f7SJan Kara udf_fiiter_write_fi(&iter, NULL);
45600bce6f7SJan Kara udf_fiiter_release(&iter);
4571da177e4SLinus Torvalds mark_inode_dirty(inode);
4581da177e4SLinus Torvalds
45900bce6f7SJan Kara err = udf_fiiter_add_entry(dir, dentry, &iter);
46000bce6f7SJan Kara if (err) {
4616d6b77f1SMiklos Szeredi clear_nlink(inode);
4625c1a68a3SAl Viro discard_new_inode(inode);
46300bce6f7SJan Kara return err;
4641da177e4SLinus Torvalds }
46500bce6f7SJan Kara iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
46600bce6f7SJan Kara iter.fi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
46700bce6f7SJan Kara *(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse =
46848d6d8ffSMarcin Slusarz cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
46900bce6f7SJan Kara iter.fi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
47000bce6f7SJan Kara udf_fiiter_write_fi(&iter, NULL);
47100bce6f7SJan Kara udf_fiiter_release(&iter);
472085cf7b7SJan Kara udf_add_fid_counter(dir->i_sb, true, 1);
473d8c76e6fSDave Hansen inc_nlink(dir);
47459ad88f2SJeff Layton dir->i_mtime = inode_set_ctime_current(dir);
4751da177e4SLinus Torvalds mark_inode_dirty(dir);
4761e2e547aSAl Viro d_instantiate_new(dentry, inode);
47728de7948SCyrill Gorcunov
47800bce6f7SJan Kara return 0;
4791da177e4SLinus Torvalds }
4801da177e4SLinus Torvalds
empty_dir(struct inode * dir)4811da177e4SLinus Torvalds static int empty_dir(struct inode *dir)
4821da177e4SLinus Torvalds {
483afb525f4SJan Kara struct udf_fileident_iter iter;
484afb525f4SJan Kara int ret;
4851da177e4SLinus Torvalds
486afb525f4SJan Kara for (ret = udf_fiiter_init(&iter, dir, 0);
487afb525f4SJan Kara !ret && iter.pos < dir->i_size;
488afb525f4SJan Kara ret = udf_fiiter_advance(&iter)) {
489afb525f4SJan Kara if (iter.fi.lengthFileIdent &&
490afb525f4SJan Kara !(iter.fi.fileCharacteristics & FID_FILE_CHAR_DELETED)) {
491afb525f4SJan Kara udf_fiiter_release(&iter);
4921da177e4SLinus Torvalds return 0;
4931da177e4SLinus Torvalds }
4941da177e4SLinus Torvalds }
495afb525f4SJan Kara udf_fiiter_release(&iter);
49628de7948SCyrill Gorcunov
4971da177e4SLinus Torvalds return 1;
4981da177e4SLinus Torvalds }
4991da177e4SLinus Torvalds
udf_rmdir(struct inode * dir,struct dentry * dentry)5001da177e4SLinus Torvalds static int udf_rmdir(struct inode *dir, struct dentry *dentry)
5011da177e4SLinus Torvalds {
502d11ffa8dSJan Kara int ret;
5032b0143b5SDavid Howells struct inode *inode = d_inode(dentry);
504d11ffa8dSJan Kara struct udf_fileident_iter iter;
5055ca4e4beSPekka Enberg struct kernel_lb_addr tloc;
5061da177e4SLinus Torvalds
507d11ffa8dSJan Kara ret = udf_fiiter_find_entry(dir, &dentry->d_name, &iter);
508d11ffa8dSJan Kara if (ret)
5091da177e4SLinus Torvalds goto out;
5101da177e4SLinus Torvalds
511d11ffa8dSJan Kara ret = -EFSCORRUPTED;
512d11ffa8dSJan Kara tloc = lelb_to_cpu(iter.fi.icb.extLocation);
51397e961fdSPekka Enberg if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino)
5141da177e4SLinus Torvalds goto end_rmdir;
515d11ffa8dSJan Kara ret = -ENOTEMPTY;
5161da177e4SLinus Torvalds if (!empty_dir(inode))
5171da177e4SLinus Torvalds goto end_rmdir;
518d11ffa8dSJan Kara udf_fiiter_delete_entry(&iter);
5191da177e4SLinus Torvalds if (inode->i_nlink != 2)
520fcbf7637SSteve Magnani udf_warn(inode->i_sb, "empty directory has nlink != 2 (%u)\n",
5211da177e4SLinus Torvalds inode->i_nlink);
522ce71ec36SDave Hansen clear_nlink(inode);
5231da177e4SLinus Torvalds inode->i_size = 0;
5243dea3c59SJan Kara if (dir->i_nlink >= 3)
525c007c06eSStephen Mollett inode_dec_link_count(dir);
5263dea3c59SJan Kara else
5273dea3c59SJan Kara udf_warn(inode->i_sb, "parent dir link count too low (%u)\n",
5283dea3c59SJan Kara dir->i_nlink);
529085cf7b7SJan Kara udf_add_fid_counter(dir->i_sb, true, -1);
53059ad88f2SJeff Layton dir->i_mtime = inode_set_ctime_to_ts(dir,
53159ad88f2SJeff Layton inode_set_ctime_current(inode));
5321da177e4SLinus Torvalds mark_inode_dirty(dir);
533d11ffa8dSJan Kara ret = 0;
5341da177e4SLinus Torvalds end_rmdir:
535d11ffa8dSJan Kara udf_fiiter_release(&iter);
5361da177e4SLinus Torvalds out:
537d11ffa8dSJan Kara return ret;
5381da177e4SLinus Torvalds }
5391da177e4SLinus Torvalds
udf_unlink(struct inode * dir,struct dentry * dentry)5401da177e4SLinus Torvalds static int udf_unlink(struct inode *dir, struct dentry *dentry)
5411da177e4SLinus Torvalds {
5426ec01a80SJan Kara int ret;
5432b0143b5SDavid Howells struct inode *inode = d_inode(dentry);
5446ec01a80SJan Kara struct udf_fileident_iter iter;
5455ca4e4beSPekka Enberg struct kernel_lb_addr tloc;
5461da177e4SLinus Torvalds
5476ec01a80SJan Kara ret = udf_fiiter_find_entry(dir, &dentry->d_name, &iter);
5486ec01a80SJan Kara if (ret)
5491da177e4SLinus Torvalds goto out;
5501da177e4SLinus Torvalds
5516ec01a80SJan Kara ret = -EFSCORRUPTED;
5526ec01a80SJan Kara tloc = lelb_to_cpu(iter.fi.icb.extLocation);
55397e961fdSPekka Enberg if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino)
5541da177e4SLinus Torvalds goto end_unlink;
5551da177e4SLinus Torvalds
556cb00ea35SCyrill Gorcunov if (!inode->i_nlink) {
557fcbf7637SSteve Magnani udf_debug("Deleting nonexistent file (%lu), %u\n",
5581da177e4SLinus Torvalds inode->i_ino, inode->i_nlink);
559bfe86848SMiklos Szeredi set_nlink(inode, 1);
5601da177e4SLinus Torvalds }
5616ec01a80SJan Kara udf_fiiter_delete_entry(&iter);
56259ad88f2SJeff Layton dir->i_mtime = inode_set_ctime_current(dir);
5631da177e4SLinus Torvalds mark_inode_dirty(dir);
5649a53c3a7SDave Hansen inode_dec_link_count(inode);
565085cf7b7SJan Kara udf_add_fid_counter(dir->i_sb, false, -1);
56659ad88f2SJeff Layton inode_set_ctime_to_ts(inode, inode_get_ctime(dir));
5676ec01a80SJan Kara ret = 0;
5681da177e4SLinus Torvalds end_unlink:
5696ec01a80SJan Kara udf_fiiter_release(&iter);
5701da177e4SLinus Torvalds out:
5716ec01a80SJan Kara return ret;
5721da177e4SLinus Torvalds }
5731da177e4SLinus Torvalds
udf_symlink(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,const char * symname)5747a77db95SChristian Brauner static int udf_symlink(struct mnt_idmap *idmap, struct inode *dir,
575549c7297SChristian Brauner struct dentry *dentry, const char *symname)
5761da177e4SLinus Torvalds {
5776ff6b2b3SFabian Frederick struct inode *inode = udf_new_inode(dir, S_IFLNK | 0777);
5781da177e4SLinus Torvalds struct pathComponent *pc;
579391e8bbdSAl Viro const char *compstart;
58028de7948SCyrill Gorcunov struct extent_position epos = {};
5811da177e4SLinus Torvalds int eoffset, elen = 0;
582391e8bbdSAl Viro uint8_t *ea;
5831da177e4SLinus Torvalds int err;
584b490bdd6SSteve Magnani udf_pblk_t block;
585391e8bbdSAl Viro unsigned char *name = NULL;
5861da177e4SLinus Torvalds int namelen;
58748d6d8ffSMarcin Slusarz struct udf_inode_info *iinfo;
588d664b6afSJan Kara struct super_block *sb = dir->i_sb;
5891da177e4SLinus Torvalds
5900b93a92bSAl Viro if (IS_ERR(inode))
5910b93a92bSAl Viro return PTR_ERR(inode);
5921da177e4SLinus Torvalds
5934d0fb621SAlessio Igor Bogani iinfo = UDF_I(inode);
5944d0fb621SAlessio Igor Bogani down_write(&iinfo->i_data_sem);
5959fba7056SAndrew Gabbasov name = kmalloc(UDF_NAME_LEN_CS0, GFP_NOFS);
596b80697c1SJan Kara if (!name) {
597b80697c1SJan Kara err = -ENOMEM;
598b80697c1SJan Kara goto out_no_entry;
599b80697c1SJan Kara }
600b80697c1SJan Kara
6011da177e4SLinus Torvalds inode->i_data.a_ops = &udf_symlink_aops;
602ad4d0532SJan Kara inode->i_op = &udf_symlink_inode_operations;
60321fc61c7SAl Viro inode_nohighmem(inode);
6041da177e4SLinus Torvalds
60548d6d8ffSMarcin Slusarz if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
6065ca4e4beSPekka Enberg struct kernel_lb_addr eloc;
60778e917d5SHarvey Harrison uint32_t bsize;
6081da177e4SLinus Torvalds
609d664b6afSJan Kara block = udf_new_block(sb, inode,
61048d6d8ffSMarcin Slusarz iinfo->i_location.partitionReferenceNum,
61148d6d8ffSMarcin Slusarz iinfo->i_location.logicalBlockNum, &err);
6121da177e4SLinus Torvalds if (!block)
6131da177e4SLinus Torvalds goto out_no_entry;
61448d6d8ffSMarcin Slusarz epos.block = iinfo->i_location;
615ff116fc8SJan Kara epos.offset = udf_file_entry_alloc_offset(inode);
616ff116fc8SJan Kara epos.bh = NULL;
6171da177e4SLinus Torvalds eloc.logicalBlockNum = block;
6184b11111aSMarcin Slusarz eloc.partitionReferenceNum =
61948d6d8ffSMarcin Slusarz iinfo->i_location.partitionReferenceNum;
620d664b6afSJan Kara bsize = sb->s_blocksize;
62178e917d5SHarvey Harrison iinfo->i_lenExtents = bsize;
6222b10074dSJan Kara err = udf_add_aext(inode, &epos, &eloc, bsize, 0);
6233bf25cb4SJan Kara brelse(epos.bh);
6242b10074dSJan Kara if (err < 0) {
6252b10074dSJan Kara udf_free_blocks(sb, inode, &eloc, 0, 1);
6262b10074dSJan Kara goto out_no_entry;
6272b10074dSJan Kara }
6281da177e4SLinus Torvalds
629d664b6afSJan Kara block = udf_get_pblock(sb, block,
63048d6d8ffSMarcin Slusarz iinfo->i_location.partitionReferenceNum,
6314b11111aSMarcin Slusarz 0);
632101ee137SJan Kara epos.bh = sb_getblk(sb, block);
633fa236c2bSArturo Giusti if (unlikely(!epos.bh)) {
634fa236c2bSArturo Giusti err = -ENOMEM;
6352b10074dSJan Kara udf_free_blocks(sb, inode, &eloc, 0, 1);
636fa236c2bSArturo Giusti goto out_no_entry;
637fa236c2bSArturo Giusti }
638ff116fc8SJan Kara lock_buffer(epos.bh);
639d664b6afSJan Kara memset(epos.bh->b_data, 0x00, bsize);
640ff116fc8SJan Kara set_buffer_uptodate(epos.bh);
641ff116fc8SJan Kara unlock_buffer(epos.bh);
642ff116fc8SJan Kara mark_buffer_dirty_inode(epos.bh, inode);
643ff116fc8SJan Kara ea = epos.bh->b_data + udf_ext0_offset(inode);
64448d6d8ffSMarcin Slusarz } else
645382a2287SJan Kara ea = iinfo->i_data + iinfo->i_lenEAttr;
6461da177e4SLinus Torvalds
647d664b6afSJan Kara eoffset = sb->s_blocksize - udf_ext0_offset(inode);
6481da177e4SLinus Torvalds pc = (struct pathComponent *)ea;
6491da177e4SLinus Torvalds
650cb00ea35SCyrill Gorcunov if (*symname == '/') {
651cb00ea35SCyrill Gorcunov do {
6521da177e4SLinus Torvalds symname++;
6531da177e4SLinus Torvalds } while (*symname == '/');
6541da177e4SLinus Torvalds
6551da177e4SLinus Torvalds pc->componentType = 1;
6561da177e4SLinus Torvalds pc->lengthComponentIdent = 0;
6571da177e4SLinus Torvalds pc->componentFileVersionNum = 0;
6581da177e4SLinus Torvalds elen += sizeof(struct pathComponent);
6591da177e4SLinus Torvalds }
6601da177e4SLinus Torvalds
6611da177e4SLinus Torvalds err = -ENAMETOOLONG;
6621da177e4SLinus Torvalds
663cb00ea35SCyrill Gorcunov while (*symname) {
6641da177e4SLinus Torvalds if (elen + sizeof(struct pathComponent) > eoffset)
6651da177e4SLinus Torvalds goto out_no_entry;
6661da177e4SLinus Torvalds
6671da177e4SLinus Torvalds pc = (struct pathComponent *)(ea + elen);
6681da177e4SLinus Torvalds
669391e8bbdSAl Viro compstart = symname;
6701da177e4SLinus Torvalds
671cb00ea35SCyrill Gorcunov do {
6721da177e4SLinus Torvalds symname++;
6731da177e4SLinus Torvalds } while (*symname && *symname != '/');
6741da177e4SLinus Torvalds
6751da177e4SLinus Torvalds pc->componentType = 5;
6761da177e4SLinus Torvalds pc->lengthComponentIdent = 0;
6771da177e4SLinus Torvalds pc->componentFileVersionNum = 0;
678cb00ea35SCyrill Gorcunov if (compstart[0] == '.') {
6791da177e4SLinus Torvalds if ((symname - compstart) == 1)
6801da177e4SLinus Torvalds pc->componentType = 4;
6814b11111aSMarcin Slusarz else if ((symname - compstart) == 2 &&
6824b11111aSMarcin Slusarz compstart[1] == '.')
6831da177e4SLinus Torvalds pc->componentType = 3;
6841da177e4SLinus Torvalds }
6851da177e4SLinus Torvalds
686cb00ea35SCyrill Gorcunov if (pc->componentType == 5) {
687525e2c56SAndrew Gabbasov namelen = udf_put_filename(sb, compstart,
688525e2c56SAndrew Gabbasov symname - compstart,
6899fba7056SAndrew Gabbasov name, UDF_NAME_LEN_CS0);
69028de7948SCyrill Gorcunov if (!namelen)
6911da177e4SLinus Torvalds goto out_no_entry;
6921da177e4SLinus Torvalds
6934b11111aSMarcin Slusarz if (elen + sizeof(struct pathComponent) + namelen >
6944b11111aSMarcin Slusarz eoffset)
6951da177e4SLinus Torvalds goto out_no_entry;
6961da177e4SLinus Torvalds else
6971da177e4SLinus Torvalds pc->lengthComponentIdent = namelen;
6981da177e4SLinus Torvalds
6991da177e4SLinus Torvalds memcpy(pc->componentIdent, name, namelen);
7001da177e4SLinus Torvalds }
7011da177e4SLinus Torvalds
7021da177e4SLinus Torvalds elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
7031da177e4SLinus Torvalds
704cb00ea35SCyrill Gorcunov if (*symname) {
705cb00ea35SCyrill Gorcunov do {
7061da177e4SLinus Torvalds symname++;
7071da177e4SLinus Torvalds } while (*symname == '/');
7081da177e4SLinus Torvalds }
7091da177e4SLinus Torvalds }
7101da177e4SLinus Torvalds
7113bf25cb4SJan Kara brelse(epos.bh);
7121da177e4SLinus Torvalds inode->i_size = elen;
71348d6d8ffSMarcin Slusarz if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
71448d6d8ffSMarcin Slusarz iinfo->i_lenAlloc = inode->i_size;
7152c948b3fSJan Kara else
7162c948b3fSJan Kara udf_truncate_tail_extent(inode);
7171da177e4SLinus Torvalds mark_inode_dirty(inode);
7184ea7772fSJan Kara up_write(&iinfo->i_data_sem);
7191da177e4SLinus Torvalds
720d2be51cbSAl Viro err = udf_add_nondir(dentry, inode);
7211da177e4SLinus Torvalds out:
722b80697c1SJan Kara kfree(name);
7231da177e4SLinus Torvalds return err;
7241da177e4SLinus Torvalds
7251da177e4SLinus Torvalds out_no_entry:
7264d0fb621SAlessio Igor Bogani up_write(&iinfo->i_data_sem);
7279a53c3a7SDave Hansen inode_dec_link_count(inode);
7285c1a68a3SAl Viro discard_new_inode(inode);
7291da177e4SLinus Torvalds goto out;
7301da177e4SLinus Torvalds }
7311da177e4SLinus Torvalds
udf_link(struct dentry * old_dentry,struct inode * dir,struct dentry * dentry)7321da177e4SLinus Torvalds static int udf_link(struct dentry *old_dentry, struct inode *dir,
7331da177e4SLinus Torvalds struct dentry *dentry)
7341da177e4SLinus Torvalds {
7352b0143b5SDavid Howells struct inode *inode = d_inode(old_dentry);
736dbfb102dSJan Kara struct udf_fileident_iter iter;
7371da177e4SLinus Torvalds int err;
7381da177e4SLinus Torvalds
739dbfb102dSJan Kara err = udf_fiiter_add_entry(dir, dentry, &iter);
740dbfb102dSJan Kara if (err)
7411da177e4SLinus Torvalds return err;
742dbfb102dSJan Kara iter.fi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
743dbfb102dSJan Kara iter.fi.icb.extLocation = cpu_to_lelb(UDF_I(inode)->i_location);
744d664b6afSJan Kara if (UDF_SB(inode->i_sb)->s_lvid_bh) {
745dbfb102dSJan Kara *(__le32 *)((struct allocDescImpUse *)iter.fi.icb.impUse)->impUse =
746d664b6afSJan Kara cpu_to_le32(lvid_get_unique_id(inode->i_sb));
7471da177e4SLinus Torvalds }
748dbfb102dSJan Kara udf_fiiter_write_fi(&iter, NULL);
749dbfb102dSJan Kara udf_fiiter_release(&iter);
75028de7948SCyrill Gorcunov
751d8c76e6fSDave Hansen inc_nlink(inode);
752085cf7b7SJan Kara udf_add_fid_counter(dir->i_sb, false, 1);
75359ad88f2SJeff Layton inode_set_ctime_current(inode);
7541da177e4SLinus Torvalds mark_inode_dirty(inode);
75559ad88f2SJeff Layton dir->i_mtime = inode_set_ctime_current(dir);
7563adc12e9SJan Kara mark_inode_dirty(dir);
7577de9c6eeSAl Viro ihold(inode);
7581da177e4SLinus Torvalds d_instantiate(dentry, inode);
75928de7948SCyrill Gorcunov
7601da177e4SLinus Torvalds return 0;
7611da177e4SLinus Torvalds }
7621da177e4SLinus Torvalds
7631da177e4SLinus Torvalds /* Anybody can rename anything with this: the permission checks are left to the
7641da177e4SLinus Torvalds * higher-level routines.
7651da177e4SLinus Torvalds */
udf_rename(struct mnt_idmap * idmap,struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)766e18275aeSChristian Brauner static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir,
767549c7297SChristian Brauner struct dentry *old_dentry, struct inode *new_dir,
768549c7297SChristian Brauner struct dentry *new_dentry, unsigned int flags)
7691da177e4SLinus Torvalds {
7702b0143b5SDavid Howells struct inode *old_inode = d_inode(old_dentry);
7712b0143b5SDavid Howells struct inode *new_inode = d_inode(new_dentry);
772e9109a92SJan Kara struct udf_fileident_iter oiter, niter, diriter;
77317b312c5SAl Viro bool has_diriter = false, is_dir = false;
774e9109a92SJan Kara int retval;
7755ca4e4beSPekka Enberg struct kernel_lb_addr tloc;
7761da177e4SLinus Torvalds
777f03b8ad8SMiklos Szeredi if (flags & ~RENAME_NOREPLACE)
778f03b8ad8SMiklos Szeredi return -EINVAL;
779f03b8ad8SMiklos Szeredi
780e9109a92SJan Kara retval = udf_fiiter_find_entry(old_dir, &old_dentry->d_name, &oiter);
781e9109a92SJan Kara if (retval)
782e9109a92SJan Kara return retval;
783e9109a92SJan Kara
784e9109a92SJan Kara tloc = lelb_to_cpu(oiter.fi.icb.extLocation);
785e9109a92SJan Kara if (udf_get_lb_pblock(old_dir->i_sb, &tloc, 0) != old_inode->i_ino) {
786e9109a92SJan Kara retval = -ENOENT;
787e9109a92SJan Kara goto out_oiter;
788231473f6SFabian Frederick }
789231473f6SFabian Frederick
790cb00ea35SCyrill Gorcunov if (S_ISDIR(old_inode->i_mode)) {
791cb00ea35SCyrill Gorcunov if (new_inode) {
7921da177e4SLinus Torvalds retval = -ENOTEMPTY;
7931da177e4SLinus Torvalds if (!empty_dir(new_inode))
794e9109a92SJan Kara goto out_oiter;
795*b41d7305SJan Kara retval = -EFSCORRUPTED;
796*b41d7305SJan Kara if (new_inode->i_nlink != 2)
797*b41d7305SJan Kara goto out_oiter;
7981da177e4SLinus Torvalds }
799*b41d7305SJan Kara retval = -EFSCORRUPTED;
800*b41d7305SJan Kara if (old_dir->i_nlink < 3)
801*b41d7305SJan Kara goto out_oiter;
80217b312c5SAl Viro is_dir = true;
803*b41d7305SJan Kara } else if (new_inode) {
804*b41d7305SJan Kara retval = -EFSCORRUPTED;
805*b41d7305SJan Kara if (new_inode->i_nlink < 1)
806*b41d7305SJan Kara goto out_oiter;
80717b312c5SAl Viro }
80817b312c5SAl Viro if (is_dir && old_dir != new_dir) {
809e9109a92SJan Kara retval = udf_fiiter_find_entry(old_inode, &dotdot_name,
810e9109a92SJan Kara &diriter);
811e9109a92SJan Kara if (retval == -ENOENT) {
812e9109a92SJan Kara udf_err(old_inode->i_sb,
813e9109a92SJan Kara "directory (ino %lu) has no '..' entry\n",
814e9109a92SJan Kara old_inode->i_ino);
815e9109a92SJan Kara retval = -EFSCORRUPTED;
8161da177e4SLinus Torvalds }
8177517ce5dSJan Kara if (retval)
818e9109a92SJan Kara goto out_oiter;
819e9109a92SJan Kara has_diriter = true;
820e9109a92SJan Kara tloc = lelb_to_cpu(diriter.fi.icb.extLocation);
82197e961fdSPekka Enberg if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) !=
822e9109a92SJan Kara old_dir->i_ino) {
823e9109a92SJan Kara retval = -EFSCORRUPTED;
824e9109a92SJan Kara udf_err(old_inode->i_sb,
825e9109a92SJan Kara "directory (ino %lu) has parent entry pointing to another inode (%lu != %u)\n",
826e9109a92SJan Kara old_inode->i_ino, old_dir->i_ino,
827e9109a92SJan Kara udf_get_lb_pblock(old_inode->i_sb, &tloc, 0));
828e9109a92SJan Kara goto out_oiter;
8291da177e4SLinus Torvalds }
830e9109a92SJan Kara }
831e9109a92SJan Kara
832e9109a92SJan Kara retval = udf_fiiter_find_entry(new_dir, &new_dentry->d_name, &niter);
833e9109a92SJan Kara if (retval && retval != -ENOENT)
834e9109a92SJan Kara goto out_oiter;
835e9109a92SJan Kara /* Entry found but not passed by VFS? */
836e9109a92SJan Kara if (!retval && !new_inode) {
837e9109a92SJan Kara retval = -EFSCORRUPTED;
838e9109a92SJan Kara udf_fiiter_release(&niter);
839e9109a92SJan Kara goto out_oiter;
840e9109a92SJan Kara }
841e9109a92SJan Kara /* Entry not found? Need to add one... */
842e9109a92SJan Kara if (retval) {
843e9109a92SJan Kara udf_fiiter_release(&niter);
844e9109a92SJan Kara retval = udf_fiiter_add_entry(new_dir, new_dentry, &niter);
845e9109a92SJan Kara if (retval)
846e9109a92SJan Kara goto out_oiter;
8471da177e4SLinus Torvalds }
8481da177e4SLinus Torvalds
8491da177e4SLinus Torvalds /*
8501da177e4SLinus Torvalds * Like most other Unix systems, set the ctime for inodes on a
8511da177e4SLinus Torvalds * rename.
8521da177e4SLinus Torvalds */
85359ad88f2SJeff Layton inode_set_ctime_current(old_inode);
8541da177e4SLinus Torvalds mark_inode_dirty(old_inode);
8551da177e4SLinus Torvalds
8561da177e4SLinus Torvalds /*
8571da177e4SLinus Torvalds * ok, that's it
8581da177e4SLinus Torvalds */
859e9109a92SJan Kara niter.fi.fileVersionNum = oiter.fi.fileVersionNum;
860e9109a92SJan Kara niter.fi.fileCharacteristics = oiter.fi.fileCharacteristics;
861e9109a92SJan Kara memcpy(&(niter.fi.icb), &(oiter.fi.icb), sizeof(oiter.fi.icb));
862e9109a92SJan Kara udf_fiiter_write_fi(&niter, NULL);
863e9109a92SJan Kara udf_fiiter_release(&niter);
8641da177e4SLinus Torvalds
865e9109a92SJan Kara /*
866e9109a92SJan Kara * The old entry may have moved due to new entry allocation. Find it
867e9109a92SJan Kara * again.
868e9109a92SJan Kara */
869e9109a92SJan Kara udf_fiiter_release(&oiter);
870e9109a92SJan Kara retval = udf_fiiter_find_entry(old_dir, &old_dentry->d_name, &oiter);
871e9109a92SJan Kara if (retval) {
872e9109a92SJan Kara udf_err(old_dir->i_sb,
873e9109a92SJan Kara "failed to find renamed entry again in directory (ino %lu)\n",
874e9109a92SJan Kara old_dir->i_ino);
875e9109a92SJan Kara } else {
876e9109a92SJan Kara udf_fiiter_delete_entry(&oiter);
877e9109a92SJan Kara udf_fiiter_release(&oiter);
878e9109a92SJan Kara }
8791da177e4SLinus Torvalds
880cb00ea35SCyrill Gorcunov if (new_inode) {
88159ad88f2SJeff Layton inode_set_ctime_current(new_inode);
8829a53c3a7SDave Hansen inode_dec_link_count(new_inode);
883085cf7b7SJan Kara udf_add_fid_counter(old_dir->i_sb, S_ISDIR(new_inode->i_mode),
884085cf7b7SJan Kara -1);
8851da177e4SLinus Torvalds }
88659ad88f2SJeff Layton old_dir->i_mtime = inode_set_ctime_current(old_dir);
88759ad88f2SJeff Layton new_dir->i_mtime = inode_set_ctime_current(new_dir);
8881da177e4SLinus Torvalds mark_inode_dirty(old_dir);
8893adc12e9SJan Kara mark_inode_dirty(new_dir);
8901da177e4SLinus Torvalds
891e9109a92SJan Kara if (has_diriter) {
892e9109a92SJan Kara diriter.fi.icb.extLocation =
893e9109a92SJan Kara cpu_to_lelb(UDF_I(new_dir)->i_location);
894e9109a92SJan Kara udf_fiiter_write_fi(&diriter, NULL);
895e9109a92SJan Kara udf_fiiter_release(&diriter);
89617b312c5SAl Viro }
8974b11111aSMarcin Slusarz
89817b312c5SAl Viro if (is_dir) {
8999a53c3a7SDave Hansen inode_dec_link_count(old_dir);
9004b11111aSMarcin Slusarz if (new_inode)
9019a53c3a7SDave Hansen inode_dec_link_count(new_inode);
9024b11111aSMarcin Slusarz else {
903d8c76e6fSDave Hansen inc_nlink(new_dir);
9041da177e4SLinus Torvalds mark_inode_dirty(new_dir);
9051da177e4SLinus Torvalds }
9061da177e4SLinus Torvalds }
907e9109a92SJan Kara return 0;
908e9109a92SJan Kara out_oiter:
9097517ce5dSJan Kara if (has_diriter)
910e9109a92SJan Kara udf_fiiter_release(&diriter);
911e9109a92SJan Kara udf_fiiter_release(&oiter);
91228de7948SCyrill Gorcunov
9131da177e4SLinus Torvalds return retval;
9141da177e4SLinus Torvalds }
9151da177e4SLinus Torvalds
udf_get_parent(struct dentry * child)916221e583aSRasmus Rohde static struct dentry *udf_get_parent(struct dentry *child)
917221e583aSRasmus Rohde {
91897e961fdSPekka Enberg struct kernel_lb_addr tloc;
919221e583aSRasmus Rohde struct inode *inode = NULL;
9209b06fbefSJan Kara struct udf_fileident_iter iter;
9219b06fbefSJan Kara int err;
922221e583aSRasmus Rohde
9239b06fbefSJan Kara err = udf_fiiter_find_entry(d_inode(child), &dotdot_name, &iter);
9249b06fbefSJan Kara if (err)
9259b06fbefSJan Kara return ERR_PTR(err);
926221e583aSRasmus Rohde
9279b06fbefSJan Kara tloc = lelb_to_cpu(iter.fi.icb.extLocation);
9289b06fbefSJan Kara udf_fiiter_release(&iter);
929fc64005cSAl Viro inode = udf_iget(child->d_sb, &tloc);
9306d3d5e86SJan Kara if (IS_ERR(inode))
9316d3d5e86SJan Kara return ERR_CAST(inode);
932221e583aSRasmus Rohde
93344003728SChristoph Hellwig return d_obtain_alias(inode);
934221e583aSRasmus Rohde }
935221e583aSRasmus Rohde
936221e583aSRasmus Rohde
udf_nfs_get_inode(struct super_block * sb,u32 block,u16 partref,__u32 generation)937221e583aSRasmus Rohde static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block,
938221e583aSRasmus Rohde u16 partref, __u32 generation)
939221e583aSRasmus Rohde {
940221e583aSRasmus Rohde struct inode *inode;
9415ca4e4beSPekka Enberg struct kernel_lb_addr loc;
942221e583aSRasmus Rohde
943221e583aSRasmus Rohde if (block == 0)
944221e583aSRasmus Rohde return ERR_PTR(-ESTALE);
945221e583aSRasmus Rohde
946221e583aSRasmus Rohde loc.logicalBlockNum = block;
947221e583aSRasmus Rohde loc.partitionReferenceNum = partref;
94897e961fdSPekka Enberg inode = udf_iget(sb, &loc);
949221e583aSRasmus Rohde
9506d3d5e86SJan Kara if (IS_ERR(inode))
9516d3d5e86SJan Kara return ERR_CAST(inode);
952221e583aSRasmus Rohde
953221e583aSRasmus Rohde if (generation && inode->i_generation != generation) {
954221e583aSRasmus Rohde iput(inode);
955221e583aSRasmus Rohde return ERR_PTR(-ESTALE);
956221e583aSRasmus Rohde }
95744003728SChristoph Hellwig return d_obtain_alias(inode);
958221e583aSRasmus Rohde }
959221e583aSRasmus Rohde
udf_fh_to_dentry(struct super_block * sb,struct fid * fid,int fh_len,int fh_type)960221e583aSRasmus Rohde static struct dentry *udf_fh_to_dentry(struct super_block *sb,
961221e583aSRasmus Rohde struct fid *fid, int fh_len, int fh_type)
962221e583aSRasmus Rohde {
96392acca45SNeilBrown if (fh_len < 3 ||
964221e583aSRasmus Rohde (fh_type != FILEID_UDF_WITH_PARENT &&
965221e583aSRasmus Rohde fh_type != FILEID_UDF_WITHOUT_PARENT))
966221e583aSRasmus Rohde return NULL;
967221e583aSRasmus Rohde
968221e583aSRasmus Rohde return udf_nfs_get_inode(sb, fid->udf.block, fid->udf.partref,
969221e583aSRasmus Rohde fid->udf.generation);
970221e583aSRasmus Rohde }
971221e583aSRasmus Rohde
udf_fh_to_parent(struct super_block * sb,struct fid * fid,int fh_len,int fh_type)972221e583aSRasmus Rohde static struct dentry *udf_fh_to_parent(struct super_block *sb,
973221e583aSRasmus Rohde struct fid *fid, int fh_len, int fh_type)
974221e583aSRasmus Rohde {
97592acca45SNeilBrown if (fh_len < 5 || fh_type != FILEID_UDF_WITH_PARENT)
976221e583aSRasmus Rohde return NULL;
977221e583aSRasmus Rohde
978221e583aSRasmus Rohde return udf_nfs_get_inode(sb, fid->udf.parent_block,
979221e583aSRasmus Rohde fid->udf.parent_partref,
980221e583aSRasmus Rohde fid->udf.parent_generation);
981221e583aSRasmus Rohde }
udf_encode_fh(struct inode * inode,__u32 * fh,int * lenp,struct inode * parent)982b0b0382bSAl Viro static int udf_encode_fh(struct inode *inode, __u32 *fh, int *lenp,
983b0b0382bSAl Viro struct inode *parent)
984221e583aSRasmus Rohde {
985221e583aSRasmus Rohde int len = *lenp;
9865ca4e4beSPekka Enberg struct kernel_lb_addr location = UDF_I(inode)->i_location;
987221e583aSRasmus Rohde struct fid *fid = (struct fid *)fh;
988221e583aSRasmus Rohde int type = FILEID_UDF_WITHOUT_PARENT;
989221e583aSRasmus Rohde
990b0b0382bSAl Viro if (parent && (len < 5)) {
9915fe0c237SAneesh Kumar K.V *lenp = 5;
99294e07a75SNamjae Jeon return FILEID_INVALID;
9935fe0c237SAneesh Kumar K.V } else if (len < 3) {
9945fe0c237SAneesh Kumar K.V *lenp = 3;
99594e07a75SNamjae Jeon return FILEID_INVALID;
9965fe0c237SAneesh Kumar K.V }
997221e583aSRasmus Rohde
998221e583aSRasmus Rohde *lenp = 3;
999221e583aSRasmus Rohde fid->udf.block = location.logicalBlockNum;
1000221e583aSRasmus Rohde fid->udf.partref = location.partitionReferenceNum;
10010143fc5eSMathias Krause fid->udf.parent_partref = 0;
1002221e583aSRasmus Rohde fid->udf.generation = inode->i_generation;
1003221e583aSRasmus Rohde
1004b0b0382bSAl Viro if (parent) {
1005b0b0382bSAl Viro location = UDF_I(parent)->i_location;
1006221e583aSRasmus Rohde fid->udf.parent_block = location.logicalBlockNum;
1007221e583aSRasmus Rohde fid->udf.parent_partref = location.partitionReferenceNum;
1008221e583aSRasmus Rohde fid->udf.parent_generation = inode->i_generation;
1009221e583aSRasmus Rohde *lenp = 5;
1010221e583aSRasmus Rohde type = FILEID_UDF_WITH_PARENT;
1011221e583aSRasmus Rohde }
1012221e583aSRasmus Rohde
1013221e583aSRasmus Rohde return type;
1014221e583aSRasmus Rohde }
1015221e583aSRasmus Rohde
1016221e583aSRasmus Rohde const struct export_operations udf_export_ops = {
1017221e583aSRasmus Rohde .encode_fh = udf_encode_fh,
1018221e583aSRasmus Rohde .fh_to_dentry = udf_fh_to_dentry,
1019221e583aSRasmus Rohde .fh_to_parent = udf_fh_to_parent,
1020221e583aSRasmus Rohde .get_parent = udf_get_parent,
1021221e583aSRasmus Rohde };
1022221e583aSRasmus Rohde
1023c5ef1c42SArjan van de Ven const struct inode_operations udf_dir_inode_operations = {
10241da177e4SLinus Torvalds .lookup = udf_lookup,
10251da177e4SLinus Torvalds .create = udf_create,
10261da177e4SLinus Torvalds .link = udf_link,
10271da177e4SLinus Torvalds .unlink = udf_unlink,
10281da177e4SLinus Torvalds .symlink = udf_symlink,
10291da177e4SLinus Torvalds .mkdir = udf_mkdir,
10301da177e4SLinus Torvalds .rmdir = udf_rmdir,
10311da177e4SLinus Torvalds .mknod = udf_mknod,
10321da177e4SLinus Torvalds .rename = udf_rename,
1033656d09dfSAl Viro .tmpfile = udf_tmpfile,
10341da177e4SLinus Torvalds };
1035