File: /usr/src/linux/fs/hpfs/ea.c

1     /*
2      *  linux/fs/hpfs/ea.c
3      *
4      *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
5      *
6      *  handling extended attributes
7      */
8     
9     #include <linux/string.h>
10     #include "hpfs_fn.h"
11     
12     /* Remove external extended attributes. ano specifies wheter a is a 
13        direct sector where eas start 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) {
28     			if (ea->valuelen != 8) {
29     				hpfs_error(s, "ea->indirect 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->anode, ea_len(ea));
36     		}
37     		pos += ea->namelen + ea->valuelen + 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_KERNEL))) {
55     		printk("HPFS: 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, char *data,
67     			    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     	struct extended_attribute *ea;
81     	struct extended_attribute *ea_end = fnode_end_ea(fnode);
82     	for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
83     		if (!strcmp(ea->name, key)) {
84     			if (ea->indirect)
85     				goto indirect;
86     			if (ea->valuelen >= size)
87     				return -EINVAL;
88     			memcpy(buf, ea_data(ea), ea->valuelen);
89     			buf[ea->valuelen] = 0;
90     			return 0;
91     		}
92     	a = fnode->ea_secno;
93     	len = fnode->ea_size_l;
94     	ano = fnode->ea_anode;
95     	pos = 0;
96     	while (pos < len) {
97     		char ex[4 + 255 + 1 + 8];
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 ? 8 : 0), ex + 4))
106     			return -EIO;
107     		if (!strcmp(ea->name, key)) {
108     			if (ea->indirect)
109     				goto indirect;
110     			if (ea->valuelen >= size)
111     				return -EINVAL;
112     			if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, buf))
113     				return -EIO;
114     			buf[ea->valuelen] = 0;
115     			return 0;
116     		}
117     		pos += ea->namelen + ea->valuelen + 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->anode, 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)
141     				return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea));
142     			if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_KERNEL))) {
143     				printk("HPFS: out of memory for EA\n");
144     				return NULL;
145     			}
146     			memcpy(ret, ea_data(ea), ea->valuelen);
147     			ret[ea->valuelen] = 0;
148     			return ret;
149     		}
150     	a = fnode->ea_secno;
151     	len = fnode->ea_size_l;
152     	ano = fnode->ea_anode;
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 ? 8 : 0), ex + 4))
164     			return NULL;
165     		if (!strcmp(ea->name, key)) {
166     			if (ea->indirect)
167     				return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea));
168     			if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_KERNEL))) {
169     				printk("HPFS: 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, ret)) {
173     				kfree(ret);
174     				return NULL;
175     			}
176     			ret[ea->valuelen] = 0;
177     			return ret;
178     		}
179     		pos += ea->namelen + ea->valuelen + 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, char *key, char *data, int size)
191     {
192     	fnode_secno fno = inode->i_ino;
193     	struct super_block *s = inode->i_sb;
194     	unsigned pos;
195     	int ano, len;
196     	secno a;
197     	unsigned char h[4];
198     	struct extended_attribute *ea;
199     	struct extended_attribute *ea_end = fnode_end_ea(fnode);
200     	for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
201     		if (!strcmp(ea->name, key)) {
202     			if (ea->indirect) {
203     				if (ea_len(ea) == size)
204     					set_indirect_ea(s, ea->anode, ea_sec(ea), data, size);
205     			} else if (ea->valuelen == size) {
206     				memcpy(ea_data(ea), data, size);
207     			}
208     			return;
209     		}
210     	a = fnode->ea_secno;
211     	len = fnode->ea_size_l;
212     	ano = fnode->ea_anode;
213     	pos = 0;
214     	while (pos < len) {
215     		char ex[4 + 255 + 1 + 8];
216     		ea = (struct extended_attribute *)ex;
217     		if (pos + 4 > len) {
218     			hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
219     				ano ? "anode" : "sectors", a, len);
220     			return;
221     		}
222     		if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
223     		if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4))
224     			return;
225     		if (!strcmp(ea->name, key)) {
226     			if (ea->indirect) {
227     				if (ea_len(ea) == size)
228     					set_indirect_ea(s, ea->anode, ea_sec(ea), data, size);
229     			}
230     			else {
231     				if (ea->valuelen == size)
232     					hpfs_ea_write(s, a, ano, pos + 4 + ea->namelen + 1, size, data);
233     			}
234     			return;
235     		}
236     		pos += ea->namelen + ea->valuelen + 5;
237     	}
238     	if (!fnode->ea_size_s) {
239     		/*if (fnode->ea_size_s) {
240     			hpfs_error(s, "fnode %08x: ea_size_s == %03x, ea_offs == 0",
241     				inode->i_ino, fnode->ea_size_s);
242     			return;
243     		}*/
244     		fnode->ea_offs = 0xc4;
245     	}
246     	if (fnode->ea_offs < 0xc4 || fnode->ea_offs + fnode->ea_size_s > 0x200) {
247     		hpfs_error(s, "fnode %08x: ea_offs == %03x, ea_size_s == %03x",
248     			inode->i_ino, fnode->ea_offs, fnode->ea_size_s);
249     		return;
250     	}
251     	if ((fnode->ea_size_s || !fnode->ea_size_l) &&
252     	     fnode->ea_offs + fnode->ea_size_s + strlen(key) + size + 5 <= 0x200) {
253     		/* I'm not sure ... maybe we overwrite ACL here. I have no info
254     		   on it right now :-( */
255     		ea = fnode_end_ea(fnode);
256     		*(char *)ea = 0;
257     		ea->namelen = strlen(key);
258     		ea->valuelen = size;
259     		strcpy(ea->name, key);
260     		memcpy(ea_data(ea), data, size);
261     		fnode->ea_size_s += strlen(key) + size + 5;
262     		goto ret;
263     	}
264     	/* Most the code here is 99.9993422% unused. I hope there are no bugs.
265     	   But what .. HPFS.IFS has also bugs in ea management. */
266     	if (fnode->ea_size_s && !fnode->ea_size_l) {
267     		secno n;
268     		struct buffer_head *bh;
269     		char *data;
270     		if (!(n = hpfs_alloc_sector(s, fno, 1, 0, 1))) return;
271     		if (!(data = hpfs_get_sector(s, n, &bh))) {
272     			hpfs_free_sectors(s, n, 1);
273     			return;
274     		}
275     		memcpy(data, fnode_ea(fnode), fnode->ea_size_s);
276     		fnode->ea_size_l = fnode->ea_size_s;
277     		fnode->ea_size_s = 0;
278     		fnode->ea_secno = n;
279     		fnode->ea_anode = 0;
280     		mark_buffer_dirty(bh);
281     		brelse(bh);
282     	}
283     	pos = fnode->ea_size_l + 5 + strlen(key) + size;
284     	len = (fnode->ea_size_l + 511) >> 9;
285     	if (pos >= 30000) goto bail;
286     	while (((pos + 511) >> 9) > len) {
287     		if (!len) {
288     			if (!(fnode->ea_secno = hpfs_alloc_sector(s, fno, 1, 0, 1)))
289     				goto bail;
290     			fnode->ea_anode = 0;
291     			len++;
292     		} else if (!fnode->ea_anode) {
293     			if (hpfs_alloc_if_possible(s, fnode->ea_secno + len)) {
294     				len++;
295     			} else {
296     				/* Aargh... don't know how to create ea anodes :-( */
297     				/*struct buffer_head *bh;
298     				struct anode *anode;
299     				anode_secno a_s;
300     				if (!(anode = hpfs_alloc_anode(s, fno, &a_s, &bh)))
301     					goto bail;
302     				anode->up = fno;
303     				anode->btree.fnode_parent = 1;
304     				anode->btree.n_free_nodes--;
305     				anode->btree.n_used_nodes++;
306     				anode->btree.first_free += 12;
307     				anode->u.external[0].disk_secno = fnode->ea_secno;
308     				anode->u.external[0].file_secno = 0;
309     				anode->u.external[0].length = len;
310     				mark_buffer_dirty(bh);
311     				brelse(bh);
312     				fnode->ea_anode = 1;
313     				fnode->ea_secno = a_s;*/
314     				secno new_sec;
315     				int i;
316     				if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9), 1)))
317     					goto bail;
318     				for (i = 0; i < len; i++) {
319     					struct buffer_head *bh1, *bh2;
320     					void *b1, *b2;
321     					if (!(b1 = hpfs_map_sector(s, fnode->ea_secno + i, &bh1, len - i - 1))) {
322     						hpfs_free_sectors(s, new_sec, (pos + 511) >> 9);
323     						goto bail;
324     					}
325     					if (!(b2 = hpfs_get_sector(s, new_sec + i, &bh2))) {
326     						brelse(bh1);
327     						hpfs_free_sectors(s, new_sec, (pos + 511) >> 9);
328     						goto bail;
329     					}
330     					memcpy(b2, b1, 512);
331     					brelse(bh1);
332     					mark_buffer_dirty(bh2);
333     					brelse(bh2);
334     				}
335     				hpfs_free_sectors(s, fnode->ea_secno, len);
336     				fnode->ea_secno = new_sec;
337     				len = (pos + 511) >> 9;
338     			}
339     		}
340     		if (fnode->ea_anode) {
341     			if (hpfs_add_sector_to_btree(s, fnode->ea_secno,
342     						     0, len) != -1) {
343     				len++;
344     			} else {
345     				goto bail;
346     			}
347     		}
348     	}
349     	h[0] = 0;
350     	h[1] = strlen(key);
351     	h[2] = size & 0xff;
352     	h[3] = size >> 8;
353     	if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l, 4, h)) goto bail;
354     	if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l + 4, h[1] + 1, key)) goto bail;
355     	if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l + 5 + h[1], size, data)) goto bail;
356     	fnode->ea_size_l = pos;
357     	ret:
358     	inode->i_hpfs_ea_size += 5 + strlen(key) + size;
359     	return;
360     	bail:
361     	if (fnode->ea_secno)
362     		if (fnode->ea_anode) hpfs_truncate_btree(s, fnode->ea_secno, 1, (fnode->ea_size_l + 511) >> 9);
363     		else hpfs_free_sectors(s, fnode->ea_secno + ((fnode->ea_size_l + 511) >> 9), len - ((fnode->ea_size_l + 511) >> 9));
364     	else fnode->ea_secno = fnode->ea_size_l = 0;
365     }
366     	
367