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