1 // SPDX-License-Identifier: GPL-2.0
5 * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
7 * directory VFS functions
10 #include <linux/slab.h>
13 static int hpfs_dir_release(struct inode
*inode
, struct file
*filp
)
15 hpfs_lock(inode
->i_sb
);
16 hpfs_del_pos(inode
, &filp
->f_pos
);
17 /*hpfs_write_if_changed(inode);*/
18 hpfs_unlock(inode
->i_sb
);
22 /* This is slow, but it's not used often */
24 static loff_t
hpfs_dir_lseek(struct file
*filp
, loff_t off
, int whence
)
26 loff_t new_off
= off
+ (whence
== 1 ? filp
->f_pos
: 0);
28 struct quad_buffer_head qbh
;
29 struct inode
*i
= file_inode(filp
);
30 struct hpfs_inode_info
*hpfs_inode
= hpfs_i(i
);
31 struct super_block
*s
= i
->i_sb
;
33 /* Somebody else will have to figure out what to do here */
34 if (whence
== SEEK_DATA
|| whence
== SEEK_HOLE
)
40 /*pr_info("dir lseek\n");*/
41 if (new_off
== 0 || new_off
== 1 || new_off
== 11 || new_off
== 12 || new_off
== 13) goto ok
;
42 pos
= ((loff_t
) hpfs_de_as_down_as_possible(s
, hpfs_inode
->i_dno
) << 4) + 1;
43 while (pos
!= new_off
) {
44 if (map_pos_dirent(i
, &pos
, &qbh
)) hpfs_brelse4(&qbh
);
46 if (pos
== 12) goto fail
;
48 if (unlikely(hpfs_add_pos(i
, &filp
->f_pos
) < 0)) {
54 filp
->f_pos
= new_off
;
59 /*pr_warn("illegal lseek: %016llx\n", new_off);*/
65 static int hpfs_readdir(struct file
*file
, struct dir_context
*ctx
)
67 struct inode
*inode
= file_inode(file
);
68 struct hpfs_inode_info
*hpfs_inode
= hpfs_i(inode
);
69 struct quad_buffer_head qbh
;
70 struct hpfs_dirent
*de
;
73 unsigned char *tempname
;
77 hpfs_lock(inode
->i_sb
);
79 if (hpfs_sb(inode
->i_sb
)->sb_chk
) {
80 if (hpfs_chk_sectors(inode
->i_sb
, inode
->i_ino
, 1, "dir_fnode")) {
84 if (hpfs_chk_sectors(inode
->i_sb
, hpfs_inode
->i_dno
, 4, "dir_dnode")) {
89 if (hpfs_sb(inode
->i_sb
)->sb_chk
>= 2) {
90 struct buffer_head
*bh
;
93 if (!(fno
= hpfs_map_fnode(inode
->i_sb
, inode
->i_ino
, &bh
))) {
97 if (!fnode_is_dir(fno
)) {
99 hpfs_error(inode
->i_sb
, "not a directory, fnode %08lx",
100 (unsigned long)inode
->i_ino
);
102 if (hpfs_inode
->i_dno
!= le32_to_cpu(fno
->u
.external
[0].disk_secno
)) {
104 hpfs_error(inode
->i_sb
, "corrupted inode: i_dno == %08x, fnode -> dnode == %08x", hpfs_inode
->i_dno
, le32_to_cpu(fno
->u
.external
[0].disk_secno
));
112 lc
= hpfs_sb(inode
->i_sb
)->sb_lowercase
;
113 if (ctx
->pos
== 12) { /* diff -r requires this (note, that diff -r */
114 ctx
->pos
= 13; /* also fails on msdos filesystem in 2.0) */
117 if (ctx
->pos
== 13) {
124 /* This won't work when cycle is longer than number of dirents
125 accepted by filldir, but what can I do?
126 maybe killall -9 ls helps */
127 if (hpfs_sb(inode
->i_sb
)->sb_chk
)
128 if (hpfs_stop_cycles(inode
->i_sb
, ctx
->pos
, &c1
, &c2
, "hpfs_readdir")) {
134 if (ctx
->pos
== 3 || ctx
->pos
== 4 || ctx
->pos
== 5) {
135 pr_err("pos==%d\n", (int)ctx
->pos
);
139 if (!dir_emit_dot(file
, ctx
))
143 if (ctx
->pos
== 11) {
144 if (!dir_emit(ctx
, "..", 2, hpfs_inode
->i_parent_dir
, DT_DIR
))
149 ret
= hpfs_add_pos(inode
, &file
->f_pos
);
150 if (unlikely(ret
< 0))
152 ctx
->pos
= ((loff_t
) hpfs_de_as_down_as_possible(inode
->i_sb
, hpfs_inode
->i_dno
) << 4) + 1;
155 if (!(de
= map_pos_dirent(inode
, &next_pos
, &qbh
))) {
160 if (de
->first
|| de
->last
) {
161 if (hpfs_sb(inode
->i_sb
)->sb_chk
) {
162 if (de
->first
&& !de
->last
&& (de
->namelen
!= 2
163 || de
->name
[0] != 1 || de
->name
[1] != 1))
164 hpfs_error(inode
->i_sb
, "hpfs_readdir: bad ^A^A entry; pos = %08lx", (unsigned long)ctx
->pos
);
165 if (de
->last
&& (de
->namelen
!= 1 || de
->name
[0] != 255))
166 hpfs_error(inode
->i_sb
, "hpfs_readdir: bad \\377 entry; pos = %08lx", (unsigned long)ctx
->pos
);
172 tempname
= hpfs_translate_name(inode
->i_sb
, de
->name
, de
->namelen
, lc
, de
->not_8x3
);
173 if (!dir_emit(ctx
, tempname
, de
->namelen
, le32_to_cpu(de
->fnode
), DT_UNKNOWN
)) {
174 if (tempname
!= de
->name
) kfree(tempname
);
179 if (tempname
!= de
->name
) kfree(tempname
);
183 hpfs_unlock(inode
->i_sb
);
188 * lookup. Search the specified directory for the specified name, set
189 * *result to the corresponding inode.
191 * lookup uses the inode number to tell read_inode whether it is reading
192 * the inode of a directory or a file -- file ino's are odd, directory
193 * ino's are even. read_inode avoids i/o for file inodes; everything
194 * needed is up here in the directory. (And file fnodes are out in
197 * - M.P.: this is over, sometimes we've got to read file's fnode for eas
198 * inode numbers are just fnode sector numbers; iget lock is used
199 * to tell read_inode to read fnode or not.
202 struct dentry
*hpfs_lookup(struct inode
*dir
, struct dentry
*dentry
, unsigned int flags
)
204 const unsigned char *name
= dentry
->d_name
.name
;
205 unsigned len
= dentry
->d_name
.len
;
206 struct quad_buffer_head qbh
;
207 struct hpfs_dirent
*de
;
210 struct inode
*result
= NULL
;
211 struct hpfs_inode_info
*hpfs_result
;
213 hpfs_lock(dir
->i_sb
);
214 if ((err
= hpfs_chk_name(name
, &len
))) {
215 if (err
== -ENAMETOOLONG
) {
216 hpfs_unlock(dir
->i_sb
);
217 return ERR_PTR(-ENAMETOOLONG
);
223 * '.' and '..' will never be passed here.
226 de
= map_dirent(dir
, hpfs_i(dir
)->i_dno
, name
, len
, NULL
, &qbh
);
229 * This is not really a bailout, just means file not found.
235 * Get inode number, what we're after.
238 ino
= le32_to_cpu(de
->fnode
);
241 * Go find or make an inode.
244 result
= iget_locked(dir
->i_sb
, ino
);
246 hpfs_error(dir
->i_sb
, "hpfs_lookup: can't get inode");
247 result
= ERR_PTR(-ENOMEM
);
250 if (result
->i_state
& I_NEW
) {
251 hpfs_init_inode(result
);
253 hpfs_read_inode(result
);
254 else if (le32_to_cpu(de
->ea_size
) && hpfs_sb(dir
->i_sb
)->sb_eas
)
255 hpfs_read_inode(result
);
257 result
->i_mode
|= S_IFREG
;
258 result
->i_mode
&= ~0111;
259 result
->i_op
= &hpfs_file_iops
;
260 result
->i_fop
= &hpfs_file_ops
;
261 set_nlink(result
, 1);
263 unlock_new_inode(result
);
265 hpfs_result
= hpfs_i(result
);
266 if (!de
->directory
) hpfs_result
->i_parent_dir
= dir
->i_ino
;
268 if (de
->has_acl
|| de
->has_xtd_perm
) if (!sb_rdonly(dir
->i_sb
)) {
269 hpfs_error(result
->i_sb
, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures");
271 result
= ERR_PTR(-EINVAL
);
276 * Fill in the info from the directory if this is a newly created
280 if (!inode_get_ctime_sec(result
)) {
281 time64_t csec
= local_to_gmt(dir
->i_sb
, le32_to_cpu(de
->creation_date
));
283 inode_set_ctime(result
, csec
? csec
: 1, 0);
284 inode_set_mtime(result
,
285 local_to_gmt(dir
->i_sb
, le32_to_cpu(de
->write_date
)),
287 inode_set_atime(result
,
288 local_to_gmt(dir
->i_sb
, le32_to_cpu(de
->read_date
)),
290 hpfs_result
->i_ea_size
= le32_to_cpu(de
->ea_size
);
291 if (!hpfs_result
->i_ea_mode
&& de
->read_only
)
292 result
->i_mode
&= ~0222;
293 if (!de
->directory
) {
294 if (result
->i_size
== -1) {
295 result
->i_size
= le32_to_cpu(de
->file_size
);
296 result
->i_data
.a_ops
= &hpfs_aops
;
297 hpfs_i(result
)->mmu_private
= result
->i_size
;
299 * i_blocks should count the fnode and any anodes.
300 * We count 1 for the fnode and don't bother about
301 * anodes -- the disk heads are on the directory band
302 * and we want them to stay there.
304 result
->i_blocks
= 1 + ((result
->i_size
+ 511) >> 9);
318 hpfs_unlock(dir
->i_sb
);
319 return d_splice_alias(result
, dentry
);
322 const struct file_operations hpfs_dir_ops
=
324 .llseek
= hpfs_dir_lseek
,
325 .read
= generic_read_dir
,
326 .iterate_shared
= hpfs_readdir
,
327 .release
= hpfs_dir_release
,
328 .fsync
= hpfs_file_fsync
,
329 .unlocked_ioctl
= hpfs_ioctl
,
330 .compat_ioctl
= compat_ptr_ioctl
,