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