Import 2.3.1pre2
[davej-history.git] / fs / minix / namei.c
blobc2366ae4b200f04cd21a5d0243a04f00db03a6c2
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->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 struct dentry *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 ERR_PTR(-EACCES);
137 d_add(dentry, inode);
138 return NULL;
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 inode = minix_new_inode(dir);
225 if (!inode)
226 return -ENOSPC;
227 inode->i_op = &minix_file_inode_operations;
228 inode->i_mode = mode;
229 mark_inode_dirty(inode);
230 error = minix_add_entry(dir, dentry->d_name.name,
231 dentry->d_name.len, &bh ,&de);
232 if (error) {
233 inode->i_nlink--;
234 mark_inode_dirty(inode);
235 iput(inode);
236 return error;
238 de->inode = inode->i_ino;
239 mark_buffer_dirty(bh, 1);
240 brelse(bh);
241 d_instantiate(dentry, inode);
242 return 0;
245 int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev)
247 int error;
248 struct inode * inode;
249 struct buffer_head * bh;
250 struct minix_dir_entry * de;
252 inode = minix_new_inode(dir);
253 if (!inode)
254 return -ENOSPC;
255 inode->i_uid = current->fsuid;
256 init_special_inode(inode, mode, rdev);
257 mark_inode_dirty(inode);
258 error = minix_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &bh, &de);
259 if (error) {
260 inode->i_nlink--;
261 mark_inode_dirty(inode);
262 iput(inode);
263 return error;
265 de->inode = inode->i_ino;
266 mark_buffer_dirty(bh, 1);
267 brelse(bh);
268 d_instantiate(dentry, inode);
269 return 0;
272 int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
274 int error;
275 struct inode * inode;
276 struct buffer_head * bh, *dir_block;
277 struct minix_dir_entry * de;
278 struct minix_sb_info * info;
280 info = &dir->i_sb->u.minix_sb;
281 if (dir->i_nlink >= info->s_link_max)
282 return -EMLINK;
283 inode = minix_new_inode(dir);
284 if (!inode)
285 return -ENOSPC;
286 inode->i_op = &minix_dir_inode_operations;
287 inode->i_size = 2 * info->s_dirsize;
288 dir_block = minix_bread(inode,0,1);
289 if (!dir_block) {
290 inode->i_nlink--;
291 mark_inode_dirty(inode);
292 iput(inode);
293 return -ENOSPC;
295 de = (struct minix_dir_entry *) dir_block->b_data;
296 de->inode=inode->i_ino;
297 strcpy(de->name,".");
298 de = (struct minix_dir_entry *) (dir_block->b_data + info->s_dirsize);
299 de->inode = dir->i_ino;
300 strcpy(de->name,"..");
301 inode->i_nlink = 2;
302 mark_buffer_dirty(dir_block, 1);
303 brelse(dir_block);
304 inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
305 if (dir->i_mode & S_ISGID)
306 inode->i_mode |= S_ISGID;
307 mark_inode_dirty(inode);
308 error = minix_add_entry(dir, dentry->d_name.name,
309 dentry->d_name.len, &bh, &de);
310 if (error) {
311 inode->i_nlink=0;
312 iput(inode);
313 return error;
315 de->inode = inode->i_ino;
316 mark_buffer_dirty(bh, 1);
317 dir->i_nlink++;
318 mark_inode_dirty(dir);
319 brelse(bh);
320 d_instantiate(dentry, inode);
321 return 0;
325 * routine to check that the specified directory is empty (for rmdir)
327 static int empty_dir(struct inode * inode)
329 unsigned int block, offset;
330 struct buffer_head * bh;
331 struct minix_dir_entry * de;
332 struct minix_sb_info * info;
334 if (!inode || !inode->i_sb)
335 return 1;
336 info = &inode->i_sb->u.minix_sb;
337 block = 0;
338 bh = NULL;
339 offset = 2*info->s_dirsize;
340 if (inode->i_size & (info->s_dirsize-1))
341 goto bad_dir;
342 if (inode->i_size < offset)
343 goto bad_dir;
344 bh = minix_bread(inode,0,0);
345 if (!bh)
346 goto bad_dir;
347 de = (struct minix_dir_entry *) bh->b_data;
348 if (!de->inode || strcmp(de->name,"."))
349 goto bad_dir;
350 de = (struct minix_dir_entry *) (bh->b_data + info->s_dirsize);
351 if (!de->inode || strcmp(de->name,".."))
352 goto bad_dir;
353 while (block*BLOCK_SIZE+offset < inode->i_size) {
354 if (!bh) {
355 bh = minix_bread(inode,block,0);
356 if (!bh) {
357 block++;
358 continue;
361 de = (struct minix_dir_entry *) (bh->b_data + offset);
362 offset += info->s_dirsize;
363 if (de->inode) {
364 brelse(bh);
365 return 0;
367 if (offset < bh->b_size)
368 continue;
369 brelse(bh);
370 bh = NULL;
371 offset = 0;
372 block++;
374 brelse(bh);
375 return 1;
376 bad_dir:
377 brelse(bh);
378 printk("Bad directory on device %s\n",
379 kdevname(inode->i_dev));
380 return 1;
383 int minix_rmdir(struct inode * dir, struct dentry *dentry)
385 int retval;
386 struct inode * inode;
387 struct buffer_head * bh;
388 struct minix_dir_entry * de;
390 inode = NULL;
391 bh = minix_find_entry(dir, dentry->d_name.name,
392 dentry->d_name.len, &de);
393 retval = -ENOENT;
394 if (!bh)
395 goto end_rmdir;
396 inode = dentry->d_inode;
398 if (!empty_dir(inode)) {
399 retval = -ENOTEMPTY;
400 goto end_rmdir;
402 if (de->inode != inode->i_ino) {
403 retval = -ENOENT;
404 goto end_rmdir;
406 if (!list_empty(&dentry->d_hash)) {
407 retval = -EBUSY;
408 goto end_rmdir;
410 if (inode->i_nlink != 2)
411 printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
412 de->inode = 0;
413 dir->i_version = ++event;
414 mark_buffer_dirty(bh, 1);
415 inode->i_nlink=0;
416 mark_inode_dirty(inode);
417 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
418 dir->i_nlink--;
419 mark_inode_dirty(dir);
420 d_delete(dentry);
421 retval = 0;
422 end_rmdir:
423 brelse(bh);
424 return retval;
427 int minix_unlink(struct inode * dir, struct dentry *dentry)
429 int retval;
430 struct inode * inode;
431 struct buffer_head * bh;
432 struct minix_dir_entry * de;
434 repeat:
435 retval = -ENOENT;
436 inode = NULL;
437 bh = minix_find_entry(dir, dentry->d_name.name,
438 dentry->d_name.len, &de);
439 if (!bh)
440 goto end_unlink;
441 inode = dentry->d_inode;
443 retval = -EPERM;
444 if (de->inode != inode->i_ino) {
445 brelse(bh);
446 current->counter = 0;
447 schedule();
448 goto repeat;
450 if (de->inode != inode->i_ino) {
451 retval = -ENOENT;
452 goto end_unlink;
454 if (!inode->i_nlink) {
455 printk("Deleting nonexistent file (%s:%lu), %d\n",
456 kdevname(inode->i_dev),
457 inode->i_ino, inode->i_nlink);
458 inode->i_nlink=1;
460 de->inode = 0;
461 dir->i_version = ++event;
462 mark_buffer_dirty(bh, 1);
463 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
464 mark_inode_dirty(dir);
465 inode->i_nlink--;
466 inode->i_ctime = dir->i_ctime;
467 mark_inode_dirty(inode);
468 d_delete(dentry); /* This also frees the inode */
469 retval = 0;
470 end_unlink:
471 brelse(bh);
472 return retval;
475 int minix_symlink(struct inode * dir, struct dentry *dentry,
476 const char * symname)
478 struct minix_dir_entry * de;
479 struct inode * inode = NULL;
480 struct buffer_head * bh = NULL, * name_block = NULL;
481 int i;
482 char c;
484 if (!(inode = minix_new_inode(dir)))
485 return -ENOSPC;
487 inode->i_mode = S_IFLNK | 0777;
488 inode->i_op = &minix_symlink_inode_operations;
489 name_block = minix_bread(inode,0,1);
490 if (!name_block) {
491 inode->i_nlink--;
492 mark_inode_dirty(inode);
493 iput(inode);
494 return -ENOSPC;
496 i = 0;
497 while (i < 1023 && (c=*(symname++)))
498 name_block->b_data[i++] = c;
499 name_block->b_data[i] = 0;
500 mark_buffer_dirty(name_block, 1);
501 brelse(name_block);
502 inode->i_size = i;
503 mark_inode_dirty(inode);
504 i = minix_add_entry(dir, dentry->d_name.name,
505 dentry->d_name.len, &bh, &de);
506 if (i) {
507 inode->i_nlink--;
508 mark_inode_dirty(inode);
509 iput(inode);
510 return i;
512 de->inode = inode->i_ino;
513 mark_buffer_dirty(bh, 1);
514 brelse(bh);
515 d_instantiate(dentry, inode);
516 return 0;
519 int minix_link(struct dentry * old_dentry, struct inode * dir,
520 struct dentry *dentry)
522 int error;
523 struct inode *inode = old_dentry->d_inode;
524 struct minix_dir_entry * de;
525 struct buffer_head * bh;
527 if (S_ISDIR(inode->i_mode))
528 return -EPERM;
530 if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max)
531 return -EMLINK;
533 error = minix_add_entry(dir, dentry->d_name.name,
534 dentry->d_name.len, &bh, &de);
535 if (error) {
536 brelse(bh);
537 return error;
539 de->inode = inode->i_ino;
540 mark_buffer_dirty(bh, 1);
541 brelse(bh);
542 inode->i_nlink++;
543 inode->i_ctime = CURRENT_TIME;
544 mark_inode_dirty(inode);
545 inode->i_count++;
546 d_instantiate(dentry, inode);
547 return 0;
550 #define PARENT_INO(buffer) \
551 (((struct minix_dir_entry *) ((buffer)+info->s_dirsize))->inode)
554 * rename uses retrying to avoid race-conditions: at least they should be minimal.
555 * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
556 * checks fail, it tries to restart itself again. Very practical - no changes
557 * are done until we know everything works ok.. and then all the changes can be
558 * done in one fell swoop when we have claimed all the buffers needed.
560 * Anybody can rename anything with this: the permission checks are left to the
561 * higher-level routines.
563 int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
564 struct inode * new_dir, struct dentry *new_dentry)
566 struct inode * old_inode, * new_inode;
567 struct buffer_head * old_bh, * new_bh, * dir_bh;
568 struct minix_dir_entry * old_de, * new_de;
569 struct minix_sb_info * info;
570 int retval;
572 info = &old_dir->i_sb->u.minix_sb;
573 goto start_up;
574 try_again:
575 brelse(old_bh);
576 brelse(new_bh);
577 brelse(dir_bh);
578 current->counter = 0;
579 schedule();
580 start_up:
581 old_inode = new_inode = NULL;
582 old_bh = new_bh = dir_bh = NULL;
583 old_bh = minix_find_entry(old_dir, old_dentry->d_name.name,
584 old_dentry->d_name.len, &old_de);
585 retval = -ENOENT;
586 if (!old_bh)
587 goto end_rename;
588 old_inode = old_dentry->d_inode;
589 retval = -EPERM;
590 new_inode = new_dentry->d_inode;
591 new_bh = minix_find_entry(new_dir, new_dentry->d_name.name,
592 new_dentry->d_name.len, &new_de);
593 if (new_bh) {
594 if (!new_inode) {
595 brelse(new_bh);
596 new_bh = NULL;
599 if (S_ISDIR(old_inode->i_mode)) {
600 if (new_inode) {
601 retval = -ENOTEMPTY;
602 if (!empty_dir(new_inode))
603 goto end_rename;
605 retval = -EIO;
606 dir_bh = minix_bread(old_inode,0,0);
607 if (!dir_bh)
608 goto end_rename;
609 if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
610 goto end_rename;
611 retval = -EMLINK;
612 if (!new_inode && new_dir->i_nlink >= info->s_link_max)
613 goto end_rename;
615 if (!new_bh) {
616 retval = minix_add_entry(new_dir,
617 new_dentry->d_name.name,
618 new_dentry->d_name.len,
619 &new_bh, &new_de);
620 if (retval)
621 goto end_rename;
623 /* sanity checking before doing the rename - avoid races */
624 if (new_inode && (new_de->inode != new_inode->i_ino))
625 goto try_again;
626 if (new_de->inode && !new_inode)
627 goto try_again;
628 if (old_de->inode != old_inode->i_ino)
629 goto try_again;
630 /* ok, that's it */
631 old_de->inode = 0;
632 new_de->inode = old_inode->i_ino;
633 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
634 mark_inode_dirty(old_dir);
635 old_dir->i_version = ++event;
636 new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
637 mark_inode_dirty(new_dir);
638 new_dir->i_version = ++event;
639 if (new_inode) {
640 new_inode->i_nlink--;
641 new_inode->i_ctime = CURRENT_TIME;
642 mark_inode_dirty(new_inode);
644 mark_buffer_dirty(old_bh, 1);
645 mark_buffer_dirty(new_bh, 1);
646 if (dir_bh) {
647 PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
648 mark_buffer_dirty(dir_bh, 1);
649 old_dir->i_nlink--;
650 mark_inode_dirty(old_dir);
651 if (new_inode) {
652 new_inode->i_nlink--;
653 mark_inode_dirty(new_inode);
654 } else {
655 new_dir->i_nlink++;
656 mark_inode_dirty(new_dir);
659 retval = 0;
660 end_rename:
661 brelse(dir_bh);
662 brelse(old_bh);
663 brelse(new_bh);
664 return retval;