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