This source file includes following definitions.
- namecompare
- minix_match
- minix_find_entry
- minix_lookup
- minix_add_entry
- minix_create
- minix_mknod
- minix_mkdir
- empty_dir
- minix_rmdir
- minix_unlink
- minix_symlink
- minix_link
- subdir
- do_minix_rename
- minix_rename
1
2
3
4
5
6
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
15 #include <asm/segment.h>
16
17
18
19
20
21
22
23 static inline int namecompare(int len, int maxlen,
24 const char * name, const char * buffer)
25 {
26 if (len > maxlen)
27 return 0;
28 if (len < maxlen && buffer[len])
29 return 0;
30 return !memcmp(name, buffer, len);
31 }
32
33
34
35
36
37
38
39
40 static int minix_match(int len, const char * name,
41 struct buffer_head * bh, unsigned long * offset,
42 struct minix_sb_info * info)
43 {
44 struct minix_dir_entry * de;
45
46 de = (struct minix_dir_entry *) (bh->b_data + *offset);
47 *offset += info->s_dirsize;
48 if (!de->inode || len > info->s_namelen)
49 return 0;
50
51 if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
52 return 1;
53 return namecompare(len,info->s_namelen,name,de->name);
54 }
55
56
57
58
59
60
61
62
63
64 static struct buffer_head * minix_find_entry(struct inode * dir,
65 const char * name, int namelen, struct minix_dir_entry ** res_dir)
66 {
67 unsigned long block, offset;
68 struct buffer_head * bh;
69 struct minix_sb_info * info;
70
71 *res_dir = NULL;
72 if (!dir || !dir->i_sb)
73 return NULL;
74 info = &dir->i_sb->u.minix_sb;
75 if (namelen > info->s_namelen) {
76 #ifdef NO_TRUNCATE
77 return NULL;
78 #else
79 namelen = info->s_namelen;
80 #endif
81 }
82 bh = NULL;
83 block = offset = 0;
84 while (block*BLOCK_SIZE+offset < dir->i_size) {
85 if (!bh) {
86 bh = minix_bread(dir,block,0);
87 if (!bh) {
88 block++;
89 continue;
90 }
91 }
92 *res_dir = (struct minix_dir_entry *) (bh->b_data + offset);
93 if (minix_match(namelen,name,bh,&offset,info))
94 return bh;
95 if (offset < bh->b_size)
96 continue;
97 brelse(bh);
98 bh = NULL;
99 offset = 0;
100 block++;
101 }
102 brelse(bh);
103 *res_dir = NULL;
104 return NULL;
105 }
106
107 int minix_lookup(struct inode * dir,const char * name, int len,
108 struct inode ** result)
109 {
110 int ino;
111 struct minix_dir_entry * de;
112 struct buffer_head * bh;
113
114 *result = NULL;
115 if (!dir)
116 return -ENOENT;
117 if (!S_ISDIR(dir->i_mode)) {
118 iput(dir);
119 return -ENOENT;
120 }
121 if (!(bh = minix_find_entry(dir,name,len,&de))) {
122 iput(dir);
123 return -ENOENT;
124 }
125 ino = de->inode;
126 brelse(bh);
127 if (!(*result = iget(dir->i_sb,ino))) {
128 iput(dir);
129 return -EACCES;
130 }
131 iput(dir);
132 return 0;
133 }
134
135
136
137
138
139
140
141
142
143
144
145 static int minix_add_entry(struct inode * dir,
146 const char * name, int namelen,
147 struct buffer_head ** res_buf,
148 struct minix_dir_entry ** res_dir)
149 {
150 int i;
151 unsigned long block, offset;
152 struct buffer_head * bh;
153 struct minix_dir_entry * de;
154 struct minix_sb_info * info;
155
156 *res_buf = NULL;
157 *res_dir = NULL;
158 if (!dir || !dir->i_sb)
159 return -ENOENT;
160 info = &dir->i_sb->u.minix_sb;
161 if (namelen > info->s_namelen) {
162 #ifdef NO_TRUNCATE
163 return -ENAMETOOLONG;
164 #else
165 namelen = info->s_namelen;
166 #endif
167 }
168 if (!namelen)
169 return -ENOENT;
170 bh = NULL;
171 block = offset = 0;
172 while (1) {
173 if (!bh) {
174 bh = minix_bread(dir,block,1);
175 if (!bh)
176 return -ENOSPC;
177 }
178 de = (struct minix_dir_entry *) (bh->b_data + offset);
179 offset += info->s_dirsize;
180 if (block*bh->b_size + offset > dir->i_size) {
181 de->inode = 0;
182 dir->i_size = block*bh->b_size + offset;
183 dir->i_dirt = 1;
184 }
185 if (de->inode) {
186 if (namecompare(namelen, info->s_namelen, name, de->name)) {
187 brelse(bh);
188 return -EEXIST;
189 }
190 } else {
191 dir->i_mtime = dir->i_ctime = CURRENT_TIME;
192 for (i = 0; i < info->s_namelen ; i++)
193 de->name[i] = (i < namelen) ? name[i] : 0;
194 dir->i_version = ++event;
195 mark_buffer_dirty(bh, 1);
196 *res_dir = de;
197 break;
198 }
199 if (offset < bh->b_size)
200 continue;
201 brelse(bh);
202 bh = NULL;
203 offset = 0;
204 block++;
205 }
206 *res_buf = bh;
207 return 0;
208 }
209
210 int minix_create(struct inode * dir,const char * name, int len, int mode,
211 struct inode ** result)
212 {
213 int error;
214 struct inode * inode;
215 struct buffer_head * bh;
216 struct minix_dir_entry * de;
217
218 *result = NULL;
219 if (!dir)
220 return -ENOENT;
221 inode = minix_new_inode(dir);
222 if (!inode) {
223 iput(dir);
224 return -ENOSPC;
225 }
226 inode->i_op = &minix_file_inode_operations;
227 inode->i_mode = mode;
228 inode->i_dirt = 1;
229 error = minix_add_entry(dir,name,len, &bh ,&de);
230 if (error) {
231 inode->i_nlink--;
232 inode->i_dirt = 1;
233 iput(inode);
234 iput(dir);
235 return error;
236 }
237 de->inode = inode->i_ino;
238 mark_buffer_dirty(bh, 1);
239 brelse(bh);
240 iput(dir);
241 *result = inode;
242 return 0;
243 }
244
245 int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev)
246 {
247 int error;
248 struct inode * inode;
249 struct buffer_head * bh;
250 struct minix_dir_entry * de;
251
252 if (!dir)
253 return -ENOENT;
254 bh = minix_find_entry(dir,name,len,&de);
255 if (bh) {
256 brelse(bh);
257 iput(dir);
258 return -EEXIST;
259 }
260 inode = minix_new_inode(dir);
261 if (!inode) {
262 iput(dir);
263 return -ENOSPC;
264 }
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_ISDIR(inode->i_mode)) {
271 inode->i_op = &minix_dir_inode_operations;
272 if (dir->i_mode & S_ISGID)
273 inode->i_mode |= S_ISGID;
274 }
275 else if (S_ISLNK(inode->i_mode))
276 inode->i_op = &minix_symlink_inode_operations;
277 else if (S_ISCHR(inode->i_mode))
278 inode->i_op = &chrdev_inode_operations;
279 else if (S_ISBLK(inode->i_mode))
280 inode->i_op = &blkdev_inode_operations;
281 else if (S_ISFIFO(inode->i_mode))
282 init_fifo(inode);
283 if (S_ISBLK(mode) || S_ISCHR(mode))
284 inode->i_rdev = rdev;
285 inode->i_dirt = 1;
286 error = minix_add_entry(dir, name, len, &bh, &de);
287 if (error) {
288 inode->i_nlink--;
289 inode->i_dirt = 1;
290 iput(inode);
291 iput(dir);
292 return error;
293 }
294 de->inode = inode->i_ino;
295 mark_buffer_dirty(bh, 1);
296 brelse(bh);
297 iput(dir);
298 iput(inode);
299 return 0;
300 }
301
302 int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
303 {
304 int error;
305 struct inode * inode;
306 struct buffer_head * bh, *dir_block;
307 struct minix_dir_entry * de;
308 struct minix_sb_info * info;
309
310 if (!dir || !dir->i_sb) {
311 iput(dir);
312 return -EINVAL;
313 }
314 info = &dir->i_sb->u.minix_sb;
315 bh = minix_find_entry(dir,name,len,&de);
316 if (bh) {
317 brelse(bh);
318 iput(dir);
319 return -EEXIST;
320 }
321 if (dir->i_nlink >= MINIX_LINK_MAX) {
322 iput(dir);
323 return -EMLINK;
324 }
325 inode = minix_new_inode(dir);
326 if (!inode) {
327 iput(dir);
328 return -ENOSPC;
329 }
330 inode->i_op = &minix_dir_inode_operations;
331 inode->i_size = 2 * info->s_dirsize;
332 dir_block = minix_bread(inode,0,1);
333 if (!dir_block) {
334 iput(dir);
335 inode->i_nlink--;
336 inode->i_dirt = 1;
337 iput(inode);
338 return -ENOSPC;
339 }
340 de = (struct minix_dir_entry *) dir_block->b_data;
341 de->inode=inode->i_ino;
342 strcpy(de->name,".");
343 de = (struct minix_dir_entry *) (dir_block->b_data + info->s_dirsize);
344 de->inode = dir->i_ino;
345 strcpy(de->name,"..");
346 inode->i_nlink = 2;
347 mark_buffer_dirty(dir_block, 1);
348 brelse(dir_block);
349 inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
350 if (dir->i_mode & S_ISGID)
351 inode->i_mode |= S_ISGID;
352 inode->i_dirt = 1;
353 error = minix_add_entry(dir, name, len, &bh, &de);
354 if (error) {
355 iput(dir);
356 inode->i_nlink=0;
357 iput(inode);
358 return error;
359 }
360 de->inode = inode->i_ino;
361 mark_buffer_dirty(bh, 1);
362 dir->i_nlink++;
363 dir->i_dirt = 1;
364 iput(dir);
365 iput(inode);
366 brelse(bh);
367 return 0;
368 }
369
370
371
372
373 static int empty_dir(struct inode * inode)
374 {
375 unsigned int block, offset;
376 struct buffer_head * bh;
377 struct minix_dir_entry * de;
378 struct minix_sb_info * info;
379
380 if (!inode || !inode->i_sb)
381 return 1;
382 info = &inode->i_sb->u.minix_sb;
383 block = 0;
384 bh = NULL;
385 offset = 2*info->s_dirsize;
386 if (inode->i_size & (info->s_dirsize-1))
387 goto bad_dir;
388 if (inode->i_size < offset)
389 goto bad_dir;
390 bh = minix_bread(inode,0,0);
391 if (!bh)
392 goto bad_dir;
393 de = (struct minix_dir_entry *) bh->b_data;
394 if (!de->inode || strcmp(de->name,"."))
395 goto bad_dir;
396 de = (struct minix_dir_entry *) (bh->b_data + info->s_dirsize);
397 if (!de->inode || strcmp(de->name,".."))
398 goto bad_dir;
399 while (block*BLOCK_SIZE+offset < inode->i_size) {
400 if (!bh) {
401 bh = minix_bread(inode,block,0);
402 if (!bh) {
403 block++;
404 continue;
405 }
406 }
407 de = (struct minix_dir_entry *) (bh->b_data + offset);
408 offset += info->s_dirsize;
409 if (de->inode) {
410 brelse(bh);
411 return 0;
412 }
413 if (offset < bh->b_size)
414 continue;
415 brelse(bh);
416 bh = NULL;
417 offset = 0;
418 block++;
419 }
420 brelse(bh);
421 return 1;
422 bad_dir:
423 brelse(bh);
424 printk("Bad directory on device %04x\n",inode->i_dev);
425 return 1;
426 }
427
428 int minix_rmdir(struct inode * dir, const char * name, int len)
429 {
430 int retval;
431 struct inode * inode;
432 struct buffer_head * bh;
433 struct minix_dir_entry * de;
434
435 inode = NULL;
436 bh = minix_find_entry(dir,name,len,&de);
437 retval = -ENOENT;
438 if (!bh)
439 goto end_rmdir;
440 retval = -EPERM;
441 if (!(inode = iget(dir->i_sb, de->inode)))
442 goto end_rmdir;
443 if ((dir->i_mode & S_ISVTX) && !fsuser() &&
444 current->fsuid != inode->i_uid &&
445 current->fsuid != dir->i_uid)
446 goto end_rmdir;
447 if (inode->i_dev != dir->i_dev)
448 goto end_rmdir;
449 if (inode == dir)
450 goto end_rmdir;
451 if (!S_ISDIR(inode->i_mode)) {
452 retval = -ENOTDIR;
453 goto end_rmdir;
454 }
455 if (!empty_dir(inode)) {
456 retval = -ENOTEMPTY;
457 goto end_rmdir;
458 }
459 if (de->inode != inode->i_ino) {
460 retval = -ENOENT;
461 goto end_rmdir;
462 }
463 if (inode->i_count > 1) {
464 retval = -EBUSY;
465 goto end_rmdir;
466 }
467 if (inode->i_nlink != 2)
468 printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
469 de->inode = 0;
470 dir->i_version = ++event;
471 mark_buffer_dirty(bh, 1);
472 inode->i_nlink=0;
473 inode->i_dirt=1;
474 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
475 dir->i_nlink--;
476 dir->i_dirt=1;
477 retval = 0;
478 end_rmdir:
479 iput(dir);
480 iput(inode);
481 brelse(bh);
482 return retval;
483 }
484
485 int minix_unlink(struct inode * dir, const char * name, int len)
486 {
487 int retval;
488 struct inode * inode;
489 struct buffer_head * bh;
490 struct minix_dir_entry * de;
491
492 repeat:
493 retval = -ENOENT;
494 inode = NULL;
495 bh = minix_find_entry(dir,name,len,&de);
496 if (!bh)
497 goto end_unlink;
498 if (!(inode = iget(dir->i_sb, de->inode)))
499 goto end_unlink;
500 retval = -EPERM;
501 if (S_ISDIR(inode->i_mode))
502 goto end_unlink;
503 if (de->inode != inode->i_ino) {
504 iput(inode);
505 brelse(bh);
506 current->counter = 0;
507 schedule();
508 goto repeat;
509 }
510 if ((dir->i_mode & S_ISVTX) && !fsuser() &&
511 current->fsuid != inode->i_uid &&
512 current->fsuid != dir->i_uid)
513 goto end_unlink;
514 if (de->inode != inode->i_ino) {
515 retval = -ENOENT;
516 goto end_unlink;
517 }
518 if (!inode->i_nlink) {
519 printk("Deleting nonexistent file (%04x:%lu), %d\n",
520 inode->i_dev,inode->i_ino,inode->i_nlink);
521 inode->i_nlink=1;
522 }
523 de->inode = 0;
524 dir->i_version = ++event;
525 mark_buffer_dirty(bh, 1);
526 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
527 dir->i_dirt = 1;
528 inode->i_nlink--;
529 inode->i_ctime = dir->i_ctime;
530 inode->i_dirt = 1;
531 retval = 0;
532 end_unlink:
533 brelse(bh);
534 iput(inode);
535 iput(dir);
536 return retval;
537 }
538
539 int minix_symlink(struct inode * dir, const char * name, int len, const char * symname)
540 {
541 struct minix_dir_entry * de;
542 struct inode * inode = NULL;
543 struct buffer_head * bh = NULL, * name_block = NULL;
544 int i;
545 char c;
546
547 if (!(inode = minix_new_inode(dir))) {
548 iput(dir);
549 return -ENOSPC;
550 }
551 inode->i_mode = S_IFLNK | 0777;
552 inode->i_op = &minix_symlink_inode_operations;
553 name_block = minix_bread(inode,0,1);
554 if (!name_block) {
555 iput(dir);
556 inode->i_nlink--;
557 inode->i_dirt = 1;
558 iput(inode);
559 return -ENOSPC;
560 }
561 i = 0;
562 while (i < 1023 && (c=*(symname++)))
563 name_block->b_data[i++] = c;
564 name_block->b_data[i] = 0;
565 mark_buffer_dirty(name_block, 1);
566 brelse(name_block);
567 inode->i_size = i;
568 inode->i_dirt = 1;
569 bh = minix_find_entry(dir,name,len,&de);
570 if (bh) {
571 inode->i_nlink--;
572 inode->i_dirt = 1;
573 iput(inode);
574 brelse(bh);
575 iput(dir);
576 return -EEXIST;
577 }
578 i = minix_add_entry(dir, name, len, &bh, &de);
579 if (i) {
580 inode->i_nlink--;
581 inode->i_dirt = 1;
582 iput(inode);
583 iput(dir);
584 return i;
585 }
586 de->inode = inode->i_ino;
587 mark_buffer_dirty(bh, 1);
588 brelse(bh);
589 iput(dir);
590 iput(inode);
591 return 0;
592 }
593
594 int minix_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
595 {
596 int error;
597 struct minix_dir_entry * de;
598 struct buffer_head * bh;
599
600 if (S_ISDIR(oldinode->i_mode)) {
601 iput(oldinode);
602 iput(dir);
603 return -EPERM;
604 }
605 if (oldinode->i_nlink >= MINIX_LINK_MAX) {
606 iput(oldinode);
607 iput(dir);
608 return -EMLINK;
609 }
610 bh = minix_find_entry(dir,name,len,&de);
611 if (bh) {
612 brelse(bh);
613 iput(dir);
614 iput(oldinode);
615 return -EEXIST;
616 }
617 error = minix_add_entry(dir, name, len, &bh, &de);
618 if (error) {
619 iput(dir);
620 iput(oldinode);
621 return error;
622 }
623 de->inode = oldinode->i_ino;
624 mark_buffer_dirty(bh, 1);
625 brelse(bh);
626 iput(dir);
627 oldinode->i_nlink++;
628 oldinode->i_ctime = CURRENT_TIME;
629 oldinode->i_dirt = 1;
630 iput(oldinode);
631 return 0;
632 }
633
634 static int subdir(struct inode * new_inode, struct inode * old_inode)
635 {
636 int ino;
637 int result;
638
639 new_inode->i_count++;
640 result = 0;
641 for (;;) {
642 if (new_inode == old_inode) {
643 result = 1;
644 break;
645 }
646 if (new_inode->i_dev != old_inode->i_dev)
647 break;
648 ino = new_inode->i_ino;
649 if (minix_lookup(new_inode,"..",2,&new_inode))
650 break;
651 if (new_inode->i_ino == ino)
652 break;
653 }
654 iput(new_inode);
655 return result;
656 }
657
658 #define PARENT_INO(buffer) \
659 (((struct minix_dir_entry *) ((buffer)+info->s_dirsize))->inode)
660
661
662
663
664
665
666
667
668
669
670
671 static int do_minix_rename(struct inode * old_dir, const char * old_name, int old_len,
672 struct inode * new_dir, const char * new_name, int new_len)
673 {
674 struct inode * old_inode, * new_inode;
675 struct buffer_head * old_bh, * new_bh, * dir_bh;
676 struct minix_dir_entry * old_de, * new_de;
677 struct minix_sb_info * info;
678 int retval;
679
680 info = &old_dir->i_sb->u.minix_sb;
681 goto start_up;
682 try_again:
683 brelse(old_bh);
684 brelse(new_bh);
685 brelse(dir_bh);
686 iput(old_inode);
687 iput(new_inode);
688 current->counter = 0;
689 schedule();
690 start_up:
691 old_inode = new_inode = NULL;
692 old_bh = new_bh = dir_bh = NULL;
693 old_bh = minix_find_entry(old_dir,old_name,old_len,&old_de);
694 retval = -ENOENT;
695 if (!old_bh)
696 goto end_rename;
697 old_inode = __iget(old_dir->i_sb, old_de->inode,0);
698 if (!old_inode)
699 goto end_rename;
700 retval = -EPERM;
701 if ((old_dir->i_mode & S_ISVTX) &&
702 current->fsuid != old_inode->i_uid &&
703 current->fsuid != old_dir->i_uid && !fsuser())
704 goto end_rename;
705 new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de);
706 if (new_bh) {
707 new_inode = __iget(new_dir->i_sb, new_de->inode, 0);
708 if (!new_inode) {
709 brelse(new_bh);
710 new_bh = NULL;
711 }
712 }
713 if (new_inode == old_inode) {
714 retval = 0;
715 goto end_rename;
716 }
717 if (new_inode && S_ISDIR(new_inode->i_mode)) {
718 retval = -EISDIR;
719 if (!S_ISDIR(old_inode->i_mode))
720 goto end_rename;
721 retval = -EINVAL;
722 if (subdir(new_dir, old_inode))
723 goto end_rename;
724 retval = -ENOTEMPTY;
725 if (!empty_dir(new_inode))
726 goto end_rename;
727 retval = -EBUSY;
728 if (new_inode->i_count > 1)
729 goto end_rename;
730 }
731 retval = -EPERM;
732 if (new_inode && (new_dir->i_mode & S_ISVTX) &&
733 current->fsuid != new_inode->i_uid &&
734 current->fsuid != new_dir->i_uid && !fsuser())
735 goto end_rename;
736 if (S_ISDIR(old_inode->i_mode)) {
737 retval = -ENOTDIR;
738 if (new_inode && !S_ISDIR(new_inode->i_mode))
739 goto end_rename;
740 retval = -EINVAL;
741 if (subdir(new_dir, old_inode))
742 goto end_rename;
743 retval = -EIO;
744 dir_bh = minix_bread(old_inode,0,0);
745 if (!dir_bh)
746 goto end_rename;
747 if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
748 goto end_rename;
749 retval = -EMLINK;
750 if (!new_inode && new_dir->i_nlink >= MINIX_LINK_MAX)
751 goto end_rename;
752 }
753 if (!new_bh) {
754 retval = minix_add_entry(new_dir,new_name,new_len,&new_bh,&new_de);
755 if (retval)
756 goto end_rename;
757 }
758
759 if (new_inode && (new_de->inode != new_inode->i_ino))
760 goto try_again;
761 if (new_de->inode && !new_inode)
762 goto try_again;
763 if (old_de->inode != old_inode->i_ino)
764 goto try_again;
765
766 old_de->inode = 0;
767 new_de->inode = old_inode->i_ino;
768 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
769 old_dir->i_dirt = 1;
770 old_dir->i_version = ++event;
771 new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
772 new_dir->i_dirt = 1;
773 new_dir->i_version = ++event;
774 if (new_inode) {
775 new_inode->i_nlink--;
776 new_inode->i_ctime = CURRENT_TIME;
777 new_inode->i_dirt = 1;
778 }
779 mark_buffer_dirty(old_bh, 1);
780 mark_buffer_dirty(new_bh, 1);
781 if (dir_bh) {
782 PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
783 mark_buffer_dirty(dir_bh, 1);
784 old_dir->i_nlink--;
785 old_dir->i_dirt = 1;
786 if (new_inode) {
787 new_inode->i_nlink--;
788 new_inode->i_dirt = 1;
789 } else {
790 new_dir->i_nlink++;
791 new_dir->i_dirt = 1;
792 }
793 }
794 retval = 0;
795 end_rename:
796 brelse(dir_bh);
797 brelse(old_bh);
798 brelse(new_bh);
799 iput(old_inode);
800 iput(new_inode);
801 iput(old_dir);
802 iput(new_dir);
803 return retval;
804 }
805
806
807
808
809
810
811
812
813
814
815 int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
816 struct inode * new_dir, const char * new_name, int new_len)
817 {
818 static struct wait_queue * wait = NULL;
819 static int lock = 0;
820 int result;
821
822 while (lock)
823 sleep_on(&wait);
824 lock = 1;
825 result = do_minix_rename(old_dir, old_name, old_len,
826 new_dir, new_name, new_len);
827 lock = 0;
828 wake_up(&wait);
829 return result;
830 }