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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [affs/] [amigaffs.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/affs/amigaffs.c
3
 *
4
 *  (c) 1996  Hans-Joachim Widmaier - Rewritten
5
 *
6
 *  (C) 1993  Ray Burr - Amiga FFS filesystem.
7
 *
8
 */
9
 
10
#include <linux/stat.h>
11
#include <linux/sched.h>
12
#include <linux/affs_fs.h>
13
#include <linux/string.h>
14
#include <linux/locks.h>
15
#include <linux/mm.h>
16
#include <linux/amigaffs.h>
17
 
18
extern struct timezone sys_tz;
19
 
20
/*
21
 * Functions for accessing Amiga-FFS structures.
22
 *
23
 */
24
 
25
/* Find the next used hash entry at or after *HASH_POS in a directory's hash
26
   table.  *HASH_POS is assigned that entry's number.  DIR_DATA points to
27
   the directory header block in memory.  If there are no more entries,
28
 
29
   is returned. */
30
 
31
int
32
affs_find_next_hash_entry(int hsize, void *dir_data, int *hash_pos)
33
{
34
        struct dir_front *dir_front = dir_data;
35
        int i;
36
 
37
        for (i = *hash_pos; i < hsize; i++)
38
                if (dir_front->hashtable[i] != 0)
39
                        break;
40
        if (i >= hsize)
41
                return 0;
42
        *hash_pos = i;
43
        return htonl(dir_front->hashtable[i]);
44
}
45
 
46
/* Set *NAME to point to the file name in a file header block in memory
47
   pointed to by FH_DATA.  The length of the name is returned. */
48
 
49
int
50
affs_get_file_name(int bsize, void *fh_data, char **name)
51
{
52
        struct file_end *file_end;
53
 
54
        file_end = GET_END_PTR(struct file_end, fh_data, bsize);
55
        if (file_end->file_name[0] == 0
56
            || file_end->file_name[0] > 30) {
57
                printk ("affs_get_file_name: OOPS! bad filename\n");
58
                printk ("  file_end->file_name[0] = %d\n",
59
                        file_end->file_name[0]);
60
                *name = "***BAD_FILE***";
61
                return 14;
62
        }
63
        *name = (char *) &file_end->file_name[1];
64
        return file_end->file_name[0];
65
}
66
 
67
/* Find the predecessor in the hash chain */
68
 
69
int
70
affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey)
71
{
72
        struct buffer_head      *bh = NULL;
73
        int                      nextkey;
74
        int                      ptype, stype;
75
        int                      retval;
76
 
77
        nextkey = startino->i_ino;
78
        retval  = -ENOENT;
79
        lock_super(startino->i_sb);
80
        while (1) {
81
                pr_debug("AFFS: fix_hash_pred(): next key=%d, offset=%d\n",nextkey,startoffset);
82
                if (nextkey == 0)
83
                        break;
84
                if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino))))
85
                        break;
86
                if (affs_checksum_block(AFFS_I2BSIZE(startino),bh->b_data,&ptype,&stype)
87
                    || ptype != T_SHORT || (stype != ST_FILE && stype != ST_USERDIR &&
88
                                            stype != ST_LINKFILE && stype != ST_LINKDIR &&
89
                                            stype != ST_ROOT && stype != ST_SOFTLINK)) {
90
                        printk("AFFS: bad block found in link chain (ptype=%d, stype=%d)\n",
91
                               ptype,stype);
92
                        affs_brelse(bh);
93
                        break;
94
                }
95
                nextkey = htonl(((__u32 *)bh->b_data)[startoffset]);
96
                if (nextkey == key) {
97
                        ((__u32 *)bh->b_data)[startoffset] = newkey;
98
                        affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5);
99
                        mark_buffer_dirty(bh,1);
100
                        affs_brelse(bh);
101
                        retval = 0;
102
                        break;
103
                }
104
                affs_brelse(bh);
105
                startoffset = AFFS_I2BSIZE(startino) / 4 - 4;
106
        }
107
        unlock_super(startino->i_sb);
108
 
109
        return retval;
110
}
111
 
112
/* Remove inode from link chain */
113
 
114
int
115
affs_fix_link_pred(struct inode *startino, int key, int newkey)
116
{
117
        struct buffer_head      *bh = NULL;
118
        int                      nextkey;
119
        int                      offset;
120
        int                      etype = 0;
121
        int                      ptype, stype;
122
        int                      retval;
123
 
124
        offset  = AFFS_I2BSIZE(startino) / 4 - 10;
125
        nextkey = startino->i_ino;
126
        retval  = -ENOENT;
127
        lock_super(startino->i_sb);
128
        while (1) {
129
                if (nextkey == 0)
130
                        break;
131
                pr_debug("AFFS: find_link_pred(): next key=%d\n",nextkey);
132
                if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino))))
133
                        break;
134
                if (affs_checksum_block(AFFS_I2BSIZE(startino),bh->b_data,&ptype,&stype)
135
                    || ptype != T_SHORT) {
136
                        affs_brelse(bh);
137
                        break;
138
                }
