xref: /openbmc/linux/fs/hpfs/ea.c (revision 498495dba268b20e8eadd7fe93c140c68b6cc9d2)
1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  linux/fs/hpfs/ea.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  *  handling extended attributes
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds 
101da177e4SLinus Torvalds #include "hpfs_fn.h"
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds /* Remove external extended attributes. ano specifies whether a is a
131da177e4SLinus Torvalds    direct sector where eas starts or an anode */
141da177e4SLinus Torvalds 
hpfs_ea_ext_remove(struct super_block * s,secno a,int ano,unsigned len)151da177e4SLinus Torvalds void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len)
161da177e4SLinus Torvalds {
171da177e4SLinus Torvalds 	unsigned pos = 0;
181da177e4SLinus Torvalds 	while (pos < len) {
191da177e4SLinus Torvalds 		char ex[4 + 255 + 1 + 8];
201da177e4SLinus Torvalds 		struct extended_attribute *ea = (struct extended_attribute *)ex;
211da177e4SLinus Torvalds 		if (pos + 4 > len) {
221da177e4SLinus Torvalds 			hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
231da177e4SLinus Torvalds 				ano ? "anode" : "sectors", a, len);
241da177e4SLinus Torvalds 			return;
251da177e4SLinus Torvalds 		}
261da177e4SLinus Torvalds 		if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
274085e155SAl Viro 		if (ea_indirect(ea)) {
28d0969d19SMikulas Patocka 			if (ea_valuelen(ea) != 8) {
294085e155SAl Viro 				hpfs_error(s, "ea_indirect(ea) set while ea->valuelen!=8, %s %08x, pos %08x",
301da177e4SLinus Torvalds 					ano ? "anode" : "sectors", a, pos);
311da177e4SLinus Torvalds 				return;
321da177e4SLinus Torvalds 			}
331da177e4SLinus Torvalds 			if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 9, ex+4))
341da177e4SLinus Torvalds 				return;
354085e155SAl Viro 			hpfs_ea_remove(s, ea_sec(ea), ea_in_anode(ea), ea_len(ea));
361da177e4SLinus Torvalds 		}
37d0969d19SMikulas Patocka 		pos += ea->namelen + ea_valuelen(ea) + 5;
381da177e4SLinus Torvalds 	}
391da177e4SLinus Torvalds 	if (!ano) hpfs_free_sectors(s, a, (len+511) >> 9);
401da177e4SLinus Torvalds 	else {
411da177e4SLinus Torvalds 		struct buffer_head *bh;
421da177e4SLinus Torvalds 		struct anode *anode;
431da177e4SLinus Torvalds 		if ((anode = hpfs_map_anode(s, a, &bh))) {
441da177e4SLinus Torvalds 			hpfs_remove_btree(s, &anode->btree);
451da177e4SLinus Torvalds 			brelse(bh);
461da177e4SLinus Torvalds 			hpfs_free_sectors(s, a, 1);
471da177e4SLinus Torvalds 		}
481da177e4SLinus Torvalds 	}
491da177e4SLinus Torvalds }
501da177e4SLinus Torvalds 
get_indirect_ea(struct super_block * s,int ano,secno a,int size)511da177e4SLinus Torvalds static char *get_indirect_ea(struct super_block *s, int ano, secno a, int size)
521da177e4SLinus Torvalds {
531da177e4SLinus Torvalds 	char *ret;
541da177e4SLinus Torvalds 	if (!(ret = kmalloc(size + 1, GFP_NOFS))) {
55a19189e5SFabian Frederick 		pr_err("out of memory for EA\n");
561da177e4SLinus Torvalds 		return NULL;
571da177e4SLinus Torvalds 	}
581da177e4SLinus Torvalds 	if (hpfs_ea_read(s, a, ano, 0, size, ret)) {
591da177e4SLinus Torvalds 		kfree(ret);
601da177e4SLinus Torvalds 		return NULL;
611da177e4SLinus Torvalds 	}
621da177e4SLinus Torvalds 	ret[size] = 0;
631da177e4SLinus Torvalds 	return ret;
641da177e4SLinus Torvalds }
651da177e4SLinus Torvalds 
set_indirect_ea(struct super_block * s,int ano,secno a,const char * data,int size)667e7742eeSAl Viro static void set_indirect_ea(struct super_block *s, int ano, secno a,
677e7742eeSAl Viro 			    const char *data, int size)
681da177e4SLinus Torvalds {
691da177e4SLinus Torvalds 	hpfs_ea_write(s, a, ano, 0, size, data);
701da177e4SLinus Torvalds }
711da177e4SLinus Torvalds 
721da177e4SLinus Torvalds /* Read an extended attribute named 'key' into the provided buffer */
731da177e4SLinus Torvalds 
hpfs_read_ea(struct super_block * s,struct fnode * fnode,char * key,char * buf,int size)741da177e4SLinus Torvalds int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
751da177e4SLinus Torvalds 		char *buf, int size)
761da177e4SLinus Torvalds {
771da177e4SLinus Torvalds 	unsigned pos;
781da177e4SLinus Torvalds 	int ano, len;
791da177e4SLinus Torvalds 	secno a;
80c3514817SMikulas Patocka 	char ex[4 + 255 + 1 + 8];
811da177e4SLinus Torvalds 	struct extended_attribute *ea;
821da177e4SLinus Torvalds 	struct extended_attribute *ea_end = fnode_end_ea(fnode);
831da177e4SLinus Torvalds 	for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
841da177e4SLinus Torvalds 		if (!strcmp(ea->name, key)) {
854085e155SAl Viro 			if (ea_indirect(ea))
861da177e4SLinus Torvalds 				goto indirect;
87d0969d19SMikulas Patocka 			if (ea_valuelen(ea) >= size)
881da177e4SLinus Torvalds 				return -EINVAL;
89d0969d19SMikulas Patocka 			memcpy(buf, ea_data(ea), ea_valuelen(ea));
90d0969d19SMikulas Patocka 			buf[ea_valuelen(ea)] = 0;
911da177e4SLinus Torvalds 			return 0;
921da177e4SLinus Torvalds 		}
930b69760bSMikulas Patocka 	a = le32_to_cpu(fnode->ea_secno);
940b69760bSMikulas Patocka 	len = le32_to_cpu(fnode->ea_size_l);
95c4c99543SAl Viro 	ano = fnode_in_anode(fnode);
961da177e4SLinus Torvalds 	pos = 0;
971da177e4SLinus Torvalds 	while (pos < len) {
981da177e4SLinus Torvalds 		ea = (struct extended_attribute *)ex;
991da177e4SLinus Torvalds 		if (pos + 4 > len) {
1001da177e4SLinus Torvalds 			hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
1011da177e4SLinus Torvalds 				ano ? "anode" : "sectors", a, len);
1021da177e4SLinus Torvalds 			return -EIO;
1031da177e4SLinus Torvalds 		}
1041da177e4SLinus Torvalds 		if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO;
1054085e155SAl Viro 		if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4))
1061da177e4SLinus Torvalds 			return -EIO;
1071da177e4SLinus Torvalds 		if (!strcmp(ea->name, key)) {
1084085e155SAl Viro 			if (ea_indirect(ea))
1091da177e4SLinus Torvalds 				goto indirect;
110d0969d19SMikulas Patocka 			if (ea_valuelen(ea) >= size)
1111da177e4SLinus Torvalds 				return -EINVAL;
112d0969d19SMikulas Patocka 			if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), buf))
1131da177e4SLinus Torvalds 				return -EIO;
114d0969d19SMikulas Patocka 			buf[ea_valuelen(ea)] = 0;
1151da177e4SLinus Torvalds 			return 0;
1161da177e4SLinus Torvalds 		}
117d0969d19SMikulas Patocka 		pos += ea->namelen + ea_valuelen(ea) + 5;
1181da177e4SLinus Torvalds 	}
1191da177e4SLinus Torvalds 	return -ENOENT;
1201da177e4SLinus Torvalds indirect:
1211da177e4SLinus Torvalds 	if (ea_len(ea) >= size)
1221da177e4SLinus Torvalds 		return -EINVAL;
1234085e155SAl Viro 	if (hpfs_ea_read(s, ea_sec(ea), ea_in_anode(ea), 0, ea_len(ea), buf))
1241da177e4SLinus Torvalds 		return -EIO;
1251da177e4SLinus Torvalds 	buf[ea_len(ea)] = 0;
1261da177e4SLinus Torvalds 	return 0;
1271da177e4SLinus Torvalds }
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds /* Read an extended attribute named 'key' */
hpfs_get_ea(struct super_block * s,struct fnode * fnode,char * key,int * size)1301da177e4SLinus Torvalds char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *size)
1311da177e4SLinus Torvalds {
1321da177e4SLinus Torvalds 	char *ret;
1331da177e4SLinus Torvalds 	unsigned pos;
1341da177e4SLinus Torvalds 	int ano, len;
1351da177e4SLinus Torvalds 	secno a;
1361da177e4SLinus Torvalds 	struct extended_attribute *ea;
1371da177e4SLinus Torvalds 	struct extended_attribute *ea_end = fnode_end_ea(fnode);
1381da177e4SLinus Torvalds 	for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
1391da177e4SLinus Torvalds 		if (!strcmp(ea->name, key)) {
1404085e155SAl Viro 			if (ea_indirect(ea))
1414085e155SAl Viro 				return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea));
142d0969d19SMikulas Patocka 			if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
143a19189e5SFabian Frederick 				pr_err("out of memory for EA\n");
1441da177e4SLinus Torvalds 				return NULL;
1451da177e4SLinus Torvalds 			}
146d0969d19SMikulas Patocka 			memcpy(ret, ea_data(ea), ea_valuelen(ea));
147d0969d19SMikulas Patocka 			ret[ea_valuelen(ea)] = 0;
1481da177e4SLinus Torvalds 			return ret;
1491da177e4SLinus Torvalds 		}
1500b69760bSMikulas Patocka 	a = le32_to_cpu(fnode->ea_secno);
1510b69760bSMikulas Patocka 	len = le32_to_cpu(fnode->ea_size_l);
152c4c99543SAl Viro 	ano = fnode_in_anode(fnode);
1531da177e4SLinus Torvalds 	pos = 0;
1541da177e4SLinus Torvalds 	while (pos < len) {
1551da177e4SLinus Torvalds 		char ex[4 + 255 + 1 + 8];
1561da177e4SLinus Torvalds 		ea = (struct extended_attribute *)ex;
1571da177e4SLinus Torvalds 		if (pos + 4 > len) {
1581da177e4SLinus Torvalds 			hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
1591da177e4SLinus Torvalds 				ano ? "anode" : "sectors", a, len);
1601da177e4SLinus Torvalds 			return NULL;
1611da177e4SLinus Torvalds 		}
1621da177e4SLinus Torvalds 		if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return NULL;
1634085e155SAl Viro 		if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4))
1641da177e4SLinus Torvalds 			return NULL;
1651da177e4SLinus Torvalds 		if (!strcmp(ea->name, key)) {
1664085e155SAl Viro 			if (ea_indirect(ea))
1674085e155SAl Viro 				return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea));
168d0969d19SMikulas Patocka 			if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
169a19189e5SFabian Frederick 				pr_err("out of memory for EA\n");
1701da177e4SLinus Torvalds 				return NULL;
1711da177e4SLinus Torvalds 			}
172d0969d19SMikulas Patocka 			if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), ret)) {
1731da177e4SLinus Torvalds 				kfree(ret);
1741da177e4SLinus Torvalds 				return NULL;
1751da177e4SLinus Torvalds 			}
176d0969d19SMikulas Patocka 			ret[ea_valuelen(ea)] = 0;
1771da177e4SLinus Torvalds 			return ret;
1781da177e4SLinus Torvalds 		}
179d0969d19SMikulas Patocka 		pos += ea->namelen + ea_valuelen(ea) + 5;
1801da177e4SLinus Torvalds 	}
1811da177e4SLinus Torvalds 	return NULL;
1821da177e4SLinus Torvalds }
1831da177e4SLinus Torvalds 
1841da177e4SLinus Torvalds /*
1851da177e4SLinus Torvalds  * Update or create extended attribute 'key' with value 'data'. Note that
1861da177e4SLinus Torvalds  * when this ea exists, it MUST have the same size as size of data.
1871da177e4SLinus Torvalds  * This driver can't change sizes of eas ('cause I just don't need it).
1881da177e4SLinus Torvalds  */
1891da177e4SLinus Torvalds 
hpfs_set_ea(struct inode * inode,struct fnode * fnode,const char * key,const char * data,int size)1907e7742eeSAl Viro void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
1917e7742eeSAl Viro 		 const char *data, int size)
1921da177e4SLinus Torvalds {
1931da177e4SLinus Torvalds 	fnode_secno fno = inode->i_ino;
1941da177e4SLinus Torvalds 	struct super_block *s = inode->i_sb;
1951da177e4SLinus Torvalds 	unsigned pos;
1961da177e4SLinus Torvalds 	int ano, len;
1971da177e4SLinus Torvalds 	secno a;
1981da177e4SLinus Torvalds 	unsigned char h[4];
1991da177e4SLinus Torvalds 	struct extended_attribute *ea;
2001da177e4SLinus Torvalds 	struct extended_attribute *ea_end = fnode_end_ea(fnode);
2011da177e4SLinus Torvalds 	for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
2021da177e4SLinus Torvalds 		if (!strcmp(ea->name, key)) {
2034085e155SAl Viro 			if (ea_indirect(ea)) {
2041da177e4SLinus Torvalds 				if (ea_len(ea) == size)
2054085e155SAl Viro 					set_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), data, size);
206d0969d19SMikulas Patocka 			} else if (ea_valuelen(ea) == size) {
2071da177e4SLinus Torvalds 				memcpy(ea_data(ea), data, size);
2081da177e4SLinus Torvalds 			}
2091da177e4SLinus Torvalds 			return;
2101da177e4SLinus Torvalds 		}
2110b69760bSMikulas Patocka 	a = le32_to_cpu(fnode->ea_secno);
2120b69760bSMikulas Patocka 	len = le32_to_cpu(fnode->ea_size_l);
213c4c99543SAl Viro 	ano = fnode_in_anode(fnode);
2141da177e4SLinus Torvalds 	pos = 0;
2151da177e4SLinus Torvalds 	while (pos < len) {
2161da177e4SLinus Torvalds 		char ex[4 + 255 + 1 + 8];
2171da177e4SLinus Torvalds 		ea = (struct extended_attribute *)ex;
2181da177e4SLinus Torvalds 		if (pos + 4 > len) {
2191da177e4SLinus Torvalds 			hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
2201da177e4SLinus Torvalds 				ano ? "anode" : "sectors", a, len);
2211da177e4SLinus Torvalds 			return;
2221da177e4SLinus Torvalds 		}
2231da177e4SLinus Torvalds 		if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
2244085e155SAl Viro 		if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4))
2251da177e4SLinus Torvalds 			return;
2261da177e4SLinus Torvalds 		if (!strcmp(ea->name, key)) {
2274085e155SAl Viro 			if (ea_indirect(ea)) {
2281da177e4SLinus Torvalds 				if (ea_len(ea) == size)
2294085e155SAl Viro 					set_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), data, size);
2301da177e4SLinus Torvalds 			}
2311da177e4SLinus Torvalds 			else {
232d0969d19SMikulas Patocka 				if (ea_valuelen(ea) == size)
2331da177e4SLinus Torvalds 					hpfs_ea_write(s, a, ano, pos + 4 + ea->namelen + 1, size, data);
2341da177e4SLinus Torvalds 			}
2351da177e4SLinus Torvalds 			return;
2361da177e4SLinus Torvalds 		}
237d0969d19SMikulas Patocka 		pos += ea->namelen + ea_valuelen(ea) + 5;
2381da177e4SLinus Torvalds 	}
2390b69760bSMikulas Patocka 	if (!le16_to_cpu(fnode->ea_offs)) {
2400b69760bSMikulas Patocka 		/*if (le16_to_cpu(fnode->ea_size_s)) {
2411da177e4SLinus Torvalds 			hpfs_error(s, "fnode %08x: ea_size_s == %03x, ea_offs == 0",
2420b69760bSMikulas Patocka 				inode->i_ino, le16_to_cpu(fnode->ea_size_s));
2431da177e4SLinus Torvalds 			return;
2441da177e4SLinus Torvalds 		}*/
2450b69760bSMikulas Patocka 		fnode->ea_offs = cpu_to_le16(0xc4);
2461da177e4SLinus Torvalds 	}
2470b69760bSMikulas Patocka 	if (le16_to_cpu(fnode->ea_offs) < 0xc4 || le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200) {
24818debbbcSRandy Dunlap 		hpfs_error(s, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x",
24918debbbcSRandy Dunlap 			(unsigned long)inode->i_ino,
250de5e2b36SAl Viro 			le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s));
2511da177e4SLinus Torvalds 		return;
2521da177e4SLinus Torvalds 	}
2530b69760bSMikulas Patocka 	if ((le16_to_cpu(fnode->ea_size_s) || !le32_to_cpu(fnode->ea_size_l)) &&
2540b69760bSMikulas Patocka 	     le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5 <= 0x200) {
2551da177e4SLinus Torvalds 		ea = fnode_end_ea(fnode);
2561da177e4SLinus Torvalds 		*(char *)ea = 0;
2571da177e4SLinus Torvalds 		ea->namelen = strlen(key);
258d0969d19SMikulas Patocka 		ea->valuelen_lo = size;
259d0969d19SMikulas Patocka 		ea->valuelen_hi = size >> 8;
2601da177e4SLinus Torvalds 		strcpy(ea->name, key);
2611da177e4SLinus Torvalds 		memcpy(ea_data(ea), data, size);
2620b69760bSMikulas Patocka 		fnode->ea_size_s = cpu_to_le16(le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5);
2631da177e4SLinus Torvalds 		goto ret;
2641da177e4SLinus Torvalds 	}
2651da177e4SLinus Torvalds 	/* Most the code here is 99.9993422% unused. I hope there are no bugs.
2661da177e4SLinus Torvalds 	   But what .. HPFS.IFS has also bugs in ea management. */
2670b69760bSMikulas Patocka 	if (le16_to_cpu(fnode->ea_size_s) && !le32_to_cpu(fnode->ea_size_l)) {
2681da177e4SLinus Torvalds 		secno n;
2691da177e4SLinus Torvalds 		struct buffer_head *bh;
2701da177e4SLinus Torvalds 		char *data;
2717d23ce36SMikulas Patocka 		if (!(n = hpfs_alloc_sector(s, fno, 1, 0))) return;
2721da177e4SLinus Torvalds 		if (!(data = hpfs_get_sector(s, n, &bh))) {
2731da177e4SLinus Torvalds 			hpfs_free_sectors(s, n, 1);
2741da177e4SLinus Torvalds 			return;
2751da177e4SLinus Torvalds 		}
2760b69760bSMikulas Patocka 		memcpy(data, fnode_ea(fnode), le16_to_cpu(fnode->ea_size_s));
2770b69760bSMikulas Patocka 		fnode->ea_size_l = cpu_to_le32(le16_to_cpu(fnode->ea_size_s));
2780b69760bSMikulas Patocka 		fnode->ea_size_s = cpu_to_le16(0);
2790b69760bSMikulas Patocka 		fnode->ea_secno = cpu_to_le32(n);
280c4c99543SAl Viro 		fnode->flags &= ~FNODE_anode;
2811da177e4SLinus Torvalds 		mark_buffer_dirty(bh);
2821da177e4SLinus Torvalds 		brelse(bh);
2831da177e4SLinus Torvalds 	}
2840b69760bSMikulas Patocka 	pos = le32_to_cpu(fnode->ea_size_l) + 5 + strlen(key) + size;
2850b69760bSMikulas Patocka 	len = (le32_to_cpu(fnode->ea_size_l) + 511) >> 9;
2861da177e4SLinus Torvalds 	if (pos >= 30000) goto bail;
2871da177e4SLinus Torvalds 	while (((pos + 511) >> 9) > len) {
2881da177e4SLinus Torvalds 		if (!len) {
2890b69760bSMikulas Patocka 			secno q = hpfs_alloc_sector(s, fno, 1, 0);
2900b69760bSMikulas Patocka 			if (!q) goto bail;
2910b69760bSMikulas Patocka 			fnode->ea_secno = cpu_to_le32(q);
292c4c99543SAl Viro 			fnode->flags &= ~FNODE_anode;
2931da177e4SLinus Torvalds 			len++;
294c4c99543SAl Viro 		} else if (!fnode_in_anode(fnode)) {
2950b69760bSMikulas Patocka 			if (hpfs_alloc_if_possible(s, le32_to_cpu(fnode->ea_secno) + len)) {
2961da177e4SLinus Torvalds 				len++;
2971da177e4SLinus Torvalds 			} else {
2981da177e4SLinus Torvalds 				/* Aargh... don't know how to create ea anodes :-( */
2991da177e4SLinus Torvalds 				/*struct buffer_head *bh;
3001da177e4SLinus Torvalds 				struct anode *anode;
3011da177e4SLinus Torvalds 				anode_secno a_s;
3021da177e4SLinus Torvalds 				if (!(anode = hpfs_alloc_anode(s, fno, &a_s, &bh)))
3031da177e4SLinus Torvalds 					goto bail;
3040b69760bSMikulas Patocka 				anode->up = cpu_to_le32(fno);
3051da177e4SLinus Torvalds 				anode->btree.fnode_parent = 1;
3061da177e4SLinus Torvalds 				anode->btree.n_free_nodes--;
3071da177e4SLinus Torvalds 				anode->btree.n_used_nodes++;
3080b69760bSMikulas Patocka 				anode->btree.first_free = cpu_to_le16(le16_to_cpu(anode->btree.first_free) + 12);
3090b69760bSMikulas Patocka 				anode->u.external[0].disk_secno = cpu_to_le32(le32_to_cpu(fnode->ea_secno));
3100b69760bSMikulas Patocka 				anode->u.external[0].file_secno = cpu_to_le32(0);
3110b69760bSMikulas Patocka 				anode->u.external[0].length = cpu_to_le32(len);
3121da177e4SLinus Torvalds 				mark_buffer_dirty(bh);
3131da177e4SLinus Torvalds 				brelse(bh);
314c4c99543SAl Viro 				fnode->flags |= FNODE_anode;
3150b69760bSMikulas Patocka 				fnode->ea_secno = cpu_to_le32(a_s);*/
3161da177e4SLinus Torvalds 				secno new_sec;
3171da177e4SLinus Torvalds 				int i;
3187d23ce36SMikulas Patocka 				if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9))))
3191da177e4SLinus Torvalds 					goto bail;
3201da177e4SLinus Torvalds 				for (i = 0; i < len; i++) {
3211da177e4SLinus Torvalds 					struct buffer_head *bh1, *bh2;
3221da177e4SLinus Torvalds 					void *b1, *b2;
3230b69760bSMikulas Patocka 					if (!(b1 = hpfs_map_sector(s, le32_to_cpu(fnode->ea_secno) + i, &bh1, len - i - 1))) {
3241da177e4SLinus Torvalds 						hpfs_free_sectors(s, new_sec, (pos + 511) >> 9);
3251da177e4SLinus Torvalds 						goto bail;
3261da177e4SLinus Torvalds 					}
3271da177e4SLinus Torvalds 					if (!(b2 = hpfs_get_sector(s, new_sec + i, &bh2))) {
3281da177e4SLinus Torvalds 						brelse(bh1);
3291da177e4SLinus Torvalds 						hpfs_free_sectors(s, new_sec, (pos + 511) >> 9);
3301da177e4SLinus Torvalds 						goto bail;
3311da177e4SLinus Torvalds 					}
3321da177e4SLinus Torvalds 					memcpy(b2, b1, 512);
3331da177e4SLinus Torvalds 					brelse(bh1);
3341da177e4SLinus Torvalds 					mark_buffer_dirty(bh2);
3351da177e4SLinus Torvalds 					brelse(bh2);
3361da177e4SLinus Torvalds 				}
3370b69760bSMikulas Patocka 				hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno), len);
3380b69760bSMikulas Patocka 				fnode->ea_secno = cpu_to_le32(new_sec);
3391da177e4SLinus Torvalds 				len = (pos + 511) >> 9;
3401da177e4SLinus Torvalds 			}
3411da177e4SLinus Torvalds 		}
342c4c99543SAl Viro 		if (fnode_in_anode(fnode)) {
3430b69760bSMikulas Patocka 			if (hpfs_add_sector_to_btree(s, le32_to_cpu(fnode->ea_secno),
3441da177e4SLinus Torvalds 						     0, len) != -1) {
3451da177e4SLinus Torvalds 				len++;
3461da177e4SLinus Torvalds 			} else {
3471da177e4SLinus Torvalds 				goto bail;
3481da177e4SLinus Torvalds 			}
3491da177e4SLinus Torvalds 		}
3501da177e4SLinus Torvalds 	}
3511da177e4SLinus Torvalds 	h[0] = 0;
3521da177e4SLinus Torvalds 	h[1] = strlen(key);
3531da177e4SLinus Torvalds 	h[2] = size & 0xff;
3541da177e4SLinus Torvalds 	h[3] = size >> 8;
355c4c99543SAl Viro 	if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l), 4, h)) goto bail;
356c4c99543SAl Viro 	if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l) + 4, h[1] + 1, key)) goto bail;
357c4c99543SAl Viro 	if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l) + 5 + h[1], size, data)) goto bail;
3580b69760bSMikulas Patocka 	fnode->ea_size_l = cpu_to_le32(pos);
3591da177e4SLinus Torvalds 	ret:
3601da177e4SLinus Torvalds 	hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size;
3611da177e4SLinus Torvalds 	return;
3621da177e4SLinus Torvalds 	bail:
3630b69760bSMikulas Patocka 	if (le32_to_cpu(fnode->ea_secno))
364c4c99543SAl Viro 		if (fnode_in_anode(fnode)) hpfs_truncate_btree(s, le32_to_cpu(fnode->ea_secno), 1, (le32_to_cpu(fnode->ea_size_l) + 511) >> 9);
3650b69760bSMikulas Patocka 		else hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno) + ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9), len - ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9));
3660b69760bSMikulas Patocka 	else fnode->ea_secno = fnode->ea_size_l = cpu_to_le32(0);
3671da177e4SLinus Torvalds }
3681da177e4SLinus Torvalds 
369