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 dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
216 dir->i_dirt = 1;
217 memcpy(de->d_name, name, namelen);
218 de->d_name[namelen]=0;
219 de->d_name_len=namelen;
220 bh->b_dirt = 1;
221 *res_dir = de;
222 if (res_pre)
223 *res_pre = de_pre;
224 return bh;
225 }
226 offset+=de->d_rec_len;
227 de_pre=de;
228 de=(struct xiafs_direct *)(bh->b_data+offset);
229 }
230 brelse(bh);
231 if (offset > XIAFS_ZSIZE(dir->i_sb)) {
232 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
233 return NULL;
234 }
235 pos+=XIAFS_ZSIZE(dir->i_sb);
236 }
237 return NULL;
238 }
239
240 int xiafs_create(struct inode * dir, const char * name, int len, int mode,
241 struct inode ** result)
242 {
243 struct inode * inode;
244 struct buffer_head * bh;
245 struct xiafs_direct * de;
246
247 *result = NULL;
248 if (!dir)
249 return -ENOENT;
250 inode = xiafs_new_inode(dir);
251 if (!inode) {
252 iput(dir);
253 return -ENOSPC;
254 }
255 inode->i_op = &xiafs_file_inode_operations;
256 inode->i_mode = mode;
257 inode->i_dirt = 1;
258 bh = xiafs_add_entry(dir, name, len, &de, NULL);
259 if (!bh) {
260 inode->i_nlink--;
261 inode->i_dirt = 1;
262 iput(inode);
263 iput(dir);
264 return -ENOSPC;
265 }
266 de->d_ino = inode->i_ino;
267 bh->b_dirt = 1;
268 brelse(bh);
269 iput(dir);
270 *result = inode;
271 return 0;
272 }
273
274 int xiafs_mknod(struct inode *dir, const char *name, int len, int mode, int rdev)
275 {
276 struct inode * inode;
277 struct buffer_head * bh;
278 struct xiafs_direct * de;
279
280 if (!dir)
281 return -ENOENT;
282 bh = xiafs_find_entry(dir,name,len,&de, NULL);
283 if (bh) {
284 brelse(bh);
285 iput(dir);
286 return -EEXIST;
287 }
288 inode = xiafs_new_inode(dir);
289 if (!inode) {
290 iput(dir);
291 return -ENOSPC;
292 }
293 inode->i_uid = current->euid;
294 inode->i_mode = mode;
295 inode->i_op = NULL;
296 if (S_ISREG(inode->i_mode))
297 inode->i_op = &xiafs_file_inode_operations;
298 else if (S_ISDIR(inode->i_mode)) {
299 inode->i_op = &xiafs_dir_inode_operations;
300 if (dir->i_mode & S_ISGID)
301 inode->i_mode |= S_ISGID;
302 }
303 else if (S_ISLNK(inode->i_mode))
304 inode->i_op = &xiafs_symlink_inode_operations;
305 else if (S_ISCHR(inode->i_mode))
306 inode->i_op = &chrdev_inode_operations;
307 else if (S_ISBLK(inode->i_mode))
308 inode->i_op = &blkdev_inode_operations;
309 else if (S_ISFIFO(inode->i_mode))
310 init_fifo(inode);
311 if (S_ISBLK(mode) || S_ISCHR(mode))
312 inode->i_rdev = rdev;
313 inode->i_atime = inode->i_ctime = inode->i_atime = CURRENT_TIME;
314 inode->i_dirt = 1;
315 bh = xiafs_add_entry(dir, name, len, &de, NULL);
316 if (!bh) {
317 inode->i_nlink--;
318 inode->i_dirt = 1;
319 iput(inode);
320 iput(dir);
321 return -ENOSPC;
322 }
323 de->d_ino = inode->i_ino;
324 bh->b_dirt = 1;
325 brelse(bh);
326 iput(dir);
327 iput(inode);
328 return 0;
329 }
330
331 int xiafs_mkdir(struct inode * dir, const char * name, int len, int mode)
332 {
333 struct inode * inode;
334 struct buffer_head * bh, *dir_block;
335 struct xiafs_direct * de;
336
337 bh = xiafs_find_entry(dir,name,len,&de, NULL);
338 if (bh) {
339 brelse(bh);
340 iput(dir);
341 return -EEXIST;
342 }
343 if (dir->i_nlink > 64000) {
344 iput(dir);
345 return -EMLINK;
346 }
347 inode = xiafs_new_inode(dir);
348 if (!inode) {
349 iput(dir);
350 return -ENOSPC;
351 }
352 inode->i_op = &xiafs_dir_inode_operations;
353 inode->i_size = XIAFS_ZSIZE(dir->i_sb);
354 inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
355 dir_block = xiafs_bread(inode,0,1);
356 if (!dir_block) {
357 iput(dir);
358 inode->i_nlink--;
359 inode->i_dirt = 1;
360 iput(inode);
361 return -ENOSPC;
362 }
363 de = (struct xiafs_direct *) dir_block->b_data;
364 de->d_ino=inode->i_ino;
365 strcpy(de->d_name,".");
366 de->d_name_len=1;
367 de->d_rec_len=12;
368 de =(struct xiafs_direct *)(12 + dir_block->b_data);
369 de->d_ino = dir->i_ino;
370 strcpy(de->d_name,"..");
371 de->d_name_len=2;
372 de->d_rec_len=XIAFS_ZSIZE(dir->i_sb)-12;
373 inode->i_nlink = 2;
374 dir_block->b_dirt = 1;
375 brelse(dir_block);
376 inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
377 if (dir->i_mode & S_ISGID)
378 inode->i_mode |= S_ISGID;
379 inode->i_dirt = 1;
380 bh = xiafs_add_entry(dir, name, len, &de, NULL);
381 if (!bh) {
382 iput(dir);
383 inode->i_nlink=0;
384 iput(inode);
385 return -ENOSPC;
386 }
387 de->d_ino = inode->i_ino;
388 bh->b_dirt = 1;
389 dir->i_nlink++;
390 dir->i_dirt = 1;
391 iput(dir);
392 iput(inode);
393 brelse(bh);
394 return 0;
395 }
396
397
398
399
400 static int empty_dir(struct inode * inode)
401 {
402 int i, zones, offset;
403 struct buffer_head * bh;
404 struct xiafs_direct * de;
405
406 if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb)-1) ) {
407 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
408 return 1;
409 }
410
411 zones=inode->i_size >> XIAFS_ZSIZE_BITS(inode->i_sb);
412 for (i=0; i < zones; i++) {
413 bh = xiafs_bread(inode, i, 0);
414 if (!i) {
415 if (!bh) {
416 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
417 return 1;
418 }
419 de=(struct xiafs_direct *)bh->b_data;
420 if (de->d_ino != inode->i_ino || strcmp(".", de->d_name) ||
421 de->d_rec_len != 12 ) {
422 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
423 brelse(bh);
424 return 1;
425 }
426 de=(struct xiafs_direct *)(12 + bh->b_data);
427 if (!de->d_ino || strcmp("..", de->d_name)) {
428 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
429 brelse(bh);
430 return 1;
431 }
432 offset=de->d_rec_len+12;
433 }
434 else
435 offset = 0;
436 if (!bh)
437 continue;
438 while (offset < XIAFS_ZSIZE(inode->i_sb)) {
439 de=(struct xiafs_direct *)(bh->b_data+offset);
440 if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
441 de->d_rec_len < 12 ||
442 (char *)de+de->d_rec_len > bh->b_data+XIAFS_ZSIZE(inode->i_sb) ||
443 de->d_name_len + 8 > de->d_rec_len ||
444 de->d_name[de->d_name_len]) {
445 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
446 brelse(bh);
447 return 1;
448 }
449 if (de->d_ino) {
450 brelse(bh);
451 return 0;
452 }
453 offset+=de->d_rec_len;
454 }
455 brelse(bh);
456 }
457 return 1;
458 }
459
460 static void xiafs_rm_entry(struct xiafs_direct *de, struct xiafs_direct * de_pre)
461 {
462 if (de==de_pre) {
463 de->d_ino=0;
464 return;
465 }
466 while (de_pre->d_rec_len+(u_char *)de_pre < (u_char *)de) {
467 if (de_pre->d_rec_len < 12) {
468 printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
469 return;
470 }
471 de_pre=(struct xiafs_direct *)(de_pre->d_rec_len+(u_char *)de_pre);
472 }
473 if (de_pre->d_rec_len+(u_char *)de_pre > (u_char *)de) {
474 printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
475 return;
476 }
477 de_pre->d_rec_len+=de->d_rec_len;
478 }
479
480 int xiafs_rmdir(struct inode * dir, const char * name, int len)
481 {
482 int retval;
483 struct inode * inode;
484 struct buffer_head * bh;
485 struct xiafs_direct * de, * de_pre;
486
487 inode = NULL;
488 bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
489 retval = -ENOENT;
490 if (!bh)
491 goto end_rmdir;
492 retval = -EPERM;
493 if (!(inode = iget(dir->i_sb, de->d_ino)))
494 goto end_rmdir;
495 if ((dir->i_mode & S_ISVTX) && current->euid &&
496 inode->i_uid != current->euid)
497 goto end_rmdir;
498 if (inode->i_dev != dir->i_dev)
499 goto end_rmdir;
500 if (inode == dir)
501 goto end_rmdir;
502 if (!S_ISDIR(inode->i_mode)) {
503 retval = -ENOTDIR;
504 goto end_rmdir;
505 }
506 if (!empty_dir(inode)) {
507 retval = -ENOTEMPTY;
508 goto end_rmdir;
509 }
510 if (inode->i_count > 1) {
511 retval = -EBUSY;
512 goto end_rmdir;
513 }
514 if (inode->i_nlink != 2)
515 printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR);
516 xiafs_rm_entry(de, de_pre);
517 bh->b_dirt = 1;
518 inode->i_nlink=0;
519 inode->i_dirt=1;
520 dir->i_nlink--;
521 dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
522 dir->i_dirt=1;
523 retval = 0;
524 end_rmdir:
525 iput(dir);
526 iput(inode);
527 brelse(bh);
528 return retval;
529 }
530
531 int xiafs_unlink(struct inode * dir, const char * name, int len)
532 {
533 int retval;
534 struct inode * inode;
535 struct buffer_head * bh;
536 struct xiafs_direct * de, * de_pre;
537
538 repeat:
539 retval = -ENOENT;
540 inode = NULL;
541 bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
542 if (!bh)
543 goto end_unlink;
544 if (!(inode = iget(dir->i_sb, de->d_ino)))
545 goto end_unlink;
546 if (de->d_ino != inode->i_ino) {
547 iput(inode);
548 brelse(bh);
549 current->counter = 0;
550 schedule();
551 goto repeat;
552 }
553 retval = -EPERM;
554 if ((dir->i_mode & S_ISVTX) && !suser() &&
555 current->euid != inode->i_uid &&
556 current->euid != dir->i_uid)
557 goto end_unlink;
558 if (S_ISDIR(inode->i_mode))
559 goto end_unlink;
560 if (!inode->i_nlink) {
561 printk("XIA-FS: Deleting nonexistent file (%s %d)\n", WHERE_ERR);
562 inode->i_nlink=1;
563 }
564 xiafs_rm_entry(de, de_pre);
565 bh->b_dirt = 1;
566 dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
567 dir->i_dirt = 1;
568 inode->i_nlink--;
569 inode->i_dirt = 1;
570 retval = 0;
571 end_unlink:
572 brelse(bh);
573 iput(inode);
574 iput(dir);
575 return retval;
576 }
577
578 int xiafs_symlink(struct inode * dir, const char * name,
579 int len, const char * symname)
580 {
581 struct xiafs_direct * de;
582 struct inode * inode = NULL;
583 struct buffer_head * bh = NULL, * name_block = NULL;
584 int i;
585 char c;
586
587 bh = xiafs_find_entry(dir,name,len, &de, NULL);
588 if (bh) {
589 brelse(bh);
590 iput(dir);
591 return -EEXIST;
592 }
593 if (!(inode = xiafs_new_inode(dir))) {
594 iput(dir);
595 return -ENOSPC;
596 }
597 inode->i_mode = S_IFLNK | 0777;
598 inode->i_op = &xiafs_symlink_inode_operations;
599 name_block = xiafs_bread(inode,0,1);
600 if (!name_block) {
601 iput(dir);
602 inode->i_nlink--;
603 inode->i_dirt = 1;
604 iput(inode);
605 return -ENOSPC;
606 }
607 for (i = 0; i < BLOCK_SIZE-1 && (c=*symname++); i++)
608 name_block->b_data[i] = c;
609 name_block->b_data[i] = 0;
610 name_block->b_dirt = 1;
611 brelse(name_block);
612 inode->i_size = i;
613 inode->i_dirt = 1;
614 bh = xiafs_add_entry(dir, name, len, &de, NULL);
615 if (!bh) {
616 inode->i_nlink--;
617 inode->i_dirt = 1;
618 iput(inode);
619 iput(dir);
620 return -ENOSPC;
621 }
622 de->d_ino = inode->i_ino;
623 bh->b_dirt = 1;
624 brelse(bh);
625 iput(dir);
626 iput(inode);
627 return 0;
628 }
629
630 int xiafs_link(struct inode * oldinode, struct inode * dir,
631 const char * name, int len)
632 {
633 struct xiafs_direct * de;
634 struct buffer_head * bh;
635
636 if (S_ISDIR(oldinode->i_mode)) {
637 iput(oldinode);
638 iput(dir);
639 return -EPERM;
640 }
641 if (oldinode->i_nlink > 64000) {
642 iput(oldinode);
643 iput(dir);
644 return -EMLINK;
645 }
646 bh = xiafs_find_entry(dir, name, len, &de, NULL);
647 if (bh) {
648 brelse(bh);
649 iput(dir);
650 iput(oldinode);
651 return -EEXIST;
652 }
653 bh = xiafs_add_entry(dir, name, len, &de, NULL);
654 if (!bh) {
655 iput(dir);
656 iput(oldinode);
657 return -ENOSPC;
658 }
659 de->d_ino = oldinode->i_ino;
660 bh->b_dirt = 1;
661 brelse(bh);
662 iput(dir);
663 oldinode->i_nlink++;
664 oldinode->i_atime = oldinode->i_ctime = CURRENT_TIME;
665 oldinode->i_dirt = 1;
666 iput(oldinode);
667 return 0;
668 }
669
670 static int subdir(struct inode * new, struct inode * old)
671 {
672 int ino;
673 int result;
674
675 new->i_count++;
676 result = 0;
677 for (;;) {
678 if (new == old) {
679 result = 1;
680 break;
681 }
682 if (new->i_dev != old->i_dev)
683 break;
684 ino = new->i_ino;
685 if (xiafs_lookup(new,"..",2,&new))
686 break;
687 if (new->i_ino == ino)
688 break;
689 }
690 iput(new);
691 return result;
692 }
693
694 #define PARENT_INO(buffer) \
695 (((struct xiafs_direct *) ((u_char *)(buffer) + 12))->d_ino)
696
697
698
699
700
701
702
703
704
705
706
707 static int do_xiafs_rename(struct inode * old_dir, const char * old_name,
708 int old_len, struct inode * new_dir,
709 const char * new_name, int new_len)
710 {
711 struct inode * old_inode, * new_inode;
712 struct buffer_head * old_bh, * new_bh, * dir_bh;
713 struct xiafs_direct * old_de, * old_de_pre, * new_de, * new_de_pre;
714 int retval;
715
716 try_again:
717 old_inode = new_inode = NULL;
718 old_bh = new_bh = dir_bh = NULL;
719 old_bh = xiafs_find_entry(old_dir, old_name, old_len, &old_de, &old_de_pre);
720 retval = -ENOENT;
721 if (!old_bh)
722 goto end_rename;
723 old_inode = iget(old_dir->i_sb, old_de->d_ino);
724 if (!old_inode)
725 goto end_rename;
726 retval = -EPERM;
727 if ((old_dir->i_mode & S_ISVTX) &&
728 current->euid != old_inode->i_uid &&
729 current->euid != old_dir->i_uid && !suser())
730 goto end_rename;
731 new_bh = xiafs_find_entry(new_dir, new_name, new_len, &new_de, NULL);
732 if (new_bh) {
733 new_inode = iget(new_dir->i_sb, new_de->d_ino);
734 if (!new_inode) {
735 brelse(new_bh);
736 new_bh = NULL;
737 }
738 }
739 if (new_inode == old_inode) {
740 retval = 0;
741 goto end_rename;
742 }
743 if (new_inode && S_ISDIR(new_inode->i_mode)) {
744 retval = -EEXIST;
745 goto end_rename;
746 }
747 retval = -EPERM;
748 if (new_inode && (new_dir->i_mode & S_ISVTX) &&
749 current->euid != new_inode->i_uid &&
750 current->euid != new_dir->i_uid && !suser())
751 goto end_rename;
752 if (S_ISDIR(old_inode->i_mode)) {
753 retval = -EEXIST;
754 if (new_bh)
755 goto end_rename;
756 retval = -EACCES;
757 if (!permission(old_inode, MAY_WRITE))
758 goto end_rename;
759 retval = -EINVAL;
760 if (subdir(new_dir, old_inode))
761 goto end_rename;
762 retval = -EIO;
763 dir_bh = xiafs_bread(old_inode,0,0);
764 if (!dir_bh)
765 goto end_rename;
766 if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
767 goto end_rename;
768 retval = -EMLINK;
769 if (new_dir->i_nlink > 64000)
770 goto end_rename;
771 }
772 if (!new_bh)
773 new_bh = xiafs_add_entry(new_dir, new_name, new_len, &new_de, &new_de_pre);
774 retval = -ENOSPC;
775 if (!new_bh)
776 goto end_rename;
777
778 if ( (new_inode && (new_de->d_ino != new_inode->i_ino))
779 || (new_de->d_ino && !new_inode)
780 || (old_de->d_ino != old_inode->i_ino)) {
781 xiafs_rm_entry(new_de, new_de_pre);
782 brelse(old_bh);
783 brelse(new_bh);
784 brelse(dir_bh);
785 iput(old_inode);
786 iput(new_inode);
787 current->counter=0;
788 schedule();
789 goto try_again;
790 }
791 xiafs_rm_entry(old_de, old_de_pre);
792 new_de->d_ino = old_inode->i_ino;
793 if (new_inode) {
794 new_inode->i_nlink--;
795 new_inode->i_dirt = 1;
796 }
797 old_bh->b_dirt = 1;
798 new_bh->b_dirt = 1;
799 if (dir_bh) {
800 PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
801 dir_bh->b_dirt = 1;
802 old_dir->i_nlink--;
803 new_dir->i_nlink++;
804 old_dir->i_dirt = 1;
805 new_dir->i_dirt = 1;
806 }
807 retval = 0;
808 end_rename:
809 brelse(dir_bh);
810 brelse(old_bh);
811 brelse(new_bh);
812 iput(old_inode);
813 iput(new_inode);
814 iput(old_dir);
815 iput(new_dir);
816 return retval;
817 }
818
819
820
821
822
823
824
825
826
827
828 int xiafs_rename(struct inode * old_dir, const char * old_name, int old_len,
829 struct inode * new_dir, const char * new_name, int new_len)
830 {
831 static struct wait_queue * wait = NULL;
832 static int lock = 0;
833 int result;
834
835 while (lock)
836 sleep_on(&wait);
837 lock = 1;
838 result = do_xiafs_rename(old_dir, old_name, old_len,
839 new_dir, new_name, new_len);
840 lock = 0;
841 wake_up(&wait);
842 return result;
843 }
844
845
846
847
848