Import 2.3.12pre4
[davej-history.git] / fs / minix / namei.c
blobae5aa8a5a78e099d98e35fe0ab52f62aa6b6d762
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 info = &dir->i_sb->u.minix_sb;
49 if (namelen > info->s_namelen) {
50 #ifdef NO_TRUNCATE
51 return NULL;
52 #else
53 namelen = info->s_namelen;
54 #endif
56 bh = NULL;
57 block = offset = 0;
58 while (block*BLOCK_SIZE+offset < dir->i_size) {
59 if (!bh) {
60 bh = minix_bread(dir,block,0);
61 if (!bh) {
62 block++;
63 continue;
66 de = (struct minix_dir_entry *) (bh->b_data + offset);
67 offset += info->s_dirsize;
68 if (de->inode && namecompare(namelen,info->s_namelen,name,de->name)) {
69 *res_dir = de;
70 return bh;
72 if (offset < bh->b_size)
73 continue;
74 brelse(bh);
75 bh = NULL;
76 offset = 0;
77 block++;
79 brelse(bh);
80 return NULL;
83 #ifndef NO_TRUNCATE
85 static int minix_hash(struct dentry *dentry, struct qstr *qstr)
87 unsigned long hash;
88 int i;
89 const unsigned char *name;
91 i = dentry->d_inode->i_sb->u.minix_sb.s_namelen;
92 if (i >= qstr->len)
93 return 0;
94 /* Truncate the name in place, avoids having to define a compare
95 function. */
96 qstr->len = i;
97 name = qstr->name;
98 hash = init_name_hash();
99 while (i--)
100 hash = partial_name_hash(*name++, hash);
101 qstr->hash = end_name_hash(hash);
102 return 0;
105 #endif
107 struct dentry_operations minix_dentry_operations = {
108 0, /* revalidate */
109 #ifndef NO_TRUNCATE
110 minix_hash,
111 #else
113 #endif
114 0 /* compare */
117 struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry)
119 struct inode * inode = NULL;
120 struct minix_dir_entry * de;
121 struct buffer_head * bh;
123 #ifndef NO_TRUNCATE
124 dentry->d_op = &minix_dentry_operations;
125 #endif
126 bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
127 if (bh) {
128 int ino = de->inode;
129 brelse (bh);
130 inode = iget(dir->i_sb, ino);
132 if (!inode)
133 return ERR_PTR(-EACCES);
135 d_add(dentry, inode);
136 return NULL;
140 * minix_add_entry()
142 * adds a file entry to the specified directory, returning a possible
143 * error value if it fails.
145 * NOTE!! The inode part of 'de' is left at 0 - which means you
146 * may not sleep between calling this and putting something into
147 * the entry, as someone else might have used it while you slept.
149 static int minix_add_entry(struct inode * dir,
150 const char * name, int namelen,
151 struct buffer_head ** res_buf,
152 struct minix_dir_entry ** res_dir)
154 int i;
155 unsigned long block, offset;
156 struct buffer_head * bh;
157 struct minix_dir_entry * de;
158 struct minix_sb_info * info;
160 *res_buf = NULL;
161 *res_dir = NULL;
162 info = &dir->i_sb->u.minix_sb;
163 if (namelen > info->s_namelen) {
164 #ifdef NO_TRUNCATE
165 return -ENAMETOOLONG;
166 #else
167 namelen = info->s_namelen;
168 #endif
170 if (!namelen)
171 return -ENOENT;
172 bh = NULL;
173 block = offset = 0;
174 while (1) {
175 if (!bh) {
176 bh = minix_bread(dir,block,1);
177 if (!bh)
178 return -ENOSPC;
180 de = (struct minix_dir_entry *) (bh->b_data + offset);
181 offset += info->s_dirsize;
182 if (block*bh->b_size + offset > dir->i_size) {
183 de->inode = 0;
184 dir->i_size = block*bh->b_size + offset;
185 mark_inode_dirty(dir);
187 if (!de->inode) {
188 dir->i_mtime = dir->i_ctime = CURRENT_TIME;
189 mark_inode_dirty(dir);
190 for (i = 0; i < info->s_namelen ; i++)
191 de->name[i] = (i < namelen) ? name[i] : 0;
192 dir->i_version = ++event;
193 mark_buffer_dirty(bh, 1);
194 *res_dir = de;
195 break;
197 if (offset < bh->b_size)
198 continue;
199 brelse(bh);
200 bh = NULL;
201 offset = 0;
202 block++;
204 *res_buf = bh;
205 return 0;
208 int minix_create(struct inode * dir, struct dentry *dentry, int mode)
210 int error;
211 struct inode * inode;
212 struct buffer_head * bh;
213 struct minix_dir_entry * de;
215 inode = minix_new_inode(dir);
216 if (!inode)
217 return -ENOSPC;
218 inode->i_op = &minix_file_inode_operations;
219 inode->i_mode = mode;
220 mark_inode_dirty(inode);
221 error = minix_add_entry(dir, dentry->d_name.name,
222 dentry->d_name.len, &bh ,&de);
223 if (error) {
224 inode->i_nlink--;
225 mark_inode_dirty(inode);
226 iput(inode);
227 return error;
229 de->inode = inode->i_ino;
230 mark_buffer_dirty(bh, 1);
231 brelse(bh);
232 d_instantiate(dentry, inode);
233 return 0;
236 int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev)
238 int error;
239 struct inode * inode;
240 struct buffer_head * bh;
241 struct minix_dir_entry * de;
243 inode = minix_new_inode(dir);
244 if (!inode)
245 return -ENOSPC;
246 inode->i_uid = current->fsuid;
247 init_special_inode(inode, mode, rdev);
248 mark_inode_dirty(inode);
249 error = minix_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &bh, &de);
250 if (error) {
251 inode->i_nlink--;
252 mark_inode_dirty(inode);
253 iput(inode);
254 return error;
256 de->inode = inode->i_ino;
257 mark_buffer_dirty(bh, 1);
258 brelse(bh);
259 d_instantiate(dentry, inode);
260 return 0;
263 int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
265 int error;
266 struct inode * inode;
267 struct buffer_head * bh, *dir_block;
268 struct minix_dir_entry * de;
269 struct minix_sb_info * info;
271 info = &dir->i_sb->u.minix_sb;
272 if (dir->i_nlink >= info->s_link_max)
273 return -EMLINK;
274 inode = minix_new_inode(dir);
275 if (!inode)
276 return -ENOSPC;
277 inode->i_op = &minix_dir_inode_operations;
278 inode->i_size = 2 * info->s_dirsize;
279 dir_block = minix_bread(inode,0,1);
280 if (!dir_block) {
281 inode->i_nlink--;
282 mark_inode_dirty(inode);
283 iput(inode);
284 return -ENOSPC;
286 de = (struct minix_dir_entry *) dir_block->b_data;
287 de->inode=inode->i_ino;
288 strcpy(de->name,".");
289 de = (struct minix_dir_entry *) (dir_block->b_data + info->s_dirsize);
290 de->inode = dir->i_ino;
291 strcpy(de->name,"..");
292 inode->i_nlink = 2;
293 mark_buffer_dirty(dir_block, 1);
294 brelse(dir_block);
295 inode->i_mode = S_IFDIR | mode;
296 if (dir->i_mode & S_ISGID)
297 inode->i_mode |= S_ISGID;
298 mark_inode_dirty(inode);
299 error = minix_add_entry(dir, dentry->d_name.name,
300 dentry->d_name.len, &bh, &de);
301 if (error) {
302 inode->i_nlink=0;
303 iput(inode);
304 return error;
306 de->inode = inode->i_ino;
307 mark_buffer_dirty(bh, 1);
308 dir->i_nlink++;
309 mark_inode_dirty(dir);
310 brelse(bh);
311 d_instantiate(dentry, inode);
312 return 0;
316 * routine to check that the specified directory is empty (for rmdir)
318 static int empty_dir(struct inode * inode)
320 unsigned int block, offset;
321 struct buffer_head * bh;
322 struct minix_dir_entry * de;
323 struct minix_sb_info * info;
325 info = &inode->i_sb->u.minix_sb;
326 block = 0;
327 bh = NULL;
328 offset = 2*info->s_dirsize;
329 if (inode->i_size & (info->s_dirsize-1))
330 goto bad_dir;
331 if (inode->i_size < offset)
332 goto bad_dir;
333 bh = minix_bread(inode,0,0);
334 if (!bh)
335 goto bad_dir;
336 de = (struct minix_dir_entry *) bh->b_data;
337 if (!de->inode || strcmp(de->name,"."))
338 goto bad_dir;
339 de = (struct minix_dir_entry *) (bh->b_data + info->s_dirsize);
340 if (!de->inode || strcmp(de->name,".."))
341 goto bad_dir;
342 while (block*BLOCK_SIZE+offset < inode->i_size) {
343 if (!bh) {
344 bh = minix_bread(inode,block,0);
345 if (!bh) {
346 block++;
347 continue;
350 de = (struct minix_dir_entry *) (bh->b_data + offset);
351 offset += info->s_dirsize;
352 if (de->inode) {
353 brelse(bh);
354 return 0;
356 if (offset < bh->b_size)
357 continue;
358 brelse(bh);
359 bh = NULL;
360 offset = 0;
361 block++;
363 brelse(bh);
364 return 1;
365 bad_dir:
366 brelse(bh);
367 printk("Bad directory on device %s\n",
368 kdevname(inode->i_dev));
369 return 1;
372 int minix_rmdir(struct inode * dir, struct dentry *dentry)
374 int retval;
375 struct inode * inode;
376 struct buffer_head * bh;
377 struct minix_dir_entry * de;
379 inode = NULL;
380 bh = minix_find_entry(dir, dentry->d_name.name,
381 dentry->d_name.len, &de);
382 retval = -ENOENT;
383 if (!bh)
384 goto end_rmdir;
385 inode = dentry->d_inode;
387 if (!empty_dir(inode)) {
388 retval = -ENOTEMPTY;
389 goto end_rmdir;
391 if (de->inode != inode->i_ino) {
392 retval = -ENOENT;
393 goto end_rmdir;
395 if (!list_empty(&dentry->d_hash)) {
396 retval = -EBUSY;
397 goto end_rmdir;
399 if (inode->i_nlink != 2)
400 printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
401 de->inode = 0;
402 dir->i_version = ++event;
403 mark_buffer_dirty(bh, 1);
404 inode->i_nlink=0;
405 mark_inode_dirty(inode);
406 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
407 dir->i_nlink--;
408 mark_inode_dirty(dir);
409 d_delete(dentry);
410 retval = 0;
411 end_rmdir:
412 brelse(bh);
413 return retval;
416 int minix_unlink(struct inode * dir, struct dentry *dentry)
418 int retval;
419 struct inode * inode;
420 struct buffer_head * bh;
421 struct minix_dir_entry * de;
423 retval = -ENOENT;
424 inode = dentry->d_inode;
425 bh = minix_find_entry(dir, dentry->d_name.name,
426 dentry->d_name.len, &de);
427 if (!bh || de->inode != inode->i_ino)
428 goto end_unlink;
429 if (!inode->i_nlink) {
430 printk("Deleting nonexistent file (%s:%lu), %d\n",
431 kdevname(inode->i_dev),
432 inode->i_ino, inode->i_nlink);
433 inode->i_nlink=1;
435 de->inode = 0;
436 dir->i_version = ++event;
437 mark_buffer_dirty(bh, 1);
438 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
439 mark_inode_dirty(dir);
440 inode->i_nlink--;
441 inode->i_ctime = dir->i_ctime;
442 mark_inode_dirty(inode);
443 d_delete(dentry); /* This also frees the inode */
444 retval = 0;
445 end_unlink:
446 brelse(bh);
447 return retval;
450 int minix_symlink(struct inode * dir, struct dentry *dentry,
451 const char * symname)
453 struct minix_dir_entry * de;
454 struct inode * inode = NULL;
455 struct buffer_head * bh = NULL, * name_block = NULL;
456 int i;
457 char c;
459 if (!(inode = minix_new_inode(dir)))
460 return -ENOSPC;
462 inode->i_mode = S_IFLNK | 0777;
463 inode->i_op = &minix_symlink_inode_operations;
464 name_block = minix_bread(inode,0,1);
465 if (!name_block) {
466 inode->i_nlink--;
467 mark_inode_dirty(inode);
468 iput(inode);
469 return -ENOSPC;
471 i = 0;
472 while (i < 1023 && (c=*(symname++)))
473 name_block->b_data[i++] = c;
474 name_block->b_data[i] = 0;
475 mark_buffer_dirty(name_block, 1);
476 brelse(name_block);
477 inode->i_size = i;
478 mark_inode_dirty(inode);
479 i = minix_add_entry(dir, dentry->d_name.name,
480 dentry->d_name.len, &bh, &de);
481 if (i) {
482 inode->i_nlink--;
483 mark_inode_dirty(inode);
484 iput(inode);
485 return i;
487 de->inode = inode->i_ino;
488 mark_buffer_dirty(bh, 1);
489 brelse(bh);
490 d_instantiate(dentry, inode);
491 return 0;
494 int minix_link(struct dentry * old_dentry, struct inode * dir,
495 struct dentry *dentry)
497 int error;
498 struct inode *inode = old_dentry->d_inode;
499 struct minix_dir_entry * de;
500 struct buffer_head * bh;
502 if (S_ISDIR(inode->i_mode))
503 return -EPERM;
505 if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max)
506 return -EMLINK;
508 error = minix_add_entry(dir, dentry->d_name.name,
509 dentry->d_name.len, &bh, &de);
510 if (error) {
511 brelse(bh);
512 return error;
514 de->inode = inode->i_ino;
515 mark_buffer_dirty(bh, 1);
516 brelse(bh);
517 inode->i_nlink++;
518 inode->i_ctime = CURRENT_TIME;
519 mark_inode_dirty(inode);
520 inode->i_count++;
521 d_instantiate(dentry, inode);
522 return 0;
525 #define PARENT_INO(buffer) \
526 (((struct minix_dir_entry *) ((buffer)+info->s_dirsize))->inode)
529 * Anybody can rename anything with this: the permission checks are left to the
530 * higher-level routines.
532 int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
533 struct inode * new_dir, struct dentry *new_dentry)
535 struct inode * old_inode, * new_inode;
536 struct buffer_head * old_bh, * new_bh, * dir_bh;
537 struct minix_dir_entry * old_de, * new_de;
538 struct minix_sb_info * info;
539 int retval;
541 info = &old_dir->i_sb->u.minix_sb;
542 new_bh = dir_bh = NULL;
543 old_inode = old_dentry->d_inode;
544 new_inode = new_dentry->d_inode;
545 old_bh = minix_find_entry(old_dir, old_dentry->d_name.name,
546 old_dentry->d_name.len, &old_de);
547 retval = -ENOENT;
548 if (!old_bh || old_de->inode != old_inode->i_ino)
549 goto end_rename;
550 retval = -EPERM;
551 new_bh = minix_find_entry(new_dir, new_dentry->d_name.name,
552 new_dentry->d_name.len, &new_de);
553 if (new_bh) {
554 if (!new_inode) {
555 brelse(new_bh);
556 new_bh = NULL;
559 if (S_ISDIR(old_inode->i_mode)) {
560 if (new_inode) {
561 retval = -ENOTEMPTY;
562 if (!empty_dir(new_inode))
563 goto end_rename;
565 retval = -EIO;
566 dir_bh = minix_bread(old_inode,0,0);
567 if (!dir_bh)
568 goto end_rename;
569 if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
570 goto end_rename;
571 retval = -EMLINK;
572 if (!new_inode && new_dir != old_dir &&
573 new_dir->i_nlink >= info->s_link_max)
574 goto end_rename;
576 if (!new_bh) {
577 retval = minix_add_entry(new_dir,
578 new_dentry->d_name.name,
579 new_dentry->d_name.len,
580 &new_bh, &new_de);
581 if (retval)
582 goto end_rename;
584 /* ok, that's it */
585 new_de->inode = old_inode->i_ino;
586 old_de->inode = 0;
587 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
588 old_dir->i_version = ++event;
589 mark_inode_dirty(old_dir);
590 new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
591 new_dir->i_version = ++event;
592 mark_inode_dirty(new_dir);
593 if (new_inode) {
594 new_inode->i_nlink--;
595 new_inode->i_ctime = CURRENT_TIME;
596 mark_inode_dirty(new_inode);
598 mark_buffer_dirty(old_bh, 1);
599 mark_buffer_dirty(new_bh, 1);
600 if (dir_bh) {
601 PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
602 mark_buffer_dirty(dir_bh, 1);
603 old_dir->i_nlink--;
604 mark_inode_dirty(old_dir);
605 if (new_inode) {
606 new_inode->i_nlink--;
607 mark_inode_dirty(new_inode);
608 } else {
609 new_dir->i_nlink++;
610 mark_inode_dirty(new_dir);
613 retval = 0;
614 end_rename:
615 brelse(dir_bh);
616 brelse(old_bh);
617 brelse(new_bh);
618 return retval;