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