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