2 * linux/fs/sysv/namei.c
5 * Copyright (C) 1991, 1992 Linus Torvalds
8 * Copyright (C) 1993 Pascal Haible, Bruno Haible
11 * Copyright (C) 1993 Bruno Haible
12 * Copyright (C) 1997, 1998 Krzysztof G. Baranowski
16 #include <linux/sched.h>
17 #include <linux/kernel.h>
19 #include <linux/sysv_fs.h>
20 #include <linux/string.h>
21 #include <linux/stat.h>
22 #include <linux/errno.h>
24 /* compare strings: name[0..len-1] (not zero-terminated) and
25 * buffer[0..] (filled with zeroes up to buffer[0..maxlen-1])
27 static inline int namecompare(int len
, int maxlen
,
28 const char * name
, const char * buffer
)
32 if (len
< maxlen
&& buffer
[len
])
34 return !memcmp(name
, buffer
, len
);
38 * ok, we cannot use strncmp, as the name is not in our data space. [Now it is!]
39 * Thus we'll have to use sysv_match. No big problem. Match also makes
42 * NOTE! unlike strncmp, sysv_match returns 1 for success, 0 for failure.
44 static int sysv_match(int len
, const char * name
, struct sysv_dir_entry
* de
)
46 if (!de
->inode
|| len
> SYSV_NAMELEN
)
48 /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
49 if (!len
&& (de
->name
[0]=='.') && (de
->name
[1]=='\0'))
51 return namecompare(len
, SYSV_NAMELEN
, name
, de
->name
);
57 * finds an entry in the specified directory with the wanted name. It
58 * returns the cache buffer in which the entry was found, and the entry
59 * itself (as a parameter - res_dir). It does NOT read the inode of the
60 * entry - you'll have to do that yourself if you want to.
62 static struct buffer_head
* sysv_find_entry(struct inode
* dir
,
63 const char * name
, int namelen
, struct sysv_dir_entry
** res_dir
)
65 struct super_block
* sb
;
66 unsigned long pos
, block
, offset
; /* pos = block * block_size + offset */
67 struct buffer_head
* bh
;
71 if (namelen
> SYSV_NAMELEN
) {
73 namelen
= SYSV_NAMELEN
;
78 pos
= block
= offset
= 0;
79 while (pos
< dir
->i_size
) {
81 bh
= sysv_file_bread(dir
, block
, 0);
83 /* offset = 0; */ block
++;
84 pos
+= sb
->sv_block_size
;
88 if (sysv_match(namelen
, name
,
89 *res_dir
= (struct sysv_dir_entry
*) (bh
->b_data
+ offset
) ))
92 offset
+= SYSV_DIRSIZE
;
93 if (offset
< sb
->sv_block_size
)
104 static struct dentry
*sysv_lookup(struct inode
* dir
, struct dentry
* dentry
)
106 struct inode
* inode
= NULL
;
107 struct sysv_dir_entry
* de
;
108 struct buffer_head
* bh
;
110 bh
= sysv_find_entry(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
, &de
);
115 inode
= iget(dir
->i_sb
, ino
);
118 return ERR_PTR(-EACCES
);
120 d_add(dentry
, inode
);
127 * adds a file entry to the specified directory, returning a possible
128 * error value if it fails.
130 * NOTE!! The inode part of 'de' is left at 0 - which means you
131 * may not sleep between calling this and putting something into
132 * the entry, as someone else might have used it while you slept.
134 static int sysv_add_entry(struct inode
* dir
,
135 const char * name
, int namelen
,
136 struct buffer_head
** res_buf
,
137 struct sysv_dir_entry
** res_dir
)
139 struct super_block
* sb
;
141 unsigned long pos
, block
, offset
; /* pos = block * block_size + offset */
142 struct buffer_head
* bh
;
143 struct sysv_dir_entry
* de
;
148 if (namelen
> SYSV_NAMELEN
) {
150 namelen
= SYSV_NAMELEN
;
152 return -ENAMETOOLONG
;
157 pos
= block
= offset
= 0;
160 bh
= sysv_file_bread(dir
, block
, 1);
164 de
= (struct sysv_dir_entry
*) (bh
->b_data
+ offset
);
166 offset
+= SYSV_DIRSIZE
;
167 if (pos
> dir
->i_size
) {
170 mark_inode_dirty(dir
);
173 if (namecompare(namelen
, SYSV_NAMELEN
, name
, de
->name
)) {
178 dir
->i_mtime
= dir
->i_ctime
= CURRENT_TIME
;
179 mark_inode_dirty(dir
);
180 for (i
= 0; i
< SYSV_NAMELEN
; i
++)
181 de
->name
[i
] = (i
< namelen
) ? name
[i
] : 0;
182 mark_buffer_dirty(bh
);
186 if (offset
< sb
->sv_block_size
)
196 static int sysv_create(struct inode
* dir
, struct dentry
* dentry
, int mode
)
199 struct inode
* inode
;
200 struct buffer_head
* bh
;
201 struct sysv_dir_entry
* de
;
203 inode
= sysv_new_inode(dir
);
206 inode
->i_op
= &sysv_file_inode_operations
;
207 inode
->i_fop
= &sysv_file_operations
;
208 inode
->i_mapping
->a_ops
= &sysv_aops
;
209 inode
->i_mode
= mode
;
210 mark_inode_dirty(inode
);
211 error
= sysv_add_entry(dir
, dentry
->d_name
.name
,
212 dentry
->d_name
.len
, &bh
, &de
);
215 mark_inode_dirty(inode
);
219 de
->inode
= inode
->i_ino
;
220 mark_buffer_dirty(bh
);
222 d_instantiate(dentry
, inode
);
226 static int sysv_mknod(struct inode
* dir
, struct dentry
* dentry
, int mode
, int rdev
)
229 struct inode
* inode
;
230 struct buffer_head
* bh
;
231 struct sysv_dir_entry
* de
;
233 bh
= sysv_find_entry(dir
, dentry
->d_name
.name
,
234 dentry
->d_name
.len
, &de
);
239 inode
= sysv_new_inode(dir
);
242 inode
->i_uid
= current
->fsuid
;
243 init_special_inode(inode
, mode
, rdev
);
244 mark_inode_dirty(inode
);
245 error
= sysv_add_entry(dir
, dentry
->d_name
.name
,
246 dentry
->d_name
.len
, &bh
, &de
);
249 mark_inode_dirty(inode
);
253 de
->inode
= inode
->i_ino
;
254 mark_buffer_dirty(bh
);
256 d_instantiate(dentry
, inode
);
260 static int sysv_mkdir(struct inode
* dir
, struct dentry
*dentry
, int mode
)
263 struct inode
* inode
;
264 struct buffer_head
* bh
, *dir_block
;
265 struct sysv_dir_entry
* de
;
267 bh
= sysv_find_entry(dir
, dentry
->d_name
.name
,
268 dentry
->d_name
.len
, &de
);
273 if (dir
->i_nlink
>= dir
->i_sb
->sv_link_max
)
275 inode
= sysv_new_inode(dir
);
278 inode
->i_op
= &sysv_dir_inode_operations
;
279 inode
->i_fop
= &sysv_dir_operations
;
280 inode
->i_size
= 2 * SYSV_DIRSIZE
;
281 dir_block
= sysv_file_bread(inode
,0,1);
284 mark_inode_dirty(inode
);
288 de
= (struct sysv_dir_entry
*) (dir_block
->b_data
+ 0*SYSV_DIRSIZE
);
289 de
->inode
= inode
->i_ino
;
290 strcpy(de
->name
,"."); /* rest of de->name is zero, see sysv_new_block */
291 de
= (struct sysv_dir_entry
*) (dir_block
->b_data
+ 1*SYSV_DIRSIZE
);
292 de
->inode
= dir
->i_ino
;
293 strcpy(de
->name
,".."); /* rest of de->name is zero, see sysv_new_block */
295 mark_buffer_dirty(dir_block
);
297 inode
->i_mode
= S_IFDIR
| mode
;
298 if (dir
->i_mode
& S_ISGID
)
299 inode
->i_mode
|= S_ISGID
;
300 mark_inode_dirty(inode
);
301 error
= sysv_add_entry(dir
, dentry
->d_name
.name
,
302 dentry
->d_name
.len
, &bh
, &de
);
308 de
->inode
= inode
->i_ino
;
309 mark_buffer_dirty(bh
);
311 mark_inode_dirty(dir
);
313 d_instantiate(dentry
, inode
);
318 * routine to check that the specified directory is empty (for rmdir)
320 static int empty_dir(struct inode
* inode
)
322 struct super_block
* sb
;
323 unsigned long pos
, block
, offset
; /* pos = block * block_size + offset */
324 struct buffer_head
* bh
;
325 struct sysv_dir_entry
* de
;
329 pos
= offset
= 2*SYSV_DIRSIZE
;
330 if ((unsigned long)(inode
->i_size
) % SYSV_DIRSIZE
)
332 if (inode
->i_size
< pos
)
334 bh
= sysv_file_bread(inode
, 0, 0);
337 de
= (struct sysv_dir_entry
*) (bh
->b_data
+ 0*SYSV_DIRSIZE
);
338 if (!de
->inode
|| strcmp(de
->name
,"."))
340 de
= (struct sysv_dir_entry
*) (bh
->b_data
+ 1*SYSV_DIRSIZE
);
341 if (!de
->inode
|| strcmp(de
->name
,".."))
344 while (pos
< inode
->i_size
) {
346 bh
= sysv_file_bread(inode
, block
, 0);
348 /* offset = 0; */ block
++;
349 pos
+= sb
->sv_block_size
;
353 de
= (struct sysv_dir_entry
*) (bh
->b_data
+ offset
);
355 offset
+= SYSV_DIRSIZE
;
360 if (offset
< sb
->sv_block_size
)
370 printk("Bad directory on device %s\n",
371 kdevname(inode
->i_dev
));
375 static int sysv_rmdir(struct inode
* dir
, struct dentry
* dentry
)
378 struct inode
* inode
;
379 struct buffer_head
* bh
;
380 struct sysv_dir_entry
* de
;
382 inode
= dentry
->d_inode
;
383 bh
= sysv_find_entry(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
, &de
);
385 if (!bh
|| de
->inode
!= inode
->i_ino
)
388 if (!empty_dir(inode
)) {
392 if (inode
->i_nlink
!= 2)
393 printk("empty directory has nlink!=2 (%d)\n", inode
->i_nlink
);
395 mark_buffer_dirty(bh
);
398 inode
->i_ctime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
399 mark_inode_dirty(inode
);
400 mark_inode_dirty(dir
);
407 static int sysv_unlink(struct inode
* dir
, struct dentry
* dentry
)
410 struct inode
* inode
;
411 struct buffer_head
* bh
;
412 struct sysv_dir_entry
* de
;
415 inode
= dentry
->d_inode
;
416 bh
= sysv_find_entry(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
, &de
);
417 if (!bh
|| de
->inode
!= inode
->i_ino
)
419 if (!inode
->i_nlink
) {
420 printk("Deleting nonexistent file (%s:%lu), %d\n",
421 kdevname(inode
->i_dev
), inode
->i_ino
, inode
->i_nlink
);
425 mark_buffer_dirty(bh
);
426 dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
427 mark_inode_dirty(dir
);
429 inode
->i_ctime
= dir
->i_ctime
;
430 mark_inode_dirty(inode
);
437 static int sysv_symlink(struct inode
* dir
, struct dentry
* dentry
,
438 const char * symname
)
440 struct inode
* inode
;
441 struct sysv_dir_entry
* de
;
442 struct buffer_head
* bh
;
447 l
= strlen(symname
)+1;
448 if (l
> dir
->i_sb
->sv_block_size_1
)
451 if (!(inode
= sysv_new_inode(dir
)))
454 inode
->i_mode
= S_IFLNK
| 0777;
455 inode
->i_op
= &sysv_symlink_inode_operations
;
456 inode
->i_mapping
->a_ops
= &sysv_aops
;
457 err
= block_symlink(inode
, symname
, l
);
460 mark_inode_dirty(inode
);
461 err
= sysv_add_entry(dir
, dentry
->d_name
.name
,
462 dentry
->d_name
.len
, &bh
, &de
);
465 de
->inode
= inode
->i_ino
;
466 mark_buffer_dirty(bh
);
468 d_instantiate(dentry
, inode
);
473 mark_inode_dirty(inode
);
478 static int sysv_link(struct dentry
* old_dentry
, struct inode
* dir
,
479 struct dentry
* dentry
)
481 struct inode
*oldinode
= old_dentry
->d_inode
;
483 struct sysv_dir_entry
* de
;
484 struct buffer_head
* bh
;
486 if (S_ISDIR(oldinode
->i_mode
)) {
489 if (oldinode
->i_nlink
>= oldinode
->i_sb
->sv_link_max
) {
492 bh
= sysv_find_entry(dir
, dentry
->d_name
.name
,
493 dentry
->d_name
.len
, &de
);
498 error
= sysv_add_entry(dir
, dentry
->d_name
.name
,
499 dentry
->d_name
.len
, &bh
, &de
);
504 de
->inode
= oldinode
->i_ino
;
505 mark_buffer_dirty(bh
);
508 oldinode
->i_ctime
= CURRENT_TIME
;
509 mark_inode_dirty(oldinode
);
510 atomic_inc(&oldinode
->i_count
);
511 d_instantiate(dentry
, oldinode
);
515 #define PARENT_INO(buffer) \
516 (((struct sysv_dir_entry *) ((buffer) + 1*SYSV_DIRSIZE))->inode)
519 * Anybody can rename anything with this: the permission checks are left to the
520 * higher-level routines.
522 static int sysv_rename(struct inode
* old_dir
, struct dentry
* old_dentry
,
523 struct inode
* new_dir
, struct dentry
* new_dentry
)
525 struct inode
* old_inode
, * new_inode
;
526 struct buffer_head
* old_bh
, * new_bh
, * dir_bh
;
527 struct sysv_dir_entry
* old_de
, * new_de
;
530 old_inode
= old_dentry
->d_inode
;
531 new_inode
= new_dentry
->d_inode
;
532 new_bh
= dir_bh
= NULL
;
533 old_bh
= sysv_find_entry(old_dir
, old_dentry
->d_name
.name
,
534 old_dentry
->d_name
.len
, &old_de
);
536 if (!old_bh
|| old_de
->inode
!= old_inode
->i_ino
)
539 new_bh
= sysv_find_entry(new_dir
, new_dentry
->d_name
.name
,
540 new_dentry
->d_name
.len
, &new_de
);
547 if (S_ISDIR(old_inode
->i_mode
)) {
550 if (!empty_dir(new_inode
))
554 dir_bh
= sysv_file_bread(old_inode
, 0, 0);
557 if (PARENT_INO(dir_bh
->b_data
) != old_dir
->i_ino
)
560 if (!new_inode
&& new_dir
!= old_dir
&&
561 new_dir
->i_nlink
>= new_dir
->i_sb
->sv_link_max
)
565 retval
= sysv_add_entry(new_dir
, new_dentry
->d_name
.name
,
566 new_dentry
->d_name
.len
, &new_bh
, &new_de
);
570 new_de
->inode
= old_inode
->i_ino
;
572 old_dir
->i_ctime
= old_dir
->i_mtime
= CURRENT_TIME
;
573 mark_inode_dirty(old_dir
);
574 new_dir
->i_ctime
= new_dir
->i_mtime
= CURRENT_TIME
;
575 mark_inode_dirty(new_dir
);
577 new_inode
->i_nlink
--;
578 new_inode
->i_ctime
= CURRENT_TIME
;
579 mark_inode_dirty(new_inode
);
581 mark_buffer_dirty(old_bh
);
582 mark_buffer_dirty(new_bh
);
584 PARENT_INO(dir_bh
->b_data
) = new_dir
->i_ino
;
585 mark_buffer_dirty(dir_bh
);
587 mark_inode_dirty(old_dir
);
589 new_inode
->i_nlink
--;
590 mark_inode_dirty(new_inode
);
593 mark_inode_dirty(new_dir
);
605 * directories can handle most operations...
607 struct inode_operations sysv_dir_inode_operations
= {
612 symlink
: sysv_symlink
,
617 setattr
: sysv_notify_change
,