]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blob - lib/ext2fs/expanddir.c
Many files:
[thirdparty/e2fsprogs.git] / lib / ext2fs / expanddir.c
1 /*
2 * expand.c --- expand an ext2fs directory
3 *
4 * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
5 * under the terms of the GNU Public License.
6 */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <stdlib.h>
12 #include <linux/fs.h>
13 #include <linux/ext2_fs.h>
14
15 #include "ext2fs.h"
16
17 struct expand_dir_struct {
18 int done;
19 errcode_t err;
20 };
21
22 static int expand_dir_proc(ext2_filsys fs,
23 blk_t *blocknr,
24 int blockcnt,
25 void *private)
26 {
27 struct expand_dir_struct *es = (struct expand_dir_struct *) private;
28 blk_t new_blk;
29 static blk_t last_blk = 0;
30 char *block;
31 errcode_t retval;
32 int group;
33
34 if (*blocknr) {
35 last_blk = *blocknr;
36 return 0;
37 }
38 retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
39 if (retval) {
40 es->err = retval;
41 return BLOCK_ABORT;
42 }
43 if (blockcnt > 0) {
44 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
45 if (retval) {
46 es->err = retval;
47 return BLOCK_ABORT;
48 }
49 es->done = 1;
50 } else {
51 block = malloc(fs->blocksize);
52 if (!block) {
53 es->err = ENOMEM;
54 return BLOCK_ABORT;
55 }
56 memset(block, 0, fs->blocksize);
57 }
58 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
59 if (retval) {
60 es->err = retval;
61 return BLOCK_ABORT;
62 }
63 free(block);
64 *blocknr = new_blk;
65 ext2fs_mark_block_bitmap(fs, fs->block_map, new_blk);
66 ext2fs_mark_bb_dirty(fs);
67 group = ext2fs_group_of_blk(fs, new_blk);
68 fs->group_desc[group].bg_free_blocks_count--;
69 fs->super->s_free_blocks_count--;
70 ext2fs_mark_super_dirty(fs);
71 if (es->done)
72 return (BLOCK_CHANGED | BLOCK_ABORT);
73 else
74 return BLOCK_CHANGED;
75 }
76
77 errcode_t ext2fs_expand_dir(ext2_filsys fs, ino_t dir)
78 {
79 errcode_t retval;
80 struct expand_dir_struct es;
81 struct ext2_inode inode;
82
83 if (!(fs->flags & EXT2_FLAG_RW))
84 return EXT2_ET_RO_FILSYS;
85
86 retval = ext2fs_check_directory(fs, dir);
87 if (retval)
88 return retval;
89
90 es.done = 0;
91 es.err = 0;
92
93 retval = ext2fs_block_iterate(fs, dir, BLOCK_FLAG_APPEND,
94 0, expand_dir_proc, &es);
95
96 if (es.err)
97 return es.err;
98 if (!es.done)
99 return EXT2_ET_EXPAND_DIR_ERR;
100
101 /*
102 * Update the size and block count fields in the inode.
103 */
104 retval = ext2fs_read_inode(fs, dir, &inode);
105 if (retval)
106 return retval;
107
108 inode.i_size += fs->blocksize;
109 inode.i_blocks += fs->blocksize / 512;
110
111 retval = ext2fs_write_inode(fs, dir, &inode);
112 if (retval)
113 return retval;
114
115 return 0;
116 }