2 * linux/fs/affs/namei.c
4 * (c) 1996 Hans-Joachim Widmaier - Rewritten
6 * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem.
8 * (C) 1991 Linus Torvalds - minix filesystem
12 #include <linux/sched.h>
13 #include <linux/affs_fs.h>
14 #include <linux/kernel.h>
15 #include <linux/string.h>
16 #include <linux/stat.h>
17 #include <linux/fcntl.h>
18 #include <linux/locks.h>
19 #include <linux/amigaffs.h>
20 #include <asm/uaccess.h>
22 #include <linux/errno.h>
24 extern struct inode_operations affs_symlink_inode_operations
;
26 /* Simple toupper() for DOS\1 */
29 affs_toupper(unsigned int ch
)
31 return ch
>= 'a' && ch
<= 'z' ? ch
-= ('a' - 'A') : ch
;
34 /* International toupper() for DOS\3 ("international") */
37 affs_intl_toupper(unsigned int ch
)
39 return (ch
>= 'a' && ch
<= 'z') || (ch
>= 0xE0
40 && ch
<= 0xFE && ch
!= 0xF7) ?
41 ch
- ('a' - 'A') : ch
;
44 static int affs_hash_dentry(struct dentry
*, struct qstr
*);
45 static int affs_compare_dentry(struct dentry
*, struct qstr
*, struct qstr
*);
46 struct dentry_operations affs_dentry_operations
= {
47 d_hash
: affs_hash_dentry
,
48 d_compare
: affs_compare_dentry
,
52 * Note: the dentry argument is the parent dentry.
55 affs_hash_dentry(struct dentry
*dentry
, struct qstr
*qstr
)
57 unsigned int (*toupper
)(unsigned int) = affs_toupper
;
61 if ((i
= affs_check_name(qstr
->name
,qstr
->len
)))
64 /* Check whether to use the international 'toupper' routine */
65 if (AFFS_I2FSTYPE(dentry
->d_inode
))
66 toupper
= affs_intl_toupper
;
67 hash
= init_name_hash();
68 for (i
= 0; i
< qstr
->len
&& i
< 30; i
++)
69 hash
= partial_name_hash(toupper(qstr
->name
[i
]), hash
);
70 qstr
->hash
= end_name_hash(hash
);
76 affs_compare_dentry(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
78 unsigned int (*toupper
)(unsigned int) = affs_toupper
;
83 /* 'a' is the qstr of an already existing dentry, so the name
84 * must be valid. 'b' must be validated first.
87 if (affs_check_name(b
->name
,b
->len
))
90 /* If the names are longer than the allowed 30 chars,
91 * the excess is ignored, so their length may differ.
100 /* Check whether to use the international 'toupper' routine */
101 if (AFFS_I2FSTYPE(dentry
->d_inode
))
102 toupper
= affs_intl_toupper
;
104 for (i
= 0; i
< alen
; i
++)
105 if (toupper(a
->name
[i
]) != toupper(b
->name
[i
]))
112 * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure.
116 affs_match(const unsigned char *name
, int len
, const unsigned char *compare
, int dlen
, int intl
)
118 unsigned int (*toupper
)(unsigned int) = intl
? affs_intl_toupper
: affs_toupper
;
129 /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
130 if (!len
&& dlen
== 1 && compare
[0] == '.')
134 for (i
= 0; i
< len
; i
++)
135 if (toupper(name
[i
]) != toupper(compare
[i
]))
141 affs_hash_name(const unsigned char *name
, int len
, int intl
, int hashsize
)
149 for (i
= 0; i
< len
; i
++)
151 x
= (x
* 13 + affs_intl_toupper(name
[i
] & 0xFF)) & 0x7ff;
153 x
= (x
* 13 + affs_toupper(name
[i
] & 0xFF)) & 0x7ff;
158 static struct buffer_head
*
159 affs_find_entry(struct inode
*dir
, struct dentry
*dentry
, unsigned long *ino
)
161 struct buffer_head
*bh
;
162 int intl
= AFFS_I2FSTYPE(dir
);
164 const char *name
= dentry
->d_name
.name
;
165 int namelen
= dentry
->d_name
.len
;
167 pr_debug("AFFS: find_entry(\"%.*s\")\n",namelen
,name
);
169 bh
= affs_bread(dir
->i_dev
,dir
->i_ino
,AFFS_I2BSIZE(dir
));
173 if (namelen
== 1 && name
[0] == '.') {
177 if (namelen
== 2 && name
[0] == '.' && name
[1] == '.') {
178 *ino
= affs_parent_ino(dir
);
182 key
= AFFS_GET_HASHENTRY(bh
->b_data
,affs_hash_name(name
,namelen
,intl
,AFFS_I2HSIZE(dir
)));
185 unsigned char *cname
;
192 bh
= affs_bread(dir
->i_dev
,key
,AFFS_I2BSIZE(dir
));
195 cnamelen
= affs_get_file_name(AFFS_I2BSIZE(dir
),bh
->b_data
,&cname
);
196 if (affs_match(name
,namelen
,cname
,cnamelen
,intl
))
198 key
= be32_to_cpu(FILE_END(bh
->b_data
,dir
)->hash_chain
);
205 affs_lookup(struct inode
*dir
, struct dentry
*dentry
)
208 struct buffer_head
*bh
;
211 pr_debug("AFFS: lookup(\"%.*s\")\n",(int)dentry
->d_name
.len
,dentry
->d_name
.name
);
214 bh
= affs_find_entry(dir
,dentry
,&ino
);
216 if (FILE_END(bh
->b_data
,dir
)->original
)
217 ino
= be32_to_cpu(FILE_END(bh
->b_data
,dir
)->original
);
219 inode
= iget(dir
->i_sb
,ino
);
221 return ERR_PTR(-EACCES
);
223 dentry
->d_op
= &affs_dentry_operations
;
229 affs_unlink(struct inode
*dir
, struct dentry
*dentry
)
232 struct buffer_head
*bh
;
236 pr_debug("AFFS: unlink(dir=%ld,\"%.*s\")\n",dir
->i_ino
,
237 (int)dentry
->d_name
.len
,dentry
->d_name
.name
);
240 if (!(bh
= affs_find_entry(dir
,dentry
,&ino
)))
243 inode
= dentry
->d_inode
;
245 if ((retval
= affs_remove_header(bh
,inode
)) < 0)
248 inode
->i_nlink
= retval
;
249 inode
->i_ctime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
250 dir
->i_version
= ++event
;
251 mark_inode_dirty(inode
);
252 mark_inode_dirty(dir
);
261 affs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
)
266 pr_debug("AFFS: create(%lu,\"%.*s\",0%o)\n",dir
->i_ino
,(int)dentry
->d_name
.len
,
267 dentry
->d_name
.name
,mode
);
270 inode
= affs_new_inode(dir
);
274 pr_debug("AFFS: ino=%lu\n",inode
->i_ino
);
275 if (dir
->i_sb
->u
.affs_sb
.s_flags
& SF_OFS
) {
276 inode
->i_op
= &affs_file_inode_operations
;
277 inode
->i_fop
= &affs_file_operations_ofs
;
279 inode
->i_op
= &affs_file_inode_operations
;
280 inode
->i_fop
= &affs_file_operations
;
281 inode
->i_mapping
->a_ops
= &affs_aops
;
282 inode
->u
.affs_i
.mmu_private
= inode
->i_size
;
284 error
= affs_add_entry(dir
,NULL
,inode
,dentry
,ST_FILE
);
287 inode
->i_mode
= mode
;
288 inode
->u
.affs_i
.i_protect
= mode_to_prot(inode
->i_mode
);
289 d_instantiate(dentry
,inode
);
290 mark_inode_dirty(inode
);
291 dir
->i_version
= ++event
;
292 mark_inode_dirty(dir
);
298 mark_inode_dirty(inode
);
304 affs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
309 pr_debug("AFFS: mkdir(%lu,\"%.*s\",0%o)\n",dir
->i_ino
,
310 (int)dentry
->d_name
.len
,dentry
->d_name
.name
,mode
);
313 inode
= affs_new_inode(dir
);
317 inode
->i_op
= &affs_dir_inode_operations
;
318 inode
->i_fop
= &affs_dir_operations
;
319 error
= affs_add_entry(dir
,NULL
,inode
,dentry
,ST_USERDIR
);
322 inode
->i_mode
= S_IFDIR
| S_ISVTX
| mode
;
323 inode
->u
.affs_i
.i_protect
= mode_to_prot(inode
->i_mode
);
324 d_instantiate(dentry
,inode
);
325 mark_inode_dirty(inode
);
326 dir
->i_version
= ++event
;
327 mark_inode_dirty(dir
);
333 mark_inode_dirty(inode
);
339 empty_dir(struct buffer_head
*bh
, int hashsize
)
341 while (--hashsize
>= 0) {
342 if (((struct dir_front
*)bh
->b_data
)->hashtable
[hashsize
])
349 affs_rmdir(struct inode
*dir
, struct dentry
*dentry
)
351 struct inode
*inode
= dentry
->d_inode
;
354 struct buffer_head
*bh
;
356 pr_debug("AFFS: rmdir(dir=%lu,\"%.*s\")\n",dir
->i_ino
,
357 (int)dentry
->d_name
.len
,dentry
->d_name
.name
);
360 if (!(bh
= affs_find_entry(dir
,dentry
,&ino
)))
364 * Make sure the directory is empty and the dentry isn't busy.
367 if (!empty_dir(bh
,AFFS_I2HSIZE(inode
)))
370 if (!d_unhashed(dentry
))
373 if ((retval
= affs_remove_header(bh
,inode
)) < 0)
376 inode
->i_nlink
= retval
;
377 inode
->i_ctime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
379 dir
->i_version
= ++event
;
380 mark_inode_dirty(dir
);
381 mark_inode_dirty(inode
);
389 affs_symlink(struct inode
*dir
, struct dentry
*dentry
, const char *symname
)
391 struct buffer_head
*bh
;
395 int i
, maxlen
, error
;
398 pr_debug("AFFS: symlink(%lu,\"%.*s\" -> \"%s\")\n",dir
->i_ino
,
399 (int)dentry
->d_name
.len
,dentry
->d_name
.name
,symname
);
401 maxlen
= 4 * AFFS_I2HSIZE(dir
) - 1;
403 inode
= affs_new_inode(dir
);
407 inode
->i_op
= &affs_symlink_inode_operations
;
408 inode
->i_data
.a_ops
= &affs_symlink_aops
;
409 inode
->i_mode
= S_IFLNK
| 0777;
410 inode
->u
.affs_i
.i_protect
= mode_to_prot(inode
->i_mode
);
412 bh
= affs_bread(inode
->i_dev
,inode
->i_ino
,AFFS_I2BSIZE(inode
));
416 p
= ((struct slink_front
*)bh
->b_data
)->symname
;
418 if (*symname
== '/') {
419 while (*symname
== '/')
421 while (inode
->i_sb
->u
.affs_sb
.s_volume
[i
]) /* Cannot overflow */
422 *p
++ = inode
->i_sb
->u
.affs_sb
.s_volume
[i
++];
424 while (i
< maxlen
&& (c
= *symname
++)) {
425 if (c
== '.' && lc
== '/' && *symname
== '.' && symname
[1] == '/') {
430 } else if (c
== '.' && lc
== '/' && *symname
== '/') {
439 while (*symname
== '/')
443 mark_buffer_dirty(bh
,1);
445 mark_inode_dirty(inode
);
447 /* N.B. This test shouldn't be necessary ... dentry must be negative */
449 bh
= affs_find_entry(dir
,dentry
,&tmp
);
452 /* N.B. Shouldn't we add the entry before dirtying the buffer? */
453 error
= affs_add_entry(dir
,NULL
,inode
,dentry
,ST_SOFTLINK
);
456 d_instantiate(dentry
,inode
);
457 dir
->i_version
= ++event
;
458 mark_inode_dirty(dir
);
467 mark_inode_dirty(inode
);
473 affs_link(struct dentry
*old_dentry
, struct inode
*dir
, struct dentry
*dentry
)
475 struct inode
*oldinode
= old_dentry
->d_inode
;
477 struct buffer_head
*bh
;
481 pr_debug("AFFS: link(%lu,%lu,\"%.*s\")\n",oldinode
->i_ino
,dir
->i_ino
,
482 (int)dentry
->d_name
.len
,dentry
->d_name
.name
);
484 /* N.B. Do we need this test? The dentry must be negative ... */
485 bh
= affs_find_entry(dir
,dentry
,&i
);
490 if (oldinode
->u
.affs_i
.i_hlink
) { /* Cannot happen */
491 affs_warning(dir
->i_sb
,"link","Impossible link to link");
495 if (!(inode
= affs_new_inode(dir
)))
498 inode
->i_op
= oldinode
->i_op
;
499 inode
->i_fop
= oldinode
->i_fop
;
500 inode
->u
.affs_i
.i_protect
= mode_to_prot(oldinode
->i_mode
);
501 inode
->u
.affs_i
.i_original
= oldinode
->i_ino
;
502 inode
->u
.affs_i
.i_hlink
= 1;
503 inode
->i_mtime
= oldinode
->i_mtime
;
505 if (S_ISDIR(oldinode
->i_mode
))
506 error
= affs_add_entry(dir
,oldinode
,inode
,dentry
,ST_LINKDIR
);
508 error
= affs_add_entry(dir
,oldinode
,inode
,dentry
,ST_LINKFILE
);
512 dir
->i_version
= ++event
;
513 mark_inode_dirty(dir
);
514 mark_inode_dirty(oldinode
);
515 atomic_inc(&oldinode
->i_count
);
516 d_instantiate(dentry
,oldinode
);
518 mark_inode_dirty(inode
);
526 affs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
527 struct inode
*new_dir
, struct dentry
*new_dentry
)
529 struct inode
*old_inode
= old_dentry
->d_inode
;
530 struct inode
*new_inode
= new_dentry
->d_inode
;
531 struct buffer_head
*old_bh
;
532 struct buffer_head
*new_bh
;
533 unsigned long old_ino
;
534 unsigned long new_ino
;
537 pr_debug("AFFS: rename(old=%lu,\"%*s\" (inode=%p) to new=%lu,\"%*s\" (inode=%p))\n",
538 old_dir
->i_ino
,old_dentry
->d_name
.len
,old_dentry
->d_name
.name
,old_inode
,
539 new_dir
->i_ino
,new_dentry
->d_name
.len
,new_dentry
->d_name
.name
,new_inode
);
541 if ((retval
= affs_check_name(new_dentry
->d_name
.name
,new_dentry
->d_name
.len
)))
546 old_bh
= affs_find_entry(old_dir
,old_dentry
,&old_ino
);
550 new_bh
= affs_find_entry(new_dir
,new_dentry
,&new_ino
);
551 if (new_bh
&& !new_inode
) {
552 affs_error(old_inode
->i_sb
,"affs_rename",
553 "No inode for entry found (key=%lu)\n",new_ino
);
556 if (S_ISDIR(old_inode
->i_mode
)) {
559 if (!d_unhashed(new_dentry
))
562 if (!empty_dir(new_bh
,AFFS_I2HSIZE(new_inode
)))
567 if (affs_parent_ino(old_inode
) != old_dir
->i_ino
)
570 /* Unlink destination if it already exists */
572 if ((retval
= affs_remove_header(new_bh
,new_dir
)) < 0)
574 new_inode
->i_nlink
= retval
;
575 mark_inode_dirty(new_inode
);
576 if (new_inode
->i_ino
== new_ino
)
577 new_inode
->i_nlink
= 0;
579 /* Remove header from its parent directory. */
580 if ((retval
= affs_remove_hash(old_bh
,old_dir
)))
582 /* And insert it into the new directory with the new name. */
583 affs_copy_name(FILE_END(old_bh
->b_data
,old_inode
)->file_name
,new_dentry
->d_name
.name
);
584 if ((retval
= affs_insert_hash(new_dir
->i_ino
,old_bh
,new_dir
)))
586 affs_fix_checksum(AFFS_I2BSIZE(new_dir
),old_bh
->b_data
,5);
588 new_dir
->i_ctime
= new_dir
->i_mtime
= old_dir
->i_ctime
589 = old_dir
->i_mtime
= CURRENT_TIME
;
590 new_dir
->i_version
= ++event
;
591 old_dir
->i_version
= ++event
;
593 mark_inode_dirty(new_dir
);
594 mark_inode_dirty(old_dir
);
595 mark_buffer_dirty(old_bh
,1);