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