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