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