OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [LINUX_2_4_26_OR32/] [linux/] [linux-2.4/] [fs/] [hpfs/] [ea.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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 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) {
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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.