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 for (i = 0; i < SYSV_NAMELEN ; i++)
188 de->name[i] = (i < namelen) ? name[i] : 0;
189 mark_buffer_dirty(bh, 1);
190 *res_dir = de;
191 break;
192 }
193 if (offset < sb->sv_block_size)
194 continue;
195 brelse(bh);
196 bh = NULL;
197 offset = 0; block++;
198 }
199 *res_buf = bh;
200 return 0;
201 }
202
203 int sysv_create(struct inode * dir,const char * name, int len, int mode,
204 struct inode ** result)
205 {
206 int error;
207 struct inode * inode;
208 struct buffer_head * bh;
209 struct sysv_dir_entry * de;
210
211 *result = NULL;
212 if (!dir)
213 return -ENOENT;
214 inode = sysv_new_inode(dir);
215 if (!inode) {
216 iput(dir);
217 return -ENOSPC;
218 }
219 inode->i_op = &sysv_file_inode_operations;
220 inode->i_mode = mode;
221 inode->i_dirt = 1;
222 error = sysv_add_entry(dir,name,len, &bh ,&de);
223 if (error) {
224 inode->i_nlink--;
225 inode->i_dirt = 1;
226 iput(inode);
227 iput(dir);
228 return error;
229 }
230 de->inode = inode->i_ino;
231 mark_buffer_dirty(bh, 1);
232 brelse(bh);
233 iput(dir);
234 *result = inode;
235 return 0;
236 }
237
238 int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rdev)
239 {
240 int error;
241 struct inode * inode;
242 struct buffer_head * bh;
243 struct sysv_dir_entry * de;
244
245 if (!dir)
246 return -ENOENT;
247 bh = sysv_find_entry(dir,name,len,&de);
248 if (bh) {
249 brelse(bh);
250 iput(dir);
251 return -EEXIST;
252 }
253 inode = sysv_new_inode(dir);
254 if (!inode) {
255 iput(dir);
256 return -ENOSPC;
257 }
258 inode->i_uid = current->fsuid;
259 inode->i_mode = mode;
260 inode->i_op = NULL;
261 if (S_ISREG(inode->i_mode))
262 inode->i_op = &sysv_file_inode_operations;
263 else if (S_ISDIR(inode->i_mode)) {
264 inode->i_op = &sysv_dir_inode_operations;
265 if (dir->i_mode & S_ISGID)
266 inode->i_mode |= S_ISGID;
267 }
268 else if (S_ISLNK(inode->i_mode))
269 inode->i_op = &sysv_symlink_inode_operations;
270 else if (S_ISCHR(inode->i_mode))
271 inode->i_op = &chrdev_inode_operations;
272 else if (S_ISBLK(inode->i_mode))
273 inode->i_op = &blkdev_inode_operations;
274 else if (S_ISFIFO(inode->i_mode))
275 init_fifo(inode);
276 if (S_ISBLK(mode) || S_ISCHR(mode))
277 inode->i_rdev = rdev;
278 inode->i_dirt = 1;
279 error = sysv_add_entry(dir, name, len, &bh, &de);
280 if (error) {
281 inode->i_nlink--;
282 inode->i_dirt = 1;
283 iput(inode);
284 iput(dir);
285 return error;
286 }
287 de->inode = inode->i_ino;
288 mark_buffer_dirty(bh, 1);
289 brelse(bh);
290 iput(dir);
291 iput(inode);
292 return 0;
293 }
294
295 int sysv_mkdir(struct inode * dir, const char * name, int len, int mode)
296 {
297 int error;
298 struct inode * inode;
299 struct buffer_head * bh, *dir_block;
300 struct sysv_dir_entry * de;
301
302 if (!dir) {
303 iput(dir);
304 return -EINVAL;
305 }
306 bh = sysv_find_entry(dir,name,len,&de);
307 if (bh) {
308 brelse(bh);
309 iput(dir);
310 return -EEXIST;
311 }
312 if (dir->i_nlink >= dir->i_sb->sv_link_max) {
313 iput(dir);
314 return -EMLINK;
315 }
316 inode = sysv_new_inode(dir);
317 if (!inode) {
318 iput(dir);
319 return -ENOSPC;
320 }
321 inode->i_op = &sysv_dir_inode_operations;
322 inode->i_size = 2 * SYSV_DIRSIZE;
323 dir_block = sysv_file_bread(inode,0,1);
324 if (!dir_block) {
325 iput(dir);
326 inode->i_nlink--;
327 inode->i_dirt = 1;
328 iput(inode);
329 return -ENOSPC;
330 }
331 de = (struct sysv_dir_entry *) (dir_block->b_data + 0*SYSV_DIRSIZE);
332 de->inode = inode->i_ino;
333 strcpy(de->name,".");
334 de = (struct sysv_dir_entry *) (dir_block->b_data + 1*SYSV_DIRSIZE);
335 de->inode = dir->i_ino;
336 strcpy(de->name,"..");
337 inode->i_nlink = 2;
338 mark_buffer_dirty(dir_block, 1);
339 brelse(dir_block);
340 inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
341 if (dir->i_mode & S_ISGID)
342 inode->i_mode |= S_ISGID;
343 inode->i_dirt = 1;
344 error = sysv_add_entry(dir, name, len, &bh, &de);
345 if (error) {
346 iput(dir);
347 inode->i_nlink=0;
348 iput(inode);
349 return error;
350 }
351 de->inode = inode->i_ino;
352 mark_buffer_dirty(bh, 1);
353 dir->i_nlink++;
354 dir->i_dirt = 1;
355 iput(dir);
356 iput(inode);
357 brelse(bh);
358 return 0;
359 }
360
361
362
363
364 static int empty_dir(struct inode * inode)
365 {
366 struct super_block * sb;
367 unsigned long pos, block, offset;
368 struct buffer_head * bh;
369 struct sysv_dir_entry * de;
370
371 if (!inode)
372 return 1;
373 block = 0;
374 bh = NULL;
375 pos = offset = 2*SYSV_DIRSIZE;
376 if (inode->i_size % SYSV_DIRSIZE)
377 goto bad_dir;
378 if (inode->i_size < pos)
379 goto bad_dir;
380 bh = sysv_file_bread(inode,0,0);
381 if (!bh)
382 goto bad_dir;
383 de = (struct sysv_dir_entry *) (bh->b_data + 0*SYSV_DIRSIZE);
384 if (!de->inode || strcmp(de->name,"."))
385 goto bad_dir;
386 de = (struct sysv_dir_entry *) (bh->b_data + 1*SYSV_DIRSIZE);
387 if (!de->inode || strcmp(de->name,".."))
388 goto bad_dir;
389 sb = inode->i_sb;
390 while (pos < inode->i_size) {
391 if (!bh) {
392 bh = sysv_file_bread(inode,block,0);
393 if (!bh) {
394 block++;
395 pos += sb->sv_block_size;
396 continue;
397 }
398 }
399 de = (struct sysv_dir_entry *) (bh->b_data + offset);
400 pos += SYSV_DIRSIZE;
401 offset += SYSV_DIRSIZE;
402 if (de->inode) {
403 brelse(bh);
404 return 0;
405 }
406 if (offset < sb->sv_block_size)
407 continue;
408 brelse(bh);
409 bh = NULL;
410 offset = 0; block++;
411 }
412 brelse(bh);
413 return 1;
414 bad_dir:
415 brelse(bh);
416 printk("Bad directory on device %04x\n",inode->i_dev);
417 return 1;
418 }
419
420 int sysv_rmdir(struct inode * dir, const char * name, int len)
421 {
422 int retval;
423 struct inode * inode;
424 struct buffer_head * bh;
425 struct sysv_dir_entry * de;
426
427 inode = NULL;
428 bh = sysv_find_entry(dir,name,len,&de);
429 retval = -ENOENT;
430 if (!bh)
431 goto end_rmdir;
432 retval = -EPERM;
433 if (!(inode = iget(dir->i_sb, de->inode)))
434 goto end_rmdir;
435 if ((dir->i_mode & S_ISVTX) && !fsuser() &&
436 current->fsuid != inode->i_uid &&
437 current->fsuid != dir->i_uid)
438 goto end_rmdir;
439 if (inode->i_dev != dir->i_dev)
440 goto end_rmdir;
441 if (inode == dir)
442 goto end_rmdir;
443 if (!S_ISDIR(inode->i_mode)) {
444 retval = -ENOTDIR;
445 goto end_rmdir;
446 }
447 if (!empty_dir(inode)) {
448 retval = -ENOTEMPTY;
449 goto end_rmdir;
450 }
451 if (de->inode != inode->i_ino) {
452 retval = -ENOENT;
453 goto end_rmdir;
454 }
455 if (inode->i_count > 1) {
456 retval = -EBUSY;
457 goto end_rmdir;
458 }
459 if (inode->i_nlink != 2)
460 printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
461 de->inode = 0;
462 mark_buffer_dirty(bh, 1);
463 inode->i_nlink=0;
464 inode->i_dirt=1;
465 dir->i_nlink--;
466 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
467 dir->i_dirt=1;
468 retval = 0;
469 end_rmdir:
470 iput(dir);
471 iput(inode);
472 brelse(bh);
473 return retval;
474 }
475
476 int sysv_unlink(struct inode * dir, const char * name, int len)
477 {
478 int retval;
479 struct inode * inode;
480 struct buffer_head * bh;
481 struct sysv_dir_entry * de;
482
483 repeat:
484 retval = -ENOENT;
485 inode = NULL;
486 bh = sysv_find_entry(dir,name,len,&de);
487 if (!bh)
488 goto end_unlink;
489 if (!(inode = iget(dir->i_sb, de->inode)))
490 goto end_unlink;
491 retval = -EPERM;
492 if (S_ISDIR(inode->i_mode))
493 goto end_unlink;
494 if (de->inode != inode->i_ino) {
495 iput(inode);
496 brelse(bh);
497 current->counter = 0;
498 schedule();
499 goto repeat;
500 }
501 if ((dir->i_mode & S_ISVTX) && !fsuser() &&
502 current->fsuid != inode->i_uid &&
503 current->fsuid != dir->i_uid)
504 goto end_unlink;
505 if (de->inode != inode->i_ino) {
506 retval = -ENOENT;
507 goto end_unlink;
508 }
509 if (!inode->i_nlink) {
510 printk("Deleting nonexistent file (%04x:%lu), %d\n",
511 inode->i_dev,inode->i_ino,inode->i_nlink);
512 inode->i_nlink=1;
513 }
514 de->inode = 0;
515 mark_buffer_dirty(bh, 1);
516 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
517 dir->i_dirt = 1;
518 inode->i_nlink--;
519 inode->i_ctime = dir->i_ctime;
520 inode->i_dirt = 1;
521 retval = 0;
522 end_unlink:
523 brelse(bh);
524 iput(inode);
525 iput(dir);
526 return retval;
527 }
528
529 int sysv_symlink(struct inode * dir, const char * name, int len, const char * symname)
530 {
531 struct sysv_dir_entry * de;
532 struct inode * inode;
533 struct buffer_head * name_block;
534 char * name_block_data;
535 struct super_block * sb;
536 int i;
537 char c;
538 struct buffer_head * bh;
539
540 if (!(inode = sysv_new_inode(dir))) {
541 iput(dir);
542 return -ENOSPC;
543 }
544 inode->i_mode = S_IFLNK | 0777;
545 inode->i_op = &sysv_symlink_inode_operations;
546 name_block = sysv_file_bread(inode,0,1);
547 if (!name_block) {
548 iput(dir);
549 inode->i_nlink--;
550 inode->i_dirt = 1;
551 iput(inode);
552 return -ENOSPC;
553 }
554 sb = inode->i_sb;
555 name_block_data = name_block->b_data;
556 i = 0;
557 while (i < sb->sv_block_size_1 && (c = *(symname++)))
558 name_block_data[i++] = c;
559 name_block_data[i] = 0;
560 mark_buffer_dirty(name_block, 1);
561 brelse(name_block);
562 inode->i_size = i;
563 inode->i_dirt = 1;
564 bh = sysv_find_entry(dir,name,len,&de);
565 if (bh) {
566 inode->i_nlink--;
567 inode->i_dirt = 1;
568 iput(inode);
569 brelse(bh);
570 iput(dir);
571 return -EEXIST;
572 }
573 i = sysv_add_entry(dir, name, len, &bh, &de);
574 if (i) {
575 inode->i_nlink--;
576 inode->i_dirt = 1;
577 iput(inode);
578 iput(dir);
579 return i;
580 }
581 de->inode = inode->i_ino;
582 mark_buffer_dirty(bh, 1);
583 brelse(bh);
584 iput(dir);
585 iput(inode);
586 return 0;
587 }
588
589 int sysv_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
590 {
591 int error;
592 struct sysv_dir_entry * de;
593 struct buffer_head * bh;
594
595 if (S_ISDIR(oldinode->i_mode)) {
596 iput(oldinode);
597 iput(dir);
598 return -EPERM;
599 }
600 if (oldinode->i_nlink >= oldinode->i_sb->sv_link_max) {
601 iput(oldinode);
602 iput(dir);
603 return -EMLINK;
604 }
605 bh = sysv_find_entry(dir,name,len,&de);
606 if (bh) {
607 brelse(bh);
608 iput(dir);
609 iput(oldinode);
610 return -EEXIST;
611 }
612 error = sysv_add_entry(dir, name, len, &bh, &de);
613 if (error) {
614 iput(dir);
615 iput(oldinode);
616 return error;
617 }
618 de->inode = oldinode->i_ino;
619 mark_buffer_dirty(bh, 1);
620 brelse(bh);
621 iput(dir);
622 oldinode->i_nlink++;
623 oldinode->i_ctime = CURRENT_TIME;
624 oldinode->i_dirt = 1;
625 iput(oldinode);
626 return 0;
627 }
628
629
630 static int subdir(struct inode * new_inode, struct inode * old_inode)
631 {
632 int ino;
633 int result;
634
635 new_inode->i_count++;
636 result = 0;
637 for (;;) {
638 if (new_inode == old_inode) {
639 result = 1;
640 break;
641 }
642 if (new_inode->i_dev != old_inode->i_dev)
643 break;
644 ino = new_inode->i_ino;
645 if (sysv_lookup(new_inode,"..",2,&new_inode))
646 break;
647 if (new_inode->i_ino == ino)
648 break;
649 }
650 iput(new_inode);
651 return result;
652 }
653
654 #define PARENT_INO(buffer) \
655 (((struct sysv_dir_entry *) ((buffer) + 1*SYSV_DIRSIZE))->inode)
656
657
658
659
660
661
662
663
664
665
666
667 static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old_len,
668 struct inode * new_dir, const char * new_name, int new_len)
669 {
670 struct inode * old_inode, * new_inode;
671 struct buffer_head * old_bh, * new_bh, * dir_bh;
672 struct sysv_dir_entry * old_de, * new_de;
673 int retval;
674
675 goto start_up;
676 try_again:
677 brelse(old_bh);
678 brelse(new_bh);
679 brelse(dir_bh);
680 iput(old_inode);
681 iput(new_inode);
682 current->counter = 0;
683 schedule();
684 start_up:
685 old_inode = new_inode = NULL;
686 old_bh = new_bh = dir_bh = NULL;
687 old_bh = sysv_find_entry(old_dir,old_name,old_len,&old_de);
688 retval = -ENOENT;
689 if (!old_bh)
690 goto end_rename;
691 old_inode = __iget(old_dir->i_sb, old_de->inode, 0);
692 if (!old_inode)
693 goto end_rename;
694 retval = -EPERM;
695 if ((old_dir->i_mode & S_ISVTX) &&
696 current->fsuid != old_inode->i_uid &&
697 current->fsuid != old_dir->i_uid && !fsuser())
698 goto end_rename;
699 new_bh = sysv_find_entry(new_dir,new_name,new_len,&new_de);
700 if (new_bh) {
701 new_inode = __iget(new_dir->i_sb, new_de->inode, 0);
702 if (!new_inode) {
703 brelse(new_bh);
704 new_bh = NULL;
705 }
706 }
707 if (new_inode == old_inode) {
708 retval = 0;
709 goto end_rename;
710 }
711 if (new_inode && S_ISDIR(new_inode->i_mode)) {
712 retval = -EISDIR;
713 if (!S_ISDIR(old_inode->i_mode))
714 goto end_rename;
715 retval = -EINVAL;
716 if (subdir(new_dir, old_inode))
717 goto end_rename;
718 retval = -ENOTEMPTY;
719 if (!empty_dir(new_inode))
720 goto end_rename;
721 retval = -EBUSY;
722 if (new_inode->i_count > 1)
723 goto end_rename;
724 }
725 retval = -EPERM;
726 if (new_inode && (new_dir->i_mode & S_ISVTX) &&
727 current->fsuid != new_inode->i_uid &&
728 current->fsuid != new_dir->i_uid && !fsuser())
729 goto end_rename;
730 if (S_ISDIR(old_inode->i_mode)) {
731 retval = -ENOTDIR;
732 if (new_inode && !S_ISDIR(new_inode->i_mode))
733 goto end_rename;
734 retval = -EINVAL;
735 if (subdir(new_dir, old_inode))
736 goto end_rename;
737 retval = -EIO;
738 dir_bh = sysv_file_bread(old_inode,0,0);
739 if (!dir_bh)
740 goto end_rename;
741 if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
742 goto end_rename;
743 retval = -EMLINK;
744 if (!new_inode && new_dir->i_nlink >= new_dir->i_sb->sv_link_max)
745 goto end_rename;
746 }
747 if (!new_bh) {
748 retval = sysv_add_entry(new_dir,new_name,new_len,&new_bh,&new_de);
749 if (retval)
750 goto end_rename;
751 }
752
753 if (new_inode && (new_de->inode != new_inode->i_ino))
754 goto try_again;
755 if (new_de->inode && !new_inode)
756 goto try_again;
757 if (old_de->inode != old_inode->i_ino)
758 goto try_again;
759
760 old_de->inode = 0;
761 new_de->inode = old_inode->i_ino;
762 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
763 old_dir->i_dirt = 1;
764 new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
765 new_dir->i_dirt = 1;
766 if (new_inode) {
767 new_inode->i_nlink--;
768 new_inode->i_ctime = CURRENT_TIME;
769 new_inode->i_dirt = 1;
770 }
771 mark_buffer_dirty(old_bh, 1);
772 mark_buffer_dirty(new_bh, 1);
773 if (dir_bh) {
774 PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
775 mark_buffer_dirty(dir_bh, 1);
776 old_dir->i_nlink--;
777 old_dir->i_dirt = 1;
778 if (new_inode) {
779 new_inode->i_nlink--;
780 new_inode->i_dirt = 1;
781 } else {
782 new_dir->i_nlink++;
783 new_dir->i_dirt = 1;
784 }
785 }
786 retval = 0;
787 end_rename:
788 brelse(dir_bh);
789 brelse(old_bh);
790 brelse(new_bh);
791 iput(old_inode);
792 iput(new_inode);
793 iput(old_dir);
794 iput(new_dir);
795 return retval;
796 }
797
798
799
800
801
802
803
804
805
806
807 int sysv_rename(struct inode * old_dir, const char * old_name, int old_len,
808 struct inode * new_dir, const char * new_name, int new_len)
809 {
810 static struct wait_queue * wait = NULL;
811 static int lock = 0;
812 int result;
813
814 while (lock)
815 sleep_on(&wait);
816 lock = 1;
817 result = do_sysv_rename(old_dir, old_name, old_len,
818 new_dir, new_name, new_len);
819 lock = 0;
820 wake_up(&wait);
821 return result;
822 }