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