^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/fs/adfs/dir_fplus.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1997-1999 Russell King
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "adfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "dir_fplus.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) /* Return the byte offset to directory entry pos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) static unsigned int adfs_fplus_offset(const struct adfs_bigdirheader *h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) unsigned int pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) return offsetof(struct adfs_bigdirheader, bigdirname) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) ALIGN(le32_to_cpu(h->bigdirnamelen), 4) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) pos * sizeof(struct adfs_bigdirentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static int adfs_fplus_validate_header(const struct adfs_bigdirheader *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned int size = le32_to_cpu(h->bigdirsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (h->bigdirversion[0] != 0 || h->bigdirversion[1] != 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) h->bigdirversion[2] != 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) h->bigdirstartname != cpu_to_le32(BIGDIRSTARTNAME) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) !size || size & 2047 || size > SZ_4M)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) size -= sizeof(struct adfs_bigdirtail) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) offsetof(struct adfs_bigdirheader, bigdirname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* Check that bigdirnamelen fits within the directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) len = ALIGN(le32_to_cpu(h->bigdirnamelen), 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if (len > size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) size -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* Check that bigdirnamesize fits within the directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) len = le32_to_cpu(h->bigdirnamesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (len > size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) size -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * Avoid division, we know that absolute maximum number of entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * can not be so large to cause overflow of the multiplication below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) len = le32_to_cpu(h->bigdirentries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (len > SZ_4M / sizeof(struct adfs_bigdirentry) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) len * sizeof(struct adfs_bigdirentry) > size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static int adfs_fplus_validate_tail(const struct adfs_bigdirheader *h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) const struct adfs_bigdirtail *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (t->bigdirendname != cpu_to_le32(BIGDIRENDNAME) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) t->bigdirendmasseq != h->startmasseq ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) t->reserved[0] != 0 || t->reserved[1] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static u8 adfs_fplus_checkbyte(struct adfs_dir *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct adfs_bigdirheader *h = dir->bighead;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct adfs_bigdirtail *t = dir->bigtail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned int end, bs, bi, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) __le32 *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u32 dircheck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) end = adfs_fplus_offset(h, le32_to_cpu(h->bigdirentries)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) le32_to_cpu(h->bigdirnamesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* Accumulate the contents of the header, entries and names */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) for (dircheck = 0, bi = 0; end; bi++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) bp = (void *)dir->bhs[bi]->b_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) bs = dir->bhs[bi]->b_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (bs > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) bs = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) for (i = 0; i < bs; i += sizeof(u32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) dircheck = ror32(dircheck, 13) ^ le32_to_cpup(bp++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) end -= bs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* Accumulate the contents of the tail except for the check byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) dircheck = ror32(dircheck, 13) ^ le32_to_cpu(t->bigdirendname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) dircheck = ror32(dircheck, 13) ^ t->bigdirendmasseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) dircheck = ror32(dircheck, 13) ^ t->reserved[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) dircheck = ror32(dircheck, 13) ^ t->reserved[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return dircheck ^ dircheck >> 8 ^ dircheck >> 16 ^ dircheck >> 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static int adfs_fplus_read(struct super_block *sb, u32 indaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) unsigned int size, struct adfs_dir *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct adfs_bigdirheader *h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct adfs_bigdirtail *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) unsigned int dirsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* Read first buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ret = adfs_dir_read_buffers(sb, indaddr, sb->s_blocksize, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) dir->bighead = h = (void *)dir->bhs[0]->b_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ret = adfs_fplus_validate_header(h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) adfs_error(sb, "dir %06x has malformed header", indaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dirsize = le32_to_cpu(h->bigdirsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (size && dirsize != size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) adfs_msg(sb, KERN_WARNING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) "dir %06x header size %X does not match directory size %X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) indaddr, dirsize, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* Read remaining buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ret = adfs_dir_read_buffers(sb, indaddr, dirsize, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) dir->bigtail = t = (struct adfs_bigdirtail *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) (dir->bhs[dir->nr_buffers - 1]->b_data + (sb->s_blocksize - 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ret = adfs_fplus_validate_tail(h, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) adfs_error(sb, "dir %06x has malformed tail", indaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (adfs_fplus_checkbyte(dir) != t->bigdircheckbyte) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) adfs_error(sb, "dir %06x checkbyte mismatch\n", indaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) dir->parent_id = le32_to_cpu(h->bigdirparent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) adfs_dir_relse(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) adfs_fplus_setpos(struct adfs_dir *dir, unsigned int fpos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (fpos <= le32_to_cpu(dir->bighead->bigdirentries)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) dir->pos = fpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) adfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct adfs_bigdirheader *h = dir->bighead;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct adfs_bigdirentry bde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) unsigned int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (dir->pos >= le32_to_cpu(h->bigdirentries))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) offset = adfs_fplus_offset(h, dir->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ret = adfs_dir_copyfrom(&bde, dir, offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) sizeof(struct adfs_bigdirentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) obj->loadaddr = le32_to_cpu(bde.bigdirload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) obj->execaddr = le32_to_cpu(bde.bigdirexec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) obj->size = le32_to_cpu(bde.bigdirlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) obj->indaddr = le32_to_cpu(bde.bigdirindaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) obj->attr = le32_to_cpu(bde.bigdirattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) obj->name_len = le32_to_cpu(bde.bigdirobnamelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) offset = adfs_fplus_offset(h, le32_to_cpu(h->bigdirentries));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) offset += le32_to_cpu(bde.bigdirobnameptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) ret = adfs_dir_copyfrom(obj->name, dir, offset, obj->name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) adfs_object_fixup(dir, obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) dir->pos += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int adfs_fplus_iterate(struct adfs_dir *dir, struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct object_info obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if ((ctx->pos - 2) >> 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (adfs_fplus_setpos(dir, ctx->pos - 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) while (!adfs_fplus_getnext(dir, &obj)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (!dir_emit(ctx, obj.name, obj.name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) obj.indaddr, DT_UNKNOWN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ctx->pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static int adfs_fplus_update(struct adfs_dir *dir, struct object_info *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct adfs_bigdirheader *h = dir->bighead;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct adfs_bigdirentry bde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) int offset, end, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) offset = adfs_fplus_offset(h, 0) - sizeof(bde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) end = adfs_fplus_offset(h, le32_to_cpu(h->bigdirentries));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) offset += sizeof(bde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (offset >= end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) adfs_error(dir->sb, "unable to locate entry to update");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ret = adfs_dir_copyfrom(&bde, dir, offset, sizeof(bde));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) adfs_error(dir->sb, "error reading directory entry");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) } while (le32_to_cpu(bde.bigdirindaddr) != obj->indaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) bde.bigdirload = cpu_to_le32(obj->loadaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) bde.bigdirexec = cpu_to_le32(obj->execaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) bde.bigdirlen = cpu_to_le32(obj->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) bde.bigdirindaddr = cpu_to_le32(obj->indaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) bde.bigdirattr = cpu_to_le32(obj->attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return adfs_dir_copyto(dir, offset, &bde, sizeof(bde));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int adfs_fplus_commit(struct adfs_dir *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* Increment directory sequence number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) dir->bighead->startmasseq += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) dir->bigtail->bigdirendmasseq += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* Update directory check byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) dir->bigtail->bigdircheckbyte = adfs_fplus_checkbyte(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* Make sure the directory still validates correctly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ret = adfs_fplus_validate_header(dir->bighead);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ret = adfs_fplus_validate_tail(dir->bighead, dir->bigtail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) const struct adfs_dir_ops adfs_fplus_dir_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .read = adfs_fplus_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .iterate = adfs_fplus_iterate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .setpos = adfs_fplus_setpos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .getnext = adfs_fplus_getnext,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .update = adfs_fplus_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .commit = adfs_fplus_commit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) };