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