Import 2.3.48
[davej-history.git] / fs / minix / namei.c
blobbaef110d2c3d2110646294e5aedfc5a5060a17c6
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>
14 #include <linux/quotaops.h>
16 #include <asm/uaccess.h>
19 * comment out this line if you want names > info->s_namelen chars to be
20 * truncated. Else they will be disallowed (ENAMETOOLONG).
22 /* #define NO_TRUNCATE */
24 static inline int namecompare(int len, int maxlen,
25 const char * name, const char * buffer)
27 if (len < maxlen && buffer[len])
28 return 0;
29 return !memcmp(name, buffer, len);
33 * minix_find_entry()
35 * finds an entry in the specified directory with the wanted name. It
36 * returns the cache buffer in which the entry was found, and the entry
37 * itself (as a parameter - res_dir). It does NOT read the inode of the
38 * entry - you'll have to do that yourself if you want to.
40 static struct buffer_head * minix_find_entry(struct inode * dir,
41 const char * name, int namelen, struct minix_dir_entry ** res_dir)
43 unsigned long block, offset;
44 struct buffer_head * bh;
45 struct minix_sb_info * info;
46 struct minix_dir_entry *de;
48 *res_dir = NULL;
49 info = &dir->i_sb->u.minix_sb;
50 if (namelen > info->s_namelen) {
51 #ifdef NO_TRUNCATE
52 return NULL;
53 #else
54 namelen = info->s_namelen;
55 #endif
57 bh = NULL;
58 block = offset = 0;
59 while (block*BLOCK_SIZE+offset < dir->i_size) {
60 if (!bh) {
61 bh = minix_bread(dir,block,0);
62 if (!bh) {
63 block++;
64 continue;
67 de = (struct minix_dir_entry *) (bh->b_data + offset);
68 offset += info->s_dirsize;
69 if (de->inode && namecompare(namelen,info->s_namelen,name,de->name)) {
70 *res_dir = de;
71 return bh;
73 if (offset < bh->b_size)
74 continue;
75 brelse(bh);
76 bh = NULL;
77 offset = 0;
78 block++;
80 brelse(bh);
81 return NULL;
84 #ifndef NO_TRUNCATE
86 static int minix_hash(struct dentry *dentry, struct qstr *qstr)
88 unsigned long hash;
89 int i;
90 const unsigned char *name;
92 i = dentry->d_inode->i_sb->u.minix_sb.s_namelen;
93 if (i >= qstr->len)
94 return 0;
95 /* Truncate the name in place, avoids having to define a compare
96 function. */
97 qstr->len = i;
98 name = qstr->name;
99 hash = init_name_hash();
100 while (i--)
101 hash = partial_name_hash(*name++, hash);
102 qstr->hash = end_name_hash(hash);
103 return 0;
106 #endif
108 struct dentry_operations minix_dentry_operations = {
109 0, /* revalidate */
110 #ifndef NO_TRUNCATE
111 minix_hash,
112 #else
114 #endif
115 0 /* compare */
118 static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry)
120 struct inode * inode = NULL;
121 struct minix_dir_entry * de;
122 struct buffer_head * bh;
124 #ifndef NO_TRUNCATE
125 dentry->d_op = &minix_dentry_operations;
126 #endif
127 bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
128 if (bh) {
129 int ino = de->inode;
130 brelse (bh);
131 inode = iget(dir->i_sb, ino);
133 if (!inode)
134 return ERR_PTR(-EACCES);
136 d_add(dentry, inode);
137 return NULL;
141 * minix_add_entry()
143 * adds a file entry to the specified directory, returning a possible
144 * error value if it fails.
146 * NOTE!! The inode part of 'de' is left at 0 - which means you
147 * may not sleep between calling this and putting something into
148 * the entry, as someone else might have used it while you slept.
150 static int minix_add_entry(struct inode * dir,
151 const char * name, int namelen,
152 struct buffer_head ** res_buf,
153 struct minix_dir_entry ** res_dir)
155 int i;
156 unsigned long block, offset;
157 struct buffer_head * bh;
158 struct minix_dir_entry * de;
159 struct minix_sb_info * info;
161 *res_buf = NULL;
162 *res_dir = NULL;
163 info = &dir->i_sb->u.minix_sb;
164 if (namelen > info->s_namelen) {
165 #ifdef NO_TRUNCATE
166 return -ENAMETOOLONG;
167 #else
168 namelen = info->s_namelen;
169 #endif
171 if (!namelen)
172 return -ENOENT;
173 bh = NULL;
174 block = offset = 0;
175 while (1) {
176 if (!bh) {
177 bh = minix_bread(dir,block,1);
178 if (!bh)
179 return -ENOSPC;
181 de = (struct minix_dir_entry *) (bh->b_data + offset);
182 offset += info->s_dirsize;
183 if (block*bh->b_size + offset > dir->i_size) {
184 de->inode = 0;
185 dir->i_size = block*bh->b_size + offset;
186 mark_inode_dirty(dir);
188 if (!de->inode) {
189 dir->i_mtime = dir->i_ctime = CURRENT_TIME;
190 mark_inode_dirty(dir);
191 for (i = 0; i < info->s_namelen ; i++)
192 de->name[i] = (i < namelen) ? name[i] : 0;
193 dir->i_version = ++event;
194 mark_buffer_dirty(bh, 1);
195 *res_dir = de;
196 break;
198 if (offset < bh->b_size)
199 continue;
200 brelse(bh);
201 bh = NULL;
202 offset = 0;
203 block++;
205 *res_buf = bh;
206 return 0;
209 static int minix_create(struct inode * dir, struct dentry *dentry, int mode)
211 int error;
212 struct inode * inode;
213 struct buffer_head * bh;
214 struct minix_dir_entry * de;
216 inode = minix_new_inode(dir, &error);
217 if (error)
218 return error;
219 if (!inode)
220 return -ENOSPC;
221 inode->i_op = &minix_file_inode_operations;
222 inode->i_fop = &minix_file_operations;
223 inode->i_mapping->a_ops = &minix_aops;
224 inode->i_mode = mode;
225 mark_inode_dirty(inode);
226 error = minix_add_entry(dir, dentry->d_name.name,
227 dentry->d_name.len, &bh ,&de);
228 if (error) {
229 inode->i_nlink--;
230 mark_inode_dirty(inode);
231 iput(inode);
232 return error;
234 de->inode = inode->i_ino;
235 mark_buffer_dirty(bh, 1);
236 brelse(bh);
237 d_instantiate(dentry, inode);
238 return 0;
241 static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev)
243 int error;
244 struct inode * inode;
245 struct buffer_head * bh;
246 struct minix_dir_entry * de;
248 inode = minix_new_inode(dir, &error);
249 if (error)
250 return error;
251 if (!inode)
252 return -ENOSPC;
253 inode->i_uid = current->fsuid;
254 init_special_inode(inode, mode, rdev);
255 mark_inode_dirty(inode);
256 error = minix_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &bh, &de);
257 if (error) {
258 inode->i_nlink--;
259 mark_inode_dirty(inode);
260 iput(inode);
261 return error;
263 de->inode = inode->i_ino;
264 mark_buffer_dirty(bh, 1);
265 brelse(bh);
266 d_instantiate(dentry, inode);
267 return 0;
270 static int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
272 int error;
273 struct inode * inode;
274 struct buffer_head * bh, *dir_block;
275 struct minix_dir_entry * de;
276 struct minix_sb_info * info;
278 info = &dir->i_sb->u.minix_sb;
279 if (dir->i_nlink >= info->s_link_max)
280 return -EMLINK;
281 inode = minix_new_inode(dir, &error);
282 if (error)
283 return error;
284 if (!inode)
285 return -ENOSPC;
286 inode->i_op = &minix_dir_inode_operations;
287 inode->i_fop = &minix_dir_operations;
288 inode->i_size = 2 * info->s_dirsize;
289 dir_block = minix_bread(inode,0,1);
290 if (!dir_block) {
291 inode->i_nlink--;
292 mark_inode_dirty(inode);
293 iput(inode);
294 return -ENOSPC;
296 de = (struct minix_dir_entry *) dir_block->b_data;
297 de->inode=inode->i_ino;
298 strcpy(de->name,".");
299 de = (struct minix_dir_entry *) (dir_block->b_data + info->s_dirsize);
300 de->inode = dir->i_ino;
301 strcpy(de->name,"..");
302 inode->i_nlink = 2;
303 mark_buffer_dirty(dir_block, 1);
304 brelse(dir_block);
305 inode->i_mode = S_IFDIR | mode;
306 if (dir->i_mode & S_ISGID)
307 inode->i_mode |= S_ISGID;
308 mark_inode_dirty(inode);
309 error = minix_add_entry(dir, dentry->d_name.name,
310 dentry->d_name.len, &bh, &de);
311 if (error) {
312 inode->i_nlink=0;
313 iput(inode);
314 return error;
316 de->inode = inode->i_ino;
317 mark_buffer_dirty(bh, 1);
318 dir->i_nlink++;
319 mark_inode_dirty(dir);
320 brelse(bh);
321 d_instantiate(dentry, inode);
322 return 0;
326 * routine to check that the specified directory is empty (for rmdir)
328 static int empty_dir(struct inode * inode)
330 unsigned int block, offset;
331 struct buffer_head * bh;
332 struct minix_dir_entry * de;
333 struct minix_sb_info * info;
335 info = &inode->i_sb->u.minix_sb;
336 block = 0;
337 bh = NULL;
338 offset = 2*info->s_dirsize;
339 if (inode->i_size & (info->s_dirsize-1))
340 goto bad_dir;
341 if (inode->i_size < offset)
342 goto bad_dir;
343 bh = minix_bread(inode,0,0);
344 if (!bh)
345 goto bad_dir;
346 de = (struct minix_dir_entry *) bh->b_data;
347 if (!de->inode || strcmp(de->name,"."))
348 goto bad_dir;
349 de = (struct minix_dir_entry *) (bh->b_data + info->s_dirsize);
350 if (!de->inode || strcmp(de->name,".."))
351 goto bad_dir;
352 while (block*BLOCK_SIZE+offset < inode->i_size) {
353 if (!bh) {
354 bh = minix_bread(inode,block,0);
355 if (!bh) {
356 block++;
357 continue;
360 de = (struct minix_dir_entry *) (bh->b_data + offset);
361 offset += info->s_dirsize;
362 if (de->inode) {
363 brelse(bh);
364 return 0;
366 if (offset < bh->b_size)
367 continue;
368 brelse(bh);
369 bh = NULL;
370 offset = 0;
371 block++;
373 brelse(bh);
374 return 1;
375 bad_dir:
376 brelse(bh);
377 printk("Bad directory on device %s\n",
378 kdevname(inode->i_dev));
379 return 1;
382 static int minix_rmdir(struct inode * dir, struct dentry *dentry)
384 int retval;
385 struct inode * inode;
386 struct buffer_head * bh;
387 struct minix_dir_entry * de;
389 inode = NULL;
390 bh = minix_find_entry(dir, dentry->d_name.name,
391 dentry->d_name.len, &de);
392 retval = -ENOENT;
393 if (!bh)
394 goto end_rmdir;
395 inode = dentry->d_inode;
396 DQUOT_INIT(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 static 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 retval = -ENOENT;
435 inode = dentry->d_inode;
436 DQUOT_INIT(inode);
437 bh = minix_find_entry(dir, dentry->d_name.name,
438 dentry->d_name.len, &de);
439 if (!bh || de->inode != inode->i_ino)
440 goto end_unlink;
441 if (!inode->i_nlink) {
442 printk("Deleting nonexistent file (%s:%lu), %d\n",
443 kdevname(inode->i_dev),
444 inode->i_ino, inode->i_nlink);
445 inode->i_nlink=1;
447 de->inode = 0;
448 dir->i_version = ++event;
449 mark_buffer_dirty(bh, 1);
450 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
451 mark_inode_dirty(dir);
452 inode->i_nlink--;
453 inode->i_ctime = dir->i_ctime;
454 mark_inode_dirty(inode);
455 d_delete(dentry); /* This also frees the inode */
456 retval = 0;
457 end_unlink:
458 brelse(bh);
459 return retval;
462 static int minix_symlink(struct inode * dir, struct dentry *dentry,
463 const char * symname)
465 struct minix_dir_entry * de;
466 struct inode * inode = NULL;
467 struct buffer_head * bh = NULL;
468 int i;
469 int err;
471 err = -ENAMETOOLONG;
472 i = strlen(symname)+1;
473 if (i>1024)
474 goto out;
475 inode = minix_new_inode(dir, &err);
476 if (err)
477 goto out;
478 err = -ENOSPC;
479 if (!inode)
480 goto out;
482 inode->i_mode = S_IFLNK | 0777;
483 inode->i_op = &page_symlink_inode_operations;
484 inode->i_mapping->a_ops = &minix_aops;
485 err = block_symlink(inode, symname, i);
486 if (err)
487 goto fail;
489 err = minix_add_entry(dir, dentry->d_name.name,
490 dentry->d_name.len, &bh, &de);
491 if (err)
492 goto fail;
494 de->inode = inode->i_ino;
495 mark_buffer_dirty(bh, 1);
496 brelse(bh);
497 d_instantiate(dentry, inode);
498 out:
499 return err;
500 fail:
501 inode->i_nlink--;
502 mark_inode_dirty(inode);
503 iput(inode);
504 goto out;
507 static int minix_link(struct dentry * old_dentry, struct inode * dir,
508 struct dentry *dentry)
510 int error;
511 struct inode *inode = old_dentry->d_inode;
512 struct minix_dir_entry * de;
513 struct buffer_head * bh;
515 if (S_ISDIR(inode->i_mode))
516 return -EPERM;
518 if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max)
519 return -EMLINK;
521 error = minix_add_entry(dir, dentry->d_name.name,
522 dentry->d_name.len, &bh, &de);
523 if (error) {
524 brelse(bh);
525 return error;
527 de->inode = inode->i_ino;
528 mark_buffer_dirty(bh, 1);
529 brelse(bh);
530 inode->i_nlink++;
531 inode->i_ctime = CURRENT_TIME;
532 mark_inode_dirty(inode);
533 inode->i_count++;
534 d_instantiate(dentry, inode);
535 return 0;
538 #define PARENT_INO(buffer) \
539 (((struct minix_dir_entry *) ((buffer)+info->s_dirsize))->inode)
542 * Anybody can rename anything with this: the permission checks are left to the
543 * higher-level routines.
545 static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
546 struct inode * new_dir, struct dentry *new_dentry)
548 struct inode * old_inode, * new_inode;
549 struct buffer_head * old_bh, * new_bh, * dir_bh;
550 struct minix_dir_entry * old_de, * new_de;
551 struct minix_sb_info * info;
552 int retval;
554 info = &old_dir->i_sb->u.minix_sb;
555 new_bh = dir_bh = NULL;
556 old_inode = old_dentry->d_inode;
557 new_inode = new_dentry->d_inode;
558 old_bh = minix_find_entry(old_dir, old_dentry->d_name.name,
559 old_dentry->d_name.len, &old_de);
560 retval = -ENOENT;
561 if (!old_bh || old_de->inode != old_inode->i_ino)
562 goto end_rename;
563 retval = -EPERM;
564 new_bh = minix_find_entry(new_dir, new_dentry->d_name.name,
565 new_dentry->d_name.len, &new_de);
566 if (new_bh) {
567 if (!new_inode) {
568 brelse(new_bh);
569 new_bh = NULL;
570 } else {
571 DQUOT_INIT(new_inode);
574 if (S_ISDIR(old_inode->i_mode)) {
575 if (new_inode) {
576 retval = -ENOTEMPTY;
577 if (!empty_dir(new_inode))
578 goto end_rename;
580 retval = -EIO;
581 dir_bh = minix_bread(old_inode,0,0);
582 if (!dir_bh)
583 goto end_rename;
584 if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
585 goto end_rename;
586 retval = -EMLINK;
587 if (!new_inode && new_dir != old_dir &&
588 new_dir->i_nlink >= info->s_link_max)
589 goto end_rename;
591 if (!new_bh) {
592 retval = minix_add_entry(new_dir,
593 new_dentry->d_name.name,
594 new_dentry->d_name.len,
595 &new_bh, &new_de);
596 if (retval)
597 goto end_rename;
599 /* ok, that's it */
600 new_de->inode = old_inode->i_ino;
601 old_de->inode = 0;
602 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
603 old_dir->i_version = ++event;
604 mark_inode_dirty(old_dir);
605 new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
606 new_dir->i_version = ++event;
607 mark_inode_dirty(new_dir);
608 if (new_inode) {
609 new_inode->i_nlink--;
610 new_inode->i_ctime = CURRENT_TIME;
611 mark_inode_dirty(new_inode);
613 mark_buffer_dirty(old_bh, 1);
614 mark_buffer_dirty(new_bh, 1);
615 if (dir_bh) {
616 PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
617 mark_buffer_dirty(dir_bh, 1);
618 old_dir->i_nlink--;
619 mark_inode_dirty(old_dir);
620 if (new_inode) {
621 new_inode->i_nlink--;
622 mark_inode_dirty(new_inode);
623 } else {
624 new_dir->i_nlink++;
625 mark_inode_dirty(new_dir);
628 retval = 0;
629 end_rename:
630 brelse(dir_bh);
631 brelse(old_bh);
632 brelse(new_bh);
633 return retval;
637 * directories can handle most operations...
639 struct inode_operations minix_dir_inode_operations = {
640 create: minix_create,
641 lookup: minix_lookup,
642 link: minix_link,
643 unlink: minix_unlink,
644 symlink: minix_symlink,
645 mkdir: minix_mkdir,
646 rmdir: minix_rmdir,
647 mknod: minix_mknod,
648 rename: minix_rename,