~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/hpfs/ea.c

Version: ~ [ linux-5.8-rc4 ] ~ [ linux-5.7.7 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.50 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.131 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.187 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.229 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.229 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  *  linux/fs/hpfs/ea.c
  4  *
  5  *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
  6  *
  7  *  handling extended attributes
  8  */
  9 
 10 #include "hpfs_fn.h"
 11 
 12 /* Remove external extended attributes. ano specifies whether a is a 
 13    direct sector where eas starts or an anode */
 14 
 15 void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len)
 16 {
 17         unsigned pos = 0;
 18         while (pos < len) {
 19                 char ex[4 + 255 + 1 + 8];
 20                 struct extended_attribute *ea = (struct extended_attribute *)ex;
 21                 if (pos + 4 > len) {
 22                         hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
 23                                 ano ? "anode" : "sectors", a, len);
 24                         return;
 25                 }
 26                 if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
 27                 if (ea_indirect(ea)) {
 28                         if (ea_valuelen(ea) != 8) {
 29                                 hpfs_error(s, "ea_indirect(ea) set while ea->valuelen!=8, %s %08x, pos %08x",
 30                                         ano ? "anode" : "sectors", a, pos);
 31                                 return;
 32                         }
 33                         if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 9, ex+4))
 34                                 return;
 35                         hpfs_ea_remove(s, ea_sec(ea), ea_in_anode(ea), ea_len(ea));
 36                 }
 37                 pos += ea->namelen + ea_valuelen(ea) + 5;
 38         }
 39         if (!ano) hpfs_free_sectors(s, a, (len+511) >> 9);
 40         else {
 41                 struct buffer_head *bh;
 42                 struct anode *anode;
 43                 if ((anode = hpfs_map_anode(s, a, &bh))) {
 44                         hpfs_remove_btree(s, &anode->btree);
 45                         brelse(bh);
 46                         hpfs_free_sectors(s, a, 1);
 47                 }
 48         }
 49 }
 50 
 51 static char *get_indirect_ea(struct super_block *s, int ano, secno a, int size)
 52 {
 53         char *ret;
 54         if (!(ret = kmalloc(size + 1, GFP_NOFS))) {
 55                 pr_err("out of memory for EA\n");
 56                 return NULL;
 57         }
 58         if (hpfs_ea_read(s, a, ano, 0, size, ret)) {
 59                 kfree(ret);
 60                 return NULL;
 61         }
 62         ret[size] = 0;
 63         return ret;
 64 }
 65 
 66 static void set_indirect_ea(struct super_block *s, int ano, secno a,
 67                             const char *data, int size)
 68 {
 69         hpfs_ea_write(s, a, ano, 0, size, data);
 70 }
 71 
 72 /* Read an extended attribute named 'key' into the provided buffer */
 73 
 74 int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
 75                 char *buf, int size)
 76 {
 77         unsigned pos;
 78         int ano, len;
 79         secno a;
 80         char ex[4 + 255 + 1 + 8];
 81         struct extended_attribute *ea;
 82         struct extended_attribute *ea_end = fnode_end_ea(fnode);
 83         for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
 84                 if (!strcmp(ea->name, key)) {
 85                         if (ea_indirect(ea))
 86                                 goto indirect;
 87                         if (ea_valuelen(ea) >= size)
 88                                 return -EINVAL;
 89                         memcpy(buf, ea_data(ea), ea_valuelen(ea));
 90                         buf[ea_valuelen(ea)] = 0;
 91                         return 0;
 92                 }
 93         a = le32_to_cpu(fnode->ea_secno);
 94         len = le32_to_cpu(fnode->ea_size_l);
 95         ano = fnode_in_anode(fnode);
 96         pos = 0;
 97         while (pos < len) {
 98                 ea = (struct extended_attribute *)ex;
 99                 if (pos + 4 > len) {
100                         hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
101                                 ano ? "anode" : "sectors", a, len);
102                         return -EIO;
103                 }
104                 if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO;
105                 if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4))
106                         return -EIO;
107                 if (!strcmp(ea->name, key)) {
108                         if (ea_indirect(ea))
109                                 goto indirect;
110                         if (ea_valuelen(ea) >= size)
111                                 return -EINVAL;
112                         if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), buf))
113                                 return -EIO;
114                         buf[ea_valuelen(ea)] = 0;
115                         return 0;
116                 }
117                 pos += ea->namelen + ea_valuelen(ea) + 5;
118         }
119         return -ENOENT;
120 indirect:
121         if (ea_len(ea) >= size)
122                 return -EINVAL;
123         if (hpfs_ea_read(s, ea_sec(ea), ea_in_anode(ea), 0, ea_len(ea), buf))
124                 return -EIO;
125         buf[ea_len(ea)] = 0;
126         return 0;
127 }
128 
129 /* Read an extended attribute named 'key' */
130 char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *size)
131 {
132         char *ret;
133         unsigned pos;
134         int ano, len;
135         secno a;
136         struct extended_attribute *ea;
137         struct extended_attribute *ea_end = fnode_end_ea(fnode);
138         for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
139                 if (!strcmp(ea->name, key)) {
140                         if (ea_indirect(ea))
141                                 return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea));
142                         if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
143                                 pr_err("out of memory for EA\n");
144                                 return NULL;
145                         }
146                         memcpy(ret, ea_data(ea), ea_valuelen(ea));
147                         ret[ea_valuelen(ea)] = 0;
148                         return ret;
149                 }
150         a = le32_to_cpu(fnode->ea_secno);
151         len = le32_to_cpu(fnode->ea_size_l);
152         ano = fnode_in_anode(fnode);
153         pos = 0;
154         while (pos < len) {
155                 char ex[4 + 255 + 1 + 8];
156                 ea = (struct extended_attribute *)ex;
157                 if (pos + 4 > len) {
158                         hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
159                                 ano ? "anode" : "sectors", a, len);
160                         return NULL;
161                 }
162                 if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return NULL;
163                 if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4))
164                         return NULL;
165                 if (!strcmp(ea->name, key)) {
166                         if (ea_indirect(ea))
167                                 return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea));
168                         if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
169                                 pr_err("out of memory for EA\n");
170                                 return NULL;
171                         }
172                         if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), ret)) {
173                                 kfree(ret);
174                                 return NULL;
175                         }
176                         ret[ea_valuelen(ea)] = 0;
177                         return ret;
178                 }
179                 pos += ea->namelen + ea_valuelen(ea) + 5;
180         }
181         return NULL;
182 }
183 
184 /* 
185  * Update or create extended attribute 'key' with value 'data'. Note that
186  * when this ea exists, it MUST have the same size as size of data.
187  * This driver can't change sizes of eas ('cause I just don't need it).
188  */
189 
190 void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
191                  const char *data, int size)
192 {
193         fnode_secno fno = inode->i_ino;
194         struct super_block *s = inode->i_sb;
195         unsigned pos;
196         int ano, len;
197         secno a;
198         unsigned char h[4];
199         struct extended_attribute *ea;
200         struct extended_attribute *ea_end = fnode_end_ea(fnode);
201         for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
202                 if (!strcmp(ea->name, key)) {
203                         if (ea_indirect(ea)) {
204                                 if (ea_len(ea) == size)
205                                         set_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), data, size);
206                         } else if (ea_valuelen(ea) == size) {
207                                 memcpy(ea_data(ea), data, size);
208                         }
209                         return;
210                 }
211         a = le32_to_cpu(fnode->ea_secno);
212         len = le32_to_cpu(fnode->ea_size_l);
213         ano = fnode_in_anode(fnode);
214         pos = 0;
215         while (pos < len) {
216                 char ex[4 + 255 + 1 + 8];
217                 ea = (struct extended_attribute *)ex;
218                 if (pos + 4 > len) {
219                         hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
220                                 ano ? "anode" : "sectors", a, len);
221                         return;
222                 }
223                 if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
224                 if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4))
225                         return;
226                 if (!strcmp(ea->name, key)) {
227                         if (ea_indirect(ea)) {
228                                 if (ea_len(ea) == size)
229                                         set_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), data, size);
230                         }
231                         else {
232                                 if (ea_valuelen(ea) == size)
233                                         hpfs_ea_write(s, a, ano, pos + 4 + ea->namelen + 1, size, data);
234                         }
235                         return;
236                 }
237                 pos += ea->namelen + ea_valuelen(ea) + 5;
238         }
239         if (!le16_to_cpu(fnode->ea_offs)) {
240                 /*if (le16_to_cpu(fnode->ea_size_s)) {
241                         hpfs_error(s, "fnode %08x: ea_size_s == %03x, ea_offs == 0",
242                                 inode->i_ino, le16_to_cpu(fnode->ea_size_s));
243                         return;
244                 }*/
245                 fnode->ea_offs = cpu_to_le16(0xc4);
246         }
247         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) {
248                 hpfs_error(s, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x",
249                         (unsigned long)inode->i_ino,
250                         le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s));
251                 return;
252         }
253         if ((le16_to_cpu(fnode->ea_size_s) || !le32_to_cpu(fnode->ea_size_l)) &&
254              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) {
255                 ea = fnode_end_ea(fnode);
256                 *(char *)ea = 0;
257                 ea->namelen = strlen(key);
258                 ea->valuelen_lo = size;
259                 ea->valuelen_hi = size >> 8;
260                 strcpy(ea->name, key);
261                 memcpy(ea_data(ea), data, size);
262                 fnode->ea_size_s = cpu_to_le16(le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5);
263                 goto ret;
264         }
265         /* Most the code here is 99.9993422% unused. I hope there are no bugs.
266            But what .. HPFS.IFS has also bugs in ea management. */
267         if (le16_to_cpu(fnode->ea_size_s) && !le32_to_cpu(fnode->ea_size_l)) {
268                 secno n;
269                 struct buffer_head *bh;
270                 char *data;
271                 if (!(n = hpfs_alloc_sector(s, fno, 1, 0))) return;
272                 if (!(data = hpfs_get_sector(s, n, &bh))) {
273                         hpfs_free_sectors(s, n, 1);
274                         return;
275                 }
276                 memcpy(data, fnode_ea(fnode), le16_to_cpu(fnode->ea_size_s));
277                 fnode->ea_size_l = cpu_to_le32(le16_to_cpu(fnode->ea_size_s));
278                 fnode->ea_size_s = cpu_to_le16(0);
279                 fnode->ea_secno = cpu_to_le32(n);
280                 fnode->flags &= ~FNODE_anode;
281                 mark_buffer_dirty(bh);
282                 brelse(bh);
283         }
284         pos = le32_to_cpu(fnode->ea_size_l) + 5 + strlen(key) + size;
285         len = (le32_to_cpu(fnode->ea_size_l) + 511) >> 9;
286         if (pos >= 30000) goto bail;
287         while (((pos + 511) >> 9) > len) {
288                 if (!len) {
289                         secno q = hpfs_alloc_sector(s, fno, 1, 0);
290                         if (!q) goto bail;
291                         fnode->ea_secno = cpu_to_le32(q);
292                         fnode->flags &= ~FNODE_anode;
293                         len++;
294                 } else if (!fnode_in_anode(fnode)) {
295                         if (hpfs_alloc_if_possible(s, le32_to_cpu(fnode->ea_secno) + len)) {
296                                 len++;
297                         } else {
298                                 /* Aargh... don't know how to create ea anodes :-( */
299                                 /*struct buffer_head *bh;
300                                 struct anode *anode;
301                                 anode_secno a_s;
302                                 if (!(anode = hpfs_alloc_anode(s, fno, &a_s, &bh)))
303                                         goto bail;
304                                 anode->up = cpu_to_le32(fno);
305                                 anode->btree.fnode_parent = 1;
306                                 anode->btree.n_free_nodes--;
307                                 anode->btree.n_used_nodes++;
308                                 anode->btree.first_free = cpu_to_le16(le16_to_cpu(anode->btree.first_free) + 12);
309                                 anode->u.external[0].disk_secno = cpu_to_le32(le32_to_cpu(fnode->ea_secno));
310                                 anode->u.external[0].file_secno = cpu_to_le32(0);
311                                 anode->u.external[0].length = cpu_to_le32(len);
312                                 mark_buffer_dirty(bh);
313                                 brelse(bh);
314                                 fnode->flags |= FNODE_anode;
315                                 fnode->ea_secno = cpu_to_le32(a_s);*/
316                                 secno new_sec;
317                                 int i;
318                                 if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9))))
319                                         goto bail;
320                                 for (i = 0; i < len; i++) {
321                                         struct buffer_head *bh1, *bh2;
322                                         void *b1, *b2;
323                                         if (!(b1 = hpfs_map_sector(s, le32_to_cpu(fnode->ea_secno) + i, &bh1, len - i - 1))) {
324                                                 hpfs_free_sectors(s, new_sec, (pos + 511) >> 9);
325                                                 goto bail;
326                                         }
327                                         if (!(b2 = hpfs_get_sector(s, new_sec + i, &bh2))) {
328                                                 brelse(bh1);
329                                                 hpfs_free_sectors(s, new_sec, (pos + 511) >> 9);
330                                                 goto bail;
331                                         }
332                                         memcpy(b2, b1, 512);
333                                         brelse(bh1);
334                                         mark_buffer_dirty(bh2);
335                                         brelse(bh2);
336                                 }
337                                 hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno), len);
338                                 fnode->ea_secno = cpu_to_le32(new_sec);
339                                 len = (pos + 511) >> 9;
340                         }
341                 }
342                 if (fnode_in_anode(fnode)) {
343                         if (hpfs_add_sector_to_btree(s, le32_to_cpu(fnode->ea_secno),
344                                                      0, len) != -1) {
345                                 len++;
346                         } else {
347                                 goto bail;
348                         }
349                 }
350         }
351         h[0] = 0;
352         h[1] = strlen(key);
353         h[2] = size & 0xff;
354         h[3] = size >> 8;
355         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;
356         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;
357         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;
358         fnode->ea_size_l = cpu_to_le32(pos);
359         ret:
360         hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size;
361         return;
362         bail:
363         if (le32_to_cpu(fnode->ea_secno))
364                 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);
365                 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));
366         else fnode->ea_secno = fnode->ea_size_l = cpu_to_le32(0);
367 }
368         
369 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp