Merge tag 'parisc-for-6.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/delle...
[platform/kernel/linux-starfive.git] / fs / udf / directory.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * directory.c
4  *
5  * PURPOSE
6  *      Directory related functions
7  *
8  */
9
10 #include "udfdecl.h"
11 #include "udf_i.h"
12
13 #include <linux/fs.h>
14 #include <linux/string.h>
15 #include <linux/bio.h>
16 #include <linux/crc-itu-t.h>
17 #include <linux/iversion.h>
18
19 static int udf_verify_fi(struct udf_fileident_iter *iter)
20 {
21         unsigned int len;
22
23         if (iter->fi.descTag.tagIdent != cpu_to_le16(TAG_IDENT_FID)) {
24                 udf_err(iter->dir->i_sb,
25                         "directory (ino %lu) has entry at pos %llu with incorrect tag %x\n",
26                         iter->dir->i_ino, (unsigned long long)iter->pos,
27                         le16_to_cpu(iter->fi.descTag.tagIdent));
28                 return -EFSCORRUPTED;
29         }
30         len = udf_dir_entry_len(&iter->fi);
31         if (le16_to_cpu(iter->fi.lengthOfImpUse) & 3) {
32                 udf_err(iter->dir->i_sb,
33                         "directory (ino %lu) has entry at pos %llu with unaligned length of impUse field\n",
34                         iter->dir->i_ino, (unsigned long long)iter->pos);
35                 return -EFSCORRUPTED;
36         }
37         /*
38          * This is in fact allowed by the spec due to long impUse field but
39          * we don't support it. If there is real media with this large impUse
40          * field, support can be added.
41          */
42         if (len > 1 << iter->dir->i_blkbits) {
43                 udf_err(iter->dir->i_sb,
44                         "directory (ino %lu) has too big (%u) entry at pos %llu\n",
45                         iter->dir->i_ino, len, (unsigned long long)iter->pos);
46                 return -EFSCORRUPTED;
47         }
48         if (iter->pos + len > iter->dir->i_size) {
49                 udf_err(iter->dir->i_sb,
50                         "directory (ino %lu) has entry past directory size at pos %llu\n",
51                         iter->dir->i_ino, (unsigned long long)iter->pos);
52                 return -EFSCORRUPTED;
53         }
54         if (udf_dir_entry_len(&iter->fi) !=
55             sizeof(struct tag) + le16_to_cpu(iter->fi.descTag.descCRCLength)) {
56                 udf_err(iter->dir->i_sb,
57                         "directory (ino %lu) has entry where CRC length (%u) does not match entry length (%u)\n",
58                         iter->dir->i_ino,
59                         (unsigned)le16_to_cpu(iter->fi.descTag.descCRCLength),
60                         (unsigned)(udf_dir_entry_len(&iter->fi) -
61                                                         sizeof(struct tag)));
62                 return -EFSCORRUPTED;
63         }
64         return 0;
65 }
66
67 static int udf_copy_fi(struct udf_fileident_iter *iter)
68 {
69         struct udf_inode_info *iinfo = UDF_I(iter->dir);
70         u32 blksize = 1 << iter->dir->i_blkbits;
71         u32 off, len, nameoff;
72         int err;
73
74         /* Skip copying when we are at EOF */
75         if (iter->pos >= iter->dir->i_size) {
76                 iter->name = NULL;
77                 return 0;
78         }
79         if (iter->dir->i_size < iter->pos + sizeof(struct fileIdentDesc)) {
80                 udf_err(iter->dir->i_sb,
81                         "directory (ino %lu) has entry straddling EOF\n",
82                         iter->dir->i_ino);
83                 return -EFSCORRUPTED;
84         }
85         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
86                 memcpy(&iter->fi, iinfo->i_data + iinfo->i_lenEAttr + iter->pos,
87                        sizeof(struct fileIdentDesc));
88                 err = udf_verify_fi(iter);
89                 if (err < 0)
90                         return err;
91                 iter->name = iinfo->i_data + iinfo->i_lenEAttr + iter->pos +
92                         sizeof(struct fileIdentDesc) +
93                         le16_to_cpu(iter->fi.lengthOfImpUse);
94                 return 0;
95         }
96
97         off = iter->pos & (blksize - 1);
98         len = min_t(u32, sizeof(struct fileIdentDesc), blksize - off);
99         memcpy(&iter->fi, iter->bh[0]->b_data + off, len);
100         if (len < sizeof(struct fileIdentDesc))
101                 memcpy((char *)(&iter->fi) + len, iter->bh[1]->b_data,
102                        sizeof(struct fileIdentDesc) - len);
103         err = udf_verify_fi(iter);
104         if (err < 0)
105                 return err;
106
107         /* Handle directory entry name */
108         nameoff = off + sizeof(struct fileIdentDesc) +
109                                 le16_to_cpu(iter->fi.lengthOfImpUse);
110         if (off + udf_dir_entry_len(&iter->fi) <= blksize) {
111                 iter->name = iter->bh[0]->b_data + nameoff;
112         } else if (nameoff >= blksize) {
113                 iter->name = iter->bh[1]->b_data + (nameoff - blksize);
114         } else {
115                 iter->name = iter->namebuf;
116                 len = blksize - nameoff;
117                 memcpy(iter->name, iter->bh[0]->b_data + nameoff, len);
118                 memcpy(iter->name + len, iter->bh[1]->b_data,
119                        iter->fi.lengthFileIdent - len);
120         }
121         return 0;
122 }
123
124 /* Readahead 8k once we are at 8k boundary */
125 static void udf_readahead_dir(struct udf_fileident_iter *iter)
126 {
127         unsigned int ralen = 16 >> (iter->dir->i_blkbits - 9);
128         struct buffer_head *tmp, *bha[16];
129         int i, num;
130         udf_pblk_t blk;
131
132         if (iter->loffset & (ralen - 1))
133                 return;
134
135         if (iter->loffset + ralen > (iter->elen >> iter->dir->i_blkbits))
136                 ralen = (iter->elen >> iter->dir->i_blkbits) - iter->loffset;
137         num = 0;
138         for (i = 0; i < ralen; i++) {
139                 blk = udf_get_lb_pblock(iter->dir->i_sb, &iter->eloc,
140                                         iter->loffset + i);
141                 tmp = sb_getblk(iter->dir->i_sb, blk);
142                 if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
143                         bha[num++] = tmp;
144                 else
145                         brelse(tmp);
146         }
147         if (num) {
148                 bh_readahead_batch(num, bha, REQ_RAHEAD);
149                 for (i = 0; i < num; i++)
150                         brelse(bha[i]);
151         }
152 }
153
154 static struct buffer_head *udf_fiiter_bread_blk(struct udf_fileident_iter *iter)
155 {
156         udf_pblk_t blk;
157
158         udf_readahead_dir(iter);
159         blk = udf_get_lb_pblock(iter->dir->i_sb, &iter->eloc, iter->loffset);
160         return sb_bread(iter->dir->i_sb, blk);
161 }
162
163 /*
164  * Updates loffset to point to next directory block; eloc, elen & epos are
165  * updated if we need to traverse to the next extent as well.
166  */
167 static int udf_fiiter_advance_blk(struct udf_fileident_iter *iter)
168 {
169         iter->loffset++;
170         if (iter->loffset < DIV_ROUND_UP(iter->elen, 1<<iter->dir->i_blkbits))
171                 return 0;
172
173         iter->loffset = 0;
174         if (udf_next_aext(iter->dir, &iter->epos, &iter->eloc, &iter->elen, 1)
175                         != (EXT_RECORDED_ALLOCATED >> 30)) {
176                 if (iter->pos == iter->dir->i_size) {
177                         iter->elen = 0;
178                         return 0;
179                 }
180                 udf_err(iter->dir->i_sb,
181                         "extent after position %llu not allocated in directory (ino %lu)\n",
182                         (unsigned long long)iter->pos, iter->dir->i_ino);
183                 return -EFSCORRUPTED;
184         }
185         return 0;
186 }
187
188 static int udf_fiiter_load_bhs(struct udf_fileident_iter *iter)
189 {
190         int blksize = 1 << iter->dir->i_blkbits;
191         int off = iter->pos & (blksize - 1);
192         int err;
193         struct fileIdentDesc *fi;
194
195         /* Is there any further extent we can map from? */
196         if (!iter->bh[0] && iter->elen) {
197                 iter->bh[0] = udf_fiiter_bread_blk(iter);
198                 if (!iter->bh[0]) {
199                         err = -ENOMEM;
200                         goto out_brelse;
201                 }
202                 if (!buffer_uptodate(iter->bh[0])) {
203                         err = -EIO;
204                         goto out_brelse;
205                 }
206         }
207         /* There's no next block so we are done */
208         if (iter->pos >= iter->dir->i_size)
209                 return 0;
210         /* Need to fetch next block as well? */
211         if (off + sizeof(struct fileIdentDesc) > blksize)
212                 goto fetch_next;
213         fi = (struct fileIdentDesc *)(iter->bh[0]->b_data + off);
214         /* Need to fetch next block to get name? */
215         if (off + udf_dir_entry_len(fi) > blksize) {
216 fetch_next:
217                 err = udf_fiiter_advance_blk(iter);
218                 if (err)
219                         goto out_brelse;
220                 iter->bh[1] = udf_fiiter_bread_blk(iter);
221                 if (!iter->bh[1]) {
222                         err = -ENOMEM;
223                         goto out_brelse;
224                 }
225                 if (!buffer_uptodate(iter->bh[1])) {
226                         err = -EIO;
227                         goto out_brelse;
228                 }
229         }
230         return 0;
231 out_brelse:
232         brelse(iter->bh[0]);
233         brelse(iter->bh[1]);
234         iter->bh[0] = iter->bh[1] = NULL;
235         return err;
236 }
237
238 int udf_fiiter_init(struct udf_fileident_iter *iter, struct inode *dir,
239                     loff_t pos)
240 {
241         struct udf_inode_info *iinfo = UDF_I(dir);
242         int err = 0;
243
244         iter->dir = dir;
245         iter->bh[0] = iter->bh[1] = NULL;
246         iter->pos = pos;
247         iter->elen = 0;
248         iter->epos.bh = NULL;
249         iter->name = NULL;
250         /*
251          * When directory is verified, we don't expect directory iteration to
252          * fail and it can be difficult to undo without corrupting filesystem.
253          * So just do not allow memory allocation failures here.
254          */
255         iter->namebuf = kmalloc(UDF_NAME_LEN_CS0, GFP_KERNEL | __GFP_NOFAIL);
256
257         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
258                 err = udf_copy_fi(iter);
259                 goto out;
260         }
261
262         if (inode_bmap(dir, iter->pos >> dir->i_blkbits, &iter->epos,
263                        &iter->eloc, &iter->elen, &iter->loffset) !=
264             (EXT_RECORDED_ALLOCATED >> 30)) {
265                 if (pos == dir->i_size)
266                         return 0;
267                 udf_err(dir->i_sb,
268                         "position %llu not allocated in directory (ino %lu)\n",
269                         (unsigned long long)pos, dir->i_ino);
270                 err = -EFSCORRUPTED;
271                 goto out;
272         }
273         err = udf_fiiter_load_bhs(iter);
274         if (err < 0)
275                 goto out;
276         err = udf_copy_fi(iter);
277 out:
278         if (err < 0)
279                 udf_fiiter_release(iter);
280         return err;
281 }
282
283 int udf_fiiter_advance(struct udf_fileident_iter *iter)
284 {
285         unsigned int oldoff, len;
286         int blksize = 1 << iter->dir->i_blkbits;
287         int err;
288
289         oldoff = iter->pos & (blksize - 1);
290         len = udf_dir_entry_len(&iter->fi);
291         iter->pos += len;
292         if (UDF_I(iter->dir)->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
293                 if (oldoff + len >= blksize) {
294                         brelse(iter->bh[0]);
295                         iter->bh[0] = NULL;
296                         /* Next block already loaded? */
297                         if (iter->bh[1]) {
298                                 iter->bh[0] = iter->bh[1];
299                                 iter->bh[1] = NULL;
300                         } else {
301                                 err = udf_fiiter_advance_blk(iter);
302                                 if (err < 0)
303                                         return err;
304                         }
305                 }
306                 err = udf_fiiter_load_bhs(iter);
307                 if (err < 0)
308                         return err;
309         }
310         return udf_copy_fi(iter);
311 }
312
313 void udf_fiiter_release(struct udf_fileident_iter *iter)
314 {
315         iter->dir = NULL;
316         brelse(iter->bh[0]);
317         brelse(iter->bh[1]);
318         iter->bh[0] = iter->bh[1] = NULL;
319         kfree(iter->namebuf);
320         iter->namebuf = NULL;
321 }
322
323 static void udf_copy_to_bufs(void *buf1, int len1, void *buf2, int len2,
324                              int off, void *src, int len)
325 {
326         int copy;
327
328         if (off >= len1) {
329                 off -= len1;
330         } else {
331                 copy = min(off + len, len1) - off;
332                 memcpy(buf1 + off, src, copy);
333                 src += copy;
334                 len -= copy;
335                 off = 0;
336         }
337         if (len > 0) {
338                 if (WARN_ON_ONCE(off + len > len2 || !buf2))
339                         return;
340                 memcpy(buf2 + off, src, len);
341         }
342 }
343
344 static uint16_t udf_crc_fi_bufs(void *buf1, int len1, void *buf2, int len2,
345                                 int off, int len)
346 {
347         int copy;
348         uint16_t crc = 0;
349
350         if (off >= len1) {
351                 off -= len1;
352         } else {
353                 copy = min(off + len, len1) - off;
354                 crc = crc_itu_t(crc, buf1 + off, copy);
355                 len -= copy;
356                 off = 0;
357         }
358         if (len > 0) {
359                 if (WARN_ON_ONCE(off + len > len2 || !buf2))
360                         return 0;
361                 crc = crc_itu_t(crc, buf2 + off, len);
362         }
363         return crc;
364 }
365
366 static void udf_copy_fi_to_bufs(char *buf1, int len1, char *buf2, int len2,
367                                 int off, struct fileIdentDesc *fi,
368                                 uint8_t *impuse, uint8_t *name)
369 {
370         uint16_t crc;
371         int fioff = off;
372         int crcoff = off + sizeof(struct tag);
373         unsigned int crclen = udf_dir_entry_len(fi) - sizeof(struct tag);
374         char zeros[UDF_NAME_PAD] = {};
375         int endoff = off + udf_dir_entry_len(fi);
376
377         udf_copy_to_bufs(buf1, len1, buf2, len2, off, fi,
378                          sizeof(struct fileIdentDesc));
379         off += sizeof(struct fileIdentDesc);
380         if (impuse)
381                 udf_copy_to_bufs(buf1, len1, buf2, len2, off, impuse,
382                                  le16_to_cpu(fi->lengthOfImpUse));
383         off += le16_to_cpu(fi->lengthOfImpUse);
384         if (name) {
385                 udf_copy_to_bufs(buf1, len1, buf2, len2, off, name,
386                                  fi->lengthFileIdent);
387                 off += fi->lengthFileIdent;
388                 udf_copy_to_bufs(buf1, len1, buf2, len2, off, zeros,
389                                  endoff - off);
390         }
391
392         crc = udf_crc_fi_bufs(buf1, len1, buf2, len2, crcoff, crclen);
393         fi->descTag.descCRC = cpu_to_le16(crc);
394         fi->descTag.descCRCLength = cpu_to_le16(crclen);
395         fi->descTag.tagChecksum = udf_tag_checksum(&fi->descTag);
396
397         udf_copy_to_bufs(buf1, len1, buf2, len2, fioff, fi, sizeof(struct tag));
398 }
399
400 void udf_fiiter_write_fi(struct udf_fileident_iter *iter, uint8_t *impuse)
401 {
402         struct udf_inode_info *iinfo = UDF_I(iter->dir);
403         void *buf1, *buf2 = NULL;
404         int len1, len2 = 0, off;
405         int blksize = 1 << iter->dir->i_blkbits;
406
407         off = iter->pos & (blksize - 1);
408         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
409                 buf1 = iinfo->i_data + iinfo->i_lenEAttr;
410                 len1 = iter->dir->i_size;
411         } else {
412                 buf1 = iter->bh[0]->b_data;
413                 len1 = blksize;
414                 if (iter->bh[1]) {
415                         buf2 = iter->bh[1]->b_data;
416                         len2 = blksize;
417                 }
418         }
419
420         udf_copy_fi_to_bufs(buf1, len1, buf2, len2, off, &iter->fi, impuse,
421                             iter->name == iter->namebuf ? iter->name : NULL);
422
423         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
424                 mark_inode_dirty(iter->dir);
425         } else {
426                 mark_buffer_dirty_inode(iter->bh[0], iter->dir);
427                 if (iter->bh[1])
428                         mark_buffer_dirty_inode(iter->bh[1], iter->dir);
429         }
430         inode_inc_iversion(iter->dir);
431 }
432
433 void udf_fiiter_update_elen(struct udf_fileident_iter *iter, uint32_t new_elen)
434 {
435         struct udf_inode_info *iinfo = UDF_I(iter->dir);
436         int diff = new_elen - iter->elen;
437
438         /* Skip update when we already went past the last extent */
439         if (!iter->elen)
440                 return;
441         iter->elen = new_elen;
442         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
443                 iter->epos.offset -= sizeof(struct short_ad);
444         else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
445                 iter->epos.offset -= sizeof(struct long_ad);
446         udf_write_aext(iter->dir, &iter->epos, &iter->eloc, iter->elen, 1);
447         iinfo->i_lenExtents += diff;
448         mark_inode_dirty(iter->dir);
449 }
450
451 /* Append new block to directory. @iter is expected to point at EOF */
452 int udf_fiiter_append_blk(struct udf_fileident_iter *iter)
453 {
454         struct udf_inode_info *iinfo = UDF_I(iter->dir);
455         int blksize = 1 << iter->dir->i_blkbits;
456         struct buffer_head *bh;
457         sector_t block;
458         uint32_t old_elen = iter->elen;
459         int err;
460
461         if (WARN_ON_ONCE(iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB))
462                 return -EINVAL;
463
464         /* Round up last extent in the file */
465         udf_fiiter_update_elen(iter, ALIGN(iter->elen, blksize));
466
467         /* Allocate new block and refresh mapping information */
468         block = iinfo->i_lenExtents >> iter->dir->i_blkbits;
469         bh = udf_bread(iter->dir, block, 1, &err);
470         if (!bh) {
471                 udf_fiiter_update_elen(iter, old_elen);
472                 return err;
473         }
474         if (inode_bmap(iter->dir, block, &iter->epos, &iter->eloc, &iter->elen,
475                        &iter->loffset) != (EXT_RECORDED_ALLOCATED >> 30)) {
476                 udf_err(iter->dir->i_sb,
477                         "block %llu not allocated in directory (ino %lu)\n",
478                         (unsigned long long)block, iter->dir->i_ino);
479                 return -EFSCORRUPTED;
480         }
481         if (!(iter->pos & (blksize - 1))) {
482                 brelse(iter->bh[0]);
483                 iter->bh[0] = bh;
484         } else {
485                 iter->bh[1] = bh;
486         }
487         return 0;
488 }
489
490 struct short_ad *udf_get_fileshortad(uint8_t *ptr, int maxoffset, uint32_t *offset,
491                               int inc)
492 {
493         struct short_ad *sa;
494
495         if ((!ptr) || (!offset)) {
496                 pr_err("%s: invalidparms\n", __func__);
497                 return NULL;
498         }
499
500         if ((*offset + sizeof(struct short_ad)) > maxoffset)
501                 return NULL;
502         else {
503                 sa = (struct short_ad *)ptr;
504                 if (sa->extLength == 0)
505                         return NULL;
506         }
507
508         if (inc)
509                 *offset += sizeof(struct short_ad);
510         return sa;
511 }
512
513 struct long_ad *udf_get_filelongad(uint8_t *ptr, int maxoffset, uint32_t *offset, int inc)
514 {
515         struct long_ad *la;
516
517         if ((!ptr) || (!offset)) {
518                 pr_err("%s: invalidparms\n", __func__);
519                 return NULL;
520         }
521
522         if ((*offset + sizeof(struct long_ad)) > maxoffset)
523                 return NULL;
524         else {
525                 la = (struct long_ad *)ptr;
526                 if (la->extLength == 0)
527                         return NULL;
528         }
529
530         if (inc)
531                 *offset += sizeof(struct long_ad);
532         return la;
533 }