139
                if (!etype) {
140
                        if (stype != ST_FILE && stype != ST_USERDIR) {
141
                                affs_brelse(bh);
142
                                break;
143
                        }
144
                        if (stype == ST_FILE)
145
                                etype = ST_LINKFILE;
146
                        else
147
                                etype = ST_LINKDIR;
148
                } else if (stype != etype) {
149
                        affs_brelse(bh);
150
                        retval = -EPERM;
151
                        break;
152
                }
153
                nextkey = htonl(((__u32 *)bh->b_data)[offset]);
154
                if (nextkey == key) {
155
                        FILE_END(bh->b_data,startino)->link_chain = newkey;
156
                        affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5);
157
                        mark_buffer_dirty(bh,1);
158
                        affs_brelse(bh);
159
                        retval = 0;
160
                        break;
161
                }
162
                affs_brelse(bh);
163
        }
164
        unlock_super(startino->i_sb);
165
        return retval;
166
}
167
 
168
/* Checksum a block, do various consistency checks and optionally return
169
   the blocks type number.  DATA points to the block.  If their pointers
170
   are non-null, *PTYPE and *STYPE are set to the primary and secondary
171
   block types respectively, *HASHSIZE is set to the size of the hashtable
172
   (which lets us calculate the block size).
173
   Returns non-zero if the block is not consistent. */
174
 
175
__u32
176
affs_checksum_block(int bsize, void *data, int *ptype, int *stype)
177
{
178
        __u32    sum;
179
        __u32   *p;
180
 
181
        bsize /= 4;
182
        if (ptype)
183
                *ptype = htonl(((__s32 *)data)[0]);
184
        if (stype)
185
                *stype = htonl(((__s32 *)data)[bsize - 1]);
186
 
187
        sum    = 0;
188
        p      = data;
189
        while (bsize--)
190
                sum += htonl(*p++);
191
        return sum;
192
}
193
 
194
void
195
affs_fix_checksum(int bsize, void *data, int cspos)
196
{
197
        __u32    ocs;
198
        __u32    cs;
199
 
200
        cs   = affs_checksum_block(bsize,data,NULL,NULL);
201
        ocs  = htonl (((__u32 *)data)[cspos]);
202
        ocs -= cs;
203
        ((__u32 *)data)[cspos] = htonl(ocs);
204
}
205
 
206
void
207
secs_to_datestamp(int secs, struct DateStamp *ds)
208
{
209
        __u32    days;
210
        __u32    minute;
211
 
212
        secs -= sys_tz.tz_minuteswest * 60 +((8 * 365 + 2) * 24 * 60 * 60);
213
        if (secs < 0)
214
                secs = 0;
215
        days    = secs / 86400;
216
        secs   -= days * 86400;
217
        minute  = secs / 60;
218
        secs   -= minute * 60;
219
 
220
        ds->ds_Days   = htonl(days);
221
        ds->ds_Minute = htonl(minute);
222
        ds->ds_Tick   = htonl(secs * 50);
223
}
224
 
225
int
226
prot_to_mode(__u32 prot)
227
{
228
        int      mode = 0;
229
 
230
        if (AFFS_UMAYWRITE(prot))
231
                mode |= S_IWUSR;
232
        if (AFFS_UMAYREAD(prot))
233
                mode |= S_IRUSR;
234
        if (AFFS_UMAYEXECUTE(prot))
235
                mode |= S_IXUSR;
236
        if (AFFS_GMAYWRITE(prot))
237
                mode |= S_IWGRP;
238
        if (AFFS_GMAYREAD(prot))
239
                mode |= S_IRGRP;
240
        if (AFFS_GMAYEXECUTE(prot))
241
                mode |= S_IXGRP;
242
        if (AFFS_OMAYWRITE(prot))
243
                mode |= S_IWOTH;
244
        if (AFFS_OMAYREAD(prot))
245
                mode |= S_IROTH;
246
        if (AFFS_OMAYEXECUTE(prot))
247
                mode |= S_IXOTH;
248
 
249
        return mode;
250
}
251
 
252
unsigned int
253
mode_to_prot(int mode)
254
{
255
        unsigned int     prot = 0;
256
 
257
        if (mode & S_IXUSR)
258
                prot |= FIBF_SCRIPT;
259
        if (mode & S_IRUSR)
260
                prot |= FIBF_READ;
261
        if (mode & S_IWUSR)
262
                prot |= FIBF_WRITE | FIBF_DELETE;
263
        if (mode & S_IRGRP)
264
                prot |= FIBF_GRP_READ;
265
        if (mode & S_IWGRP)
266
                prot |= FIBF_GRP_WRITE;
267
        if (mode & S_IROTH)
268
                prot |= FIBF_OTR_READ;
269
        if (mode & S_IWOTH)
270
                prot |= FIBF_OTR_WRITE;
271
 
272
        return prot;
273
}

powered by: WebSVN 2.1.0

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