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 bh->b_dirt = 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 bh->b_dirt = 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->euid;
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 bh->b_dirt = 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 dir_block->b_dirt = 1;
379 brelse(dir_block);
380 inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->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 bh->b_dirt = 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) && current->euid &&
500 inode->i_uid != current->euid)
501 goto end_rmdir;
502 if (inode->i_dev != dir->i_dev)
503 goto end_rmdir;
504 if (inode == dir)
505 goto end_rmdir;
506 if (!S_ISDIR(inode->i_mode)) {
507 retval = -ENOTDIR;
508 goto end_rmdir;
509 }
510 if (!empty_dir(inode)) {
511 retval = -ENOTEMPTY;
512 goto end_rmdir;
513 }
514 if (inode->i_count > 1) {
515 retval = -EBUSY;
516 goto end_rmdir;
517 }
518 if (inode->i_nlink != 2)
519 printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR);
520 xiafs_rm_entry(de, de_pre);
521 bh->b_dirt = 1;
522 inode->i_nlink=0;
523 inode->i_dirt=1;
524 dir->i_nlink--;
525 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
526 dir->i_dirt=1;
527 retval = 0;
528 end_rmdir:
529 iput(dir);
530 iput(inode);
531 brelse(bh);
532 return retval;
533 }
534
535 int xiafs_unlink(struct inode * dir, const char * name, int len)
536 {
537 int retval;
538 struct inode * inode;
539 struct buffer_head * bh;
540 struct xiafs_direct * de, * de_pre;
541
542 repeat:
543 retval = -ENOENT;
544 inode = NULL;
545 bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
546 if (!bh)
547 goto end_unlink;
548 if (!(inode = iget(dir->i_sb, de->d_ino)))
549 goto end_unlink;
550 retval = -EPERM;
551 if (S_ISDIR(inode->i_mode))
552 goto end_unlink;
553 if (de->d_ino != inode->i_ino) {
554 iput(inode);
555 brelse(bh);
556 current->counter = 0;
557 schedule();
558 goto repeat;
559 }
560 if ((dir->i_mode & S_ISVTX) && !suser() &&
561 current->euid != inode->i_uid &&
562 current->euid != dir->i_uid)
563 goto end_unlink;
564 if (!inode->i_nlink) {
565 printk("XIA-FS: Deleting nonexistent file (%s %d)\n", WHERE_ERR);
566 inode->i_nlink=1;
567 }
568 xiafs_rm_entry(de, de_pre);
569 bh->b_dirt = 1;
570 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
571 dir->i_dirt = 1;
572 inode->i_nlink--;
573 inode->i_dirt = 1;
574 retval = 0;
575 end_unlink:
576 brelse(bh);
577 iput(inode);
578 iput(dir);
579 return retval;
580 }
581
582 int xiafs_symlink(struct inode * dir, const char * name,
583 int len, const char * symname)
584 {
585 struct xiafs_direct * de;
586 struct inode * inode = NULL;
587 struct buffer_head * bh = NULL, * name_block = NULL;
588 int i;
589 char c;
590
591 bh = xiafs_find_entry(dir,name,len, &de, NULL);
592 if (bh) {
593 brelse(bh);
594 iput(dir);
595 return -EEXIST;
596 }
597 if (!(inode = xiafs_new_inode(dir))) {
598 iput(dir);
599 return -ENOSPC;
600 }
601 inode->i_mode = S_IFLNK | S_IRWXUGO;
602 inode->i_op = &xiafs_symlink_inode_operations;
603 name_block = xiafs_bread(inode,0,1);
604 if (!name_block) {
605 iput(dir);
606 inode->i_nlink--;
607 inode->i_dirt = 1;
608 iput(inode);
609 return -ENOSPC;
610 }
611 for (i = 0; i < BLOCK_SIZE-1 && (c=*symname++); i++)
612 name_block->b_data[i] = c;
613 name_block->b_data[i] = 0;
614 name_block->b_dirt = 1;
615 brelse(name_block);
616 inode->i_size = i;
617 inode->i_dirt = 1;
618 bh = xiafs_add_entry(dir, name, len, &de, NULL);
619 if (!bh) {
620 inode->i_nlink--;
621 inode->i_dirt = 1;
622 iput(inode);
623 iput(dir);
624 return -ENOSPC;
625 }
626 de->d_ino = inode->i_ino;
627 bh->b_dirt = 1;
628 brelse(bh);
629 iput(dir);
630 iput(inode);
631 return 0;
632 }
633
634 int xiafs_link(struct inode * oldinode, struct inode * dir,
635 const char * name, int len)
636 {
637 struct xiafs_direct * de;
638 struct buffer_head * bh;
639
640 if (S_ISDIR(oldinode->i_mode)) {
641 iput(oldinode);
642 iput(dir);
643 return -EPERM;
644 }
645 if (oldinode->i_nlink > 64000) {
646 iput(oldinode);
647 iput(dir);
648 return -EMLINK;
649 }
650 bh = xiafs_find_entry(dir, name, len, &de, NULL);
651 if (bh) {
652 brelse(bh);
653 iput(dir);
654 iput(oldinode);
655 return -EEXIST;
656 }
657 bh = xiafs_add_entry(dir, name, len, &de, NULL);
658 if (!bh) {
659 iput(dir);
660 iput(oldinode);
661 return -ENOSPC;
662 }
663 de->d_ino = oldinode->i_ino;
664 bh->b_dirt = 1;
665 brelse(bh);
666 iput(dir);
667 oldinode->i_nlink++;
668 oldinode->i_ctime = CURRENT_TIME;
669 oldinode->i_dirt = 1;
670 iput(oldinode);
671 return 0;
672 }
673
674 static int subdir(struct inode * new_inode, struct inode * old_inode)
675 {
676 int ino;
677 int result;
678
679 new_inode->i_count++;
680 result = 0;
681 for (;;) {
682 if (new_inode == old_inode) {
683 result = 1;
684 break;
685 }
686 if (new_inode->i_dev != old_inode->i_dev)
687 break;
688 ino = new_inode->i_ino;
689 if (xiafs_lookup(new_inode,"..",2,&new_inode))
690 break;
691 if (new_inode->i_ino == ino)
692 break;
693 }
694 iput(new_inode);
695 return result;
696 }
697
698 #define PARENT_INO(buffer) \
699 (((struct xiafs_direct *) ((u_char *)(buffer) + 12))->d_ino)
700
701
702
703
704
705
706
707
708
709
710
711 static int do_xiafs_rename(struct inode * old_dir, const char * old_name,
712 int old_len, struct inode * new_dir,
713 const char * new_name, int new_len)
714 {
715 struct inode * old_inode, * new_inode;
716 struct buffer_head * old_bh, * new_bh, * dir_bh;
717 struct xiafs_direct * old_de, * old_de_pre, * new_de, * new_de_pre;
718 int retval;
719
720 try_again:
721 old_inode = new_inode = NULL;
722 old_bh = new_bh = dir_bh = NULL;
723 old_bh = xiafs_find_entry(old_dir, old_name, old_len, &old_de, &old_de_pre);
724 retval = -ENOENT;
725 if (!old_bh)
726 goto end_rename;
727 old_inode = __iget(old_dir->i_sb, old_de->d_ino, 0);
728 if (!old_inode)
729 goto end_rename;
730 retval = -EPERM;
731 if ((old_dir->i_mode & S_ISVTX) &&
732 current->euid != old_inode->i_uid &&
733 current->euid != old_dir->i_uid && !suser())
734 goto end_rename;
735 new_bh = xiafs_find_entry(new_dir, new_name, new_len, &new_de, NULL);
736 if (new_bh) {
737 new_inode = __iget(new_dir->i_sb, new_de->d_ino, 0);
738 if (!new_inode) {
739 brelse(new_bh);
740 new_bh = NULL;
741 }
742 }
743 if (new_inode == old_inode) {
744 retval = 0;
745 goto end_rename;
746 }
747 if (new_inode && S_ISDIR(new_inode->i_mode)) {
748 retval = -EEXIST;
749 goto end_rename;
750 }
751 retval = -EPERM;
752 if (new_inode && (new_dir->i_mode & S_ISVTX) &&
753 current->euid != new_inode->i_uid &&
754 current->euid != new_dir->i_uid && !suser())
755 goto end_rename;
756 if (S_ISDIR(old_inode->i_mode)) {
757 retval = -EEXIST;
758 if (new_bh)
759 goto end_rename;
760 retval = -EACCES;
761 if (!permission(old_inode, MAY_WRITE))
762 goto end_rename;
763 retval = -EINVAL;
764 if (subdir(new_dir, old_inode))
765 goto end_rename;
766 retval = -EIO;
767 dir_bh = xiafs_bread(old_inode,0,0);
768 if (!dir_bh)
769 goto end_rename;
770 if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
771 goto end_rename;
772 retval = -EMLINK;
773 if (new_dir->i_nlink > 64000)
774 goto end_rename;
775 }
776 if (!new_bh)
777 new_bh = xiafs_add_entry(new_dir, new_name, new_len, &new_de, &new_de_pre);
778 retval = -ENOSPC;
779 if (!new_bh)
780 goto end_rename;
781
782 if ( (new_inode && (new_de->d_ino != new_inode->i_ino))
783 || (new_de->d_ino && !new_inode)
784 || (old_de->d_ino != old_inode->i_ino)) {
785 xiafs_rm_entry(new_de, new_de_pre);
786 brelse(old_bh);
787 brelse(new_bh);
788 brelse(dir_bh);
789 iput(old_inode);
790 iput(new_inode);
791 current->counter=0;
792 schedule();
793 goto try_again;
794 }
795 xiafs_rm_entry(old_de, old_de_pre);
796 new_de->d_ino = old_inode->i_ino;
797 if (new_inode) {
798 new_inode->i_nlink--;
799 new_inode->i_dirt = 1;
800 }
801 old_bh->b_dirt = 1;
802 new_bh->b_dirt = 1;
803 if (dir_bh) {
804 PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
805 dir_bh->b_dirt = 1;
806 old_dir->i_nlink--;
807 new_dir->i_nlink++;
808 old_dir->i_dirt = 1;
809 new_dir->i_dirt = 1;
810 }
811 retval = 0;
812 end_rename:
813 brelse(dir_bh);
814 brelse(old_bh);
815 brelse(new_bh);
816 iput(old_inode);
817 iput(new_inode);
818 iput(old_dir);
819 iput(new_dir);
820 return retval;
821 }
822
823
824
825
826
827
828
829
830
831
832 int xiafs_rename(struct inode * old_dir, const char * old_name, int old_len,
833 struct inode * new_dir, const char * new_name, int new_len)
834 {
835 static struct wait_queue * wait = NULL;
836 static int lock = 0;
837 int result;
838
839 while (lock)
840 sleep_on(&wait);
841 lock = 1;
842 result = do_xiafs_rename(old_dir, old_name, old_len,
843 new_dir, new_name, new_len);
844 lock = 0;
845 wake_up(&wait);
846 return result;
847 }