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