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 = to_kdev_t(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 %s\n",
422 kdevname(inode->i_dev));
423 return 1;
424 }
425
426 int sysv_rmdir(struct inode * dir, const char * name, int len)
427 {
428 int retval;
429 struct inode * inode;
430 struct buffer_head * bh;
431 struct sysv_dir_entry * de;
432
433 inode = NULL;
434 bh = sysv_find_entry(dir,name,len,&de);
435 retval = -ENOENT;
436 if (!bh)
437 goto end_rmdir;
438 retval = -EPERM;
439 if (!(inode = iget(dir->i_sb, de->inode)))
440 goto end_rmdir;
441 if ((dir->i_mode & S_ISVTX) && !fsuser() &&
442 current->fsuid != inode->i_uid &&
443 current->fsuid != dir->i_uid)
444 goto end_rmdir;
445 if (inode->i_dev != dir->i_dev)
446 goto end_rmdir;
447 if (inode == dir)
448 goto end_rmdir;
449 if (!S_ISDIR(inode->i_mode)) {
450 retval = -ENOTDIR;
451 goto end_rmdir;
452 }
453 if (!empty_dir(inode)) {
454 retval = -ENOTEMPTY;
455 goto end_rmdir;
456 }
457 if (de->inode != inode->i_ino) {
458 retval = -ENOENT;
459 goto end_rmdir;
460 }
461 if (inode->i_count > 1) {
462 retval = -EBUSY;
463 goto end_rmdir;
464 }
465 if (inode->i_nlink != 2)
466 printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
467 de->inode = 0;
468 mark_buffer_dirty(bh, 1);
469 inode->i_nlink=0;
470 inode->i_dirt=1;
471 dir->i_nlink--;
472 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
473 dir->i_dirt=1;
474 retval = 0;
475 end_rmdir:
476 iput(dir);
477 iput(inode);
478 brelse(bh);
479 return retval;
480 }
481
482 int sysv_unlink(struct inode * dir, const char * name, int len)
483 {
484 int retval;
485 struct inode * inode;
486 struct buffer_head * bh;
487 struct sysv_dir_entry * de;
488
489 repeat:
490 retval = -ENOENT;
491 inode = NULL;
492 bh = sysv_find_entry(dir,name,len,&de);
493 if (!bh)
494 goto end_unlink;
495 if (!(inode = iget(dir->i_sb, de->inode)))
496 goto end_unlink;
497 retval = -EPERM;
498 if (S_ISDIR(inode->i_mode))
499 goto end_unlink;
500 if (de->inode != inode->i_ino) {
501 iput(inode);
502 brelse(bh);
503 current->counter = 0;
504 schedule();
505 goto repeat;
506 }
507 if ((dir->i_mode & S_ISVTX) && !fsuser() &&
508 current->fsuid != inode->i_uid &&
509 current->fsuid != dir->i_uid)
510 goto end_unlink;
511 if (de->inode != inode->i_ino) {
512 retval = -ENOENT;
513 goto end_unlink;
514 }
515 if (!inode->i_nlink) {
516 printk("Deleting nonexistent file (%s:%lu), %d\n",
517 kdevname(inode->i_dev),
518 inode->i_ino, inode->i_nlink);
519 inode->i_nlink=1;
520 }
521 de->inode = 0;
522 mark_buffer_dirty(bh, 1);
523 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
524 dir->i_dirt = 1;
525 inode->i_nlink--;
526 inode->i_ctime = dir->i_ctime;
527 inode->i_dirt = 1;
528 retval = 0;
529 end_unlink:
530 brelse(bh);
531 iput(inode);
532 iput(dir);
533 return retval;
534 }
535
536 int sysv_symlink(struct inode * dir, const char * name, int len, const char * symname)
537 {
538 struct sysv_dir_entry * de;
539 struct inode * inode;
540 struct buffer_head * name_block;
541 char * name_block_data;
542 struct super_block * sb;
543 int i;
544 char c;
545 struct buffer_head * bh;
546
547 if (!(inode = sysv_new_inode(dir))) {
548 iput(dir);
549 return -ENOSPC;
550 }
551 inode->i_mode = S_IFLNK | 0777;
552 inode->i_op = &sysv_symlink_inode_operations;
553 name_block = sysv_file_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 sb = inode->i_sb;
562 name_block_data = name_block->b_data;
563 i = 0;
564 while (i < sb->sv_block_size_1 && (c = *(symname++)))
565 name_block_data[i++] = c;
566 name_block_data[i] = 0;
567 mark_buffer_dirty(name_block, 1);
568 brelse(name_block);
569 inode->i_size = i;
570 inode->i_dirt = 1;
571 bh = sysv_find_entry(dir,name,len,&de);
572 if (bh) {
573 inode->i_nlink--;
574 inode->i_dirt = 1;
575 iput(inode);
576 brelse(bh);
577 iput(dir);
578 return -EEXIST;
579 }
580 i = sysv_add_entry(dir, name, len, &bh, &de);
581 if (i) {
582 inode->i_nlink--;
583 inode->i_dirt = 1;
584 iput(inode);
585 iput(dir);
586 return i;
587 }
588 de->inode = inode->i_ino;
589 mark_buffer_dirty(bh, 1);
590 brelse(bh);
591 iput(dir);
592 iput(inode);
593 return 0;
594 }
595
596 int sysv_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
597 {
598 int error;
599 struct sysv_dir_entry * de;
600 struct buffer_head * bh;
601
602 if (S_ISDIR(oldinode->i_mode)) {
603 iput(oldinode);
604 iput(dir);
605 return -EPERM;
606 }
607 if (oldinode->i_nlink >= oldinode->i_sb->sv_link_max) {
608 iput(oldinode);
609 iput(dir);
610 return -EMLINK;
611 }
612 bh = sysv_find_entry(dir,name,len,&de);
613 if (bh) {
614 brelse(bh);
615 iput(dir);
616 iput(oldinode);
617 return -EEXIST;
618 }
619 error = sysv_add_entry(dir, name, len, &bh, &de);
620 if (error) {
621 iput(dir);
622 iput(oldinode);
623 return error;
624 }
625 de->inode = oldinode->i_ino;
626 mark_buffer_dirty(bh, 1);
627 brelse(bh);
628 iput(dir);
629 oldinode->i_nlink++;
630 oldinode->i_ctime = CURRENT_TIME;
631 oldinode->i_dirt = 1;
632 iput(oldinode);
633 return 0;
634 }
635
636
637 static int subdir(struct inode * new_inode, struct inode * old_inode)
638 {
639 int ino;
640 int result;
641
642 new_inode->i_count++;
643 result = 0;
644 for (;;) {
645 if (new_inode == old_inode) {
646 result = 1;
647 break;
648 }
649 if (new_inode->i_dev != old_inode->i_dev)
650 break;
651 ino = new_inode->i_ino;
652 if (sysv_lookup(new_inode,"..",2,&new_inode))
653 break;
654 if (new_inode->i_ino == ino)
655 break;
656 }
657 iput(new_inode);
658 return result;
659 }
660
661 #define PARENT_INO(buffer) \
662 (((struct sysv_dir_entry *) ((buffer) + 1*SYSV_DIRSIZE))->inode)
663
664
665
666
667
668
669
670
671
672
673
674 static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old_len,
675 struct inode * new_dir, const char * new_name, int new_len)
676 {
677 struct inode * old_inode, * new_inode;
678 struct buffer_head * old_bh, * new_bh, * dir_bh;
679 struct sysv_dir_entry * old_de, * new_de;
680 int retval;
681
682 goto start_up;
683 try_again:
684 brelse(old_bh);
685 brelse(new_bh);
686 brelse(dir_bh);
687 iput(old_inode);
688 iput(new_inode);
689 current->counter = 0;
690 schedule();
691 start_up:
692 old_inode = new_inode = NULL;
693 old_bh = new_bh = dir_bh = NULL;
694 old_bh = sysv_find_entry(old_dir,old_name,old_len,&old_de);
695 retval = -ENOENT;
696 if (!old_bh)
697 goto end_rename;
698 old_inode = __iget(old_dir->i_sb, old_de->inode, 0);
699 if (!old_inode)
700 goto end_rename;
701 retval = -EPERM;
702 if ((old_dir->i_mode & S_ISVTX) &&
703 current->fsuid != old_inode->i_uid &&
704 current->fsuid != old_dir->i_uid && !fsuser())
705 goto end_rename;
706 new_bh = sysv_find_entry(new_dir,new_name,new_len,&new_de);
707 if (new_bh) {
708 new_inode = __iget(new_dir->i_sb, new_de->inode, 0);
709 if (!new_inode) {
710 brelse(new_bh);
711 new_bh = NULL;
712 }
713 }
714 if (new_inode == old_inode) {
715 retval = 0;
716 goto end_rename;
717 }
718 if (new_inode && S_ISDIR(new_inode->i_mode)) {
719 retval = -EISDIR;
720 if (!S_ISDIR(old_inode->i_mode))
721 goto end_rename;
722 retval = -EINVAL;
723 if (subdir(new_dir, old_inode))
724 goto end_rename;
725 retval = -ENOTEMPTY;
726 if (!empty_dir(new_inode))
727 goto end_rename;
728 retval = -EBUSY;
729 if (new_inode->i_count > 1)
730 goto end_rename;
731 }
732 retval = -EPERM;
733 if (new_inode && (new_dir->i_mode & S_ISVTX) &&
734 current->fsuid != new_inode->i_uid &&
735 current->fsuid != new_dir->i_uid && !fsuser())
736 goto end_rename;
737 if (S_ISDIR(old_inode->i_mode)) {
738 retval = -ENOTDIR;
739 if (new_inode && !S_ISDIR(new_inode->i_mode))
740 goto end_rename;
741 retval = -EINVAL;
742 if (subdir(new_dir, old_inode))
743 goto end_rename;
744 retval = -EIO;
745 dir_bh = sysv_file_bread(old_inode,0,0);
746 if (!dir_bh)
747 goto end_rename;
748 if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
749 goto end_rename;
750 retval = -EMLINK;
751 if (!new_inode && new_dir->i_nlink >= new_dir->i_sb->sv_link_max)
752 goto end_rename;
753 }
754 if (!new_bh) {
755 retval = sysv_add_entry(new_dir,new_name,new_len,&new_bh,&new_de);
756 if (retval)
757 goto end_rename;
758 }
759
760 if (new_inode && (new_de->inode != new_inode->i_ino))
761 goto try_again;
762 if (new_de->inode && !new_inode)
763 goto try_again;
764 if (old_de->inode != old_inode->i_ino)
765 goto try_again;
766
767 old_de->inode = 0;
768 new_de->inode = old_inode->i_ino;
769 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
770 old_dir->i_dirt = 1;
771 new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
772 new_dir->i_dirt = 1;
773 if (new_inode) {
774 new_inode->i_nlink--;
775 new_inode->i_ctime = CURRENT_TIME;
776 new_inode->i_dirt = 1;
777 }
778 mark_buffer_dirty(old_bh, 1);
779 mark_buffer_dirty(new_bh, 1);
780 if (dir_bh) {
781 PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
782 mark_buffer_dirty(dir_bh, 1);
783 old_dir->i_nlink--;
784 old_dir->i_dirt = 1;
785 if (new_inode) {
786 new_inode->i_nlink--;
787 new_inode->i_dirt = 1;
788 } else {
789 new_dir->i_nlink++;
790 new_dir->i_dirt = 1;
791 }
792 }
793 retval = 0;
794 end_rename:
795 brelse(dir_bh);
796 brelse(old_bh);
797 brelse(new_bh);
798 iput(old_inode);
799 iput(new_inode);
800 iput(old_dir);
801 iput(new_dir);
802 return retval;
803 }
804
805
806
807
808
809
810
811
812
813
814 int sysv_rename(struct inode * old_dir, const char * old_name, int old_len,
815 struct inode * new_dir, const char * new_name, int new_len)
816 {
817 static struct wait_queue * wait = NULL;
818 static int lock = 0;
819 int result;
820
821 while (lock)
822 sleep_on(&wait);
823 lock = 1;
824 result = do_sysv_rename(old_dir, old_name, old_len,
825 new_dir, new_name, new_len);
826 lock = 0;
827 wake_up(&wait);
828 return result;
829 }