Import 2.2.6pre1
[davej-history.git] / fs / minix / namei.c
blob3bf0f22dc48c875ac10026d9d67107fcf234d105
1 /*
2 * linux/fs/minix/namei.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
7 #include <linux/sched.h>
8 #include <linux/minix_fs.h>
9 #include <linux/kernel.h>
10 #include <linux/string.h>
11 #include <linux/stat.h>
12 #include <linux/fcntl.h>
13 #include <linux/errno.h>
15 #include <asm/uaccess.h>
18 * comment out this line if you want names > info->s_namelen chars to be
19 * truncated. Else they will be disallowed (ENAMETOOLONG).
21 /* #define NO_TRUNCATE */
23 static inline int namecompare(int len, int maxlen,
24 const char * name, const char * buffer)
26 if (len < maxlen && buffer[len])
27 return 0;
28 return !memcmp(name, buffer, len);
32 * minix_find_entry()
34 * finds an entry in the specified directory with the wanted name. It
35 * returns the cache buffer in which the entry was found, and the entry
36 * itself (as a parameter - res_dir). It does NOT read the inode of the
37 * entry - you'll have to do that yourself if you want to.
39 static struct buffer_head * minix_find_entry(struct inode * dir,
40 const char * name, int namelen, struct minix_dir_entry ** res_dir)
42 unsigned long block, offset;
43 struct buffer_head * bh;
44 struct minix_sb_info * info;
45 struct minix_dir_entry *de;
47 *res_dir = NULL;
48 if (!dir || !dir->i_sb)
49 return NULL;
50 info = &dir->i_sb->u.minix_sb;
51 if (namelen > info->s_namelen) {
52 #ifdef NO_TRUNCATE
53 return NULL;
54 #else
55 namelen = info->s_namelen;
56 #endif
58 bh = NULL;
59 block = offset = 0;
60 while (block*BLOCK_SIZE+offset < dir->i_size) {
61 if (!bh) {
62 bh = minix_bread(dir,block,0);
63 if (!bh) {
64 block++;
65 continue;
68 de = (struct minix_dir_entry *) (bh->b_data + offset);
69 offset += info->s_dirsize;
70 if (de->inode && namecompare(namelen,info->s_namelen,name,de->name)) {
71 *res_dir = de;
72 return bh;
74 if (offset < bh->b_size)
75 continue;
76 brelse(bh);
77 bh = NULL;
78 offset = 0;
79 block++;
81 brelse(bh);
82 return NULL;
85 #ifndef NO_TRUNCATE
87 static int minix_hash(struct dentry *dentry, struct qstr *qstr)
89 unsigned long hash;
90 int i;
91 const unsigned char *name;
93 i = dentry->d_inode->i_sb->u.minix_sb.s_namelen;
94 if (i >= qstr->len)
95 return 0;
96 /* Truncate the name in place, avoids having to define a compare
97 function. */
98 qstr->len = i;
99 name = qstr->name;
100 hash = init_name_hash();
101 while (i--)
102 hash = partial_name_hash(*name++, hash);
103 qstr->hash = end_name_hash(hash);
104 return 0;
107 #endif
109 struct dentry_operations minix_dentry_operations = {
110 0, /* revalidate */
111 #ifndef NO_TRUNCATE
112 minix_hash,
113 #else
115 #endif
116 0 /* compare */
119 int minix_lookup(struct inode * dir, struct dentry *dentry)
121 struct inode * inode = NULL;
122 struct minix_dir_entry * de;
123 struct buffer_head * bh;
125 #ifndef NO_TRUNCATE
126 dentry->d_op = &minix_dentry_operations;
127 #endif
128 bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
129 if (bh) {
130 int ino = de->inode;
131 brelse (bh);
132 inode = iget(dir->i_sb, ino);
134 if (!inode)
135 return -EACCES;
137 d_add(dentry, inode);
138 return 0;
142 * minix_add_entry()
144 * adds a file entry to the specified directory, returning a possible
145 * error value if it fails.
147 * NOTE!! The inode part of 'de' is left at 0 - which means you
148 * may not sleep between calling this and putting something into
149 * the entry, as someone else might have used it while you slept.
151 static int minix_add_entry(struct inode * dir,
152 const char * name, int namelen,
153 struct buffer_head ** res_buf,
154 struct minix_dir_entry ** res_dir)
156 int i;
157 unsigned long block, offset;
158 struct buffer_head * bh;
159 struct minix_dir_entry * de;
160 struct minix_sb_info * info;
162 *res_buf = NULL;
163 *res_dir = NULL;
164 if (!dir || !dir->i_sb)
165 return -ENOENT;
166 info = &dir->i_sb->u.minix_sb;
167 if (namelen > info->s_namelen) {
168 #ifdef NO_TRUNCATE
169 return -ENAMETOOLONG;
170 #else
171 namelen = info->s_namelen;
172 #endif
174 if (!namelen)
175 return -ENOENT;
176 bh = NULL;
177 block = offset = 0;
178 while (1) {
179 if (!bh) {
180 bh = minix_bread(dir,block,1);
181 if (!bh)
182 return -ENOSPC;
184 de = (struct minix_dir_entry *) (bh->b_data + offset);
185 offset += info->s_dirsize;
186 if (block*bh->b_size + offset > dir->i_size) {
187 de->inode = 0;
188 dir->i_size = block*bh->b_size + offset;
189 mark_inode_dirty(dir);
191 if (de->inode) {
192 if (namecompare(namelen, info->s_namelen, name, de->name)) {
193 brelse(bh);
194 return -EEXIST;
196 } else {
197 dir->i_mtime = dir->i_ctime = CURRENT_TIME;
198 mark_inode_dirty(dir);
199 for (i = 0; i < info->s_namelen ; i++)
200 de->name[i] = (i < namelen) ? name[i] : 0;
201 dir->i_version = ++event;
202 mark_buffer_dirty(bh, 1);
203 *res_dir = de;
204 break;
206 if (offset < bh->b_size)
207 continue;
208 brelse(bh);
209 bh = NULL;
210 offset = 0;
211 block++;
213 *res_buf = bh;
214 return 0;
217 int minix_create(struct inode * dir, struct dentry *dentry, int mode)
219 int error;
220 struct inode * inode;
221 struct buffer_head * bh;
222 struct minix_dir_entry * de;
224 if (!dir)
225 return -ENOENT;
226 inode = minix_new_inode(dir);
227 if (!inode)
228 return -ENOSPC;
229 inode->i_op = &minix_file_inode_operations;
230 inode->i_mode = mode;
231 mark_inode_dirty(inode);
232 error = minix_add_entry(dir, dentry->d_name.name,
233 dentry->d_name.len, &bh ,&de);
234 if (error) {
235 inode->i_nlink--;
236 mark_inode_dirty(inode);
237 iput(inode);
238 return error;
240 de->inode = inode->i_ino;
241 mark_buffer_dirty(bh, 1);
242 brelse(bh);
243 d_instantiate(dentry, inode);
244 return 0;
247 int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev)
249 int error;
250 struct inode * inode;
251 struct buffer_head * bh;
252 struct minix_dir_entry * de;
254 if (!dir)
255 return -ENOENT;
256 bh = minix_find_entry(dir, dentry->d_name.name,
257 dentry->d_name.len, &de);
258 if (bh) {
259 brelse(bh);
260 return -EEXIST;
262 inode = minix_new_inode(dir);
263 if (!inode)
264 return -ENOSPC;
265 inode->i_uid = current->fsuid;
266 inode->i_mode = mode;
267 inode->i_op = NULL;
268 if (S_ISREG(inode->i_mode))
269 inode->i_op = &minix_file_inode_operations;
270 else if (S_ISCHR(inode->i_mode))
271 inode->i_op = &chrdev_inode_operations;
272 else if (S_ISBLK(inode->i_mode))
273 inode->i_op = &blkdev_inode_operations;
274 else if (S_ISFIFO(inode->i_mode))
275 init_fifo(inode);
276 if (S_ISBLK(mode) || S_ISCHR(mode))
277 inode->i_rdev = to_kdev_t(rdev);
278 mark_inode_dirty(inode);
279 error = minix_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &bh, &de);
280 if (error) {
281 inode->i_nlink--;
282 mark_inode_dirty(inode);
283 iput(inode);
284 return error;
286 de->inode = inode->i_ino;
287 mark_buffer_dirty(bh, 1);
288 brelse(bh);
289 d_instantiate(dentry, inode);
290 return 0;
293 int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
295 int error;
296 struct inode * inode;
297 struct buffer_head * bh, *dir_block;
298 struct minix_dir_entry * de;
299 struct minix_sb_info * info;
301 if (!dir || !dir->i_sb)
302 return -EINVAL;
303 info = &dir->i_sb->u.minix_sb;
304 bh = minix_find_entry(dir, dentry->d_name.name,
305 dentry->d_name.len, &de);
306 if (bh) {
307 brelse(bh);
308 return -EEXIST;
310 if (dir->i_nlink >= info->s_link_max)
311 return -EMLINK;
312 inode = minix_new_inode(dir);
313 if (!inode)
314 return -ENOSPC;
315 inode->i_op = &minix_dir_inode_operations;
316 inode->i_size = 2 * info->s_dirsize;
317 dir_block = minix_bread(inode,0,1);
318 if (!dir_block) {
319 inode->i_nlink--;
320 mark_inode_dirty(inode);
321 iput(inode);
322 return -ENOSPC;
324 de = (struct minix_dir_entry *) dir_block->b_data;
325 de->inode=inode->i_ino;
326 strcpy(de->name,".");
327 de = (struct minix_dir_entry *) (dir_block->b_data + info->s_dirsize);
328 de->inode = dir->i_ino;
329 strcpy(de->name,"..");
330 inode->i_nlink = 2;
331 mark_buffer_dirty(dir_block, 1);
332 brelse(dir_block);
333 inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
334 if (dir->i_mode & S_ISGID)
335 inode->i_mode |= S_ISGID;
336 mark_inode_dirty(inode);
337 error = minix_add_entry(dir, dentry->d_name.name,
338 dentry->d_name.len, &bh, &de);
339 if (error) {
340 inode->i_nlink=0;
341 iput(inode);
342 return error;
344 de->inode = inode->i_ino;
345 mark_buffer_dirty(bh, 1);
346 dir->i_nlink++;
347 mark_inode_dirty(dir);
348 brelse(bh);
349 d_instantiate(dentry, inode);
350 return 0;
354 * routine to check that the specified directory is empty (for rmdir)
356 static int empty_dir(struct inode * inode)
358 unsigned int block, offset;
359 struct buffer_head * bh;
360 struct minix_dir_entry * de;
361 struct minix_sb_info * info;
363 if (!inode || !inode->i_sb)
364 return 1;
365 info = &inode->i_sb->u.minix_sb;
366 block = 0;
367 bh = NULL;
368 offset = 2*info->s_dirsize;
369 if (inode->i_size & (info->s_dirsize-1))
370 goto bad_dir;
371 if (inode->i_size < offset)
372 goto bad_dir;
373 bh = minix_bread(inode,0,0);
374 if (!bh)
375 goto bad_dir;
376 de = (struct minix_dir_entry *) bh->b_data;
377 if (!de->inode || strcmp(de->name,"."))
378 goto bad_dir;
379 de = (struct minix_dir_entry *) (bh->b_data + info->s_dirsize);
380 if (!de->inode || strcmp(de->name,".."))
381 goto bad_dir;
382 while (block*BLOCK_SIZE+offset < inode->i_size) {
383 if (!bh) {
384 bh = minix_bread(inode,block,0);
385 if (!bh) {
386 block++;
387 continue;
390 de = (struct minix_dir_entry *) (bh->b_data + offset);
391 offset += info->s_dirsize;
392 if (de->inode) {
393 brelse(bh);
394 return 0;
396 if (offset < bh->b_size)
397 continue;
398 brelse(bh);
399 bh = NULL;
400 offset = 0;
401 block++;
403 brelse(bh);
404 return 1;
405 bad_dir:
406 brelse(bh);
407 printk("Bad directory on device %s\n",
408 kdevname(inode->i_dev));
409 return 1;
412 int minix_rmdir(struct inode * dir, struct dentry *dentry)
414 int retval;
415 struct inode * inode;
416 struct buffer_head * bh;
417 struct minix_dir_entry * de;
419 inode = NULL;
420 bh = minix_find_entry(dir, dentry->d_name.name,
421 dentry->d_name.len, &de);
422 retval = -ENOENT;
423 if (!bh)
424 goto end_rmdir;
425 inode = dentry->d_inode;
427 if (!empty_dir(inode)) {
428 retval = -ENOTEMPTY;
429 goto end_rmdir;
431 if (de->inode != inode->i_ino) {
432 retval = -ENOENT;
433 goto end_rmdir;
435 if (!list_empty(&dentry->d_hash)) {
436 retval = -EBUSY;
437 goto end_rmdir;
439 if (inode->i_nlink != 2)
440 printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
441 de->inode = 0;
442 dir->i_version = ++event;
443 mark_buffer_dirty(bh, 1);
444 inode->i_nlink=0;
445 mark_inode_dirty(inode);
446 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
447 dir->i_nlink--;
448 mark_inode_dirty(dir);
449 d_delete(dentry);
450 retval = 0;
451 end_rmdir:
452 brelse(bh);
453 return retval;
456 int minix_unlink(struct inode * dir, struct dentry *dentry)
458 int retval;
459 struct inode * inode;
460 struct buffer_head * bh;
461 struct minix_dir_entry * de;
463 repeat:
464 retval = -ENOENT;
465 inode = NULL;
466 bh = minix_find_entry(dir, dentry->d_name.name,
467 dentry->d_name.len, &de);
468 if (!bh)
469 goto end_unlink;
470 inode = dentry->d_inode;
472 retval = -EPERM;
473 if (de->inode != inode->i_ino) {
474 brelse(bh);
475 current->counter = 0;
476 schedule();
477 goto repeat;
479 if (de->inode != inode->i_ino) {
480 retval = -ENOENT;
481 goto end_unlink;
483 if (!inode->i_nlink) {
484 printk("Deleting nonexistent file (%s:%lu), %d\n",
485 kdevname(inode->i_dev),
486 inode->i_ino, inode->i_nlink);
487 inode->i_nlink=1;
489 de->inode = 0;
490 dir->i_version = ++event;
491 mark_buffer_dirty(bh, 1);
492 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
493 mark_inode_dirty(dir);
494 inode->i_nlink--;
495 inode->i_ctime = dir->i_ctime;
496 mark_inode_dirty(inode);
497 d_delete(dentry); /* This also frees the inode */
498 retval = 0;
499 end_unlink:
500 brelse(bh);
501 return retval;
504 int minix_symlink(struct inode * dir, struct dentry *dentry,
505 const char * symname)
507 struct minix_dir_entry * de;
508 struct inode * inode = NULL;
509 struct buffer_head * bh = NULL, * name_block = NULL;
510 int i;
511 char c;
513 if (!(inode = minix_new_inode(dir)))
514 return -ENOSPC;
516 inode->i_mode = S_IFLNK | 0777;
517 inode->i_op = &minix_symlink_inode_operations;
518 name_block = minix_bread(inode,0,1);
519 if (!name_block) {
520 inode->i_nlink--;
521 mark_inode_dirty(inode);
522 iput(inode);
523 return -ENOSPC;
525 i = 0;
526 while (i < 1023 && (c=*(symname++)))
527 name_block->b_data[i++] = c;
528 name_block->b_data[i] = 0;
529 mark_buffer_dirty(name_block, 1);
530 brelse(name_block);
531 inode->i_size = i;
532 mark_inode_dirty(inode);
533 bh = minix_find_entry(dir, dentry->d_name.name,
534 dentry->d_name.len, &de);
535 if (bh) {
536 inode->i_nlink--;
537 mark_inode_dirty(inode);
538 iput(inode);
539 brelse(bh);
540 return -EEXIST;
542 i = minix_add_entry(dir, dentry->d_name.name,
543 dentry->d_name.len, &bh, &de);
544 if (i) {
545 inode->i_nlink--;
546 mark_inode_dirty(inode);
547 iput(inode);
548 return i;
550 de->inode = inode->i_ino;
551 mark_buffer_dirty(bh, 1);
552 brelse(bh);
553 d_instantiate(dentry, inode);
554 return 0;
557 int minix_link(struct dentry * old_dentry, struct inode * dir,
558 struct dentry *dentry)
560 int error;
561 struct inode *inode = old_dentry->d_inode;
562 struct minix_dir_entry * de;
563 struct buffer_head * bh;
565 if (S_ISDIR(inode->i_mode))
566 return -EPERM;
568 if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max)
569 return -EMLINK;
571 bh = minix_find_entry(dir, dentry->d_name.name,
572 dentry->d_name.len, &de);
573 if (bh) {
574 brelse(bh);
575 return -EEXIST;
577 error = minix_add_entry(dir, dentry->d_name.name,
578 dentry->d_name.len, &bh, &de);
579 if (error) {
580 brelse(bh);
581 return error;
583 de->inode = inode->i_ino;
584 mark_buffer_dirty(bh, 1);
585 brelse(bh);
586 inode->i_nlink++;
587 inode->i_ctime = CURRENT_TIME;
588 mark_inode_dirty(inode);
589 inode->i_count++;
590 d_instantiate(dentry, inode);
591 return 0;
594 #define PARENT_INO(buffer) \
595 (((struct minix_dir_entry *) ((buffer)+info->s_dirsize))->inode)
598 * rename uses retrying to avoid race-conditions: at least they should be minimal.
599 * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
600 * checks fail, it tries to restart itself again. Very practical - no changes
601 * are done until we know everything works ok.. and then all the changes can be
602 * done in one fell swoop when we have claimed all the buffers needed.
604 * Anybody can rename anything with this: the permission checks are left to the
605 * higher-level routines.
607 int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
608 struct inode * new_dir, struct dentry *new_dentry)
610 struct inode * old_inode, * new_inode;
611 struct buffer_head * old_bh, * new_bh, * dir_bh;
612 struct minix_dir_entry * old_de, * new_de;
613 struct minix_sb_info * info;
614 int retval;
616 info = &old_dir->i_sb->u.minix_sb;
617 goto start_up;
618 try_again:
619 brelse(old_bh);
620 brelse(new_bh);
621 brelse(dir_bh);
622 current->counter = 0;
623 schedule();
624 start_up:
625 old_inode = new_inode = NULL;
626 old_bh = new_bh = dir_bh = NULL;
627 old_bh = minix_find_entry(old_dir, old_dentry->d_name.name,
628 old_dentry->d_name.len, &old_de);
629 retval = -ENOENT;
630 if (!old_bh)
631 goto end_rename;
632 old_inode = old_dentry->d_inode;
633 retval = -EPERM;
634 new_inode = new_dentry->d_inode;
635 new_bh = minix_find_entry(new_dir, new_dentry->d_name.name,
636 new_dentry->d_name.len, &new_de);
637 if (new_bh) {
638 if (!new_inode) {
639 brelse(new_bh);
640 new_bh = NULL;
643 if (S_ISDIR(old_inode->i_mode)) {
644 if (new_inode) {
645 retval = -ENOTEMPTY;
646 if (!empty_dir(new_inode))
647 goto end_rename;
649 retval = -EIO;
650 dir_bh = minix_bread(old_inode,0,0);
651 if (!dir_bh)
652 goto end_rename;
653 if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
654 goto end_rename;
655 retval = -EMLINK;
656 if (!new_inode && new_dir->i_nlink >= info->s_link_max)
657 goto end_rename;
659 if (!new_bh) {
660 retval = minix_add_entry(new_dir,
661 new_dentry->d_name.name,
662 new_dentry->d_name.len,
663 &new_bh, &new_de);
664 if (retval)
665 goto end_rename;
667 /* sanity checking before doing the rename - avoid races */
668 if (new_inode && (new_de->inode != new_inode->i_ino))
669 goto try_again;
670 if (new_de->inode && !new_inode)
671 goto try_again;
672 if (old_de->inode != old_inode->i_ino)
673 goto try_again;
674 /* ok, that's it */
675 old_de->inode = 0;
676 new_de->inode = old_inode->i_ino;
677 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
678 mark_inode_dirty(old_dir);
679 old_dir->i_version = ++event;
680 new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
681 mark_inode_dirty(new_dir);
682 new_dir->i_version = ++event;
683 if (new_inode) {
684 new_inode->i_nlink--;
685 new_inode->i_ctime = CURRENT_TIME;
686 mark_inode_dirty(new_inode);
688 mark_buffer_dirty(old_bh, 1);
689 mark_buffer_dirty(new_bh, 1);
690 if (dir_bh) {
691 PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
692 mark_buffer_dirty(dir_bh, 1);
693 old_dir->i_nlink--;
694 mark_inode_dirty(old_dir);
695 if (new_inode) {
696 new_inode->i_nlink--;
697 mark_inode_dirty(new_inode);
698 } else {
699 new_dir->i_nlink++;
700 mark_inode_dirty(new_dir);
703 retval = 0;
704 end_rename:
705 brelse(dir_bh);
706 brelse(old_bh);
707 brelse(new_bh);
708 return retval;