VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

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