4 * Copyright (C) 1997 Russell King
7 #include <linux/errno.h>
9 #include <linux/adfs_fs.h>
10 #include <linux/sched.h>
11 #include <linux/stat.h>
13 static ssize_t
adfs_dirread (struct file
*filp
, char *buf
,
14 size_t siz
, loff_t
*ppos
)
19 static int adfs_readdir (struct file
*, void *, filldir_t
);
21 static struct file_operations adfs_dir_operations
= {
22 NULL
, /* lseek - default */
23 adfs_dirread
, /* read */
24 NULL
, /* write - bad */
25 adfs_readdir
, /* readdir */
26 NULL
, /* select - default */
29 NULL
, /* no special open code */
31 NULL
, /* no special release code */
32 file_fsync
, /* fsync */
34 NULL
, /* check_media_change */
39 * directories can handle most operations...
41 struct inode_operations adfs_dir_inode_operations
= {
42 &adfs_dir_operations
, /* default directory file-ops */
44 adfs_lookup
, /* lookup */
53 NULL
, /* follow link */
55 NULL
, /* write page */
58 NULL
, /* permission */
62 unsigned int adfs_val (unsigned char *p
, int len
)
79 static unsigned int adfs_time (unsigned int load
, unsigned int exec
)
81 unsigned int high
, low
;
83 high
= ((load
<< 24) | (exec
>> 8)) - 0x336e996a;
87 * (h256 % 100) = 56 h256 / 100 = 2
88 * 56 << 8 = 14336 2 * 256 = 512
93 return (((high
% 100) << 8) + low
) / 100 + (high
/ 100 << 8);
96 int adfs_readname (char *buf
, char *ptr
, int maxlen
)
99 while (*ptr
>= ' ' && maxlen
--) {
115 int adfs_dir_read_parent (struct inode
*inode
, struct buffer_head
**bhp
)
117 struct super_block
*sb
;
125 size
= 2048 >> sb
->s_blocksize_bits
;
127 for (i
= 0; i
< size
; i
++) {
130 block
= adfs_parent_bmap (inode
, i
);
132 bhp
[i
] = bread (sb
->s_dev
, block
, sb
->s_blocksize
);
134 adfs_error (sb
, "adfs_dir_read_parent",
135 "directory %lu with a hole at offset %d", inode
->i_ino
, i
);
136 if (!block
|| !bhp
[i
]) {
138 for (j
= i
- 1; j
>= 0; j
--)
146 int adfs_dir_read (struct inode
*inode
, struct buffer_head
**bhp
)
148 struct super_block
*sb
;
151 if (!inode
|| !S_ISDIR(inode
->i_mode
))
156 size
= inode
->i_size
>> sb
->s_blocksize_bits
;
158 for (i
= 0; i
< size
; i
++) {
161 block
= adfs_bmap (inode
, i
);
163 bhp
[i
] = bread (sb
->s_dev
, block
, sb
->s_blocksize
);
165 adfs_error (sb
, "adfs_dir_read",
166 "directory %lX,%lX with a hole at offset %d",
167 inode
->i_ino
, inode
->u
.adfs_i
.file_id
, i
);
168 if (!block
|| !bhp
[i
]) {
170 for (j
= i
- 1; j
>= 0; j
--)
178 int adfs_dir_check (struct inode
*inode
, struct buffer_head
**bhp
, int buffers
, union adfs_dirtail
*dtp
)
180 struct adfs_dirheader dh
;
181 union adfs_dirtail dt
;
183 memcpy (&dh
, bhp
[0]->b_data
, sizeof (dh
));
184 memcpy (&dt
, bhp
[3]->b_data
+ 471, sizeof(dt
));
186 if (memcmp (&dh
.startmasseq
, &dt
.new.endmasseq
, 5) ||
187 (memcmp (&dh
.startname
, "Nick", 4) &&
188 memcmp (&dh
.startname
, "Hugo", 4))) {
189 adfs_error (inode
->i_sb
, "adfs_check_dir",
190 "corrupted directory inode %lX,%lX",
191 inode
->i_ino
, inode
->u
.adfs_i
.file_id
);
199 void adfs_dir_free (struct buffer_head
**bhp
, int buffers
)
203 for (i
= buffers
- 1; i
>= 0; i
--)
207 int adfs_dir_get (struct super_block
*sb
, struct buffer_head
**bhp
,
208 int buffers
, int pos
, unsigned long parent_object_id
,
209 struct adfs_idir_entry
*ide
)
211 struct adfs_direntry de
;
212 int thissize
, buffer
, offset
;
214 offset
= pos
& (sb
->s_blocksize
- 1);
215 buffer
= pos
>> sb
->s_blocksize_bits
;
217 if (buffer
> buffers
)
220 thissize
= sb
->s_blocksize
- offset
;
224 memcpy (&de
, bhp
[buffer
]->b_data
+ offset
, thissize
);
226 memcpy (((char *)&de
) + thissize
, bhp
[buffer
+ 1]->b_data
, 26 - thissize
);
228 if (!de
.dirobname
[0])
231 ide
->name_len
= adfs_readname (ide
->name
, de
.dirobname
, ADFS_NAME_LEN
);
232 ide
->inode_no
= adfs_inode_generate (parent_object_id
, pos
);
233 ide
->file_id
= adfs_val (de
.dirinddiscadd
, 3);
234 ide
->size
= adfs_val (de
.dirlen
, 4);
235 ide
->mode
= de
.newdiratts
;
236 ide
->mtime
= adfs_time (adfs_val (de
.dirload
, 4), adfs_val (de
.direxec
, 4));
237 ide
->filetype
= (adfs_val (de
.dirload
, 4) >> 8) & 0xfff;
241 int adfs_dir_find_entry (struct super_block
*sb
, struct buffer_head
**bhp
,
242 int buffers
, unsigned int pos
,
243 struct adfs_idir_entry
*ide
)
245 struct adfs_direntry de
;
246 int offset
, buffer
, thissize
;
248 offset
= pos
& (sb
->s_blocksize
- 1);
249 buffer
= pos
>> sb
->s_blocksize_bits
;
251 if (buffer
> buffers
)
254 thissize
= sb
->s_blocksize
- offset
;
258 memcpy (&de
, bhp
[buffer
]->b_data
+ offset
, thissize
);
260 memcpy (((char *)&de
) + thissize
, bhp
[buffer
+ 1]->b_data
, 26 - thissize
);
262 if (!de
.dirobname
[0])
265 ide
->name_len
= adfs_readname (ide
->name
, de
.dirobname
, ADFS_NAME_LEN
);
266 ide
->size
= adfs_val (de
.dirlen
, 4);
267 ide
->mode
= de
.newdiratts
;
268 ide
->file_id
= adfs_val (de
.dirinddiscadd
, 3);
269 ide
->mtime
= adfs_time (adfs_val (de
.dirload
, 4), adfs_val (de
.direxec
, 4));
270 ide
->filetype
= (adfs_val (de
.dirload
, 4) >> 8) & 0xfff;
274 static int adfs_readdir (struct file
*filp
, void *dirent
, filldir_t filldir
)
276 struct inode
*inode
= filp
->f_dentry
->d_inode
;
277 struct super_block
*sb
;
278 struct buffer_head
*bh
[4];
279 union adfs_dirtail dt
;
280 unsigned long parent_object_id
, dir_object_id
;
285 if (filp
->f_pos
> ADFS_NUM_DIR_ENTRIES
+ 2)
288 if (!(buffers
= adfs_dir_read (inode
, bh
))) {
289 adfs_error (sb
, "adfs_readdir", "unable to read directory");
293 if (adfs_dir_check (inode
, bh
, buffers
, &dt
)) {
294 adfs_dir_free (bh
, buffers
);
298 parent_object_id
= adfs_val (dt
.new.dirparent
, 3);
299 dir_object_id
= adfs_inode_objid (inode
);
301 if (filp
->f_pos
< 2) {
302 if (filp
->f_pos
< 1) {
303 if (filldir (dirent
, ".", 1, 0, inode
->i_ino
) < 0)
307 if (filldir (dirent
, "..", 2, 1,
308 adfs_inode_generate (parent_object_id
, 0)) < 0)
313 pos
= 5 + (filp
->f_pos
- 2) * 26;
314 while (filp
->f_pos
< 79) {
315 struct adfs_idir_entry ide
;
317 if (!adfs_dir_get (sb
, bh
, buffers
, pos
, dir_object_id
, &ide
))
320 if (filldir (dirent
, ide
.name
, ide
.name_len
, filp
->f_pos
, ide
.inode_no
) < 0)
325 adfs_dir_free (bh
, buffers
);