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