This source file includes following definitions.
- ext2_match
- ext2_find_entry
- ext2_lookup
- ext2_add_entry
- ext2_delete_entry
- ext2_create
- ext2_mknod
- ext2_mkdir
- empty_dir
- ext2_rmdir
- ext2_unlink
- ext2_symlink
- ext2_link
- subdir
- do_ext2_rename
- ext2_rename
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/sched.h>
14 #include <linux/ext2_fs.h>
15 #include <linux/kernel.h>
16 #include <linux/string.h>
17 #include <linux/stat.h>
18 #include <linux/fcntl.h>
19 #include <linux/errno.h>
20
21 #include <asm/segment.h>
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 static int ext2_match (int len, const char * const name,
37 struct ext2_dir_entry * de)
38 {
39 unsigned char same;
40
41 if (!de || !de->inode || len > EXT2_NAME_LEN)
42 return 0;
43
44 if (!len && de->name_len == 1 && (de->name[0] == '.') &&
45 (de->name[1] == '\0'))
46 return 1;
47 if (len != de->name_len)
48 return 0;
49 __asm__("cld\n\t"
50 "repe ; cmpsb\n\t"
51 "setz %0"
52 :"=q" (same)
53 :"S" ((long) name), "D" ((long) de->name), "c" (len)
54 :"cx", "di", "si");
55 return (int) same;
56 }
57
58
59
60
61
62
63
64
65
66
67 static struct buffer_head * ext2_find_entry (struct inode * dir,
68 const char * const name, int namelen,
69 struct ext2_dir_entry ** res_dir)
70 {
71 long offset;
72 struct buffer_head * bh;
73 struct ext2_dir_entry * de;
74 struct super_block * sb;
75 int err;
76
77 *res_dir = NULL;
78 if (!dir)
79 return NULL;
80 sb = dir->i_sb;
81 #ifdef NO_TRUNCATE
82 if (namelen > EXT2_NAME_LEN)
83 return NULL;
84 #else
85 if (namelen > EXT2_NAME_LEN)
86 namelen = EXT2_NAME_LEN;
87 #endif
88 bh = ext2_bread (dir, 0, 0, &err);
89 if (!bh)
90 return NULL;
91 offset = 0;
92 de = (struct ext2_dir_entry *) bh->b_data;
93 while (offset < dir->i_size) {
94 if (!bh || (char *)de >= sb->s_blocksize + bh->b_data) {
95 brelse (bh);
96 bh = ext2_bread (dir, offset >> EXT2_BLOCK_SIZE_BITS(sb), 0, &err);
97 if (!bh) {
98 offset += sb->s_blocksize;
99 continue;
100 }
101 de = (struct ext2_dir_entry *) bh->b_data;
102 }
103 if (! ext2_check_dir_entry ("ext2_find_entry", dir, de, bh,
104 offset)) {
105 brelse (bh);
106 return NULL;
107 }
108 if (ext2_match (namelen, name, de)) {
109 *res_dir = de;
110 return bh;
111 }
112 offset += de->rec_len;
113 de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
114 }
115 brelse (bh);
116 return NULL;
117 }
118
119 int ext2_lookup (struct inode * dir, const char * name, int len,
120 struct inode ** result)
121 {
122 int ino;
123 struct ext2_dir_entry * de;
124 struct buffer_head * bh;
125
126 *result = NULL;
127 if (!dir)
128 return -ENOENT;
129 if (!S_ISDIR(dir->i_mode)) {
130 iput (dir);
131 return -ENOENT;
132 }
133 #ifndef DONT_USE_DCACHE
134 if (!(ino = ext2_dcache_lookup (dir->i_dev, dir->i_ino, name, len))) {
135 #endif
136 if (!(bh = ext2_find_entry (dir, name, len, &de))) {
137 iput (dir);
138 return -ENOENT;
139 }
140 ino = de->inode;
141 #ifndef DONT_USE_DCACHE
142 ext2_dcache_add (dir->i_dev, dir->i_ino, de->name,
143 de->name_len, ino);
144 #endif
145 brelse (bh);
146 #ifndef DONT_USE_DCACHE
147 }
148 #endif
149 if (!(*result = iget (dir->i_sb, ino))) {
150 iput (dir);
151 return -EACCES;
152 }
153 iput (dir);
154 return 0;
155 }
156
157
158
159
160
161
162
163
164
165
166
167 static struct buffer_head * ext2_add_entry (struct inode * dir,
168 const char * name, int namelen,
169 struct ext2_dir_entry ** res_dir,
170 int *err)
171 {
172 int i;
173 long offset;
174 unsigned short rec_len;
175 struct buffer_head * bh;
176 struct ext2_dir_entry * de, * de1;
177 struct super_block * sb;
178
179 *err = -EINVAL;
180 *res_dir = NULL;
181 if (!dir)
182 return NULL;
183 sb = dir->i_sb;
184 #ifdef NO_TRUNCATE
185 if (namelen > EXT2_NAME_LEN)
186 return NULL;
187 #else
188 if (namelen > EXT2_NAME_LEN)
189 namelen = EXT2_NAME_LEN;
190 #endif
191 if (!namelen)
192 return NULL;
193
194
195 if (dir->i_size == 0)
196 {
197 *err = -ENOENT;
198 return NULL;
199 }
200 bh = ext2_bread (dir, 0, 0, err);
201 if (!bh)
202 return NULL;
203 rec_len = EXT2_DIR_REC_LEN(namelen);
204 offset = 0;
205 de = (struct ext2_dir_entry *) bh->b_data;
206 *err = -ENOSPC;
207 while (1) {
208 if ((char *)de >= sb->s_blocksize + bh->b_data) {
209 brelse (bh);
210 bh = NULL;
211 bh = ext2_bread (dir, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, err);
212 if (!bh)
213 return NULL;
214 if (dir->i_size <= offset) {
215 if (dir->i_size == 0) {
216 *err = -ENOENT;
217 return NULL;
218 }
219 #ifdef EXT2FS_DEBUG
220 printk ("ext2_add_entry: creating next block\n");
221 #endif
222 de = (struct ext2_dir_entry *) bh->b_data;
223 de->inode = 0;
224 de->rec_len = sb->s_blocksize;
225 dir->i_size = offset + sb->s_blocksize;
226 dir->i_dirt = 1;
227 dir->i_ctime = CURRENT_TIME;
228 } else {
229 #ifdef EXT2FS_DEBUG
230 printk ("ext2_add_entry: skipping to next block\n");
231 #endif
232 de = (struct ext2_dir_entry *) bh->b_data;
233 }
234 }
235 if (! ext2_check_dir_entry ("ext2_add_entry", dir, de, bh,
236 offset)) {
237 *err = -ENOENT;
238 brelse (bh);
239 return NULL;
240 }
241 if (de->inode) {
242 if (ext2_match (namelen, name, de)) {
243 *err = -EEXIST;
244 brelse (bh);
245 return NULL;
246 }
247 }
248 if ((!de->inode && de->rec_len >= rec_len) ||
249 (de->rec_len >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) {
250 offset += de->rec_len;
251 if (de->inode) {
252 de1 = (struct ext2_dir_entry *) ((char *) de +
253 EXT2_DIR_REC_LEN(de->name_len));
254 de1->rec_len = de->rec_len -
255 EXT2_DIR_REC_LEN(de->name_len);
256 de->rec_len = EXT2_DIR_REC_LEN(de->name_len);
257 de = de1;
258 }
259 de->inode = 0;
260 de->name_len = namelen;
261 for (i = 0; i < namelen ; i++)
262 de->name[i] = name [i];
263 dir->i_mtime = dir->i_ctime = CURRENT_TIME;
264 bh->b_dirt = 1;
265 *res_dir = de;
266 *err = 0;
267 return bh;
268 }
269 offset += de->rec_len;
270 de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
271 }
272 brelse (bh);
273 return NULL;
274 }
275
276
277
278
279
280 static int ext2_delete_entry (struct ext2_dir_entry * dir,
281 struct buffer_head *bh)
282 {
283 struct ext2_dir_entry * de, * pde;
284 int i;
285
286 i = 0;
287 pde = NULL;
288 de = (struct ext2_dir_entry *) bh->b_data;
289 while (i < bh->b_size) {
290 if (! ext2_check_dir_entry ("ext2_delete_entry", NULL,
291 de, bh, i))
292 return -EIO;
293 if (de == dir) {
294 if (pde)
295 pde->rec_len += dir->rec_len;
296 else
297 dir->inode = 0;
298 return 0;
299 }
300 i += de->rec_len;
301 pde = de;
302 de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
303 }
304 return -ENOENT;
305 }
306
307 int ext2_create (struct inode * dir,const char * name, int len, int mode,
308 struct inode ** result)
309 {
310 struct inode * inode;
311 struct buffer_head * bh;
312 struct ext2_dir_entry * de;
313 int err;
314
315 *result = NULL;
316 if (!dir)
317 return -ENOENT;
318 inode = ext2_new_inode (dir, mode);
319 if (!inode) {
320 iput (dir);
321 return -ENOSPC;
322 }
323 inode->i_op = &ext2_file_inode_operations;
324 inode->i_mode = mode;
325 inode->i_dirt = 1;
326 bh = ext2_add_entry (dir, name, len, &de, &err);
327 if (!bh) {
328 inode->i_nlink --;
329 inode->i_dirt = 1;
330 iput (inode);
331 iput (dir);
332 return err;
333 }
334 de->inode = inode->i_ino;
335 #ifndef DONT_USE_DCACHE
336 ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
337 de->inode);
338 #endif
339 bh->b_dirt = 1;
340 brelse (bh);
341 iput (dir);
342 *result = inode;
343 return 0;
344 }
345
346 int ext2_mknod (struct inode * dir, const char * name, int len, int mode,
347 int rdev)
348 {
349 struct inode * inode;
350 struct buffer_head * bh;
351 struct ext2_dir_entry * de;
352 int err;
353
354 if (!dir)
355 return -ENOENT;
356 bh = ext2_find_entry (dir, name, len, &de);
357 if (bh) {
358 brelse (bh);
359 iput (dir);
360 return -EEXIST;
361 }
362 inode = ext2_new_inode (dir, mode);
363 if (!inode) {
364 iput (dir);
365 return -ENOSPC;
366 }
367 inode->i_uid = current->euid;
368 inode->i_mode = mode;
369 inode->i_op = NULL;
370 if (S_ISREG(inode->i_mode))
371 inode->i_op = &ext2_file_inode_operations;
372 else if (S_ISDIR(inode->i_mode)) {
373 inode->i_op = &ext2_dir_inode_operations;
374 if (dir->i_mode & S_ISGID)
375 inode->i_mode |= S_ISGID;
376 }
377 else if (S_ISLNK(inode->i_mode))
378 inode->i_op = &ext2_symlink_inode_operations;
379 else if (S_ISCHR(inode->i_mode))
380 inode->i_op = &chrdev_inode_operations;
381 else if (S_ISBLK(inode->i_mode))
382 inode->i_op = &blkdev_inode_operations;
383 else if (S_ISFIFO(inode->i_mode))
384 init_fifo(inode);
385 if (S_ISBLK(mode) || S_ISCHR(mode))
386 inode->i_rdev = rdev;
387 inode->i_mtime = inode->i_atime = CURRENT_TIME;
388 inode->i_dirt = 1;
389 bh = ext2_add_entry (dir, name, len, &de, &err);
390 if (!bh) {
391 inode->i_nlink --;
392 inode->i_dirt = 1;
393 iput (inode);
394 iput (dir);
395 return err;
396 }
397 de->inode = inode->i_ino;
398 #ifndef DONT_USE_DCACHE
399 ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
400 de->inode);
401 #endif
402 bh->b_dirt = 1;
403 brelse (bh);
404 iput (dir);
405 iput (inode);
406 return 0;
407 }
408
409 int ext2_mkdir (struct inode * dir, const char * name, int len, int mode)
410 {
411 struct inode * inode;
412 struct buffer_head * bh, * dir_block;
413 struct ext2_dir_entry * de;
414 int err;
415
416 if (!dir)
417 return -ENOENT;
418 bh = ext2_find_entry (dir, name, len, &de);
419 if (bh) {
420 brelse (bh);
421 iput (dir);
422 return -EEXIST;
423 }
424 if (dir->i_nlink >= EXT2_LINK_MAX) {
425 iput (dir);
426 return -EMLINK;
427 }
428 inode = ext2_new_inode (dir, S_IFDIR);
429 if (!inode) {
430 iput (dir);
431 return -ENOSPC;
432 }
433 inode->i_op = &ext2_dir_inode_operations;
434 inode->i_size = inode->i_sb->s_blocksize;
435 inode->i_mtime = inode->i_atime = CURRENT_TIME;
436 dir_block = ext2_bread (inode, 0, 1, &err);
437 if (!dir_block) {
438 iput (dir);
439 inode->i_nlink --;
440 inode->i_dirt = 1;
441 iput (inode);
442 return err;
443 }
444 inode->i_blocks = inode->i_sb->s_blocksize / 512;
445 de = (struct ext2_dir_entry *) dir_block->b_data;
446 de->inode = inode->i_ino;
447 de->name_len = 1;
448 de->rec_len = EXT2_DIR_REC_LEN(de->name_len);
449 strcpy (de->name, ".");
450 de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
451 de->inode = dir->i_ino;
452 de->rec_len = inode->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1);
453 de->name_len = 2;
454 strcpy (de->name, "..");
455 inode->i_nlink = 2;
456 dir_block->b_dirt = 1;
457 brelse (dir_block);
458 inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
459 if (dir->i_mode & S_ISGID)
460 inode->i_mode |= S_ISGID;
461 inode->i_dirt = 1;
462 bh = ext2_add_entry (dir, name, len, &de, &err);
463 if (!bh) {
464 iput (dir);
465 inode->i_nlink = 0;
466 iput (inode);
467 return err;
468 }
469 de->inode = inode->i_ino;
470 #ifndef DONT_USE_DCACHE
471 ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
472 de->inode);
473 #endif
474 bh->b_dirt = 1;
475 dir->i_nlink ++;
476 dir->i_dirt = 1;
477 iput (dir);
478 iput (inode);
479 brelse (bh);
480 return 0;
481 }
482
483
484
485
486 static int empty_dir (struct inode * inode)
487 {
488 unsigned long offset;
489 struct buffer_head * bh;
490 struct ext2_dir_entry * de, * de1;
491 struct super_block * sb;
492 int err;
493
494 sb = inode->i_sb;
495 if (inode->i_size < EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) ||
496 !(bh = ext2_bread (inode, 0, 0, &err))) {
497 printk ("warning - bad directory (dev %04x, dir %d)\n",
498 inode->i_dev, inode->i_ino);
499 return 1;
500 }
501 de = (struct ext2_dir_entry *) bh->b_data;
502 de1 = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
503 if (de->inode != inode->i_ino || !de1->inode ||
504 strcmp (".", de->name) || strcmp ("..", de1->name)) {
505 printk ("warning - bad directory (dev %04x, dir %d)\n",
506 inode->i_dev, inode->i_ino);
507 return 1;
508 }
509 offset = de->rec_len + de1->rec_len;
510 de = (struct ext2_dir_entry *) ((char *) de1 + de1->rec_len);
511 while (offset < inode->i_size ) {
512 if ((void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
513 brelse (bh);
514 bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, &err);
515 if (!bh) {
516 offset += sb->s_blocksize;
517 continue;
518 }
519 de = (struct ext2_dir_entry *) bh->b_data;
520 }
521 if (! ext2_check_dir_entry ("empty_dir", inode, de, bh,
522 offset)) {
523 brelse (bh);
524 return 1;
525 }
526 if (de->inode) {
527 brelse (bh);
528 return 0;
529 }
530 offset += de->rec_len;
531 de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
532 }
533 brelse (bh);
534 return 1;
535 }
536
537 int ext2_rmdir (struct inode * dir, const char * name, int len)
538 {
539 int retval;
540 struct inode * inode;
541 struct buffer_head * bh;
542 struct ext2_dir_entry * de;
543
544 repeat:
545 if (!dir)
546 return -ENOENT;
547 inode = NULL;
548 bh = ext2_find_entry (dir, name, len, &de);
549 retval = -ENOENT;
550 if (!bh)
551 goto end_rmdir;
552 retval = -EPERM;
553 if (!(inode = iget (dir->i_sb, de->inode)))
554 goto end_rmdir;
555 if (de->inode != 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) && current->euid &&
563 inode->i_uid != current->euid)
564 goto end_rmdir;
565 if (inode->i_dev != dir->i_dev)
566 goto end_rmdir;
567 if (inode == dir)
568 goto end_rmdir;
569 if (!S_ISDIR(inode->i_mode)) {
570 retval = -ENOTDIR;
571 goto end_rmdir;
572 }
573 if (!empty_dir (inode)) {
574 retval = -ENOTEMPTY;
575 goto end_rmdir;
576 }
577 if (inode->i_count > 1 && inode->i_nlink <= 2) {
578
579
580
581
582 inode->i_size = 0;
583 #ifndef DONT_USE_DCACHE
584 ext2_dcache_remove(inode->i_dev, inode->i_ino, ".", 1);
585 ext2_dcache_remove(inode->i_dev, inode->i_ino, "..", 2);
586 #endif
587 }
588 if (inode->i_nlink != 2)
589 printk ("empty directory has nlink!=2 (%d)\n", inode->i_nlink);
590 #ifndef DONT_USE_DCACHE
591 ext2_dcache_remove (dir->i_dev, dir->i_ino, de->name, de->name_len);
592 #endif
593 retval = ext2_delete_entry (de, bh);
594 if (retval)
595 goto end_rmdir;
596 bh->b_dirt = 1;
597 inode->i_nlink = 0;
598 inode->i_dirt = 1;
599 dir->i_nlink --;
600 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
601 dir->i_dirt = 1;
602 end_rmdir:
603 iput (dir);
604 iput (inode);
605 brelse (bh);
606 return retval;
607 }
608
609 int ext2_unlink (struct inode * dir, const char * name, int len)
610 {
611 int retval;
612 struct inode * inode;
613 struct buffer_head * bh;
614 struct ext2_dir_entry * de;
615
616 repeat:
617 if (!dir)
618 return -ENOENT;
619 retval = -ENOENT;
620 inode = NULL;
621 bh = ext2_find_entry (dir, name, len, &de);
622 if (!bh)
623 goto end_unlink;
624 if (!(inode = iget (dir->i_sb, de->inode)))
625 goto end_unlink;
626 if (de->inode != inode->i_ino) {
627 iput(inode);
628 brelse(bh);
629 current->counter = 0;
630 schedule();
631 goto repeat;
632 }
633 retval = -EPERM;
634 if ((dir->i_mode & S_ISVTX) && !suser() &&
635 current->euid != inode->i_uid &&
636 current->euid != dir->i_uid)
637 goto end_unlink;
638 if (S_ISDIR(inode->i_mode))
639 goto end_unlink;
640 if (!inode->i_nlink) {
641 printk ("Deleting nonexistent file (%04x:%d), %d\n",
642 inode->i_dev, inode->i_ino, inode->i_nlink);
643 inode->i_nlink = 1;
644 }
645 #ifndef DONT_USE_DCACHE
646 ext2_dcache_remove (dir->i_dev, dir->i_ino, de->name, de->name_len);
647 #endif
648 retval = ext2_delete_entry (de, bh);
649 if (retval)
650 goto end_unlink;
651 bh->b_dirt = 1;
652 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
653 dir->i_dirt = 1;
654 inode->i_nlink --;
655 inode->i_dirt = 1;
656 inode->i_ctime = CURRENT_TIME;
657 retval = 0;
658 end_unlink:
659 brelse (bh);
660 iput (inode);
661 iput (dir);
662 return retval;
663 }
664
665 int ext2_symlink (struct inode * dir, const char * name, int len,
666 const char * symname)
667 {
668 struct ext2_dir_entry * de;
669 struct inode * inode = NULL;
670 struct buffer_head * bh = NULL, * name_block = NULL;
671 char * link;
672 int i, err;
673 int l;
674 char c;
675
676 if (!(inode = ext2_new_inode (dir, S_IFLNK))) {
677 iput (dir);
678 return -ENOSPC;
679 }
680 inode->i_mode = S_IFLNK | 0777;
681 inode->i_op = &ext2_symlink_inode_operations;
682 for (l = 0; l < inode->i_sb->s_blocksize - 1 &&
683 symname [l]; l++)
684 ;
685 if (l >= EXT2_N_BLOCKS * sizeof (unsigned long)) {
686 #ifdef EXT2FS_DEBUG
687 printk ("ext2_symlink: l=%d, normal symlink\n", l);
688 #endif
689 name_block = ext2_bread (inode, 0, 1, &err);
690 if (!name_block) {
691 iput (dir);
692 inode->i_nlink --;
693 inode->i_dirt = 1;
694 iput (inode);
695 return err;
696 }
697 link = name_block->b_data;
698 } else {
699 link = (char *) inode->u.ext2_i.i_data;
700 #ifdef EXT2FS_DEBUG
701 printk ("ext2_symlink: l=%d, fast symlink\n", l);
702 #endif
703 }
704 i = 0;
705 while (i < inode->i_sb->s_blocksize - 1 && (c = *(symname ++)))
706 link[i++] = c;
707 link[i] = 0;
708 if (name_block) {
709 name_block->b_dirt = 1;
710 brelse (name_block);
711 }
712 inode->i_size = i;
713 inode->i_dirt = 1;
714 bh = ext2_find_entry (dir, name, len, &de);
715 if (bh) {
716 inode->i_nlink --;
717 inode->i_dirt = 1;
718 iput (inode);
719 brelse (bh);
720 iput (dir);
721 return -EEXIST;
722 }
723 bh = ext2_add_entry (dir, name, len, &de, &err);
724 if (!bh) {
725 inode->i_nlink --;
726 inode->i_dirt = 1;
727 iput (inode);
728 iput (dir);
729 return err;
730 }
731 de->inode = inode->i_ino;
732 #ifndef DONT_USE_DCACHE
733 ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
734 de->inode);
735 #endif
736 bh->b_dirt = 1;
737 brelse (bh);
738 iput (dir);
739 iput (inode);
740 return 0;
741 }
742
743 int ext2_link (struct inode * oldinode, struct inode * dir,
744 const char * name, int len)
745 {
746 struct ext2_dir_entry * de;
747 struct buffer_head * bh;
748 int err;
749
750 if (S_ISDIR(oldinode->i_mode)) {
751 iput (oldinode);
752 iput (dir);
753 return -EPERM;
754 }
755 if (oldinode->i_nlink > EXT2_LINK_MAX) {
756 iput (oldinode);
757 iput (dir);
758 return -EMLINK;
759 }
760 bh = ext2_find_entry (dir, name, len, &de);
761 if (bh) {
762 brelse (bh);
763 iput (dir);
764 iput (oldinode);
765 return -EEXIST;
766 }
767 bh = ext2_add_entry (dir, name, len, &de, &err);
768 if (!bh) {
769 iput (dir);
770 iput (oldinode);
771 return err;
772 }
773 de->inode = oldinode->i_ino;
774 #ifndef DONT_USE_DCACHE
775 ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
776 de->inode);
777 #endif
778 bh->b_dirt = 1;
779 brelse (bh);
780 iput (dir);
781 oldinode->i_nlink ++;
782 oldinode->i_ctime = CURRENT_TIME;
783 oldinode->i_dirt = 1;
784 iput (oldinode);
785 return 0;
786 }
787
788 static int subdir (struct inode * new, struct inode * old)
789 {
790 int ino;
791 int result;
792
793 new->i_count ++;
794 result = 0;
795 for (;;) {
796 if (new == old) {
797 result = 1;
798 break;
799 }
800 if (new->i_dev != old->i_dev)
801 break;
802 ino = new->i_ino;
803 if (ext2_lookup (new, "..", 2, &new))
804 break;
805 if (new->i_ino == ino)
806 break;
807 }
808 iput (new);
809 return result;
810 }
811
812 #define PARENT_INO(buffer) \
813 ((struct ext2_dir_entry *) ((char *) buffer + \
814 ((struct ext2_dir_entry *) buffer)->rec_len))->inode
815
816 #define PARENT_NAME(buffer) \
817 ((struct ext2_dir_entry *) ((char *) buffer + \
818 ((struct ext2_dir_entry *) buffer)->rec_len))->name
819
820
821
822
823
824
825
826
827
828
829
830
831 static int do_ext2_rename (struct inode * old_dir, const char * old_name,
832 int old_len, struct inode * new_dir,
833 const char * new_name, int new_len)
834 {
835 struct inode * old_inode, * new_inode;
836 struct buffer_head * old_bh, * new_bh, * dir_bh;
837 struct ext2_dir_entry * old_de, * new_de;
838 int retval;
839
840 goto start_up;
841 try_again:
842 if (new_bh && new_de)
843 ext2_delete_entry(new_de, new_bh);
844 brelse (old_bh);
845 brelse (new_bh);
846 brelse (dir_bh);
847 iput (old_inode);
848 iput (new_inode);
849 current->counter = 0;
850 schedule ();
851 start_up:
852 old_inode = new_inode = NULL;
853 old_bh = new_bh = dir_bh = NULL;
854 new_de = NULL;
855 old_bh = ext2_find_entry (old_dir, old_name, old_len, &old_de);
856 retval = -ENOENT;
857 if (!old_bh)
858 goto end_rename;
859 old_inode = iget (old_dir->i_sb, old_de->inode);
860 if (!old_inode)
861 goto end_rename;
862 retval = -EPERM;
863 if ((old_dir->i_mode & S_ISVTX) &&
864 current->euid != old_inode->i_uid &&
865 current->euid != old_dir->i_uid && !suser())
866 goto end_rename;
867 new_bh = ext2_find_entry (new_dir, new_name, new_len, &new_de);
868 if (new_bh) {
869 new_inode = iget (new_dir->i_sb, new_de->inode);
870 if (!new_inode) {
871 brelse (new_bh);
872 new_bh = NULL;
873 }
874 }
875 if (new_inode == old_inode) {
876 retval = 0;
877 goto end_rename;
878 }
879 if (new_inode && S_ISDIR(new_inode->i_mode)) {
880 retval = -EISDIR;
881 if (!S_ISDIR(old_inode->i_mode))
882 goto end_rename;
883 retval = -EINVAL;
884 if (subdir (new_dir, old_inode))
885 goto end_rename;
886 retval = -ENOTEMPTY;
887 if (!empty_dir (new_inode))
888 goto end_rename;
889 retval = -EBUSY;
890 if (new_inode->i_count > 1)
891 goto end_rename;
892 }
893 retval = -EPERM;
894 if (new_inode && (new_dir->i_mode & S_ISVTX) &&
895 current->euid != new_inode->i_uid &&
896 current->euid != new_dir->i_uid && !suser())
897 goto end_rename;
898 if (S_ISDIR(old_inode->i_mode)) {
899 retval = -ENOTDIR;
900 if (new_inode && !S_ISDIR(new_inode->i_mode))
901 goto end_rename;
902 retval = -EINVAL;
903 if (subdir (new_dir, old_inode))
904 goto end_rename;
905 dir_bh = ext2_bread (old_inode, 0, 0, &retval);
906 if (!dir_bh)
907 goto end_rename;
908 if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
909 goto end_rename;
910 retval = -EMLINK;
911 if (!new_inode && new_dir->i_nlink >= EXT2_LINK_MAX)
912 goto end_rename;
913 }
914 if (!new_bh)
915 new_bh = ext2_add_entry (new_dir, new_name, new_len, &new_de,
916 &retval);
917 if (!new_bh)
918 goto end_rename;
919
920 if (new_inode && (new_de->inode != new_inode->i_ino))
921 goto try_again;
922 if (new_de->inode && !new_inode)
923 goto try_again;
924 if (old_de->inode != old_inode->i_ino)
925 goto try_again;
926
927 new_de->inode = old_inode->i_ino;
928 #ifndef DONT_USE_DCACHE
929 ext2_dcache_remove (old_dir->i_dev, old_dir->i_ino, old_de->name,
930 old_de->name_len);
931 ext2_dcache_add (new_dir->i_dev, new_dir->i_ino, new_de->name,
932 new_de->name_len, new_de->inode);
933 #endif
934 retval = ext2_delete_entry (old_de, old_bh);
935 if (retval == -ENOENT)
936 goto try_again;
937 if (retval)
938 goto end_rename;
939 if (new_inode) {
940 new_inode->i_nlink --;
941 new_inode->i_dirt = 1;
942 }
943 old_bh->b_dirt = 1;
944 new_bh->b_dirt = 1;
945 if (dir_bh) {
946 PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
947 dir_bh->b_dirt = 1;
948 old_dir->i_nlink --;
949 new_dir->i_nlink ++;
950 old_dir->i_dirt = 1;
951 new_dir->i_dirt = 1;
952 }
953 retval = 0;
954 end_rename:
955 brelse (dir_bh);
956 brelse (old_bh);
957 brelse (new_bh);
958 iput (old_inode);
959 iput (new_inode);
960 iput (old_dir);
961 iput (new_dir);
962 return retval;
963 }
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978 int ext2_rename (struct inode * old_dir, const char * old_name, int old_len,
979 struct inode * new_dir, const char * new_name, int new_len)
980 {
981 int result;
982
983 while (old_dir->i_sb->u.ext2_sb.s_rename_lock)
984 sleep_on (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
985 old_dir->i_sb->u.ext2_sb.s_rename_lock = 1;
986 result = do_ext2_rename (old_dir, old_name, old_len, new_dir,
987 new_name, new_len);
988 old_dir->i_sb->u.ext2_sb.s_rename_lock = 0;
989 wake_up (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
990 return result;
991 }