162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/fs/hpfs/ea.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * handling extended attributes 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "hpfs_fn.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* Remove external extended attributes. ano specifies whether a is a 1362306a36Sopenharmony_ci direct sector where eas starts or an anode */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_civoid hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci unsigned pos = 0; 1862306a36Sopenharmony_ci while (pos < len) { 1962306a36Sopenharmony_ci char ex[4 + 255 + 1 + 8]; 2062306a36Sopenharmony_ci struct extended_attribute *ea = (struct extended_attribute *)ex; 2162306a36Sopenharmony_ci if (pos + 4 > len) { 2262306a36Sopenharmony_ci hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x", 2362306a36Sopenharmony_ci ano ? "anode" : "sectors", a, len); 2462306a36Sopenharmony_ci return; 2562306a36Sopenharmony_ci } 2662306a36Sopenharmony_ci if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return; 2762306a36Sopenharmony_ci if (ea_indirect(ea)) { 2862306a36Sopenharmony_ci if (ea_valuelen(ea) != 8) { 2962306a36Sopenharmony_ci hpfs_error(s, "ea_indirect(ea) set while ea->valuelen!=8, %s %08x, pos %08x", 3062306a36Sopenharmony_ci ano ? "anode" : "sectors", a, pos); 3162306a36Sopenharmony_ci return; 3262306a36Sopenharmony_ci } 3362306a36Sopenharmony_ci if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 9, ex+4)) 3462306a36Sopenharmony_ci return; 3562306a36Sopenharmony_ci hpfs_ea_remove(s, ea_sec(ea), ea_in_anode(ea), ea_len(ea)); 3662306a36Sopenharmony_ci } 3762306a36Sopenharmony_ci pos += ea->namelen + ea_valuelen(ea) + 5; 3862306a36Sopenharmony_ci } 3962306a36Sopenharmony_ci if (!ano) hpfs_free_sectors(s, a, (len+511) >> 9); 4062306a36Sopenharmony_ci else { 4162306a36Sopenharmony_ci struct buffer_head *bh; 4262306a36Sopenharmony_ci struct anode *anode; 4362306a36Sopenharmony_ci if ((anode = hpfs_map_anode(s, a, &bh))) { 4462306a36Sopenharmony_ci hpfs_remove_btree(s, &anode->btree); 4562306a36Sopenharmony_ci brelse(bh); 4662306a36Sopenharmony_ci hpfs_free_sectors(s, a, 1); 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci } 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic char *get_indirect_ea(struct super_block *s, int ano, secno a, int size) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci char *ret; 5462306a36Sopenharmony_ci if (!(ret = kmalloc(size + 1, GFP_NOFS))) { 5562306a36Sopenharmony_ci pr_err("out of memory for EA\n"); 5662306a36Sopenharmony_ci return NULL; 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci if (hpfs_ea_read(s, a, ano, 0, size, ret)) { 5962306a36Sopenharmony_ci kfree(ret); 6062306a36Sopenharmony_ci return NULL; 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci ret[size] = 0; 6362306a36Sopenharmony_ci return ret; 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic void set_indirect_ea(struct super_block *s, int ano, secno a, 6762306a36Sopenharmony_ci const char *data, int size) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci hpfs_ea_write(s, a, ano, 0, size, data); 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* Read an extended attribute named 'key' into the provided buffer */ 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ciint hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key, 7562306a36Sopenharmony_ci char *buf, int size) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci unsigned pos; 7862306a36Sopenharmony_ci int ano, len; 7962306a36Sopenharmony_ci secno a; 8062306a36Sopenharmony_ci char ex[4 + 255 + 1 + 8]; 8162306a36Sopenharmony_ci struct extended_attribute *ea; 8262306a36Sopenharmony_ci struct extended_attribute *ea_end = fnode_end_ea(fnode); 8362306a36Sopenharmony_ci for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) 8462306a36Sopenharmony_ci if (!strcmp(ea->name, key)) { 8562306a36Sopenharmony_ci if (ea_indirect(ea)) 8662306a36Sopenharmony_ci goto indirect; 8762306a36Sopenharmony_ci if (ea_valuelen(ea) >= size) 8862306a36Sopenharmony_ci return -EINVAL; 8962306a36Sopenharmony_ci memcpy(buf, ea_data(ea), ea_valuelen(ea)); 9062306a36Sopenharmony_ci buf[ea_valuelen(ea)] = 0; 9162306a36Sopenharmony_ci return 0; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci a = le32_to_cpu(fnode->ea_secno); 9462306a36Sopenharmony_ci len = le32_to_cpu(fnode->ea_size_l); 9562306a36Sopenharmony_ci ano = fnode_in_anode(fnode); 9662306a36Sopenharmony_ci pos = 0; 9762306a36Sopenharmony_ci while (pos < len) { 9862306a36Sopenharmony_ci ea = (struct extended_attribute *)ex; 9962306a36Sopenharmony_ci if (pos + 4 > len) { 10062306a36Sopenharmony_ci hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x", 10162306a36Sopenharmony_ci ano ? "anode" : "sectors", a, len); 10262306a36Sopenharmony_ci return -EIO; 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO; 10562306a36Sopenharmony_ci if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4)) 10662306a36Sopenharmony_ci return -EIO; 10762306a36Sopenharmony_ci if (!strcmp(ea->name, key)) { 10862306a36Sopenharmony_ci if (ea_indirect(ea)) 10962306a36Sopenharmony_ci goto indirect; 11062306a36Sopenharmony_ci if (ea_valuelen(ea) >= size) 11162306a36Sopenharmony_ci return -EINVAL; 11262306a36Sopenharmony_ci if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), buf)) 11362306a36Sopenharmony_ci return -EIO; 11462306a36Sopenharmony_ci buf[ea_valuelen(ea)] = 0; 11562306a36Sopenharmony_ci return 0; 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci pos += ea->namelen + ea_valuelen(ea) + 5; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci return -ENOENT; 12062306a36Sopenharmony_ciindirect: 12162306a36Sopenharmony_ci if (ea_len(ea) >= size) 12262306a36Sopenharmony_ci return -EINVAL; 12362306a36Sopenharmony_ci if (hpfs_ea_read(s, ea_sec(ea), ea_in_anode(ea), 0, ea_len(ea), buf)) 12462306a36Sopenharmony_ci return -EIO; 12562306a36Sopenharmony_ci buf[ea_len(ea)] = 0; 12662306a36Sopenharmony_ci return 0; 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/* Read an extended attribute named 'key' */ 13062306a36Sopenharmony_cichar *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *size) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci char *ret; 13362306a36Sopenharmony_ci unsigned pos; 13462306a36Sopenharmony_ci int ano, len; 13562306a36Sopenharmony_ci secno a; 13662306a36Sopenharmony_ci struct extended_attribute *ea; 13762306a36Sopenharmony_ci struct extended_attribute *ea_end = fnode_end_ea(fnode); 13862306a36Sopenharmony_ci for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) 13962306a36Sopenharmony_ci if (!strcmp(ea->name, key)) { 14062306a36Sopenharmony_ci if (ea_indirect(ea)) 14162306a36Sopenharmony_ci return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea)); 14262306a36Sopenharmony_ci if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { 14362306a36Sopenharmony_ci pr_err("out of memory for EA\n"); 14462306a36Sopenharmony_ci return NULL; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci memcpy(ret, ea_data(ea), ea_valuelen(ea)); 14762306a36Sopenharmony_ci ret[ea_valuelen(ea)] = 0; 14862306a36Sopenharmony_ci return ret; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci a = le32_to_cpu(fnode->ea_secno); 15162306a36Sopenharmony_ci len = le32_to_cpu(fnode->ea_size_l); 15262306a36Sopenharmony_ci ano = fnode_in_anode(fnode); 15362306a36Sopenharmony_ci pos = 0; 15462306a36Sopenharmony_ci while (pos < len) { 15562306a36Sopenharmony_ci char ex[4 + 255 + 1 + 8]; 15662306a36Sopenharmony_ci ea = (struct extended_attribute *)ex; 15762306a36Sopenharmony_ci if (pos + 4 > len) { 15862306a36Sopenharmony_ci hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x", 15962306a36Sopenharmony_ci ano ? "anode" : "sectors", a, len); 16062306a36Sopenharmony_ci return NULL; 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return NULL; 16362306a36Sopenharmony_ci if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4)) 16462306a36Sopenharmony_ci return NULL; 16562306a36Sopenharmony_ci if (!strcmp(ea->name, key)) { 16662306a36Sopenharmony_ci if (ea_indirect(ea)) 16762306a36Sopenharmony_ci return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea)); 16862306a36Sopenharmony_ci if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { 16962306a36Sopenharmony_ci pr_err("out of memory for EA\n"); 17062306a36Sopenharmony_ci return NULL; 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), ret)) { 17362306a36Sopenharmony_ci kfree(ret); 17462306a36Sopenharmony_ci return NULL; 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci ret[ea_valuelen(ea)] = 0; 17762306a36Sopenharmony_ci return ret; 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci pos += ea->namelen + ea_valuelen(ea) + 5; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci return NULL; 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci/* 18562306a36Sopenharmony_ci * Update or create extended attribute 'key' with value 'data'. Note that 18662306a36Sopenharmony_ci * when this ea exists, it MUST have the same size as size of data. 18762306a36Sopenharmony_ci * This driver can't change sizes of eas ('cause I just don't need it). 18862306a36Sopenharmony_ci */ 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_civoid hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, 19162306a36Sopenharmony_ci const char *data, int size) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci fnode_secno fno = inode->i_ino; 19462306a36Sopenharmony_ci struct super_block *s = inode->i_sb; 19562306a36Sopenharmony_ci unsigned pos; 19662306a36Sopenharmony_ci int ano, len; 19762306a36Sopenharmony_ci secno a; 19862306a36Sopenharmony_ci unsigned char h[4]; 19962306a36Sopenharmony_ci struct extended_attribute *ea; 20062306a36Sopenharmony_ci struct extended_attribute *ea_end = fnode_end_ea(fnode); 20162306a36Sopenharmony_ci for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) 20262306a36Sopenharmony_ci if (!strcmp(ea->name, key)) { 20362306a36Sopenharmony_ci if (ea_indirect(ea)) { 20462306a36Sopenharmony_ci if (ea_len(ea) == size) 20562306a36Sopenharmony_ci set_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), data, size); 20662306a36Sopenharmony_ci } else if (ea_valuelen(ea) == size) { 20762306a36Sopenharmony_ci memcpy(ea_data(ea), data, size); 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci return; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci a = le32_to_cpu(fnode->ea_secno); 21262306a36Sopenharmony_ci len = le32_to_cpu(fnode->ea_size_l); 21362306a36Sopenharmony_ci ano = fnode_in_anode(fnode); 21462306a36Sopenharmony_ci pos = 0; 21562306a36Sopenharmony_ci while (pos < len) { 21662306a36Sopenharmony_ci char ex[4 + 255 + 1 + 8]; 21762306a36Sopenharmony_ci ea = (struct extended_attribute *)ex; 21862306a36Sopenharmony_ci if (pos + 4 > len) { 21962306a36Sopenharmony_ci hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x", 22062306a36Sopenharmony_ci ano ? "anode" : "sectors", a, len); 22162306a36Sopenharmony_ci return; 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return; 22462306a36Sopenharmony_ci if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4)) 22562306a36Sopenharmony_ci return; 22662306a36Sopenharmony_ci if (!strcmp(ea->name, key)) { 22762306a36Sopenharmony_ci if (ea_indirect(ea)) { 22862306a36Sopenharmony_ci if (ea_len(ea) == size) 22962306a36Sopenharmony_ci set_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), data, size); 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci else { 23262306a36Sopenharmony_ci if (ea_valuelen(ea) == size) 23362306a36Sopenharmony_ci hpfs_ea_write(s, a, ano, pos + 4 + ea->namelen + 1, size, data); 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci return; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci pos += ea->namelen + ea_valuelen(ea) + 5; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci if (!le16_to_cpu(fnode->ea_offs)) { 24062306a36Sopenharmony_ci /*if (le16_to_cpu(fnode->ea_size_s)) { 24162306a36Sopenharmony_ci hpfs_error(s, "fnode %08x: ea_size_s == %03x, ea_offs == 0", 24262306a36Sopenharmony_ci inode->i_ino, le16_to_cpu(fnode->ea_size_s)); 24362306a36Sopenharmony_ci return; 24462306a36Sopenharmony_ci }*/ 24562306a36Sopenharmony_ci fnode->ea_offs = cpu_to_le16(0xc4); 24662306a36Sopenharmony_ci } 24762306a36Sopenharmony_ci 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) { 24862306a36Sopenharmony_ci hpfs_error(s, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x", 24962306a36Sopenharmony_ci (unsigned long)inode->i_ino, 25062306a36Sopenharmony_ci le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s)); 25162306a36Sopenharmony_ci return; 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci if ((le16_to_cpu(fnode->ea_size_s) || !le32_to_cpu(fnode->ea_size_l)) && 25462306a36Sopenharmony_ci 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) { 25562306a36Sopenharmony_ci ea = fnode_end_ea(fnode); 25662306a36Sopenharmony_ci *(char *)ea = 0; 25762306a36Sopenharmony_ci ea->namelen = strlen(key); 25862306a36Sopenharmony_ci ea->valuelen_lo = size; 25962306a36Sopenharmony_ci ea->valuelen_hi = size >> 8; 26062306a36Sopenharmony_ci strcpy(ea->name, key); 26162306a36Sopenharmony_ci memcpy(ea_data(ea), data, size); 26262306a36Sopenharmony_ci fnode->ea_size_s = cpu_to_le16(le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5); 26362306a36Sopenharmony_ci goto ret; 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci /* Most the code here is 99.9993422% unused. I hope there are no bugs. 26662306a36Sopenharmony_ci But what .. HPFS.IFS has also bugs in ea management. */ 26762306a36Sopenharmony_ci if (le16_to_cpu(fnode->ea_size_s) && !le32_to_cpu(fnode->ea_size_l)) { 26862306a36Sopenharmony_ci secno n; 26962306a36Sopenharmony_ci struct buffer_head *bh; 27062306a36Sopenharmony_ci char *data; 27162306a36Sopenharmony_ci if (!(n = hpfs_alloc_sector(s, fno, 1, 0))) return; 27262306a36Sopenharmony_ci if (!(data = hpfs_get_sector(s, n, &bh))) { 27362306a36Sopenharmony_ci hpfs_free_sectors(s, n, 1); 27462306a36Sopenharmony_ci return; 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci memcpy(data, fnode_ea(fnode), le16_to_cpu(fnode->ea_size_s)); 27762306a36Sopenharmony_ci fnode->ea_size_l = cpu_to_le32(le16_to_cpu(fnode->ea_size_s)); 27862306a36Sopenharmony_ci fnode->ea_size_s = cpu_to_le16(0); 27962306a36Sopenharmony_ci fnode->ea_secno = cpu_to_le32(n); 28062306a36Sopenharmony_ci fnode->flags &= ~FNODE_anode; 28162306a36Sopenharmony_ci mark_buffer_dirty(bh); 28262306a36Sopenharmony_ci brelse(bh); 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci pos = le32_to_cpu(fnode->ea_size_l) + 5 + strlen(key) + size; 28562306a36Sopenharmony_ci len = (le32_to_cpu(fnode->ea_size_l) + 511) >> 9; 28662306a36Sopenharmony_ci if (pos >= 30000) goto bail; 28762306a36Sopenharmony_ci while (((pos + 511) >> 9) > len) { 28862306a36Sopenharmony_ci if (!len) { 28962306a36Sopenharmony_ci secno q = hpfs_alloc_sector(s, fno, 1, 0); 29062306a36Sopenharmony_ci if (!q) goto bail; 29162306a36Sopenharmony_ci fnode->ea_secno = cpu_to_le32(q); 29262306a36Sopenharmony_ci fnode->flags &= ~FNODE_anode; 29362306a36Sopenharmony_ci len++; 29462306a36Sopenharmony_ci } else if (!fnode_in_anode(fnode)) { 29562306a36Sopenharmony_ci if (hpfs_alloc_if_possible(s, le32_to_cpu(fnode->ea_secno) + len)) { 29662306a36Sopenharmony_ci len++; 29762306a36Sopenharmony_ci } else { 29862306a36Sopenharmony_ci /* Aargh... don't know how to create ea anodes :-( */ 29962306a36Sopenharmony_ci /*struct buffer_head *bh; 30062306a36Sopenharmony_ci struct anode *anode; 30162306a36Sopenharmony_ci anode_secno a_s; 30262306a36Sopenharmony_ci if (!(anode = hpfs_alloc_anode(s, fno, &a_s, &bh))) 30362306a36Sopenharmony_ci goto bail; 30462306a36Sopenharmony_ci anode->up = cpu_to_le32(fno); 30562306a36Sopenharmony_ci anode->btree.fnode_parent = 1; 30662306a36Sopenharmony_ci anode->btree.n_free_nodes--; 30762306a36Sopenharmony_ci anode->btree.n_used_nodes++; 30862306a36Sopenharmony_ci anode->btree.first_free = cpu_to_le16(le16_to_cpu(anode->btree.first_free) + 12); 30962306a36Sopenharmony_ci anode->u.external[0].disk_secno = cpu_to_le32(le32_to_cpu(fnode->ea_secno)); 31062306a36Sopenharmony_ci anode->u.external[0].file_secno = cpu_to_le32(0); 31162306a36Sopenharmony_ci anode->u.external[0].length = cpu_to_le32(len); 31262306a36Sopenharmony_ci mark_buffer_dirty(bh); 31362306a36Sopenharmony_ci brelse(bh); 31462306a36Sopenharmony_ci fnode->flags |= FNODE_anode; 31562306a36Sopenharmony_ci fnode->ea_secno = cpu_to_le32(a_s);*/ 31662306a36Sopenharmony_ci secno new_sec; 31762306a36Sopenharmony_ci int i; 31862306a36Sopenharmony_ci if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9)))) 31962306a36Sopenharmony_ci goto bail; 32062306a36Sopenharmony_ci for (i = 0; i < len; i++) { 32162306a36Sopenharmony_ci struct buffer_head *bh1, *bh2; 32262306a36Sopenharmony_ci void *b1, *b2; 32362306a36Sopenharmony_ci if (!(b1 = hpfs_map_sector(s, le32_to_cpu(fnode->ea_secno) + i, &bh1, len - i - 1))) { 32462306a36Sopenharmony_ci hpfs_free_sectors(s, new_sec, (pos + 511) >> 9); 32562306a36Sopenharmony_ci goto bail; 32662306a36Sopenharmony_ci } 32762306a36Sopenharmony_ci if (!(b2 = hpfs_get_sector(s, new_sec + i, &bh2))) { 32862306a36Sopenharmony_ci brelse(bh1); 32962306a36Sopenharmony_ci hpfs_free_sectors(s, new_sec, (pos + 511) >> 9); 33062306a36Sopenharmony_ci goto bail; 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci memcpy(b2, b1, 512); 33362306a36Sopenharmony_ci brelse(bh1); 33462306a36Sopenharmony_ci mark_buffer_dirty(bh2); 33562306a36Sopenharmony_ci brelse(bh2); 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno), len); 33862306a36Sopenharmony_ci fnode->ea_secno = cpu_to_le32(new_sec); 33962306a36Sopenharmony_ci len = (pos + 511) >> 9; 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci if (fnode_in_anode(fnode)) { 34362306a36Sopenharmony_ci if (hpfs_add_sector_to_btree(s, le32_to_cpu(fnode->ea_secno), 34462306a36Sopenharmony_ci 0, len) != -1) { 34562306a36Sopenharmony_ci len++; 34662306a36Sopenharmony_ci } else { 34762306a36Sopenharmony_ci goto bail; 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci h[0] = 0; 35262306a36Sopenharmony_ci h[1] = strlen(key); 35362306a36Sopenharmony_ci h[2] = size & 0xff; 35462306a36Sopenharmony_ci h[3] = size >> 8; 35562306a36Sopenharmony_ci 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; 35662306a36Sopenharmony_ci 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; 35762306a36Sopenharmony_ci 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; 35862306a36Sopenharmony_ci fnode->ea_size_l = cpu_to_le32(pos); 35962306a36Sopenharmony_ci ret: 36062306a36Sopenharmony_ci hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size; 36162306a36Sopenharmony_ci return; 36262306a36Sopenharmony_ci bail: 36362306a36Sopenharmony_ci if (le32_to_cpu(fnode->ea_secno)) 36462306a36Sopenharmony_ci 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); 36562306a36Sopenharmony_ci 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)); 36662306a36Sopenharmony_ci else fnode->ea_secno = fnode->ea_size_l = cpu_to_le32(0); 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 369