Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) };