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