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