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 inode->i_dirt = 1;
360 dir_block = xiafs_bread(inode,0,1);
361 if (!dir_block) {
362 iput(dir);
363 inode->i_nlink--;
364 inode->i_dirt = 1;
365 iput(inode);
366 return -ENOSPC;
367 }
368 de = (struct xiafs_direct *) dir_block->b_data;
369 de->d_ino=inode->i_ino;
370 strcpy(de->d_name,".");
371 de->d_name_len=1;
372 de->d_rec_len=12;
373 de =(struct xiafs_direct *)(12 + dir_block->b_data);
374 de->d_ino = dir->i_ino;
375 strcpy(de->d_name,"..");
376 de->d_name_len=2;
377 de->d_rec_len=XIAFS_ZSIZE(dir->i_sb)-12;
378 inode->i_nlink = 2;
379 mark_buffer_dirty(dir_block, 1);
380 brelse(dir_block);
381 inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->fs->umask);
382 if (dir->i_mode & S_ISGID)
383 inode->i_mode |= S_ISGID;
384 inode->i_dirt = 1;
385 bh = xiafs_add_entry(dir, name, len, &de, NULL);
386 if (!bh) {
387 iput(dir);
388 inode->i_nlink=0;
389 iput(inode);
390 return -ENOSPC;
391 }
392 de->d_ino = inode->i_ino;
393 mark_buffer_dirty(bh, 1);
394 dir->i_nlink++;
395 dir->i_dirt = 1;
396 iput(dir);
397 iput(inode);
398 brelse(bh);
399 return 0;
400 }
401
402
403
404
405 static int empty_dir(struct inode * inode)
406 {
407 int i, zones, offset;
408 struct buffer_head * bh;
409 struct xiafs_direct * de;
410
411 if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb)-1) ) {
412 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
413 return 1;
414 }
415
416 zones=inode->i_size >> XIAFS_ZSIZE_BITS(inode->i_sb);
417 for (i=0; i < zones; i++) {
418 bh = xiafs_bread(inode, i, 0);
419 if (!i) {
420 if (!bh) {
421 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
422 return 1;
423 }
424 de=(struct xiafs_direct *)bh->b_data;
425 if (de->d_ino != inode->i_ino || strcmp(".", de->d_name) ||
426 de->d_rec_len != 12 ) {
427 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
428 brelse(bh);
429 return 1;
430 }
431 de=(struct xiafs_direct *)(12 + bh->b_data);
432 if (!de->d_ino || strcmp("..", de->d_name)) {
433 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
434 brelse(bh);
435 return 1;
436 }
437 offset=de->d_rec_len+12;
438 }
439 else
440 offset = 0;
441 if (!bh)
442 continue;
443 while (offset < XIAFS_ZSIZE(inode->i_sb)) {
444 de=(struct xiafs_direct *)(bh->b_data+offset);
445 if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
446 de->d_rec_len < 12 ||
447 (char *)de+de->d_rec_len > bh->b_data+XIAFS_ZSIZE(inode->i_sb) ||
448 de->d_name_len + 8 > de->d_rec_len ||
449 de->d_name[de->d_name_len]) {
450 printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
451 brelse(bh);
452 return 1;
453 }
454 if (de->d_ino) {
455 brelse(bh);
456 return 0;
457 }
458 offset+=de->d_rec_len;
459 }
460 brelse(bh);
461 }
462 return 1;
463 }
464
465 static void xiafs_rm_entry(struct xiafs_direct *de, struct xiafs_direct * de_pre)
466 {
467 if (de==de_pre) {
468 de->d_ino=0;
469 return;
470 }
471 while (de_pre->d_rec_len+(u_char *)de_pre < (u_char *)de) {
472 if (de_pre->d_rec_len < 12) {
473 printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
474 return;
475 }
476 de_pre=(struct xiafs_direct *)(de_pre->d_rec_len+(u_char *)de_pre);
477 }
478 if (de_pre->d_rec_len+(u_char *)de_pre > (u_char *)de) {
479 printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
480 return;
481 }
482 de_pre->d_rec_len+=de->d_rec_len;
483 }
484
485 int xiafs_rmdir(struct inode * dir, const char * name, int len)
486 {
487 int retval;
488 struct inode * inode;
489 struct buffer_head * bh;
490 struct xiafs_direct * de, * de_pre;
491
492 inode = NULL;
493 bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
494 retval = -ENOENT;
495 if (!bh)
496 goto end_rmdir;
497 retval = -EPERM;
498 if (!(inode = iget(dir->i_sb, de->d_ino)))
499 goto end_rmdir;
500 if ((dir->i_mode & S_ISVTX) && !fsuser() &&
501 current->fsuid != inode->i_uid &&
502 current->fsuid != dir->i_uid)
503 goto end_rmdir;
504 if (inode->i_dev != dir->i_dev)
505 goto end_rmdir;
506 if (inode == dir)
507 goto end_rmdir;
508 if (!S_ISDIR(inode->i_mode)) {
509 retval = -ENOTDIR;
510 goto end_rmdir;
511 }
512 if (!empty_dir(inode)) {
513 retval = -ENOTEMPTY;
514 goto end_rmdir;
515 }
516 if (inode->i_count > 1) {
517 retval = -EBUSY;
518 goto end_rmdir;
519 }
520 if (inode->i_nlink != 2)
521 printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR);
522 xiafs_rm_entry(de, de_pre);
523 mark_buffer_dirty(bh, 1);
524 inode->i_nlink=0;
525 inode->i_dirt=1;
526 dir->i_nlink--;
527 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
528 dir->i_dirt=1;
529 retval = 0;
530 end_rmdir:
531 iput(dir);
532 iput(inode);
533 brelse(bh);
534 return retval;
535 }
536
537 int xiafs_unlink(struct inode * dir, const char * name, int len)
538 {
539 int retval;
540 struct inode * inode;
541 struct buffer_head * bh;
542 struct xiafs_direct * de, * de_pre;
543
544 repeat:
545 retval = -ENOENT;
546 inode = NULL;
547 bh = xiafs_find_entry(dir, name, len, &de, &de_pre);
548 if (!bh)
549 goto end_unlink;
550 if (!(inode = iget(dir->i_sb, de->d_ino)))
551 goto end_unlink;
552 retval = -EPERM;
553 if (S_ISDIR(inode->i_mode))
554 goto end_unlink;
555 if (de->d_ino != inode->i_ino) {
556 iput(inode);
557 brelse(bh);
558 current->counter = 0;
559 schedule();
560 goto repeat;
561 }
562 if ((dir->i_mode & S_ISVTX) && !fsuser() &&
563 current->fsuid != inode->i_uid &&
564 current->fsuid != dir->i_uid)
565 goto end_unlink;
566 if (!inode->i_nlink) {
567 printk("XIA-FS: Deleting nonexistent file (%s %d)\n", WHERE_ERR);
568 inode->i_nlink=1;
569 }
570 xiafs_rm_entry(de, de_pre);
571 mark_buffer_dirty(bh, 1);
572 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
573 dir->i_dirt = 1;
574 inode->i_nlink--;
575 inode->i_dirt = 1;
576 retval = 0;
577 end_unlink:
578 brelse(bh);
579 iput(inode);
580 iput(dir);
581 return retval;
582 }
583
584 int xiafs_symlink(struct inode * dir, const char * name,
585 int len, const char * symname)
586 {
587 struct xiafs_direct * de;
588 struct inode * inode = NULL;
589 struct buffer_head * bh = NULL, * name_block = NULL;
590 int i;
591 char c;
592
593 bh = xiafs_find_entry(dir,name,len, &de, NULL);
594 if (bh) {
595 brelse(bh);
596 iput(dir);
597 return -EEXIST;
598 }
599 if (!(inode = xiafs_new_inode(dir))) {
600 iput(dir);
601 return -ENOSPC;
602 }
603 inode->i_mode = S_IFLNK | S_IRWXUGO;
604 inode->i_op = &xiafs_symlink_inode_operations;
605 name_block = xiafs_bread(inode,0,1);
606 if (!name_block) {
607 iput(dir);
608 inode->i_nlink--;
609 inode->i_dirt = 1;
610 iput(inode);
611 return -ENOSPC;
612 }
613 for (i = 0; i < BLOCK_SIZE-1 && (c=*symname++); i++)
614 name_block->b_data[i] = c;
615 name_block->b_data[i] = 0;
616 mark_buffer_dirty(name_block, 1);
617 brelse(name_block);
618 inode->i_size = i;
619 inode->i_dirt = 1;
620 bh = xiafs_add_entry(dir, name, len, &de, NULL);
621 if (!bh) {
622 inode->i_nlink--;
623 inode->i_dirt = 1;
624 iput(inode);
625 iput(dir);
626 return -ENOSPC;
627 }
628 de->d_ino = inode->i_ino;
629 mark_buffer_dirty(bh, 1);
630 brelse(bh);
631 iput(dir);
632 iput(inode);
633 return 0;
634 }
635
636 int xiafs_link(struct inode * oldinode, struct inode * dir,
637 const char * name, int len)
638 {
639 struct xiafs_direct * de;
640 struct buffer_head * bh;
641
642 if (S_ISDIR(oldinode->i_mode)) {
643 iput(oldinode);
644 iput(dir);
645 return -EPERM;
646 }
647 if (oldinode->i_nlink > 64000) {
648 iput(oldinode);
649 iput(dir);
650 return -EMLINK;
651 }
652 bh = xiafs_find_entry(dir, name, len, &de, NULL);
653 if (bh) {
654 brelse(bh);
655 iput(dir);
656 iput(oldinode);
657 return -EEXIST;
658 }
659 bh = xiafs_add_entry(dir, name, len, &de, NULL);
660 if (!bh) {
661 iput(dir);
662 iput(oldinode);
663 return -ENOSPC;
664 }
665 de->d_ino = oldinode->i_ino;
666 mark_buffer_dirty(bh, 1);
667 brelse(bh);
668 iput(dir);
669 oldinode->i_nlink++;
670 oldinode->i_ctime = CURRENT_TIME;
671 oldinode->i_dirt = 1;
672 iput(oldinode);
673 return 0;
674 }
675
676 static int subdir(struct inode * new_inode, struct inode * old_inode)
677 {
678 int ino;
679 int result;
680
681 new_inode->i_count++;
682 result = 0;
683 for (;;) {
684 if (new_inode == old_inode) {
685 result = 1;
686 break;
687 }
688 if (new_inode->i_dev != old_inode->i_dev)
689 break;
690 ino = new_inode->i_ino;
691 if (xiafs_lookup(new_inode,"..",2,&new_inode))
692 break;
693 if (new_inode->i_ino == ino)
694 break;
695 }
696 iput(new_inode);
697 return result;
698 }
699
700 #define PARENT_INO(buffer) \
701 (((struct xiafs_direct *) ((u_char *)(buffer) + 12))->d_ino)
702
703
704
705
706
707
708
709
710
711
712
713 static int do_xiafs_rename(struct inode * old_dir, const char * old_name,
714 int old_len, struct inode * new_dir,
715 const char * new_name, int new_len)
716 {
717 struct inode * old_inode, * new_inode;
718 struct buffer_head * old_bh, * new_bh, * dir_bh;
719 struct xiafs_direct * old_de, * old_de_pre, * new_de, * new_de_pre;
720 int retval;
721
722 try_again:
723 old_inode = new_inode = NULL;
724 old_bh = new_bh = dir_bh = NULL;
725 old_bh = xiafs_find_entry(old_dir, old_name, old_len, &old_de, &old_de_pre);
726 retval = -ENOENT;
727 if (!old_bh)
728 goto end_rename;
729 old_inode = __iget(old_dir->i_sb, old_de->d_ino, 0);
730 if (!old_inode)
731 goto end_rename;
732 retval = -EPERM;
733 if ((old_dir->i_mode & S_ISVTX) &&
734 current->fsuid != old_inode->i_uid &&
735 current->fsuid != old_dir->i_uid && !fsuser())
736 goto end_rename;
737 new_bh = xiafs_find_entry(new_dir, new_name, new_len, &new_de, NULL);
738 if (new_bh) {
739 new_inode = __iget(new_dir->i_sb, new_de->d_ino, 0);
740 if (!new_inode) {
741 brelse(new_bh);
742 new_bh = NULL;
743 }
744 }
745 if (new_inode == old_inode) {
746 retval = 0;
747 goto end_rename;
748 }
749 if (new_inode && S_ISDIR(new_inode->i_mode)) {
750 retval = -EEXIST;
751 goto end_rename;
752 }
753 retval = -EPERM;
754 if (new_inode && (new_dir->i_mode & S_ISVTX) &&
755 current->fsuid != new_inode->i_uid &&
756 current->fsuid != new_dir->i_uid && !fsuser())
757 goto end_rename;
758 if (S_ISDIR(old_inode->i_mode)) {
759 retval = -EEXIST;
760 if (new_bh)
761 goto end_rename;
762 if ((retval = permission(old_inode, MAY_WRITE)) != 0)
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 }