Commit 715b56fe2b47e073e6f2425e0cedba0e92a4014d
1 parent
a7e8c15f71
Exists in
master
and in
49 other branches
Revert "ext4fs: Add ext4 extent cache for read operations"
This reverts commit fc0fc50f38a4d7d0554558076a79dfe8b0d78cd5. The author has asked on the mailing list that we revert this for now as it breaks write support. Reported-by: Łukasz Majewski <l.majewski@samsung.com> Signed-off-by: Tom Rini <trini@ti.com>
Showing 3 changed files with 73 additions and 130 deletions Inline Diff
fs/ext4/ext4_common.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2011 - 2012 Samsung Electronics | 2 | * (C) Copyright 2011 - 2012 Samsung Electronics |
3 | * EXT4 filesystem implementation in Uboot by | 3 | * EXT4 filesystem implementation in Uboot by |
4 | * Uma Shankar <uma.shankar@samsung.com> | 4 | * Uma Shankar <uma.shankar@samsung.com> |
5 | * Manjunatha C Achar <a.manjunatha@samsung.com> | 5 | * Manjunatha C Achar <a.manjunatha@samsung.com> |
6 | * | 6 | * |
7 | * ext4ls and ext4load : Based on ext2 ls load support in Uboot. | 7 | * ext4ls and ext4load : Based on ext2 ls load support in Uboot. |
8 | * | 8 | * |
9 | * (C) Copyright 2004 | 9 | * (C) Copyright 2004 |
10 | * esd gmbh <www.esd-electronics.com> | 10 | * esd gmbh <www.esd-electronics.com> |
11 | * Reinhard Arlt <reinhard.arlt@esd-electronics.com> | 11 | * Reinhard Arlt <reinhard.arlt@esd-electronics.com> |
12 | * | 12 | * |
13 | * based on code from grub2 fs/ext2.c and fs/fshelp.c by | 13 | * based on code from grub2 fs/ext2.c and fs/fshelp.c by |
14 | * GRUB -- GRand Unified Bootloader | 14 | * GRUB -- GRand Unified Bootloader |
15 | * Copyright (C) 2003, 2004 Free Software Foundation, Inc. | 15 | * Copyright (C) 2003, 2004 Free Software Foundation, Inc. |
16 | * | 16 | * |
17 | * ext4write : Based on generic ext4 protocol. | 17 | * ext4write : Based on generic ext4 protocol. |
18 | * | 18 | * |
19 | * SPDX-License-Identifier: GPL-2.0+ | 19 | * SPDX-License-Identifier: GPL-2.0+ |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <common.h> | 22 | #include <common.h> |
23 | #include <ext_common.h> | 23 | #include <ext_common.h> |
24 | #include <ext4fs.h> | 24 | #include <ext4fs.h> |
25 | #include <malloc.h> | 25 | #include <malloc.h> |
26 | #include <stddef.h> | 26 | #include <stddef.h> |
27 | #include <linux/stat.h> | 27 | #include <linux/stat.h> |
28 | #include <linux/time.h> | 28 | #include <linux/time.h> |
29 | #include <linux/list.h> | ||
30 | #include <asm/byteorder.h> | 29 | #include <asm/byteorder.h> |
31 | #include "ext4_common.h" | 30 | #include "ext4_common.h" |
32 | 31 | ||
33 | struct ext2_data *ext4fs_root; | 32 | struct ext2_data *ext4fs_root; |
34 | struct ext2fs_node *ext4fs_file; | 33 | struct ext2fs_node *ext4fs_file; |
35 | uint32_t *ext4fs_indir1_block; | 34 | uint32_t *ext4fs_indir1_block; |
36 | int ext4fs_indir1_size; | 35 | int ext4fs_indir1_size; |
37 | int ext4fs_indir1_blkno = -1; | 36 | int ext4fs_indir1_blkno = -1; |
38 | uint32_t *ext4fs_indir2_block; | 37 | uint32_t *ext4fs_indir2_block; |
39 | int ext4fs_indir2_size; | 38 | int ext4fs_indir2_size; |
40 | int ext4fs_indir2_blkno = -1; | 39 | int ext4fs_indir2_blkno = -1; |
41 | 40 | ||
42 | uint32_t *ext4fs_indir3_block; | 41 | uint32_t *ext4fs_indir3_block; |
43 | int ext4fs_indir3_size; | 42 | int ext4fs_indir3_size; |
44 | int ext4fs_indir3_blkno = -1; | 43 | int ext4fs_indir3_blkno = -1; |
45 | struct ext2_inode *g_parent_inode; | 44 | struct ext2_inode *g_parent_inode; |
46 | static int symlinknest; | 45 | static int symlinknest; |
47 | 46 | ||
48 | struct ext4_extent_node { | ||
49 | uint32_t block; | ||
50 | uint16_t len; | ||
51 | uint64_t start; | ||
52 | struct list_head lh; | ||
53 | }; | ||
54 | static LIST_HEAD(ext4_extent_lh); | ||
55 | |||
56 | #if defined(CONFIG_EXT4_WRITE) | 47 | #if defined(CONFIG_EXT4_WRITE) |
57 | uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n) | 48 | uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n) |
58 | { | 49 | { |
59 | uint32_t res = size / n; | 50 | uint32_t res = size / n; |
60 | if (res * n != size) | 51 | if (res * n != size) |
61 | res++; | 52 | res++; |
62 | 53 | ||
63 | return res; | 54 | return res; |
64 | } | 55 | } |
65 | 56 | ||
66 | void put_ext4(uint64_t off, void *buf, uint32_t size) | 57 | void put_ext4(uint64_t off, void *buf, uint32_t size) |
67 | { | 58 | { |
68 | uint64_t startblock; | 59 | uint64_t startblock; |
69 | uint64_t remainder; | 60 | uint64_t remainder; |
70 | unsigned char *temp_ptr = NULL; | 61 | unsigned char *temp_ptr = NULL; |
71 | struct ext_filesystem *fs = get_fs(); | 62 | struct ext_filesystem *fs = get_fs(); |
72 | int log2blksz = fs->dev_desc->log2blksz; | 63 | int log2blksz = fs->dev_desc->log2blksz; |
73 | ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf, fs->dev_desc->blksz); | 64 | ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf, fs->dev_desc->blksz); |
74 | 65 | ||
75 | startblock = off >> log2blksz; | 66 | startblock = off >> log2blksz; |
76 | startblock += part_offset; | 67 | startblock += part_offset; |
77 | remainder = off & (uint64_t)(fs->dev_desc->blksz - 1); | 68 | remainder = off & (uint64_t)(fs->dev_desc->blksz - 1); |
78 | 69 | ||
79 | if (fs->dev_desc == NULL) | 70 | if (fs->dev_desc == NULL) |
80 | return; | 71 | return; |
81 | 72 | ||
82 | if ((startblock + (size >> log2blksz)) > | 73 | if ((startblock + (size >> log2blksz)) > |
83 | (part_offset + fs->total_sect)) { | 74 | (part_offset + fs->total_sect)) { |
84 | printf("part_offset is " LBAFU "\n", part_offset); | 75 | printf("part_offset is " LBAFU "\n", part_offset); |
85 | printf("total_sector is %llu\n", fs->total_sect); | 76 | printf("total_sector is %llu\n", fs->total_sect); |
86 | printf("error: overflow occurs\n"); | 77 | printf("error: overflow occurs\n"); |
87 | return; | 78 | return; |
88 | } | 79 | } |
89 | 80 | ||
90 | if (remainder) { | 81 | if (remainder) { |
91 | if (fs->dev_desc->block_read) { | 82 | if (fs->dev_desc->block_read) { |
92 | fs->dev_desc->block_read(fs->dev_desc->dev, | 83 | fs->dev_desc->block_read(fs->dev_desc->dev, |
93 | startblock, 1, sec_buf); | 84 | startblock, 1, sec_buf); |
94 | temp_ptr = sec_buf; | 85 | temp_ptr = sec_buf; |
95 | memcpy((temp_ptr + remainder), | 86 | memcpy((temp_ptr + remainder), |
96 | (unsigned char *)buf, size); | 87 | (unsigned char *)buf, size); |
97 | fs->dev_desc->block_write(fs->dev_desc->dev, | 88 | fs->dev_desc->block_write(fs->dev_desc->dev, |
98 | startblock, 1, sec_buf); | 89 | startblock, 1, sec_buf); |
99 | } | 90 | } |
100 | } else { | 91 | } else { |
101 | if (size >> log2blksz != 0) { | 92 | if (size >> log2blksz != 0) { |
102 | fs->dev_desc->block_write(fs->dev_desc->dev, | 93 | fs->dev_desc->block_write(fs->dev_desc->dev, |
103 | startblock, | 94 | startblock, |
104 | size >> log2blksz, | 95 | size >> log2blksz, |
105 | (unsigned long *)buf); | 96 | (unsigned long *)buf); |
106 | } else { | 97 | } else { |
107 | fs->dev_desc->block_read(fs->dev_desc->dev, | 98 | fs->dev_desc->block_read(fs->dev_desc->dev, |
108 | startblock, 1, sec_buf); | 99 | startblock, 1, sec_buf); |
109 | temp_ptr = sec_buf; | 100 | temp_ptr = sec_buf; |
110 | memcpy(temp_ptr, buf, size); | 101 | memcpy(temp_ptr, buf, size); |
111 | fs->dev_desc->block_write(fs->dev_desc->dev, | 102 | fs->dev_desc->block_write(fs->dev_desc->dev, |
112 | startblock, 1, | 103 | startblock, 1, |
113 | (unsigned long *)sec_buf); | 104 | (unsigned long *)sec_buf); |
114 | } | 105 | } |
115 | } | 106 | } |
116 | } | 107 | } |
117 | 108 | ||
118 | static int _get_new_inode_no(unsigned char *buffer) | 109 | static int _get_new_inode_no(unsigned char *buffer) |
119 | { | 110 | { |
120 | struct ext_filesystem *fs = get_fs(); | 111 | struct ext_filesystem *fs = get_fs(); |
121 | unsigned char input; | 112 | unsigned char input; |
122 | int operand, status; | 113 | int operand, status; |
123 | int count = 1; | 114 | int count = 1; |
124 | int j = 0; | 115 | int j = 0; |
125 | 116 | ||
126 | /* get the blocksize of the filesystem */ | 117 | /* get the blocksize of the filesystem */ |
127 | unsigned char *ptr = buffer; | 118 | unsigned char *ptr = buffer; |
128 | while (*ptr == 255) { | 119 | while (*ptr == 255) { |
129 | ptr++; | 120 | ptr++; |
130 | count += 8; | 121 | count += 8; |
131 | if (count > ext4fs_root->sblock.inodes_per_group) | 122 | if (count > ext4fs_root->sblock.inodes_per_group) |
132 | return -1; | 123 | return -1; |
133 | } | 124 | } |
134 | 125 | ||
135 | for (j = 0; j < fs->blksz; j++) { | 126 | for (j = 0; j < fs->blksz; j++) { |
136 | input = *ptr; | 127 | input = *ptr; |
137 | int i = 0; | 128 | int i = 0; |
138 | while (i <= 7) { | 129 | while (i <= 7) { |
139 | operand = 1 << i; | 130 | operand = 1 << i; |
140 | status = input & operand; | 131 | status = input & operand; |
141 | if (status) { | 132 | if (status) { |
142 | i++; | 133 | i++; |
143 | count++; | 134 | count++; |
144 | } else { | 135 | } else { |
145 | *ptr |= operand; | 136 | *ptr |= operand; |
146 | return count; | 137 | return count; |
147 | } | 138 | } |
148 | } | 139 | } |
149 | ptr = ptr + 1; | 140 | ptr = ptr + 1; |
150 | } | 141 | } |
151 | 142 | ||
152 | return -1; | 143 | return -1; |
153 | } | 144 | } |
154 | 145 | ||
155 | static int _get_new_blk_no(unsigned char *buffer) | 146 | static int _get_new_blk_no(unsigned char *buffer) |
156 | { | 147 | { |
157 | unsigned char input; | 148 | unsigned char input; |
158 | int operand, status; | 149 | int operand, status; |
159 | int count = 0; | 150 | int count = 0; |
160 | int j = 0; | 151 | int j = 0; |
161 | unsigned char *ptr = buffer; | 152 | unsigned char *ptr = buffer; |
162 | struct ext_filesystem *fs = get_fs(); | 153 | struct ext_filesystem *fs = get_fs(); |
163 | 154 | ||
164 | if (fs->blksz != 1024) | 155 | if (fs->blksz != 1024) |
165 | count = 0; | 156 | count = 0; |
166 | else | 157 | else |
167 | count = 1; | 158 | count = 1; |
168 | 159 | ||
169 | while (*ptr == 255) { | 160 | while (*ptr == 255) { |
170 | ptr++; | 161 | ptr++; |
171 | count += 8; | 162 | count += 8; |
172 | if (count == (fs->blksz * 8)) | 163 | if (count == (fs->blksz * 8)) |
173 | return -1; | 164 | return -1; |
174 | } | 165 | } |
175 | 166 | ||
176 | for (j = 0; j < fs->blksz; j++) { | 167 | for (j = 0; j < fs->blksz; j++) { |
177 | input = *ptr; | 168 | input = *ptr; |
178 | int i = 0; | 169 | int i = 0; |
179 | while (i <= 7) { | 170 | while (i <= 7) { |
180 | operand = 1 << i; | 171 | operand = 1 << i; |
181 | status = input & operand; | 172 | status = input & operand; |
182 | if (status) { | 173 | if (status) { |
183 | i++; | 174 | i++; |
184 | count++; | 175 | count++; |
185 | } else { | 176 | } else { |
186 | *ptr |= operand; | 177 | *ptr |= operand; |
187 | return count; | 178 | return count; |
188 | } | 179 | } |
189 | } | 180 | } |
190 | ptr = ptr + 1; | 181 | ptr = ptr + 1; |
191 | } | 182 | } |
192 | 183 | ||
193 | return -1; | 184 | return -1; |
194 | } | 185 | } |
195 | 186 | ||
196 | int ext4fs_set_block_bmap(long int blockno, unsigned char *buffer, int index) | 187 | int ext4fs_set_block_bmap(long int blockno, unsigned char *buffer, int index) |
197 | { | 188 | { |
198 | int i, remainder, status; | 189 | int i, remainder, status; |
199 | unsigned char *ptr = buffer; | 190 | unsigned char *ptr = buffer; |
200 | unsigned char operand; | 191 | unsigned char operand; |
201 | i = blockno / 8; | 192 | i = blockno / 8; |
202 | remainder = blockno % 8; | 193 | remainder = blockno % 8; |
203 | int blocksize = EXT2_BLOCK_SIZE(ext4fs_root); | 194 | int blocksize = EXT2_BLOCK_SIZE(ext4fs_root); |
204 | 195 | ||
205 | i = i - (index * blocksize); | 196 | i = i - (index * blocksize); |
206 | if (blocksize != 1024) { | 197 | if (blocksize != 1024) { |
207 | ptr = ptr + i; | 198 | ptr = ptr + i; |
208 | operand = 1 << remainder; | 199 | operand = 1 << remainder; |
209 | status = *ptr & operand; | 200 | status = *ptr & operand; |
210 | if (status) | 201 | if (status) |
211 | return -1; | 202 | return -1; |
212 | 203 | ||
213 | *ptr = *ptr | operand; | 204 | *ptr = *ptr | operand; |
214 | return 0; | 205 | return 0; |
215 | } else { | 206 | } else { |
216 | if (remainder == 0) { | 207 | if (remainder == 0) { |
217 | ptr = ptr + i - 1; | 208 | ptr = ptr + i - 1; |
218 | operand = (1 << 7); | 209 | operand = (1 << 7); |
219 | } else { | 210 | } else { |
220 | ptr = ptr + i; | 211 | ptr = ptr + i; |
221 | operand = (1 << (remainder - 1)); | 212 | operand = (1 << (remainder - 1)); |
222 | } | 213 | } |
223 | status = *ptr & operand; | 214 | status = *ptr & operand; |
224 | if (status) | 215 | if (status) |
225 | return -1; | 216 | return -1; |
226 | 217 | ||
227 | *ptr = *ptr | operand; | 218 | *ptr = *ptr | operand; |
228 | return 0; | 219 | return 0; |
229 | } | 220 | } |
230 | } | 221 | } |
231 | 222 | ||
232 | void ext4fs_reset_block_bmap(long int blockno, unsigned char *buffer, int index) | 223 | void ext4fs_reset_block_bmap(long int blockno, unsigned char *buffer, int index) |
233 | { | 224 | { |
234 | int i, remainder, status; | 225 | int i, remainder, status; |
235 | unsigned char *ptr = buffer; | 226 | unsigned char *ptr = buffer; |
236 | unsigned char operand; | 227 | unsigned char operand; |
237 | i = blockno / 8; | 228 | i = blockno / 8; |
238 | remainder = blockno % 8; | 229 | remainder = blockno % 8; |
239 | int blocksize = EXT2_BLOCK_SIZE(ext4fs_root); | 230 | int blocksize = EXT2_BLOCK_SIZE(ext4fs_root); |
240 | 231 | ||
241 | i = i - (index * blocksize); | 232 | i = i - (index * blocksize); |
242 | if (blocksize != 1024) { | 233 | if (blocksize != 1024) { |
243 | ptr = ptr + i; | 234 | ptr = ptr + i; |
244 | operand = (1 << remainder); | 235 | operand = (1 << remainder); |
245 | status = *ptr & operand; | 236 | status = *ptr & operand; |
246 | if (status) | 237 | if (status) |
247 | *ptr = *ptr & ~(operand); | 238 | *ptr = *ptr & ~(operand); |
248 | } else { | 239 | } else { |
249 | if (remainder == 0) { | 240 | if (remainder == 0) { |
250 | ptr = ptr + i - 1; | 241 | ptr = ptr + i - 1; |
251 | operand = (1 << 7); | 242 | operand = (1 << 7); |
252 | } else { | 243 | } else { |
253 | ptr = ptr + i; | 244 | ptr = ptr + i; |
254 | operand = (1 << (remainder - 1)); | 245 | operand = (1 << (remainder - 1)); |
255 | } | 246 | } |
256 | status = *ptr & operand; | 247 | status = *ptr & operand; |
257 | if (status) | 248 | if (status) |
258 | *ptr = *ptr & ~(operand); | 249 | *ptr = *ptr & ~(operand); |
259 | } | 250 | } |
260 | } | 251 | } |
261 | 252 | ||
262 | int ext4fs_set_inode_bmap(int inode_no, unsigned char *buffer, int index) | 253 | int ext4fs_set_inode_bmap(int inode_no, unsigned char *buffer, int index) |
263 | { | 254 | { |
264 | int i, remainder, status; | 255 | int i, remainder, status; |
265 | unsigned char *ptr = buffer; | 256 | unsigned char *ptr = buffer; |
266 | unsigned char operand; | 257 | unsigned char operand; |
267 | 258 | ||
268 | inode_no -= (index * ext4fs_root->sblock.inodes_per_group); | 259 | inode_no -= (index * ext4fs_root->sblock.inodes_per_group); |
269 | i = inode_no / 8; | 260 | i = inode_no / 8; |
270 | remainder = inode_no % 8; | 261 | remainder = inode_no % 8; |
271 | if (remainder == 0) { | 262 | if (remainder == 0) { |
272 | ptr = ptr + i - 1; | 263 | ptr = ptr + i - 1; |
273 | operand = (1 << 7); | 264 | operand = (1 << 7); |
274 | } else { | 265 | } else { |
275 | ptr = ptr + i; | 266 | ptr = ptr + i; |
276 | operand = (1 << (remainder - 1)); | 267 | operand = (1 << (remainder - 1)); |
277 | } | 268 | } |
278 | status = *ptr & operand; | 269 | status = *ptr & operand; |
279 | if (status) | 270 | if (status) |
280 | return -1; | 271 | return -1; |
281 | 272 | ||
282 | *ptr = *ptr | operand; | 273 | *ptr = *ptr | operand; |
283 | 274 | ||
284 | return 0; | 275 | return 0; |
285 | } | 276 | } |
286 | 277 | ||
287 | void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index) | 278 | void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index) |
288 | { | 279 | { |
289 | int i, remainder, status; | 280 | int i, remainder, status; |
290 | unsigned char *ptr = buffer; | 281 | unsigned char *ptr = buffer; |
291 | unsigned char operand; | 282 | unsigned char operand; |
292 | 283 | ||
293 | inode_no -= (index * ext4fs_root->sblock.inodes_per_group); | 284 | inode_no -= (index * ext4fs_root->sblock.inodes_per_group); |
294 | i = inode_no / 8; | 285 | i = inode_no / 8; |
295 | remainder = inode_no % 8; | 286 | remainder = inode_no % 8; |
296 | if (remainder == 0) { | 287 | if (remainder == 0) { |
297 | ptr = ptr + i - 1; | 288 | ptr = ptr + i - 1; |
298 | operand = (1 << 7); | 289 | operand = (1 << 7); |
299 | } else { | 290 | } else { |
300 | ptr = ptr + i; | 291 | ptr = ptr + i; |
301 | operand = (1 << (remainder - 1)); | 292 | operand = (1 << (remainder - 1)); |
302 | } | 293 | } |
303 | status = *ptr & operand; | 294 | status = *ptr & operand; |
304 | if (status) | 295 | if (status) |
305 | *ptr = *ptr & ~(operand); | 296 | *ptr = *ptr & ~(operand); |
306 | } | 297 | } |
307 | 298 | ||
308 | int ext4fs_checksum_update(unsigned int i) | 299 | int ext4fs_checksum_update(unsigned int i) |
309 | { | 300 | { |
310 | struct ext2_block_group *desc; | 301 | struct ext2_block_group *desc; |
311 | struct ext_filesystem *fs = get_fs(); | 302 | struct ext_filesystem *fs = get_fs(); |
312 | __u16 crc = 0; | 303 | __u16 crc = 0; |
313 | 304 | ||
314 | desc = (struct ext2_block_group *)&fs->bgd[i]; | 305 | desc = (struct ext2_block_group *)&fs->bgd[i]; |
315 | if (fs->sb->feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) { | 306 | if (fs->sb->feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) { |
316 | int offset = offsetof(struct ext2_block_group, bg_checksum); | 307 | int offset = offsetof(struct ext2_block_group, bg_checksum); |
317 | 308 | ||
318 | crc = ext2fs_crc16(~0, fs->sb->unique_id, | 309 | crc = ext2fs_crc16(~0, fs->sb->unique_id, |
319 | sizeof(fs->sb->unique_id)); | 310 | sizeof(fs->sb->unique_id)); |
320 | crc = ext2fs_crc16(crc, &i, sizeof(i)); | 311 | crc = ext2fs_crc16(crc, &i, sizeof(i)); |
321 | crc = ext2fs_crc16(crc, desc, offset); | 312 | crc = ext2fs_crc16(crc, desc, offset); |
322 | offset += sizeof(desc->bg_checksum); /* skip checksum */ | 313 | offset += sizeof(desc->bg_checksum); /* skip checksum */ |
323 | assert(offset == sizeof(*desc)); | 314 | assert(offset == sizeof(*desc)); |
324 | } | 315 | } |
325 | 316 | ||
326 | return crc; | 317 | return crc; |
327 | } | 318 | } |
328 | 319 | ||
329 | static int check_void_in_dentry(struct ext2_dirent *dir, char *filename) | 320 | static int check_void_in_dentry(struct ext2_dirent *dir, char *filename) |
330 | { | 321 | { |
331 | int dentry_length; | 322 | int dentry_length; |
332 | int sizeof_void_space; | 323 | int sizeof_void_space; |
333 | int new_entry_byte_reqd; | 324 | int new_entry_byte_reqd; |
334 | short padding_factor = 0; | 325 | short padding_factor = 0; |
335 | 326 | ||
336 | if (dir->namelen % 4 != 0) | 327 | if (dir->namelen % 4 != 0) |
337 | padding_factor = 4 - (dir->namelen % 4); | 328 | padding_factor = 4 - (dir->namelen % 4); |
338 | 329 | ||
339 | dentry_length = sizeof(struct ext2_dirent) + | 330 | dentry_length = sizeof(struct ext2_dirent) + |
340 | dir->namelen + padding_factor; | 331 | dir->namelen + padding_factor; |
341 | sizeof_void_space = dir->direntlen - dentry_length; | 332 | sizeof_void_space = dir->direntlen - dentry_length; |
342 | if (sizeof_void_space == 0) | 333 | if (sizeof_void_space == 0) |
343 | return 0; | 334 | return 0; |
344 | 335 | ||
345 | padding_factor = 0; | 336 | padding_factor = 0; |
346 | if (strlen(filename) % 4 != 0) | 337 | if (strlen(filename) % 4 != 0) |
347 | padding_factor = 4 - (strlen(filename) % 4); | 338 | padding_factor = 4 - (strlen(filename) % 4); |
348 | 339 | ||
349 | new_entry_byte_reqd = strlen(filename) + | 340 | new_entry_byte_reqd = strlen(filename) + |
350 | sizeof(struct ext2_dirent) + padding_factor; | 341 | sizeof(struct ext2_dirent) + padding_factor; |
351 | if (sizeof_void_space >= new_entry_byte_reqd) { | 342 | if (sizeof_void_space >= new_entry_byte_reqd) { |
352 | dir->direntlen = dentry_length; | 343 | dir->direntlen = dentry_length; |
353 | return sizeof_void_space; | 344 | return sizeof_void_space; |
354 | } | 345 | } |
355 | 346 | ||
356 | return 0; | 347 | return 0; |
357 | } | 348 | } |
358 | 349 | ||
359 | void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type) | 350 | void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type) |
360 | { | 351 | { |
361 | unsigned int *zero_buffer = NULL; | 352 | unsigned int *zero_buffer = NULL; |
362 | char *root_first_block_buffer = NULL; | 353 | char *root_first_block_buffer = NULL; |
363 | int direct_blk_idx; | 354 | int direct_blk_idx; |
364 | long int root_blknr; | 355 | long int root_blknr; |
365 | long int first_block_no_of_root = 0; | 356 | long int first_block_no_of_root = 0; |
366 | long int previous_blknr = -1; | 357 | long int previous_blknr = -1; |
367 | int totalbytes = 0; | 358 | int totalbytes = 0; |
368 | short int padding_factor = 0; | 359 | short int padding_factor = 0; |
369 | unsigned int new_entry_byte_reqd; | 360 | unsigned int new_entry_byte_reqd; |
370 | unsigned int last_entry_dirlen; | 361 | unsigned int last_entry_dirlen; |
371 | int sizeof_void_space = 0; | 362 | int sizeof_void_space = 0; |
372 | int templength = 0; | 363 | int templength = 0; |
373 | int inodeno; | 364 | int inodeno; |
374 | int status; | 365 | int status; |
375 | struct ext_filesystem *fs = get_fs(); | 366 | struct ext_filesystem *fs = get_fs(); |
376 | /* directory entry */ | 367 | /* directory entry */ |
377 | struct ext2_dirent *dir; | 368 | struct ext2_dirent *dir; |
378 | char *temp_dir = NULL; | 369 | char *temp_dir = NULL; |
379 | 370 | ||
380 | zero_buffer = zalloc(fs->blksz); | 371 | zero_buffer = zalloc(fs->blksz); |
381 | if (!zero_buffer) { | 372 | if (!zero_buffer) { |
382 | printf("No Memory\n"); | 373 | printf("No Memory\n"); |
383 | return; | 374 | return; |
384 | } | 375 | } |
385 | root_first_block_buffer = zalloc(fs->blksz); | 376 | root_first_block_buffer = zalloc(fs->blksz); |
386 | if (!root_first_block_buffer) { | 377 | if (!root_first_block_buffer) { |
387 | free(zero_buffer); | 378 | free(zero_buffer); |
388 | printf("No Memory\n"); | 379 | printf("No Memory\n"); |
389 | return; | 380 | return; |
390 | } | 381 | } |
391 | restart: | 382 | restart: |
392 | 383 | ||
393 | /* read the block no allocated to a file */ | 384 | /* read the block no allocated to a file */ |
394 | for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; | 385 | for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; |
395 | direct_blk_idx++) { | 386 | direct_blk_idx++) { |
396 | root_blknr = read_allocated_block(g_parent_inode, | 387 | root_blknr = read_allocated_block(g_parent_inode, |
397 | direct_blk_idx); | 388 | direct_blk_idx); |
398 | if (root_blknr == 0) { | 389 | if (root_blknr == 0) { |
399 | first_block_no_of_root = previous_blknr; | 390 | first_block_no_of_root = previous_blknr; |
400 | break; | 391 | break; |
401 | } | 392 | } |
402 | previous_blknr = root_blknr; | 393 | previous_blknr = root_blknr; |
403 | } | 394 | } |
404 | 395 | ||
405 | status = ext4fs_devread((lbaint_t)first_block_no_of_root | 396 | status = ext4fs_devread((lbaint_t)first_block_no_of_root |
406 | * fs->sect_perblk, | 397 | * fs->sect_perblk, |
407 | 0, fs->blksz, root_first_block_buffer); | 398 | 0, fs->blksz, root_first_block_buffer); |
408 | if (status == 0) | 399 | if (status == 0) |
409 | goto fail; | 400 | goto fail; |
410 | 401 | ||
411 | if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root)) | 402 | if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root)) |
412 | goto fail; | 403 | goto fail; |
413 | dir = (struct ext2_dirent *)root_first_block_buffer; | 404 | dir = (struct ext2_dirent *)root_first_block_buffer; |
414 | totalbytes = 0; | 405 | totalbytes = 0; |
415 | while (dir->direntlen > 0) { | 406 | while (dir->direntlen > 0) { |
416 | /* | 407 | /* |
417 | * blocksize-totalbytes because last directory length | 408 | * blocksize-totalbytes because last directory length |
418 | * i.e. dir->direntlen is free availble space in the | 409 | * i.e. dir->direntlen is free availble space in the |
419 | * block that means it is a last entry of directory | 410 | * block that means it is a last entry of directory |
420 | * entry | 411 | * entry |
421 | */ | 412 | */ |
422 | 413 | ||
423 | /* traversing the each directory entry */ | 414 | /* traversing the each directory entry */ |
424 | if (fs->blksz - totalbytes == dir->direntlen) { | 415 | if (fs->blksz - totalbytes == dir->direntlen) { |
425 | if (strlen(filename) % 4 != 0) | 416 | if (strlen(filename) % 4 != 0) |
426 | padding_factor = 4 - (strlen(filename) % 4); | 417 | padding_factor = 4 - (strlen(filename) % 4); |
427 | 418 | ||
428 | new_entry_byte_reqd = strlen(filename) + | 419 | new_entry_byte_reqd = strlen(filename) + |
429 | sizeof(struct ext2_dirent) + padding_factor; | 420 | sizeof(struct ext2_dirent) + padding_factor; |
430 | padding_factor = 0; | 421 | padding_factor = 0; |
431 | /* | 422 | /* |
432 | * update last directory entry length to its | 423 | * update last directory entry length to its |
433 | * length because we are creating new directory | 424 | * length because we are creating new directory |
434 | * entry | 425 | * entry |
435 | */ | 426 | */ |
436 | if (dir->namelen % 4 != 0) | 427 | if (dir->namelen % 4 != 0) |
437 | padding_factor = 4 - (dir->namelen % 4); | 428 | padding_factor = 4 - (dir->namelen % 4); |
438 | 429 | ||
439 | last_entry_dirlen = dir->namelen + | 430 | last_entry_dirlen = dir->namelen + |
440 | sizeof(struct ext2_dirent) + padding_factor; | 431 | sizeof(struct ext2_dirent) + padding_factor; |
441 | if ((fs->blksz - totalbytes - last_entry_dirlen) < | 432 | if ((fs->blksz - totalbytes - last_entry_dirlen) < |
442 | new_entry_byte_reqd) { | 433 | new_entry_byte_reqd) { |
443 | printf("1st Block Full:Allocate new block\n"); | 434 | printf("1st Block Full:Allocate new block\n"); |
444 | 435 | ||
445 | if (direct_blk_idx == INDIRECT_BLOCKS - 1) { | 436 | if (direct_blk_idx == INDIRECT_BLOCKS - 1) { |
446 | printf("Directory exceeds limit\n"); | 437 | printf("Directory exceeds limit\n"); |
447 | goto fail; | 438 | goto fail; |
448 | } | 439 | } |
449 | g_parent_inode->b.blocks.dir_blocks | 440 | g_parent_inode->b.blocks.dir_blocks |
450 | [direct_blk_idx] = ext4fs_get_new_blk_no(); | 441 | [direct_blk_idx] = ext4fs_get_new_blk_no(); |
451 | if (g_parent_inode->b.blocks.dir_blocks | 442 | if (g_parent_inode->b.blocks.dir_blocks |
452 | [direct_blk_idx] == -1) { | 443 | [direct_blk_idx] == -1) { |
453 | printf("no block left to assign\n"); | 444 | printf("no block left to assign\n"); |
454 | goto fail; | 445 | goto fail; |
455 | } | 446 | } |
456 | put_ext4(((uint64_t) | 447 | put_ext4(((uint64_t) |
457 | ((uint64_t)g_parent_inode->b. | 448 | ((uint64_t)g_parent_inode->b. |
458 | blocks.dir_blocks[direct_blk_idx] * | 449 | blocks.dir_blocks[direct_blk_idx] * |
459 | (uint64_t)fs->blksz)), zero_buffer, fs->blksz); | 450 | (uint64_t)fs->blksz)), zero_buffer, fs->blksz); |
460 | g_parent_inode->size = | 451 | g_parent_inode->size = |
461 | g_parent_inode->size + fs->blksz; | 452 | g_parent_inode->size + fs->blksz; |
462 | g_parent_inode->blockcnt = | 453 | g_parent_inode->blockcnt = |
463 | g_parent_inode->blockcnt + fs->sect_perblk; | 454 | g_parent_inode->blockcnt + fs->sect_perblk; |
464 | if (ext4fs_put_metadata | 455 | if (ext4fs_put_metadata |
465 | (root_first_block_buffer, | 456 | (root_first_block_buffer, |
466 | first_block_no_of_root)) | 457 | first_block_no_of_root)) |
467 | goto fail; | 458 | goto fail; |
468 | goto restart; | 459 | goto restart; |
469 | } | 460 | } |
470 | dir->direntlen = last_entry_dirlen; | 461 | dir->direntlen = last_entry_dirlen; |
471 | break; | 462 | break; |
472 | } | 463 | } |
473 | 464 | ||
474 | templength = dir->direntlen; | 465 | templength = dir->direntlen; |
475 | totalbytes = totalbytes + templength; | 466 | totalbytes = totalbytes + templength; |
476 | sizeof_void_space = check_void_in_dentry(dir, filename); | 467 | sizeof_void_space = check_void_in_dentry(dir, filename); |
477 | if (sizeof_void_space) | 468 | if (sizeof_void_space) |
478 | break; | 469 | break; |
479 | 470 | ||
480 | dir = (struct ext2_dirent *)((char *)dir + templength); | 471 | dir = (struct ext2_dirent *)((char *)dir + templength); |
481 | } | 472 | } |
482 | 473 | ||
483 | /* make a pointer ready for creating next directory entry */ | 474 | /* make a pointer ready for creating next directory entry */ |
484 | templength = dir->direntlen; | 475 | templength = dir->direntlen; |
485 | totalbytes = totalbytes + templength; | 476 | totalbytes = totalbytes + templength; |
486 | dir = (struct ext2_dirent *)((char *)dir + templength); | 477 | dir = (struct ext2_dirent *)((char *)dir + templength); |
487 | 478 | ||
488 | /* get the next available inode number */ | 479 | /* get the next available inode number */ |
489 | inodeno = ext4fs_get_new_inode_no(); | 480 | inodeno = ext4fs_get_new_inode_no(); |
490 | if (inodeno == -1) { | 481 | if (inodeno == -1) { |
491 | printf("no inode left to assign\n"); | 482 | printf("no inode left to assign\n"); |
492 | goto fail; | 483 | goto fail; |
493 | } | 484 | } |
494 | dir->inode = inodeno; | 485 | dir->inode = inodeno; |
495 | if (sizeof_void_space) | 486 | if (sizeof_void_space) |
496 | dir->direntlen = sizeof_void_space; | 487 | dir->direntlen = sizeof_void_space; |
497 | else | 488 | else |
498 | dir->direntlen = fs->blksz - totalbytes; | 489 | dir->direntlen = fs->blksz - totalbytes; |
499 | 490 | ||
500 | dir->namelen = strlen(filename); | 491 | dir->namelen = strlen(filename); |
501 | dir->filetype = FILETYPE_REG; /* regular file */ | 492 | dir->filetype = FILETYPE_REG; /* regular file */ |
502 | temp_dir = (char *)dir; | 493 | temp_dir = (char *)dir; |
503 | temp_dir = temp_dir + sizeof(struct ext2_dirent); | 494 | temp_dir = temp_dir + sizeof(struct ext2_dirent); |
504 | memcpy(temp_dir, filename, strlen(filename)); | 495 | memcpy(temp_dir, filename, strlen(filename)); |
505 | 496 | ||
506 | *p_ino = inodeno; | 497 | *p_ino = inodeno; |
507 | 498 | ||
508 | /* update or write the 1st block of root inode */ | 499 | /* update or write the 1st block of root inode */ |
509 | if (ext4fs_put_metadata(root_first_block_buffer, | 500 | if (ext4fs_put_metadata(root_first_block_buffer, |
510 | first_block_no_of_root)) | 501 | first_block_no_of_root)) |
511 | goto fail; | 502 | goto fail; |
512 | 503 | ||
513 | fail: | 504 | fail: |
514 | free(zero_buffer); | 505 | free(zero_buffer); |
515 | free(root_first_block_buffer); | 506 | free(root_first_block_buffer); |
516 | } | 507 | } |
517 | 508 | ||
518 | static int search_dir(struct ext2_inode *parent_inode, char *dirname) | 509 | static int search_dir(struct ext2_inode *parent_inode, char *dirname) |
519 | { | 510 | { |
520 | int status; | 511 | int status; |
521 | int inodeno; | 512 | int inodeno; |
522 | int totalbytes; | 513 | int totalbytes; |
523 | int templength; | 514 | int templength; |
524 | int direct_blk_idx; | 515 | int direct_blk_idx; |
525 | long int blknr; | 516 | long int blknr; |
526 | int found = 0; | 517 | int found = 0; |
527 | char *ptr = NULL; | 518 | char *ptr = NULL; |
528 | unsigned char *block_buffer = NULL; | 519 | unsigned char *block_buffer = NULL; |
529 | struct ext2_dirent *dir = NULL; | 520 | struct ext2_dirent *dir = NULL; |
530 | struct ext2_dirent *previous_dir = NULL; | 521 | struct ext2_dirent *previous_dir = NULL; |
531 | struct ext_filesystem *fs = get_fs(); | 522 | struct ext_filesystem *fs = get_fs(); |
532 | 523 | ||
533 | /* read the block no allocated to a file */ | 524 | /* read the block no allocated to a file */ |
534 | for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; | 525 | for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; |
535 | direct_blk_idx++) { | 526 | direct_blk_idx++) { |
536 | blknr = read_allocated_block(parent_inode, direct_blk_idx); | 527 | blknr = read_allocated_block(parent_inode, direct_blk_idx); |
537 | if (blknr == 0) | 528 | if (blknr == 0) |
538 | goto fail; | 529 | goto fail; |
539 | 530 | ||
540 | /* read the blocks of parenet inode */ | 531 | /* read the blocks of parenet inode */ |
541 | block_buffer = zalloc(fs->blksz); | 532 | block_buffer = zalloc(fs->blksz); |
542 | if (!block_buffer) | 533 | if (!block_buffer) |
543 | goto fail; | 534 | goto fail; |
544 | 535 | ||
545 | status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, | 536 | status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, |
546 | 0, fs->blksz, (char *)block_buffer); | 537 | 0, fs->blksz, (char *)block_buffer); |
547 | if (status == 0) | 538 | if (status == 0) |
548 | goto fail; | 539 | goto fail; |
549 | 540 | ||
550 | dir = (struct ext2_dirent *)block_buffer; | 541 | dir = (struct ext2_dirent *)block_buffer; |
551 | ptr = (char *)dir; | 542 | ptr = (char *)dir; |
552 | totalbytes = 0; | 543 | totalbytes = 0; |
553 | while (dir->direntlen >= 0) { | 544 | while (dir->direntlen >= 0) { |
554 | /* | 545 | /* |
555 | * blocksize-totalbytes because last directory | 546 | * blocksize-totalbytes because last directory |
556 | * length i.e.,*dir->direntlen is free availble | 547 | * length i.e.,*dir->direntlen is free availble |
557 | * space in the block that means | 548 | * space in the block that means |
558 | * it is a last entry of directory entry | 549 | * it is a last entry of directory entry |
559 | */ | 550 | */ |
560 | if (strlen(dirname) == dir->namelen) { | 551 | if (strlen(dirname) == dir->namelen) { |
561 | if (strncmp(dirname, ptr + | 552 | if (strncmp(dirname, ptr + |
562 | sizeof(struct ext2_dirent), | 553 | sizeof(struct ext2_dirent), |
563 | dir->namelen) == 0) { | 554 | dir->namelen) == 0) { |
564 | previous_dir->direntlen += | 555 | previous_dir->direntlen += |
565 | dir->direntlen; | 556 | dir->direntlen; |
566 | inodeno = dir->inode; | 557 | inodeno = dir->inode; |
567 | dir->inode = 0; | 558 | dir->inode = 0; |
568 | found = 1; | 559 | found = 1; |
569 | break; | 560 | break; |
570 | } | 561 | } |
571 | } | 562 | } |
572 | 563 | ||
573 | if (fs->blksz - totalbytes == dir->direntlen) | 564 | if (fs->blksz - totalbytes == dir->direntlen) |
574 | break; | 565 | break; |
575 | 566 | ||
576 | /* traversing the each directory entry */ | 567 | /* traversing the each directory entry */ |
577 | templength = dir->direntlen; | 568 | templength = dir->direntlen; |
578 | totalbytes = totalbytes + templength; | 569 | totalbytes = totalbytes + templength; |
579 | previous_dir = dir; | 570 | previous_dir = dir; |
580 | dir = (struct ext2_dirent *)((char *)dir + templength); | 571 | dir = (struct ext2_dirent *)((char *)dir + templength); |
581 | ptr = (char *)dir; | 572 | ptr = (char *)dir; |
582 | } | 573 | } |
583 | 574 | ||
584 | if (found == 1) { | 575 | if (found == 1) { |
585 | free(block_buffer); | 576 | free(block_buffer); |
586 | block_buffer = NULL; | 577 | block_buffer = NULL; |
587 | return inodeno; | 578 | return inodeno; |
588 | } | 579 | } |
589 | 580 | ||
590 | free(block_buffer); | 581 | free(block_buffer); |
591 | block_buffer = NULL; | 582 | block_buffer = NULL; |
592 | } | 583 | } |
593 | 584 | ||
594 | fail: | 585 | fail: |
595 | free(block_buffer); | 586 | free(block_buffer); |
596 | 587 | ||
597 | return -1; | 588 | return -1; |
598 | } | 589 | } |
599 | 590 | ||
600 | static int find_dir_depth(char *dirname) | 591 | static int find_dir_depth(char *dirname) |
601 | { | 592 | { |
602 | char *token = strtok(dirname, "/"); | 593 | char *token = strtok(dirname, "/"); |
603 | int count = 0; | 594 | int count = 0; |
604 | while (token != NULL) { | 595 | while (token != NULL) { |
605 | token = strtok(NULL, "/"); | 596 | token = strtok(NULL, "/"); |
606 | count++; | 597 | count++; |
607 | } | 598 | } |
608 | return count + 1 + 1; | 599 | return count + 1 + 1; |
609 | /* | 600 | /* |
610 | * for example for string /home/temp | 601 | * for example for string /home/temp |
611 | * depth=home(1)+temp(1)+1 extra for NULL; | 602 | * depth=home(1)+temp(1)+1 extra for NULL; |
612 | * so count is 4; | 603 | * so count is 4; |
613 | */ | 604 | */ |
614 | } | 605 | } |
615 | 606 | ||
616 | static int parse_path(char **arr, char *dirname) | 607 | static int parse_path(char **arr, char *dirname) |
617 | { | 608 | { |
618 | char *token = strtok(dirname, "/"); | 609 | char *token = strtok(dirname, "/"); |
619 | int i = 0; | 610 | int i = 0; |
620 | 611 | ||
621 | /* add root */ | 612 | /* add root */ |
622 | arr[i] = zalloc(strlen("/") + 1); | 613 | arr[i] = zalloc(strlen("/") + 1); |
623 | if (!arr[i]) | 614 | if (!arr[i]) |
624 | return -ENOMEM; | 615 | return -ENOMEM; |
625 | 616 | ||
626 | arr[i++] = "/"; | 617 | arr[i++] = "/"; |
627 | 618 | ||
628 | /* add each path entry after root */ | 619 | /* add each path entry after root */ |
629 | while (token != NULL) { | 620 | while (token != NULL) { |
630 | arr[i] = zalloc(strlen(token) + 1); | 621 | arr[i] = zalloc(strlen(token) + 1); |
631 | if (!arr[i]) | 622 | if (!arr[i]) |
632 | return -ENOMEM; | 623 | return -ENOMEM; |
633 | memcpy(arr[i++], token, strlen(token)); | 624 | memcpy(arr[i++], token, strlen(token)); |
634 | token = strtok(NULL, "/"); | 625 | token = strtok(NULL, "/"); |
635 | } | 626 | } |
636 | arr[i] = NULL; | 627 | arr[i] = NULL; |
637 | 628 | ||
638 | return 0; | 629 | return 0; |
639 | } | 630 | } |
640 | 631 | ||
641 | int ext4fs_iget(int inode_no, struct ext2_inode *inode) | 632 | int ext4fs_iget(int inode_no, struct ext2_inode *inode) |
642 | { | 633 | { |
643 | if (ext4fs_read_inode(ext4fs_root, inode_no, inode) == 0) | 634 | if (ext4fs_read_inode(ext4fs_root, inode_no, inode) == 0) |
644 | return -1; | 635 | return -1; |
645 | 636 | ||
646 | return 0; | 637 | return 0; |
647 | } | 638 | } |
648 | 639 | ||
649 | /* | 640 | /* |
650 | * Function: ext4fs_get_parent_inode_num | 641 | * Function: ext4fs_get_parent_inode_num |
651 | * Return Value: inode Number of the parent directory of file/Directory to be | 642 | * Return Value: inode Number of the parent directory of file/Directory to be |
652 | * created | 643 | * created |
653 | * dirname : Input parmater, input path name of the file/directory to be created | 644 | * dirname : Input parmater, input path name of the file/directory to be created |
654 | * dname : Output parameter, to be filled with the name of the directory | 645 | * dname : Output parameter, to be filled with the name of the directory |
655 | * extracted from dirname | 646 | * extracted from dirname |
656 | */ | 647 | */ |
657 | int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags) | 648 | int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags) |
658 | { | 649 | { |
659 | int i; | 650 | int i; |
660 | int depth = 0; | 651 | int depth = 0; |
661 | int matched_inode_no; | 652 | int matched_inode_no; |
662 | int result_inode_no = -1; | 653 | int result_inode_no = -1; |
663 | char **ptr = NULL; | 654 | char **ptr = NULL; |
664 | char *depth_dirname = NULL; | 655 | char *depth_dirname = NULL; |
665 | char *parse_dirname = NULL; | 656 | char *parse_dirname = NULL; |
666 | struct ext2_inode *parent_inode = NULL; | 657 | struct ext2_inode *parent_inode = NULL; |
667 | struct ext2_inode *first_inode = NULL; | 658 | struct ext2_inode *first_inode = NULL; |
668 | struct ext2_inode temp_inode; | 659 | struct ext2_inode temp_inode; |
669 | 660 | ||
670 | if (*dirname != '/') { | 661 | if (*dirname != '/') { |
671 | printf("Please supply Absolute path\n"); | 662 | printf("Please supply Absolute path\n"); |
672 | return -1; | 663 | return -1; |
673 | } | 664 | } |
674 | 665 | ||
675 | /* TODO: input validation make equivalent to linux */ | 666 | /* TODO: input validation make equivalent to linux */ |
676 | depth_dirname = zalloc(strlen(dirname) + 1); | 667 | depth_dirname = zalloc(strlen(dirname) + 1); |
677 | if (!depth_dirname) | 668 | if (!depth_dirname) |
678 | return -ENOMEM; | 669 | return -ENOMEM; |
679 | 670 | ||
680 | memcpy(depth_dirname, dirname, strlen(dirname)); | 671 | memcpy(depth_dirname, dirname, strlen(dirname)); |
681 | depth = find_dir_depth(depth_dirname); | 672 | depth = find_dir_depth(depth_dirname); |
682 | parse_dirname = zalloc(strlen(dirname) + 1); | 673 | parse_dirname = zalloc(strlen(dirname) + 1); |
683 | if (!parse_dirname) | 674 | if (!parse_dirname) |
684 | goto fail; | 675 | goto fail; |
685 | memcpy(parse_dirname, dirname, strlen(dirname)); | 676 | memcpy(parse_dirname, dirname, strlen(dirname)); |
686 | 677 | ||
687 | /* allocate memory for each directory level */ | 678 | /* allocate memory for each directory level */ |
688 | ptr = zalloc((depth) * sizeof(char *)); | 679 | ptr = zalloc((depth) * sizeof(char *)); |
689 | if (!ptr) | 680 | if (!ptr) |
690 | goto fail; | 681 | goto fail; |
691 | if (parse_path(ptr, parse_dirname)) | 682 | if (parse_path(ptr, parse_dirname)) |
692 | goto fail; | 683 | goto fail; |
693 | parent_inode = zalloc(sizeof(struct ext2_inode)); | 684 | parent_inode = zalloc(sizeof(struct ext2_inode)); |
694 | if (!parent_inode) | 685 | if (!parent_inode) |
695 | goto fail; | 686 | goto fail; |
696 | first_inode = zalloc(sizeof(struct ext2_inode)); | 687 | first_inode = zalloc(sizeof(struct ext2_inode)); |
697 | if (!first_inode) | 688 | if (!first_inode) |
698 | goto fail; | 689 | goto fail; |
699 | memcpy(parent_inode, ext4fs_root->inode, sizeof(struct ext2_inode)); | 690 | memcpy(parent_inode, ext4fs_root->inode, sizeof(struct ext2_inode)); |
700 | memcpy(first_inode, parent_inode, sizeof(struct ext2_inode)); | 691 | memcpy(first_inode, parent_inode, sizeof(struct ext2_inode)); |
701 | if (flags & F_FILE) | 692 | if (flags & F_FILE) |
702 | result_inode_no = EXT2_ROOT_INO; | 693 | result_inode_no = EXT2_ROOT_INO; |
703 | for (i = 1; i < depth; i++) { | 694 | for (i = 1; i < depth; i++) { |
704 | matched_inode_no = search_dir(parent_inode, ptr[i]); | 695 | matched_inode_no = search_dir(parent_inode, ptr[i]); |
705 | if (matched_inode_no == -1) { | 696 | if (matched_inode_no == -1) { |
706 | if (ptr[i + 1] == NULL && i == 1) { | 697 | if (ptr[i + 1] == NULL && i == 1) { |
707 | result_inode_no = EXT2_ROOT_INO; | 698 | result_inode_no = EXT2_ROOT_INO; |
708 | goto end; | 699 | goto end; |
709 | } else { | 700 | } else { |
710 | if (ptr[i + 1] == NULL) | 701 | if (ptr[i + 1] == NULL) |
711 | break; | 702 | break; |
712 | printf("Invalid path\n"); | 703 | printf("Invalid path\n"); |
713 | result_inode_no = -1; | 704 | result_inode_no = -1; |
714 | goto fail; | 705 | goto fail; |
715 | } | 706 | } |
716 | } else { | 707 | } else { |
717 | if (ptr[i + 1] != NULL) { | 708 | if (ptr[i + 1] != NULL) { |
718 | memset(parent_inode, '\0', | 709 | memset(parent_inode, '\0', |
719 | sizeof(struct ext2_inode)); | 710 | sizeof(struct ext2_inode)); |
720 | if (ext4fs_iget(matched_inode_no, | 711 | if (ext4fs_iget(matched_inode_no, |
721 | parent_inode)) { | 712 | parent_inode)) { |
722 | result_inode_no = -1; | 713 | result_inode_no = -1; |
723 | goto fail; | 714 | goto fail; |
724 | } | 715 | } |
725 | result_inode_no = matched_inode_no; | 716 | result_inode_no = matched_inode_no; |
726 | } else { | 717 | } else { |
727 | break; | 718 | break; |
728 | } | 719 | } |
729 | } | 720 | } |
730 | } | 721 | } |
731 | 722 | ||
732 | end: | 723 | end: |
733 | if (i == 1) | 724 | if (i == 1) |
734 | matched_inode_no = search_dir(first_inode, ptr[i]); | 725 | matched_inode_no = search_dir(first_inode, ptr[i]); |
735 | else | 726 | else |
736 | matched_inode_no = search_dir(parent_inode, ptr[i]); | 727 | matched_inode_no = search_dir(parent_inode, ptr[i]); |
737 | 728 | ||
738 | if (matched_inode_no != -1) { | 729 | if (matched_inode_no != -1) { |
739 | ext4fs_iget(matched_inode_no, &temp_inode); | 730 | ext4fs_iget(matched_inode_no, &temp_inode); |
740 | if (temp_inode.mode & S_IFDIR) { | 731 | if (temp_inode.mode & S_IFDIR) { |
741 | printf("It is a Directory\n"); | 732 | printf("It is a Directory\n"); |
742 | result_inode_no = -1; | 733 | result_inode_no = -1; |
743 | goto fail; | 734 | goto fail; |
744 | } | 735 | } |
745 | } | 736 | } |
746 | 737 | ||
747 | if (strlen(ptr[i]) > 256) { | 738 | if (strlen(ptr[i]) > 256) { |
748 | result_inode_no = -1; | 739 | result_inode_no = -1; |
749 | goto fail; | 740 | goto fail; |
750 | } | 741 | } |
751 | memcpy(dname, ptr[i], strlen(ptr[i])); | 742 | memcpy(dname, ptr[i], strlen(ptr[i])); |
752 | 743 | ||
753 | fail: | 744 | fail: |
754 | free(depth_dirname); | 745 | free(depth_dirname); |
755 | free(parse_dirname); | 746 | free(parse_dirname); |
756 | free(ptr); | 747 | free(ptr); |
757 | free(parent_inode); | 748 | free(parent_inode); |
758 | free(first_inode); | 749 | free(first_inode); |
759 | 750 | ||
760 | return result_inode_no; | 751 | return result_inode_no; |
761 | } | 752 | } |
762 | 753 | ||
763 | static int check_filename(char *filename, unsigned int blknr) | 754 | static int check_filename(char *filename, unsigned int blknr) |
764 | { | 755 | { |
765 | unsigned int first_block_no_of_root; | 756 | unsigned int first_block_no_of_root; |
766 | int totalbytes = 0; | 757 | int totalbytes = 0; |
767 | int templength = 0; | 758 | int templength = 0; |
768 | int status, inodeno; | 759 | int status, inodeno; |
769 | int found = 0; | 760 | int found = 0; |
770 | char *root_first_block_buffer = NULL; | 761 | char *root_first_block_buffer = NULL; |
771 | char *root_first_block_addr = NULL; | 762 | char *root_first_block_addr = NULL; |
772 | struct ext2_dirent *dir = NULL; | 763 | struct ext2_dirent *dir = NULL; |
773 | struct ext2_dirent *previous_dir = NULL; | 764 | struct ext2_dirent *previous_dir = NULL; |
774 | char *ptr = NULL; | 765 | char *ptr = NULL; |
775 | struct ext_filesystem *fs = get_fs(); | 766 | struct ext_filesystem *fs = get_fs(); |
776 | 767 | ||
777 | /* get the first block of root */ | 768 | /* get the first block of root */ |
778 | first_block_no_of_root = blknr; | 769 | first_block_no_of_root = blknr; |
779 | root_first_block_buffer = zalloc(fs->blksz); | 770 | root_first_block_buffer = zalloc(fs->blksz); |
780 | if (!root_first_block_buffer) | 771 | if (!root_first_block_buffer) |
781 | return -ENOMEM; | 772 | return -ENOMEM; |
782 | root_first_block_addr = root_first_block_buffer; | 773 | root_first_block_addr = root_first_block_buffer; |
783 | status = ext4fs_devread((lbaint_t)first_block_no_of_root * | 774 | status = ext4fs_devread((lbaint_t)first_block_no_of_root * |
784 | fs->sect_perblk, 0, | 775 | fs->sect_perblk, 0, |
785 | fs->blksz, root_first_block_buffer); | 776 | fs->blksz, root_first_block_buffer); |
786 | if (status == 0) | 777 | if (status == 0) |
787 | goto fail; | 778 | goto fail; |
788 | 779 | ||
789 | if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root)) | 780 | if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root)) |
790 | goto fail; | 781 | goto fail; |
791 | dir = (struct ext2_dirent *)root_first_block_buffer; | 782 | dir = (struct ext2_dirent *)root_first_block_buffer; |
792 | ptr = (char *)dir; | 783 | ptr = (char *)dir; |
793 | totalbytes = 0; | 784 | totalbytes = 0; |
794 | while (dir->direntlen >= 0) { | 785 | while (dir->direntlen >= 0) { |
795 | /* | 786 | /* |
796 | * blocksize-totalbytes because last | 787 | * blocksize-totalbytes because last |
797 | * directory length i.e., *dir->direntlen | 788 | * directory length i.e., *dir->direntlen |
798 | * is free availble space in the block that | 789 | * is free availble space in the block that |
799 | * means it is a last entry of directory entry | 790 | * means it is a last entry of directory entry |
800 | */ | 791 | */ |
801 | if (strlen(filename) == dir->namelen) { | 792 | if (strlen(filename) == dir->namelen) { |
802 | if (strncmp(filename, ptr + sizeof(struct ext2_dirent), | 793 | if (strncmp(filename, ptr + sizeof(struct ext2_dirent), |
803 | dir->namelen) == 0) { | 794 | dir->namelen) == 0) { |
804 | printf("file found deleting\n"); | 795 | printf("file found deleting\n"); |
805 | previous_dir->direntlen += dir->direntlen; | 796 | previous_dir->direntlen += dir->direntlen; |
806 | inodeno = dir->inode; | 797 | inodeno = dir->inode; |
807 | dir->inode = 0; | 798 | dir->inode = 0; |
808 | found = 1; | 799 | found = 1; |
809 | break; | 800 | break; |
810 | } | 801 | } |
811 | } | 802 | } |
812 | 803 | ||
813 | if (fs->blksz - totalbytes == dir->direntlen) | 804 | if (fs->blksz - totalbytes == dir->direntlen) |
814 | break; | 805 | break; |
815 | 806 | ||
816 | /* traversing the each directory entry */ | 807 | /* traversing the each directory entry */ |
817 | templength = dir->direntlen; | 808 | templength = dir->direntlen; |
818 | totalbytes = totalbytes + templength; | 809 | totalbytes = totalbytes + templength; |
819 | previous_dir = dir; | 810 | previous_dir = dir; |
820 | dir = (struct ext2_dirent *)((char *)dir + templength); | 811 | dir = (struct ext2_dirent *)((char *)dir + templength); |
821 | ptr = (char *)dir; | 812 | ptr = (char *)dir; |
822 | } | 813 | } |
823 | 814 | ||
824 | 815 | ||
825 | if (found == 1) { | 816 | if (found == 1) { |
826 | if (ext4fs_put_metadata(root_first_block_addr, | 817 | if (ext4fs_put_metadata(root_first_block_addr, |
827 | first_block_no_of_root)) | 818 | first_block_no_of_root)) |
828 | goto fail; | 819 | goto fail; |
829 | return inodeno; | 820 | return inodeno; |
830 | } | 821 | } |
831 | fail: | 822 | fail: |
832 | free(root_first_block_buffer); | 823 | free(root_first_block_buffer); |
833 | 824 | ||
834 | return -1; | 825 | return -1; |
835 | } | 826 | } |
836 | 827 | ||
837 | int ext4fs_filename_check(char *filename) | 828 | int ext4fs_filename_check(char *filename) |
838 | { | 829 | { |
839 | short direct_blk_idx = 0; | 830 | short direct_blk_idx = 0; |
840 | long int blknr = -1; | 831 | long int blknr = -1; |
841 | int inodeno = -1; | 832 | int inodeno = -1; |
842 | 833 | ||
843 | /* read the block no allocated to a file */ | 834 | /* read the block no allocated to a file */ |
844 | for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; | 835 | for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS; |
845 | direct_blk_idx++) { | 836 | direct_blk_idx++) { |
846 | blknr = read_allocated_block(g_parent_inode, direct_blk_idx); | 837 | blknr = read_allocated_block(g_parent_inode, direct_blk_idx); |
847 | if (blknr == 0) | 838 | if (blknr == 0) |
848 | break; | 839 | break; |
849 | inodeno = check_filename(filename, blknr); | 840 | inodeno = check_filename(filename, blknr); |
850 | if (inodeno != -1) | 841 | if (inodeno != -1) |
851 | return inodeno; | 842 | return inodeno; |
852 | } | 843 | } |
853 | 844 | ||
854 | return -1; | 845 | return -1; |
855 | } | 846 | } |
856 | 847 | ||
857 | long int ext4fs_get_new_blk_no(void) | 848 | long int ext4fs_get_new_blk_no(void) |
858 | { | 849 | { |
859 | short i; | 850 | short i; |
860 | short status; | 851 | short status; |
861 | int remainder; | 852 | int remainder; |
862 | unsigned int bg_idx; | 853 | unsigned int bg_idx; |
863 | static int prev_bg_bitmap_index = -1; | 854 | static int prev_bg_bitmap_index = -1; |
864 | unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; | 855 | unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; |
865 | struct ext_filesystem *fs = get_fs(); | 856 | struct ext_filesystem *fs = get_fs(); |
866 | char *journal_buffer = zalloc(fs->blksz); | 857 | char *journal_buffer = zalloc(fs->blksz); |
867 | char *zero_buffer = zalloc(fs->blksz); | 858 | char *zero_buffer = zalloc(fs->blksz); |
868 | if (!journal_buffer || !zero_buffer) | 859 | if (!journal_buffer || !zero_buffer) |
869 | goto fail; | 860 | goto fail; |
870 | struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable; | 861 | struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable; |
871 | 862 | ||
872 | if (fs->first_pass_bbmap == 0) { | 863 | if (fs->first_pass_bbmap == 0) { |
873 | for (i = 0; i < fs->no_blkgrp; i++) { | 864 | for (i = 0; i < fs->no_blkgrp; i++) { |
874 | if (bgd[i].free_blocks) { | 865 | if (bgd[i].free_blocks) { |
875 | if (bgd[i].bg_flags & EXT4_BG_BLOCK_UNINIT) { | 866 | if (bgd[i].bg_flags & EXT4_BG_BLOCK_UNINIT) { |
876 | put_ext4(((uint64_t) ((uint64_t)bgd[i].block_id * | 867 | put_ext4(((uint64_t) ((uint64_t)bgd[i].block_id * |
877 | (uint64_t)fs->blksz)), | 868 | (uint64_t)fs->blksz)), |
878 | zero_buffer, fs->blksz); | 869 | zero_buffer, fs->blksz); |
879 | bgd[i].bg_flags = | 870 | bgd[i].bg_flags = |
880 | bgd[i]. | 871 | bgd[i]. |
881 | bg_flags & ~EXT4_BG_BLOCK_UNINIT; | 872 | bg_flags & ~EXT4_BG_BLOCK_UNINIT; |
882 | memcpy(fs->blk_bmaps[i], zero_buffer, | 873 | memcpy(fs->blk_bmaps[i], zero_buffer, |
883 | fs->blksz); | 874 | fs->blksz); |
884 | } | 875 | } |
885 | fs->curr_blkno = | 876 | fs->curr_blkno = |
886 | _get_new_blk_no(fs->blk_bmaps[i]); | 877 | _get_new_blk_no(fs->blk_bmaps[i]); |
887 | if (fs->curr_blkno == -1) | 878 | if (fs->curr_blkno == -1) |
888 | /* if block bitmap is completely fill */ | 879 | /* if block bitmap is completely fill */ |
889 | continue; | 880 | continue; |
890 | fs->curr_blkno = fs->curr_blkno + | 881 | fs->curr_blkno = fs->curr_blkno + |
891 | (i * fs->blksz * 8); | 882 | (i * fs->blksz * 8); |
892 | fs->first_pass_bbmap++; | 883 | fs->first_pass_bbmap++; |
893 | bgd[i].free_blocks--; | 884 | bgd[i].free_blocks--; |
894 | fs->sb->free_blocks--; | 885 | fs->sb->free_blocks--; |
895 | status = ext4fs_devread((lbaint_t) | 886 | status = ext4fs_devread((lbaint_t) |
896 | bgd[i].block_id * | 887 | bgd[i].block_id * |
897 | fs->sect_perblk, 0, | 888 | fs->sect_perblk, 0, |
898 | fs->blksz, | 889 | fs->blksz, |
899 | journal_buffer); | 890 | journal_buffer); |
900 | if (status == 0) | 891 | if (status == 0) |
901 | goto fail; | 892 | goto fail; |
902 | if (ext4fs_log_journal(journal_buffer, | 893 | if (ext4fs_log_journal(journal_buffer, |
903 | bgd[i].block_id)) | 894 | bgd[i].block_id)) |
904 | goto fail; | 895 | goto fail; |
905 | goto success; | 896 | goto success; |
906 | } else { | 897 | } else { |
907 | debug("no space left on block group %d\n", i); | 898 | debug("no space left on block group %d\n", i); |
908 | } | 899 | } |
909 | } | 900 | } |
910 | 901 | ||
911 | goto fail; | 902 | goto fail; |
912 | } else { | 903 | } else { |
913 | restart: | 904 | restart: |
914 | fs->curr_blkno++; | 905 | fs->curr_blkno++; |
915 | /* get the blockbitmap index respective to blockno */ | 906 | /* get the blockbitmap index respective to blockno */ |
916 | if (fs->blksz != 1024) { | 907 | if (fs->blksz != 1024) { |
917 | bg_idx = fs->curr_blkno / blk_per_grp; | 908 | bg_idx = fs->curr_blkno / blk_per_grp; |
918 | } else { | 909 | } else { |
919 | bg_idx = fs->curr_blkno / blk_per_grp; | 910 | bg_idx = fs->curr_blkno / blk_per_grp; |
920 | remainder = fs->curr_blkno % blk_per_grp; | 911 | remainder = fs->curr_blkno % blk_per_grp; |
921 | if (!remainder) | 912 | if (!remainder) |
922 | bg_idx--; | 913 | bg_idx--; |
923 | } | 914 | } |
924 | 915 | ||
925 | /* | 916 | /* |
926 | * To skip completely filled block group bitmaps | 917 | * To skip completely filled block group bitmaps |
927 | * Optimize the block allocation | 918 | * Optimize the block allocation |
928 | */ | 919 | */ |
929 | if (bg_idx >= fs->no_blkgrp) | 920 | if (bg_idx >= fs->no_blkgrp) |
930 | goto fail; | 921 | goto fail; |
931 | 922 | ||
932 | if (bgd[bg_idx].free_blocks == 0) { | 923 | if (bgd[bg_idx].free_blocks == 0) { |
933 | debug("block group %u is full. Skipping\n", bg_idx); | 924 | debug("block group %u is full. Skipping\n", bg_idx); |
934 | fs->curr_blkno = fs->curr_blkno + blk_per_grp; | 925 | fs->curr_blkno = fs->curr_blkno + blk_per_grp; |
935 | fs->curr_blkno--; | 926 | fs->curr_blkno--; |
936 | goto restart; | 927 | goto restart; |
937 | } | 928 | } |
938 | 929 | ||
939 | if (bgd[bg_idx].bg_flags & EXT4_BG_BLOCK_UNINIT) { | 930 | if (bgd[bg_idx].bg_flags & EXT4_BG_BLOCK_UNINIT) { |
940 | memset(zero_buffer, '\0', fs->blksz); | 931 | memset(zero_buffer, '\0', fs->blksz); |
941 | put_ext4(((uint64_t) ((uint64_t)bgd[bg_idx].block_id * | 932 | put_ext4(((uint64_t) ((uint64_t)bgd[bg_idx].block_id * |
942 | (uint64_t)fs->blksz)), zero_buffer, fs->blksz); | 933 | (uint64_t)fs->blksz)), zero_buffer, fs->blksz); |
943 | memcpy(fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz); | 934 | memcpy(fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz); |
944 | bgd[bg_idx].bg_flags = bgd[bg_idx].bg_flags & | 935 | bgd[bg_idx].bg_flags = bgd[bg_idx].bg_flags & |
945 | ~EXT4_BG_BLOCK_UNINIT; | 936 | ~EXT4_BG_BLOCK_UNINIT; |
946 | } | 937 | } |
947 | 938 | ||
948 | if (ext4fs_set_block_bmap(fs->curr_blkno, fs->blk_bmaps[bg_idx], | 939 | if (ext4fs_set_block_bmap(fs->curr_blkno, fs->blk_bmaps[bg_idx], |
949 | bg_idx) != 0) { | 940 | bg_idx) != 0) { |
950 | debug("going for restart for the block no %ld %u\n", | 941 | debug("going for restart for the block no %ld %u\n", |
951 | fs->curr_blkno, bg_idx); | 942 | fs->curr_blkno, bg_idx); |
952 | goto restart; | 943 | goto restart; |
953 | } | 944 | } |
954 | 945 | ||
955 | /* journal backup */ | 946 | /* journal backup */ |
956 | if (prev_bg_bitmap_index != bg_idx) { | 947 | if (prev_bg_bitmap_index != bg_idx) { |
957 | memset(journal_buffer, '\0', fs->blksz); | 948 | memset(journal_buffer, '\0', fs->blksz); |
958 | status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id | 949 | status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id |
959 | * fs->sect_perblk, | 950 | * fs->sect_perblk, |
960 | 0, fs->blksz, journal_buffer); | 951 | 0, fs->blksz, journal_buffer); |
961 | if (status == 0) | 952 | if (status == 0) |
962 | goto fail; | 953 | goto fail; |
963 | if (ext4fs_log_journal(journal_buffer, | 954 | if (ext4fs_log_journal(journal_buffer, |
964 | bgd[bg_idx].block_id)) | 955 | bgd[bg_idx].block_id)) |
965 | goto fail; | 956 | goto fail; |
966 | 957 | ||
967 | prev_bg_bitmap_index = bg_idx; | 958 | prev_bg_bitmap_index = bg_idx; |
968 | } | 959 | } |
969 | bgd[bg_idx].free_blocks--; | 960 | bgd[bg_idx].free_blocks--; |
970 | fs->sb->free_blocks--; | 961 | fs->sb->free_blocks--; |
971 | goto success; | 962 | goto success; |
972 | } | 963 | } |
973 | success: | 964 | success: |
974 | free(journal_buffer); | 965 | free(journal_buffer); |
975 | free(zero_buffer); | 966 | free(zero_buffer); |
976 | 967 | ||
977 | return fs->curr_blkno; | 968 | return fs->curr_blkno; |
978 | fail: | 969 | fail: |
979 | free(journal_buffer); | 970 | free(journal_buffer); |
980 | free(zero_buffer); | 971 | free(zero_buffer); |
981 | 972 | ||
982 | return -1; | 973 | return -1; |
983 | } | 974 | } |
984 | 975 | ||
985 | int ext4fs_get_new_inode_no(void) | 976 | int ext4fs_get_new_inode_no(void) |
986 | { | 977 | { |
987 | short i; | 978 | short i; |
988 | short status; | 979 | short status; |
989 | unsigned int ibmap_idx; | 980 | unsigned int ibmap_idx; |
990 | static int prev_inode_bitmap_index = -1; | 981 | static int prev_inode_bitmap_index = -1; |
991 | unsigned int inodes_per_grp = ext4fs_root->sblock.inodes_per_group; | 982 | unsigned int inodes_per_grp = ext4fs_root->sblock.inodes_per_group; |
992 | struct ext_filesystem *fs = get_fs(); | 983 | struct ext_filesystem *fs = get_fs(); |
993 | char *journal_buffer = zalloc(fs->blksz); | 984 | char *journal_buffer = zalloc(fs->blksz); |
994 | char *zero_buffer = zalloc(fs->blksz); | 985 | char *zero_buffer = zalloc(fs->blksz); |
995 | if (!journal_buffer || !zero_buffer) | 986 | if (!journal_buffer || !zero_buffer) |
996 | goto fail; | 987 | goto fail; |
997 | struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable; | 988 | struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable; |
998 | 989 | ||
999 | if (fs->first_pass_ibmap == 0) { | 990 | if (fs->first_pass_ibmap == 0) { |
1000 | for (i = 0; i < fs->no_blkgrp; i++) { | 991 | for (i = 0; i < fs->no_blkgrp; i++) { |
1001 | if (bgd[i].free_inodes) { | 992 | if (bgd[i].free_inodes) { |
1002 | if (bgd[i].bg_itable_unused != | 993 | if (bgd[i].bg_itable_unused != |
1003 | bgd[i].free_inodes) | 994 | bgd[i].free_inodes) |
1004 | bgd[i].bg_itable_unused = | 995 | bgd[i].bg_itable_unused = |
1005 | bgd[i].free_inodes; | 996 | bgd[i].free_inodes; |
1006 | if (bgd[i].bg_flags & EXT4_BG_INODE_UNINIT) { | 997 | if (bgd[i].bg_flags & EXT4_BG_INODE_UNINIT) { |
1007 | put_ext4(((uint64_t) | 998 | put_ext4(((uint64_t) |
1008 | ((uint64_t)bgd[i].inode_id * | 999 | ((uint64_t)bgd[i].inode_id * |
1009 | (uint64_t)fs->blksz)), | 1000 | (uint64_t)fs->blksz)), |
1010 | zero_buffer, fs->blksz); | 1001 | zero_buffer, fs->blksz); |
1011 | bgd[i].bg_flags = bgd[i].bg_flags & | 1002 | bgd[i].bg_flags = bgd[i].bg_flags & |
1012 | ~EXT4_BG_INODE_UNINIT; | 1003 | ~EXT4_BG_INODE_UNINIT; |
1013 | memcpy(fs->inode_bmaps[i], | 1004 | memcpy(fs->inode_bmaps[i], |
1014 | zero_buffer, fs->blksz); | 1005 | zero_buffer, fs->blksz); |
1015 | } | 1006 | } |
1016 | fs->curr_inode_no = | 1007 | fs->curr_inode_no = |
1017 | _get_new_inode_no(fs->inode_bmaps[i]); | 1008 | _get_new_inode_no(fs->inode_bmaps[i]); |
1018 | if (fs->curr_inode_no == -1) | 1009 | if (fs->curr_inode_no == -1) |
1019 | /* if block bitmap is completely fill */ | 1010 | /* if block bitmap is completely fill */ |
1020 | continue; | 1011 | continue; |
1021 | fs->curr_inode_no = fs->curr_inode_no + | 1012 | fs->curr_inode_no = fs->curr_inode_no + |
1022 | (i * inodes_per_grp); | 1013 | (i * inodes_per_grp); |
1023 | fs->first_pass_ibmap++; | 1014 | fs->first_pass_ibmap++; |
1024 | bgd[i].free_inodes--; | 1015 | bgd[i].free_inodes--; |
1025 | bgd[i].bg_itable_unused--; | 1016 | bgd[i].bg_itable_unused--; |
1026 | fs->sb->free_inodes--; | 1017 | fs->sb->free_inodes--; |
1027 | status = ext4fs_devread((lbaint_t) | 1018 | status = ext4fs_devread((lbaint_t) |
1028 | bgd[i].inode_id * | 1019 | bgd[i].inode_id * |
1029 | fs->sect_perblk, 0, | 1020 | fs->sect_perblk, 0, |
1030 | fs->blksz, | 1021 | fs->blksz, |
1031 | journal_buffer); | 1022 | journal_buffer); |
1032 | if (status == 0) | 1023 | if (status == 0) |
1033 | goto fail; | 1024 | goto fail; |
1034 | if (ext4fs_log_journal(journal_buffer, | 1025 | if (ext4fs_log_journal(journal_buffer, |
1035 | bgd[i].inode_id)) | 1026 | bgd[i].inode_id)) |
1036 | goto fail; | 1027 | goto fail; |
1037 | goto success; | 1028 | goto success; |
1038 | } else | 1029 | } else |
1039 | debug("no inode left on block group %d\n", i); | 1030 | debug("no inode left on block group %d\n", i); |
1040 | } | 1031 | } |
1041 | goto fail; | 1032 | goto fail; |
1042 | } else { | 1033 | } else { |
1043 | restart: | 1034 | restart: |
1044 | fs->curr_inode_no++; | 1035 | fs->curr_inode_no++; |
1045 | /* get the blockbitmap index respective to blockno */ | 1036 | /* get the blockbitmap index respective to blockno */ |
1046 | ibmap_idx = fs->curr_inode_no / inodes_per_grp; | 1037 | ibmap_idx = fs->curr_inode_no / inodes_per_grp; |
1047 | if (bgd[ibmap_idx].bg_flags & EXT4_BG_INODE_UNINIT) { | 1038 | if (bgd[ibmap_idx].bg_flags & EXT4_BG_INODE_UNINIT) { |
1048 | memset(zero_buffer, '\0', fs->blksz); | 1039 | memset(zero_buffer, '\0', fs->blksz); |
1049 | put_ext4(((uint64_t) ((uint64_t)bgd[ibmap_idx].inode_id * | 1040 | put_ext4(((uint64_t) ((uint64_t)bgd[ibmap_idx].inode_id * |
1050 | (uint64_t)fs->blksz)), zero_buffer, | 1041 | (uint64_t)fs->blksz)), zero_buffer, |
1051 | fs->blksz); | 1042 | fs->blksz); |
1052 | bgd[ibmap_idx].bg_flags = | 1043 | bgd[ibmap_idx].bg_flags = |
1053 | bgd[ibmap_idx].bg_flags & ~EXT4_BG_INODE_UNINIT; | 1044 | bgd[ibmap_idx].bg_flags & ~EXT4_BG_INODE_UNINIT; |
1054 | memcpy(fs->inode_bmaps[ibmap_idx], zero_buffer, | 1045 | memcpy(fs->inode_bmaps[ibmap_idx], zero_buffer, |
1055 | fs->blksz); | 1046 | fs->blksz); |
1056 | } | 1047 | } |
1057 | 1048 | ||
1058 | if (ext4fs_set_inode_bmap(fs->curr_inode_no, | 1049 | if (ext4fs_set_inode_bmap(fs->curr_inode_no, |
1059 | fs->inode_bmaps[ibmap_idx], | 1050 | fs->inode_bmaps[ibmap_idx], |
1060 | ibmap_idx) != 0) { | 1051 | ibmap_idx) != 0) { |
1061 | debug("going for restart for the block no %d %u\n", | 1052 | debug("going for restart for the block no %d %u\n", |
1062 | fs->curr_inode_no, ibmap_idx); | 1053 | fs->curr_inode_no, ibmap_idx); |
1063 | goto restart; | 1054 | goto restart; |
1064 | } | 1055 | } |
1065 | 1056 | ||
1066 | /* journal backup */ | 1057 | /* journal backup */ |
1067 | if (prev_inode_bitmap_index != ibmap_idx) { | 1058 | if (prev_inode_bitmap_index != ibmap_idx) { |
1068 | memset(journal_buffer, '\0', fs->blksz); | 1059 | memset(journal_buffer, '\0', fs->blksz); |
1069 | status = ext4fs_devread((lbaint_t) | 1060 | status = ext4fs_devread((lbaint_t) |
1070 | bgd[ibmap_idx].inode_id | 1061 | bgd[ibmap_idx].inode_id |
1071 | * fs->sect_perblk, | 1062 | * fs->sect_perblk, |
1072 | 0, fs->blksz, journal_buffer); | 1063 | 0, fs->blksz, journal_buffer); |
1073 | if (status == 0) | 1064 | if (status == 0) |
1074 | goto fail; | 1065 | goto fail; |
1075 | if (ext4fs_log_journal(journal_buffer, | 1066 | if (ext4fs_log_journal(journal_buffer, |
1076 | bgd[ibmap_idx].inode_id)) | 1067 | bgd[ibmap_idx].inode_id)) |
1077 | goto fail; | 1068 | goto fail; |
1078 | prev_inode_bitmap_index = ibmap_idx; | 1069 | prev_inode_bitmap_index = ibmap_idx; |
1079 | } | 1070 | } |
1080 | if (bgd[ibmap_idx].bg_itable_unused != | 1071 | if (bgd[ibmap_idx].bg_itable_unused != |
1081 | bgd[ibmap_idx].free_inodes) | 1072 | bgd[ibmap_idx].free_inodes) |
1082 | bgd[ibmap_idx].bg_itable_unused = | 1073 | bgd[ibmap_idx].bg_itable_unused = |
1083 | bgd[ibmap_idx].free_inodes; | 1074 | bgd[ibmap_idx].free_inodes; |
1084 | bgd[ibmap_idx].free_inodes--; | 1075 | bgd[ibmap_idx].free_inodes--; |
1085 | bgd[ibmap_idx].bg_itable_unused--; | 1076 | bgd[ibmap_idx].bg_itable_unused--; |
1086 | fs->sb->free_inodes--; | 1077 | fs->sb->free_inodes--; |
1087 | goto success; | 1078 | goto success; |
1088 | } | 1079 | } |
1089 | 1080 | ||
1090 | success: | 1081 | success: |
1091 | free(journal_buffer); | 1082 | free(journal_buffer); |
1092 | free(zero_buffer); | 1083 | free(zero_buffer); |
1093 | 1084 | ||
1094 | return fs->curr_inode_no; | 1085 | return fs->curr_inode_no; |
1095 | fail: | 1086 | fail: |
1096 | free(journal_buffer); | 1087 | free(journal_buffer); |
1097 | free(zero_buffer); | 1088 | free(zero_buffer); |
1098 | 1089 | ||
1099 | return -1; | 1090 | return -1; |
1100 | 1091 | ||
1101 | } | 1092 | } |
1102 | 1093 | ||
1103 | 1094 | ||
1104 | static void alloc_single_indirect_block(struct ext2_inode *file_inode, | 1095 | static void alloc_single_indirect_block(struct ext2_inode *file_inode, |
1105 | unsigned int *total_remaining_blocks, | 1096 | unsigned int *total_remaining_blocks, |
1106 | unsigned int *no_blks_reqd) | 1097 | unsigned int *no_blks_reqd) |
1107 | { | 1098 | { |
1108 | short i; | 1099 | short i; |
1109 | short status; | 1100 | short status; |
1110 | long int actual_block_no; | 1101 | long int actual_block_no; |
1111 | long int si_blockno; | 1102 | long int si_blockno; |
1112 | /* si :single indirect */ | 1103 | /* si :single indirect */ |
1113 | unsigned int *si_buffer = NULL; | 1104 | unsigned int *si_buffer = NULL; |
1114 | unsigned int *si_start_addr = NULL; | 1105 | unsigned int *si_start_addr = NULL; |
1115 | struct ext_filesystem *fs = get_fs(); | 1106 | struct ext_filesystem *fs = get_fs(); |
1116 | 1107 | ||
1117 | if (*total_remaining_blocks != 0) { | 1108 | if (*total_remaining_blocks != 0) { |
1118 | si_buffer = zalloc(fs->blksz); | 1109 | si_buffer = zalloc(fs->blksz); |
1119 | if (!si_buffer) { | 1110 | if (!si_buffer) { |
1120 | printf("No Memory\n"); | 1111 | printf("No Memory\n"); |
1121 | return; | 1112 | return; |
1122 | } | 1113 | } |
1123 | si_start_addr = si_buffer; | 1114 | si_start_addr = si_buffer; |
1124 | si_blockno = ext4fs_get_new_blk_no(); | 1115 | si_blockno = ext4fs_get_new_blk_no(); |
1125 | if (si_blockno == -1) { | 1116 | if (si_blockno == -1) { |
1126 | printf("no block left to assign\n"); | 1117 | printf("no block left to assign\n"); |
1127 | goto fail; | 1118 | goto fail; |
1128 | } | 1119 | } |
1129 | (*no_blks_reqd)++; | 1120 | (*no_blks_reqd)++; |
1130 | debug("SIPB %ld: %u\n", si_blockno, *total_remaining_blocks); | 1121 | debug("SIPB %ld: %u\n", si_blockno, *total_remaining_blocks); |
1131 | 1122 | ||
1132 | status = ext4fs_devread((lbaint_t)si_blockno * fs->sect_perblk, | 1123 | status = ext4fs_devread((lbaint_t)si_blockno * fs->sect_perblk, |
1133 | 0, fs->blksz, (char *)si_buffer); | 1124 | 0, fs->blksz, (char *)si_buffer); |
1134 | memset(si_buffer, '\0', fs->blksz); | 1125 | memset(si_buffer, '\0', fs->blksz); |
1135 | if (status == 0) | 1126 | if (status == 0) |
1136 | goto fail; | 1127 | goto fail; |
1137 | 1128 | ||
1138 | for (i = 0; i < (fs->blksz / sizeof(int)); i++) { | 1129 | for (i = 0; i < (fs->blksz / sizeof(int)); i++) { |
1139 | actual_block_no = ext4fs_get_new_blk_no(); | 1130 | actual_block_no = ext4fs_get_new_blk_no(); |
1140 | if (actual_block_no == -1) { | 1131 | if (actual_block_no == -1) { |
1141 | printf("no block left to assign\n"); | 1132 | printf("no block left to assign\n"); |
1142 | goto fail; | 1133 | goto fail; |
1143 | } | 1134 | } |
1144 | *si_buffer = actual_block_no; | 1135 | *si_buffer = actual_block_no; |
1145 | debug("SIAB %u: %u\n", *si_buffer, | 1136 | debug("SIAB %u: %u\n", *si_buffer, |
1146 | *total_remaining_blocks); | 1137 | *total_remaining_blocks); |
1147 | 1138 | ||
1148 | si_buffer++; | 1139 | si_buffer++; |
1149 | (*total_remaining_blocks)--; | 1140 | (*total_remaining_blocks)--; |
1150 | if (*total_remaining_blocks == 0) | 1141 | if (*total_remaining_blocks == 0) |
1151 | break; | 1142 | break; |
1152 | } | 1143 | } |
1153 | 1144 | ||
1154 | /* write the block to disk */ | 1145 | /* write the block to disk */ |
1155 | put_ext4(((uint64_t) ((uint64_t)si_blockno * (uint64_t)fs->blksz)), | 1146 | put_ext4(((uint64_t) ((uint64_t)si_blockno * (uint64_t)fs->blksz)), |
1156 | si_start_addr, fs->blksz); | 1147 | si_start_addr, fs->blksz); |
1157 | file_inode->b.blocks.indir_block = si_blockno; | 1148 | file_inode->b.blocks.indir_block = si_blockno; |
1158 | } | 1149 | } |
1159 | fail: | 1150 | fail: |
1160 | free(si_start_addr); | 1151 | free(si_start_addr); |
1161 | } | 1152 | } |
1162 | 1153 | ||
1163 | static void alloc_double_indirect_block(struct ext2_inode *file_inode, | 1154 | static void alloc_double_indirect_block(struct ext2_inode *file_inode, |
1164 | unsigned int *total_remaining_blocks, | 1155 | unsigned int *total_remaining_blocks, |
1165 | unsigned int *no_blks_reqd) | 1156 | unsigned int *no_blks_reqd) |
1166 | { | 1157 | { |
1167 | short i; | 1158 | short i; |
1168 | short j; | 1159 | short j; |
1169 | short status; | 1160 | short status; |
1170 | long int actual_block_no; | 1161 | long int actual_block_no; |
1171 | /* di:double indirect */ | 1162 | /* di:double indirect */ |
1172 | long int di_blockno_parent; | 1163 | long int di_blockno_parent; |
1173 | long int di_blockno_child; | 1164 | long int di_blockno_child; |
1174 | unsigned int *di_parent_buffer = NULL; | 1165 | unsigned int *di_parent_buffer = NULL; |
1175 | unsigned int *di_child_buff = NULL; | 1166 | unsigned int *di_child_buff = NULL; |
1176 | unsigned int *di_block_start_addr = NULL; | 1167 | unsigned int *di_block_start_addr = NULL; |
1177 | unsigned int *di_child_buff_start = NULL; | 1168 | unsigned int *di_child_buff_start = NULL; |
1178 | struct ext_filesystem *fs = get_fs(); | 1169 | struct ext_filesystem *fs = get_fs(); |
1179 | 1170 | ||
1180 | if (*total_remaining_blocks != 0) { | 1171 | if (*total_remaining_blocks != 0) { |
1181 | /* double indirect parent block connecting to inode */ | 1172 | /* double indirect parent block connecting to inode */ |
1182 | di_blockno_parent = ext4fs_get_new_blk_no(); | 1173 | di_blockno_parent = ext4fs_get_new_blk_no(); |
1183 | if (di_blockno_parent == -1) { | 1174 | if (di_blockno_parent == -1) { |
1184 | printf("no block left to assign\n"); | 1175 | printf("no block left to assign\n"); |
1185 | goto fail; | 1176 | goto fail; |
1186 | } | 1177 | } |
1187 | di_parent_buffer = zalloc(fs->blksz); | 1178 | di_parent_buffer = zalloc(fs->blksz); |
1188 | if (!di_parent_buffer) | 1179 | if (!di_parent_buffer) |
1189 | goto fail; | 1180 | goto fail; |
1190 | 1181 | ||
1191 | di_block_start_addr = di_parent_buffer; | 1182 | di_block_start_addr = di_parent_buffer; |
1192 | (*no_blks_reqd)++; | 1183 | (*no_blks_reqd)++; |
1193 | debug("DIPB %ld: %u\n", di_blockno_parent, | 1184 | debug("DIPB %ld: %u\n", di_blockno_parent, |
1194 | *total_remaining_blocks); | 1185 | *total_remaining_blocks); |
1195 | 1186 | ||
1196 | status = ext4fs_devread((lbaint_t)di_blockno_parent * | 1187 | status = ext4fs_devread((lbaint_t)di_blockno_parent * |
1197 | fs->sect_perblk, 0, | 1188 | fs->sect_perblk, 0, |
1198 | fs->blksz, (char *)di_parent_buffer); | 1189 | fs->blksz, (char *)di_parent_buffer); |
1199 | 1190 | ||
1200 | if (!status) { | 1191 | if (!status) { |
1201 | printf("%s: Device read error!\n", __func__); | 1192 | printf("%s: Device read error!\n", __func__); |
1202 | goto fail; | 1193 | goto fail; |
1203 | } | 1194 | } |
1204 | memset(di_parent_buffer, '\0', fs->blksz); | 1195 | memset(di_parent_buffer, '\0', fs->blksz); |
1205 | 1196 | ||
1206 | /* | 1197 | /* |
1207 | * start:for each double indirect parent | 1198 | * start:for each double indirect parent |
1208 | * block create one more block | 1199 | * block create one more block |
1209 | */ | 1200 | */ |
1210 | for (i = 0; i < (fs->blksz / sizeof(int)); i++) { | 1201 | for (i = 0; i < (fs->blksz / sizeof(int)); i++) { |
1211 | di_blockno_child = ext4fs_get_new_blk_no(); | 1202 | di_blockno_child = ext4fs_get_new_blk_no(); |
1212 | if (di_blockno_child == -1) { | 1203 | if (di_blockno_child == -1) { |
1213 | printf("no block left to assign\n"); | 1204 | printf("no block left to assign\n"); |
1214 | goto fail; | 1205 | goto fail; |
1215 | } | 1206 | } |
1216 | di_child_buff = zalloc(fs->blksz); | 1207 | di_child_buff = zalloc(fs->blksz); |
1217 | if (!di_child_buff) | 1208 | if (!di_child_buff) |
1218 | goto fail; | 1209 | goto fail; |
1219 | 1210 | ||
1220 | di_child_buff_start = di_child_buff; | 1211 | di_child_buff_start = di_child_buff; |
1221 | *di_parent_buffer = di_blockno_child; | 1212 | *di_parent_buffer = di_blockno_child; |
1222 | di_parent_buffer++; | 1213 | di_parent_buffer++; |
1223 | (*no_blks_reqd)++; | 1214 | (*no_blks_reqd)++; |
1224 | debug("DICB %ld: %u\n", di_blockno_child, | 1215 | debug("DICB %ld: %u\n", di_blockno_child, |
1225 | *total_remaining_blocks); | 1216 | *total_remaining_blocks); |
1226 | 1217 | ||
1227 | status = ext4fs_devread((lbaint_t)di_blockno_child * | 1218 | status = ext4fs_devread((lbaint_t)di_blockno_child * |
1228 | fs->sect_perblk, 0, | 1219 | fs->sect_perblk, 0, |
1229 | fs->blksz, | 1220 | fs->blksz, |
1230 | (char *)di_child_buff); | 1221 | (char *)di_child_buff); |
1231 | 1222 | ||
1232 | if (!status) { | 1223 | if (!status) { |
1233 | printf("%s: Device read error!\n", __func__); | 1224 | printf("%s: Device read error!\n", __func__); |
1234 | goto fail; | 1225 | goto fail; |
1235 | } | 1226 | } |
1236 | memset(di_child_buff, '\0', fs->blksz); | 1227 | memset(di_child_buff, '\0', fs->blksz); |
1237 | /* filling of actual datablocks for each child */ | 1228 | /* filling of actual datablocks for each child */ |
1238 | for (j = 0; j < (fs->blksz / sizeof(int)); j++) { | 1229 | for (j = 0; j < (fs->blksz / sizeof(int)); j++) { |
1239 | actual_block_no = ext4fs_get_new_blk_no(); | 1230 | actual_block_no = ext4fs_get_new_blk_no(); |
1240 | if (actual_block_no == -1) { | 1231 | if (actual_block_no == -1) { |
1241 | printf("no block left to assign\n"); | 1232 | printf("no block left to assign\n"); |
1242 | goto fail; | 1233 | goto fail; |
1243 | } | 1234 | } |
1244 | *di_child_buff = actual_block_no; | 1235 | *di_child_buff = actual_block_no; |
1245 | debug("DIAB %ld: %u\n", actual_block_no, | 1236 | debug("DIAB %ld: %u\n", actual_block_no, |
1246 | *total_remaining_blocks); | 1237 | *total_remaining_blocks); |
1247 | 1238 | ||
1248 | di_child_buff++; | 1239 | di_child_buff++; |
1249 | (*total_remaining_blocks)--; | 1240 | (*total_remaining_blocks)--; |
1250 | if (*total_remaining_blocks == 0) | 1241 | if (*total_remaining_blocks == 0) |
1251 | break; | 1242 | break; |
1252 | } | 1243 | } |
1253 | /* write the block table */ | 1244 | /* write the block table */ |
1254 | put_ext4(((uint64_t) ((uint64_t)di_blockno_child * (uint64_t)fs->blksz)), | 1245 | put_ext4(((uint64_t) ((uint64_t)di_blockno_child * (uint64_t)fs->blksz)), |
1255 | di_child_buff_start, fs->blksz); | 1246 | di_child_buff_start, fs->blksz); |
1256 | free(di_child_buff_start); | 1247 | free(di_child_buff_start); |
1257 | di_child_buff_start = NULL; | 1248 | di_child_buff_start = NULL; |
1258 | 1249 | ||
1259 | if (*total_remaining_blocks == 0) | 1250 | if (*total_remaining_blocks == 0) |
1260 | break; | 1251 | break; |
1261 | } | 1252 | } |
1262 | put_ext4(((uint64_t) ((uint64_t)di_blockno_parent * (uint64_t)fs->blksz)), | 1253 | put_ext4(((uint64_t) ((uint64_t)di_blockno_parent * (uint64_t)fs->blksz)), |
1263 | di_block_start_addr, fs->blksz); | 1254 | di_block_start_addr, fs->blksz); |
1264 | file_inode->b.blocks.double_indir_block = di_blockno_parent; | 1255 | file_inode->b.blocks.double_indir_block = di_blockno_parent; |
1265 | } | 1256 | } |
1266 | fail: | 1257 | fail: |
1267 | free(di_block_start_addr); | 1258 | free(di_block_start_addr); |
1268 | } | 1259 | } |
1269 | 1260 | ||
1270 | static void alloc_triple_indirect_block(struct ext2_inode *file_inode, | 1261 | static void alloc_triple_indirect_block(struct ext2_inode *file_inode, |
1271 | unsigned int *total_remaining_blocks, | 1262 | unsigned int *total_remaining_blocks, |
1272 | unsigned int *no_blks_reqd) | 1263 | unsigned int *no_blks_reqd) |
1273 | { | 1264 | { |
1274 | short i; | 1265 | short i; |
1275 | short j; | 1266 | short j; |
1276 | short k; | 1267 | short k; |
1277 | long int actual_block_no; | 1268 | long int actual_block_no; |
1278 | /* ti: Triple Indirect */ | 1269 | /* ti: Triple Indirect */ |
1279 | long int ti_gp_blockno; | 1270 | long int ti_gp_blockno; |
1280 | long int ti_parent_blockno; | 1271 | long int ti_parent_blockno; |
1281 | long int ti_child_blockno; | 1272 | long int ti_child_blockno; |
1282 | unsigned int *ti_gp_buff = NULL; | 1273 | unsigned int *ti_gp_buff = NULL; |
1283 | unsigned int *ti_parent_buff = NULL; | 1274 | unsigned int *ti_parent_buff = NULL; |
1284 | unsigned int *ti_child_buff = NULL; | 1275 | unsigned int *ti_child_buff = NULL; |
1285 | unsigned int *ti_gp_buff_start_addr = NULL; | 1276 | unsigned int *ti_gp_buff_start_addr = NULL; |
1286 | unsigned int *ti_pbuff_start_addr = NULL; | 1277 | unsigned int *ti_pbuff_start_addr = NULL; |
1287 | unsigned int *ti_cbuff_start_addr = NULL; | 1278 | unsigned int *ti_cbuff_start_addr = NULL; |
1288 | struct ext_filesystem *fs = get_fs(); | 1279 | struct ext_filesystem *fs = get_fs(); |
1289 | if (*total_remaining_blocks != 0) { | 1280 | if (*total_remaining_blocks != 0) { |
1290 | /* triple indirect grand parent block connecting to inode */ | 1281 | /* triple indirect grand parent block connecting to inode */ |
1291 | ti_gp_blockno = ext4fs_get_new_blk_no(); | 1282 | ti_gp_blockno = ext4fs_get_new_blk_no(); |
1292 | if (ti_gp_blockno == -1) { | 1283 | if (ti_gp_blockno == -1) { |
1293 | printf("no block left to assign\n"); | 1284 | printf("no block left to assign\n"); |
1294 | goto fail; | 1285 | goto fail; |
1295 | } | 1286 | } |
1296 | ti_gp_buff = zalloc(fs->blksz); | 1287 | ti_gp_buff = zalloc(fs->blksz); |
1297 | if (!ti_gp_buff) | 1288 | if (!ti_gp_buff) |
1298 | goto fail; | 1289 | goto fail; |
1299 | 1290 | ||
1300 | ti_gp_buff_start_addr = ti_gp_buff; | 1291 | ti_gp_buff_start_addr = ti_gp_buff; |
1301 | (*no_blks_reqd)++; | 1292 | (*no_blks_reqd)++; |
1302 | debug("TIGPB %ld: %u\n", ti_gp_blockno, | 1293 | debug("TIGPB %ld: %u\n", ti_gp_blockno, |
1303 | *total_remaining_blocks); | 1294 | *total_remaining_blocks); |
1304 | 1295 | ||
1305 | /* for each 4 byte grand parent entry create one more block */ | 1296 | /* for each 4 byte grand parent entry create one more block */ |
1306 | for (i = 0; i < (fs->blksz / sizeof(int)); i++) { | 1297 | for (i = 0; i < (fs->blksz / sizeof(int)); i++) { |
1307 | ti_parent_blockno = ext4fs_get_new_blk_no(); | 1298 | ti_parent_blockno = ext4fs_get_new_blk_no(); |
1308 | if (ti_parent_blockno == -1) { | 1299 | if (ti_parent_blockno == -1) { |
1309 | printf("no block left to assign\n"); | 1300 | printf("no block left to assign\n"); |
1310 | goto fail; | 1301 | goto fail; |
1311 | } | 1302 | } |
1312 | ti_parent_buff = zalloc(fs->blksz); | 1303 | ti_parent_buff = zalloc(fs->blksz); |
1313 | if (!ti_parent_buff) | 1304 | if (!ti_parent_buff) |
1314 | goto fail; | 1305 | goto fail; |
1315 | 1306 | ||
1316 | ti_pbuff_start_addr = ti_parent_buff; | 1307 | ti_pbuff_start_addr = ti_parent_buff; |
1317 | *ti_gp_buff = ti_parent_blockno; | 1308 | *ti_gp_buff = ti_parent_blockno; |
1318 | ti_gp_buff++; | 1309 | ti_gp_buff++; |
1319 | (*no_blks_reqd)++; | 1310 | (*no_blks_reqd)++; |
1320 | debug("TIPB %ld: %u\n", ti_parent_blockno, | 1311 | debug("TIPB %ld: %u\n", ti_parent_blockno, |
1321 | *total_remaining_blocks); | 1312 | *total_remaining_blocks); |
1322 | 1313 | ||
1323 | /* for each 4 byte entry parent create one more block */ | 1314 | /* for each 4 byte entry parent create one more block */ |
1324 | for (j = 0; j < (fs->blksz / sizeof(int)); j++) { | 1315 | for (j = 0; j < (fs->blksz / sizeof(int)); j++) { |
1325 | ti_child_blockno = ext4fs_get_new_blk_no(); | 1316 | ti_child_blockno = ext4fs_get_new_blk_no(); |
1326 | if (ti_child_blockno == -1) { | 1317 | if (ti_child_blockno == -1) { |
1327 | printf("no block left assign\n"); | 1318 | printf("no block left assign\n"); |
1328 | goto fail; | 1319 | goto fail; |
1329 | } | 1320 | } |
1330 | ti_child_buff = zalloc(fs->blksz); | 1321 | ti_child_buff = zalloc(fs->blksz); |
1331 | if (!ti_child_buff) | 1322 | if (!ti_child_buff) |
1332 | goto fail; | 1323 | goto fail; |
1333 | 1324 | ||
1334 | ti_cbuff_start_addr = ti_child_buff; | 1325 | ti_cbuff_start_addr = ti_child_buff; |
1335 | *ti_parent_buff = ti_child_blockno; | 1326 | *ti_parent_buff = ti_child_blockno; |
1336 | ti_parent_buff++; | 1327 | ti_parent_buff++; |
1337 | (*no_blks_reqd)++; | 1328 | (*no_blks_reqd)++; |
1338 | debug("TICB %ld: %u\n", ti_parent_blockno, | 1329 | debug("TICB %ld: %u\n", ti_parent_blockno, |
1339 | *total_remaining_blocks); | 1330 | *total_remaining_blocks); |
1340 | 1331 | ||
1341 | /* fill actual datablocks for each child */ | 1332 | /* fill actual datablocks for each child */ |
1342 | for (k = 0; k < (fs->blksz / sizeof(int)); | 1333 | for (k = 0; k < (fs->blksz / sizeof(int)); |
1343 | k++) { | 1334 | k++) { |
1344 | actual_block_no = | 1335 | actual_block_no = |
1345 | ext4fs_get_new_blk_no(); | 1336 | ext4fs_get_new_blk_no(); |
1346 | if (actual_block_no == -1) { | 1337 | if (actual_block_no == -1) { |
1347 | printf("no block left\n"); | 1338 | printf("no block left\n"); |
1348 | goto fail; | 1339 | goto fail; |
1349 | } | 1340 | } |
1350 | *ti_child_buff = actual_block_no; | 1341 | *ti_child_buff = actual_block_no; |
1351 | debug("TIAB %ld: %u\n", actual_block_no, | 1342 | debug("TIAB %ld: %u\n", actual_block_no, |
1352 | *total_remaining_blocks); | 1343 | *total_remaining_blocks); |
1353 | 1344 | ||
1354 | ti_child_buff++; | 1345 | ti_child_buff++; |
1355 | (*total_remaining_blocks)--; | 1346 | (*total_remaining_blocks)--; |
1356 | if (*total_remaining_blocks == 0) | 1347 | if (*total_remaining_blocks == 0) |
1357 | break; | 1348 | break; |
1358 | } | 1349 | } |
1359 | /* write the child block */ | 1350 | /* write the child block */ |
1360 | put_ext4(((uint64_t) ((uint64_t)ti_child_blockno * | 1351 | put_ext4(((uint64_t) ((uint64_t)ti_child_blockno * |
1361 | (uint64_t)fs->blksz)), | 1352 | (uint64_t)fs->blksz)), |
1362 | ti_cbuff_start_addr, fs->blksz); | 1353 | ti_cbuff_start_addr, fs->blksz); |
1363 | free(ti_cbuff_start_addr); | 1354 | free(ti_cbuff_start_addr); |
1364 | 1355 | ||
1365 | if (*total_remaining_blocks == 0) | 1356 | if (*total_remaining_blocks == 0) |
1366 | break; | 1357 | break; |
1367 | } | 1358 | } |
1368 | /* write the parent block */ | 1359 | /* write the parent block */ |
1369 | put_ext4(((uint64_t) ((uint64_t)ti_parent_blockno * (uint64_t)fs->blksz)), | 1360 | put_ext4(((uint64_t) ((uint64_t)ti_parent_blockno * (uint64_t)fs->blksz)), |
1370 | ti_pbuff_start_addr, fs->blksz); | 1361 | ti_pbuff_start_addr, fs->blksz); |
1371 | free(ti_pbuff_start_addr); | 1362 | free(ti_pbuff_start_addr); |
1372 | 1363 | ||
1373 | if (*total_remaining_blocks == 0) | 1364 | if (*total_remaining_blocks == 0) |
1374 | break; | 1365 | break; |
1375 | } | 1366 | } |
1376 | /* write the grand parent block */ | 1367 | /* write the grand parent block */ |
1377 | put_ext4(((uint64_t) ((uint64_t)ti_gp_blockno * (uint64_t)fs->blksz)), | 1368 | put_ext4(((uint64_t) ((uint64_t)ti_gp_blockno * (uint64_t)fs->blksz)), |
1378 | ti_gp_buff_start_addr, fs->blksz); | 1369 | ti_gp_buff_start_addr, fs->blksz); |
1379 | file_inode->b.blocks.triple_indir_block = ti_gp_blockno; | 1370 | file_inode->b.blocks.triple_indir_block = ti_gp_blockno; |
1380 | } | 1371 | } |
1381 | fail: | 1372 | fail: |
1382 | free(ti_gp_buff_start_addr); | 1373 | free(ti_gp_buff_start_addr); |
1383 | } | 1374 | } |
1384 | 1375 | ||
1385 | void ext4fs_allocate_blocks(struct ext2_inode *file_inode, | 1376 | void ext4fs_allocate_blocks(struct ext2_inode *file_inode, |
1386 | unsigned int total_remaining_blocks, | 1377 | unsigned int total_remaining_blocks, |
1387 | unsigned int *total_no_of_block) | 1378 | unsigned int *total_no_of_block) |
1388 | { | 1379 | { |
1389 | short i; | 1380 | short i; |
1390 | long int direct_blockno; | 1381 | long int direct_blockno; |
1391 | unsigned int no_blks_reqd = 0; | 1382 | unsigned int no_blks_reqd = 0; |
1392 | 1383 | ||
1393 | /* allocation of direct blocks */ | 1384 | /* allocation of direct blocks */ |
1394 | for (i = 0; i < INDIRECT_BLOCKS; i++) { | 1385 | for (i = 0; i < INDIRECT_BLOCKS; i++) { |
1395 | direct_blockno = ext4fs_get_new_blk_no(); | 1386 | direct_blockno = ext4fs_get_new_blk_no(); |
1396 | if (direct_blockno == -1) { | 1387 | if (direct_blockno == -1) { |
1397 | printf("no block left to assign\n"); | 1388 | printf("no block left to assign\n"); |
1398 | return; | 1389 | return; |
1399 | } | 1390 | } |
1400 | file_inode->b.blocks.dir_blocks[i] = direct_blockno; | 1391 | file_inode->b.blocks.dir_blocks[i] = direct_blockno; |
1401 | debug("DB %ld: %u\n", direct_blockno, total_remaining_blocks); | 1392 | debug("DB %ld: %u\n", direct_blockno, total_remaining_blocks); |
1402 | 1393 | ||
1403 | total_remaining_blocks--; | 1394 | total_remaining_blocks--; |
1404 | if (total_remaining_blocks == 0) | 1395 | if (total_remaining_blocks == 0) |
1405 | break; | 1396 | break; |
1406 | } | 1397 | } |
1407 | 1398 | ||
1408 | alloc_single_indirect_block(file_inode, &total_remaining_blocks, | 1399 | alloc_single_indirect_block(file_inode, &total_remaining_blocks, |
1409 | &no_blks_reqd); | 1400 | &no_blks_reqd); |
1410 | alloc_double_indirect_block(file_inode, &total_remaining_blocks, | 1401 | alloc_double_indirect_block(file_inode, &total_remaining_blocks, |
1411 | &no_blks_reqd); | 1402 | &no_blks_reqd); |
1412 | alloc_triple_indirect_block(file_inode, &total_remaining_blocks, | 1403 | alloc_triple_indirect_block(file_inode, &total_remaining_blocks, |
1413 | &no_blks_reqd); | 1404 | &no_blks_reqd); |
1414 | *total_no_of_block += no_blks_reqd; | 1405 | *total_no_of_block += no_blks_reqd; |
1415 | } | 1406 | } |
1416 | 1407 | ||
1417 | #endif | 1408 | #endif |
1418 | 1409 | ||
1419 | static void ext4fs_extent_cache_insert(struct ext4_extent_node *new) | 1410 | static struct ext4_extent_header *ext4fs_get_extent_block |
1411 | (struct ext2_data *data, char *buf, | ||
1412 | struct ext4_extent_header *ext_block, | ||
1413 | uint32_t fileblock, int log2_blksz) | ||
1420 | { | 1414 | { |
1421 | struct ext4_extent_node *node; | ||
1422 | |||
1423 | list_for_each_entry(node, &ext4_extent_lh, lh) | ||
1424 | if (node->block > new->block) { | ||
1425 | list_add_tail(&new->lh, &node->lh); | ||
1426 | return; | ||
1427 | } | ||
1428 | list_add_tail(&new->lh, &ext4_extent_lh); | ||
1429 | } | ||
1430 | |||
1431 | static int __ext4fs_build_extent_cache(struct ext2_data *data, | ||
1432 | struct ext4_extent_header *ext_block) | ||
1433 | { | ||
1434 | int blksz = EXT2_BLOCK_SIZE(data); | ||
1435 | int log2_blksz = LOG2_BLOCK_SIZE(data) | ||
1436 | - get_fs()->dev_desc->log2blksz; | ||
1437 | struct ext4_extent_node *node; | ||
1438 | struct ext4_extent_idx *index; | 1415 | struct ext4_extent_idx *index; |
1439 | struct ext4_extent *extent; | ||
1440 | unsigned long long block; | 1416 | unsigned long long block; |
1441 | char *buf; | 1417 | int blksz = EXT2_BLOCK_SIZE(data); |
1442 | int i, err; | 1418 | int i; |
1443 | 1419 | ||
1444 | if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC) | 1420 | while (1) { |
1445 | return -EINVAL; | 1421 | index = (struct ext4_extent_idx *)(ext_block + 1); |
1446 | 1422 | ||
1447 | if (ext_block->eh_depth == 0) { | 1423 | if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC) |
1448 | extent = (struct ext4_extent *)(ext_block + 1); | 1424 | return 0; |
1449 | for (i = 0; i < le16_to_cpu(ext_block->eh_entries); i++) { | ||
1450 | node = malloc(sizeof(*node)); | ||
1451 | if (!node) | ||
1452 | return -ENOMEM; | ||
1453 | node->block = le32_to_cpu(extent[i].ee_block); | ||
1454 | node->len = le16_to_cpu(extent[i].ee_len); | ||
1455 | node->start = le16_to_cpu(extent[i].ee_start_hi); | ||
1456 | node->start = (node->start << 32) + | ||
1457 | le32_to_cpu(extent[i].ee_start_lo); | ||
1458 | ext4fs_extent_cache_insert(node); | ||
1459 | } | ||
1460 | return 0; | ||
1461 | } | ||
1462 | 1425 | ||
1463 | index = (struct ext4_extent_idx *)(ext_block + 1); | 1426 | if (ext_block->eh_depth == 0) |
1464 | for (i = 0; i < le16_to_cpu(ext_block->eh_entries); i++) { | 1427 | return ext_block; |
1465 | buf = malloc(blksz); | 1428 | i = -1; |
1466 | if (!buf) | 1429 | do { |
1467 | return -ENOMEM; | 1430 | i++; |
1431 | if (i >= le16_to_cpu(ext_block->eh_entries)) | ||
1432 | break; | ||
1433 | } while (fileblock >= le32_to_cpu(index[i].ei_block)); | ||
1468 | 1434 | ||
1435 | if (--i < 0) | ||
1436 | return 0; | ||
1437 | |||
1469 | block = le16_to_cpu(index[i].ei_leaf_hi); | 1438 | block = le16_to_cpu(index[i].ei_leaf_hi); |
1470 | block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo); | 1439 | block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo); |
1471 | 1440 | ||
1472 | if (!ext4fs_devread(block << log2_blksz, 0, blksz, buf)) { | 1441 | if (ext4fs_devread((lbaint_t)block << log2_blksz, 0, blksz, |
1473 | free(buf); | 1442 | buf)) |
1474 | return -EIO; | 1443 | ext_block = (struct ext4_extent_header *)buf; |
1475 | } | 1444 | else |
1476 | 1445 | return 0; | |
1477 | err = __ext4fs_build_extent_cache(data, | ||
1478 | (struct ext4_extent_header *) buf); | ||
1479 | free(buf); | ||
1480 | if (err < 0) | ||
1481 | return err; | ||
1482 | } | 1446 | } |
1483 | |||
1484 | return 0; | ||
1485 | } | 1447 | } |
1486 | 1448 | ||
1487 | int ext4fs_build_extent_cache(struct ext2_inode *inode) | ||
1488 | { | ||
1489 | return __ext4fs_build_extent_cache(ext4fs_root, | ||
1490 | (struct ext4_extent_header *) | ||
1491 | inode->b.blocks.dir_blocks); | ||
1492 | } | ||
1493 | |||
1494 | void ext4fs_free_extent_cache(void) | ||
1495 | { | ||
1496 | struct ext4_extent_node *node, *tmp; | ||
1497 | |||
1498 | list_for_each_entry_safe(node, tmp, &ext4_extent_lh, lh) { | ||
1499 | list_del(&node->lh); | ||
1500 | free(node); | ||
1501 | } | ||
1502 | } | ||
1503 | |||
1504 | static struct ext4_extent_node *ext4fs_extent_cache_get(uint32_t block) | ||
1505 | { | ||
1506 | struct ext4_extent_node *node; | ||
1507 | |||
1508 | list_for_each_entry(node, &ext4_extent_lh, lh) | ||
1509 | if (block >= node->block && block < node->block + node->len) | ||
1510 | return node; | ||
1511 | |||
1512 | return NULL; | ||
1513 | } | ||
1514 | |||
1515 | static int ext4fs_blockgroup | 1449 | static int ext4fs_blockgroup |
1516 | (struct ext2_data *data, int group, struct ext2_block_group *blkgrp) | 1450 | (struct ext2_data *data, int group, struct ext2_block_group *blkgrp) |
1517 | { | 1451 | { |
1518 | long int blkno; | 1452 | long int blkno; |
1519 | unsigned int blkoff, desc_per_blk; | 1453 | unsigned int blkoff, desc_per_blk; |
1520 | int log2blksz = get_fs()->dev_desc->log2blksz; | 1454 | int log2blksz = get_fs()->dev_desc->log2blksz; |
1521 | 1455 | ||
1522 | desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group); | 1456 | desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group); |
1523 | 1457 | ||
1524 | blkno = __le32_to_cpu(data->sblock.first_data_block) + 1 + | 1458 | blkno = __le32_to_cpu(data->sblock.first_data_block) + 1 + |
1525 | group / desc_per_blk; | 1459 | group / desc_per_blk; |
1526 | blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group); | 1460 | blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group); |
1527 | 1461 | ||
1528 | debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n", | 1462 | debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n", |
1529 | group, blkno, blkoff); | 1463 | group, blkno, blkoff); |
1530 | 1464 | ||
1531 | return ext4fs_devread((lbaint_t)blkno << | 1465 | return ext4fs_devread((lbaint_t)blkno << |
1532 | (LOG2_BLOCK_SIZE(data) - log2blksz), | 1466 | (LOG2_BLOCK_SIZE(data) - log2blksz), |
1533 | blkoff, sizeof(struct ext2_block_group), | 1467 | blkoff, sizeof(struct ext2_block_group), |
1534 | (char *)blkgrp); | 1468 | (char *)blkgrp); |
1535 | } | 1469 | } |
1536 | 1470 | ||
1537 | int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode) | 1471 | int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode) |
1538 | { | 1472 | { |
1539 | struct ext2_block_group blkgrp; | 1473 | struct ext2_block_group blkgrp; |
1540 | struct ext2_sblock *sblock = &data->sblock; | 1474 | struct ext2_sblock *sblock = &data->sblock; |
1541 | struct ext_filesystem *fs = get_fs(); | 1475 | struct ext_filesystem *fs = get_fs(); |
1542 | int log2blksz = get_fs()->dev_desc->log2blksz; | 1476 | int log2blksz = get_fs()->dev_desc->log2blksz; |
1543 | int inodes_per_block, status; | 1477 | int inodes_per_block, status; |
1544 | long int blkno; | 1478 | long int blkno; |
1545 | unsigned int blkoff; | 1479 | unsigned int blkoff; |
1546 | 1480 | ||
1547 | /* It is easier to calculate if the first inode is 0. */ | 1481 | /* It is easier to calculate if the first inode is 0. */ |
1548 | ino--; | 1482 | ino--; |
1549 | status = ext4fs_blockgroup(data, ino / __le32_to_cpu | 1483 | status = ext4fs_blockgroup(data, ino / __le32_to_cpu |
1550 | (sblock->inodes_per_group), &blkgrp); | 1484 | (sblock->inodes_per_group), &blkgrp); |
1551 | if (status == 0) | 1485 | if (status == 0) |
1552 | return 0; | 1486 | return 0; |
1553 | 1487 | ||
1554 | inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz; | 1488 | inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz; |
1555 | blkno = __le32_to_cpu(blkgrp.inode_table_id) + | 1489 | blkno = __le32_to_cpu(blkgrp.inode_table_id) + |
1556 | (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; | 1490 | (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; |
1557 | blkoff = (ino % inodes_per_block) * fs->inodesz; | 1491 | blkoff = (ino % inodes_per_block) * fs->inodesz; |
1558 | /* Read the inode. */ | 1492 | /* Read the inode. */ |
1559 | status = ext4fs_devread((lbaint_t)blkno << (LOG2_BLOCK_SIZE(data) - | 1493 | status = ext4fs_devread((lbaint_t)blkno << (LOG2_BLOCK_SIZE(data) - |
1560 | log2blksz), blkoff, | 1494 | log2blksz), blkoff, |
1561 | sizeof(struct ext2_inode), (char *)inode); | 1495 | sizeof(struct ext2_inode), (char *)inode); |
1562 | if (status == 0) | 1496 | if (status == 0) |
1563 | return 0; | 1497 | return 0; |
1564 | 1498 | ||
1565 | return 1; | 1499 | return 1; |
1566 | } | 1500 | } |
1567 | 1501 | ||
1568 | long int read_allocated_block(struct ext2_inode *inode, int fileblock) | 1502 | long int read_allocated_block(struct ext2_inode *inode, int fileblock) |
1569 | { | 1503 | { |
1570 | long int blknr; | 1504 | long int blknr; |
1571 | int blksz; | 1505 | int blksz; |
1572 | int log2_blksz; | 1506 | int log2_blksz; |
1573 | int status; | 1507 | int status; |
1574 | long int rblock; | 1508 | long int rblock; |
1575 | long int perblock_parent; | 1509 | long int perblock_parent; |
1576 | long int perblock_child; | 1510 | long int perblock_child; |
1577 | 1511 | unsigned long long start; | |
1578 | /* get the blocksize of the filesystem */ | 1512 | /* get the blocksize of the filesystem */ |
1579 | blksz = EXT2_BLOCK_SIZE(ext4fs_root); | 1513 | blksz = EXT2_BLOCK_SIZE(ext4fs_root); |
1580 | log2_blksz = LOG2_BLOCK_SIZE(ext4fs_root) | 1514 | log2_blksz = LOG2_BLOCK_SIZE(ext4fs_root) |
1581 | - get_fs()->dev_desc->log2blksz; | 1515 | - get_fs()->dev_desc->log2blksz; |
1582 | 1516 | ||
1583 | if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) { | 1517 | if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) { |
1584 | struct ext4_extent_node *node; | 1518 | char *buf = zalloc(blksz); |
1519 | if (!buf) | ||
1520 | return -ENOMEM; | ||
1521 | struct ext4_extent_header *ext_block; | ||
1522 | struct ext4_extent *extent; | ||
1523 | int i = -1; | ||
1524 | ext_block = | ||
1525 | ext4fs_get_extent_block(ext4fs_root, buf, | ||
1526 | (struct ext4_extent_header *) | ||
1527 | inode->b.blocks.dir_blocks, | ||
1528 | fileblock, log2_blksz); | ||
1529 | if (!ext_block) { | ||
1530 | printf("invalid extent block\n"); | ||
1531 | free(buf); | ||
1532 | return -EINVAL; | ||
1533 | } | ||
1585 | 1534 | ||
1586 | node = ext4fs_extent_cache_get(fileblock); | 1535 | extent = (struct ext4_extent *)(ext_block + 1); |
1587 | if (!node) { | 1536 | |
1588 | printf("Extent Error\n"); | 1537 | do { |
1589 | return -1; | 1538 | i++; |
1539 | if (i >= le16_to_cpu(ext_block->eh_entries)) | ||
1540 | break; | ||
1541 | } while (fileblock >= le32_to_cpu(extent[i].ee_block)); | ||
1542 | if (--i >= 0) { | ||
1543 | fileblock -= le32_to_cpu(extent[i].ee_block); | ||
1544 | if (fileblock >= le16_to_cpu(extent[i].ee_len)) { | ||
1545 | free(buf); | ||
1546 | return 0; | ||
1547 | } | ||
1548 | |||
1549 | start = le16_to_cpu(extent[i].ee_start_hi); | ||
1550 | start = (start << 32) + | ||
1551 | le32_to_cpu(extent[i].ee_start_lo); | ||
1552 | free(buf); | ||
1553 | return fileblock + start; | ||
1590 | } | 1554 | } |
1591 | 1555 | ||
1592 | return fileblock - node->block + node->start; | 1556 | printf("Extent Error\n"); |
1557 | free(buf); | ||
1558 | return -1; | ||
1593 | } | 1559 | } |
1594 | 1560 | ||
1595 | /* Direct blocks. */ | 1561 | /* Direct blocks. */ |
1596 | if (fileblock < INDIRECT_BLOCKS) | 1562 | if (fileblock < INDIRECT_BLOCKS) |
1597 | blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]); | 1563 | blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]); |
1598 | 1564 | ||
1599 | /* Indirect. */ | 1565 | /* Indirect. */ |
1600 | else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) { | 1566 | else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) { |
1601 | if (ext4fs_indir1_block == NULL) { | 1567 | if (ext4fs_indir1_block == NULL) { |
1602 | ext4fs_indir1_block = zalloc(blksz); | 1568 | ext4fs_indir1_block = zalloc(blksz); |
1603 | if (ext4fs_indir1_block == NULL) { | 1569 | if (ext4fs_indir1_block == NULL) { |
1604 | printf("** SI ext2fs read block (indir 1)" | 1570 | printf("** SI ext2fs read block (indir 1)" |
1605 | "malloc failed. **\n"); | 1571 | "malloc failed. **\n"); |
1606 | return -1; | 1572 | return -1; |
1607 | } | 1573 | } |
1608 | ext4fs_indir1_size = blksz; | 1574 | ext4fs_indir1_size = blksz; |
1609 | ext4fs_indir1_blkno = -1; | 1575 | ext4fs_indir1_blkno = -1; |
1610 | } | 1576 | } |
1611 | if (blksz != ext4fs_indir1_size) { | 1577 | if (blksz != ext4fs_indir1_size) { |
1612 | free(ext4fs_indir1_block); | 1578 | free(ext4fs_indir1_block); |
1613 | ext4fs_indir1_block = NULL; | 1579 | ext4fs_indir1_block = NULL; |
1614 | ext4fs_indir1_size = 0; | 1580 | ext4fs_indir1_size = 0; |
1615 | ext4fs_indir1_blkno = -1; | 1581 | ext4fs_indir1_blkno = -1; |
1616 | ext4fs_indir1_block = zalloc(blksz); | 1582 | ext4fs_indir1_block = zalloc(blksz); |
1617 | if (ext4fs_indir1_block == NULL) { | 1583 | if (ext4fs_indir1_block == NULL) { |
1618 | printf("** SI ext2fs read block (indir 1):" | 1584 | printf("** SI ext2fs read block (indir 1):" |
1619 | "malloc failed. **\n"); | 1585 | "malloc failed. **\n"); |
1620 | return -1; | 1586 | return -1; |
1621 | } | 1587 | } |
1622 | ext4fs_indir1_size = blksz; | 1588 | ext4fs_indir1_size = blksz; |
1623 | } | 1589 | } |
1624 | if ((__le32_to_cpu(inode->b.blocks.indir_block) << | 1590 | if ((__le32_to_cpu(inode->b.blocks.indir_block) << |
1625 | log2_blksz) != ext4fs_indir1_blkno) { | 1591 | log2_blksz) != ext4fs_indir1_blkno) { |
1626 | status = | 1592 | status = |
1627 | ext4fs_devread((lbaint_t)__le32_to_cpu | 1593 | ext4fs_devread((lbaint_t)__le32_to_cpu |
1628 | (inode->b.blocks. | 1594 | (inode->b.blocks. |
1629 | indir_block) << log2_blksz, 0, | 1595 | indir_block) << log2_blksz, 0, |
1630 | blksz, (char *)ext4fs_indir1_block); | 1596 | blksz, (char *)ext4fs_indir1_block); |
1631 | if (status == 0) { | 1597 | if (status == 0) { |
1632 | printf("** SI ext2fs read block (indir 1)" | 1598 | printf("** SI ext2fs read block (indir 1)" |
1633 | "failed. **\n"); | 1599 | "failed. **\n"); |
1634 | return 0; | 1600 | return 0; |
1635 | } | 1601 | } |
1636 | ext4fs_indir1_blkno = | 1602 | ext4fs_indir1_blkno = |
1637 | __le32_to_cpu(inode->b.blocks. | 1603 | __le32_to_cpu(inode->b.blocks. |
1638 | indir_block) << log2_blksz; | 1604 | indir_block) << log2_blksz; |
1639 | } | 1605 | } |
1640 | blknr = __le32_to_cpu(ext4fs_indir1_block | 1606 | blknr = __le32_to_cpu(ext4fs_indir1_block |
1641 | [fileblock - INDIRECT_BLOCKS]); | 1607 | [fileblock - INDIRECT_BLOCKS]); |
1642 | } | 1608 | } |
1643 | /* Double indirect. */ | 1609 | /* Double indirect. */ |
1644 | else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4 * | 1610 | else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4 * |
1645 | (blksz / 4 + 1)))) { | 1611 | (blksz / 4 + 1)))) { |
1646 | 1612 | ||
1647 | long int perblock = blksz / 4; | 1613 | long int perblock = blksz / 4; |
1648 | long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4); | 1614 | long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4); |
1649 | 1615 | ||
1650 | if (ext4fs_indir1_block == NULL) { | 1616 | if (ext4fs_indir1_block == NULL) { |
1651 | ext4fs_indir1_block = zalloc(blksz); | 1617 | ext4fs_indir1_block = zalloc(blksz); |
1652 | if (ext4fs_indir1_block == NULL) { | 1618 | if (ext4fs_indir1_block == NULL) { |
1653 | printf("** DI ext2fs read block (indir 2 1)" | 1619 | printf("** DI ext2fs read block (indir 2 1)" |
1654 | "malloc failed. **\n"); | 1620 | "malloc failed. **\n"); |
1655 | return -1; | 1621 | return -1; |
1656 | } | 1622 | } |
1657 | ext4fs_indir1_size = blksz; | 1623 | ext4fs_indir1_size = blksz; |
1658 | ext4fs_indir1_blkno = -1; | 1624 | ext4fs_indir1_blkno = -1; |
1659 | } | 1625 | } |
1660 | if (blksz != ext4fs_indir1_size) { | 1626 | if (blksz != ext4fs_indir1_size) { |
1661 | free(ext4fs_indir1_block); | 1627 | free(ext4fs_indir1_block); |
1662 | ext4fs_indir1_block = NULL; | 1628 | ext4fs_indir1_block = NULL; |
1663 | ext4fs_indir1_size = 0; | 1629 | ext4fs_indir1_size = 0; |
1664 | ext4fs_indir1_blkno = -1; | 1630 | ext4fs_indir1_blkno = -1; |
1665 | ext4fs_indir1_block = zalloc(blksz); | 1631 | ext4fs_indir1_block = zalloc(blksz); |
1666 | if (ext4fs_indir1_block == NULL) { | 1632 | if (ext4fs_indir1_block == NULL) { |
1667 | printf("** DI ext2fs read block (indir 2 1)" | 1633 | printf("** DI ext2fs read block (indir 2 1)" |
1668 | "malloc failed. **\n"); | 1634 | "malloc failed. **\n"); |
1669 | return -1; | 1635 | return -1; |
1670 | } | 1636 | } |
1671 | ext4fs_indir1_size = blksz; | 1637 | ext4fs_indir1_size = blksz; |
1672 | } | 1638 | } |
1673 | if ((__le32_to_cpu(inode->b.blocks.double_indir_block) << | 1639 | if ((__le32_to_cpu(inode->b.blocks.double_indir_block) << |
1674 | log2_blksz) != ext4fs_indir1_blkno) { | 1640 | log2_blksz) != ext4fs_indir1_blkno) { |
1675 | status = | 1641 | status = |
1676 | ext4fs_devread((lbaint_t)__le32_to_cpu | 1642 | ext4fs_devread((lbaint_t)__le32_to_cpu |
1677 | (inode->b.blocks. | 1643 | (inode->b.blocks. |
1678 | double_indir_block) << log2_blksz, | 1644 | double_indir_block) << log2_blksz, |
1679 | 0, blksz, | 1645 | 0, blksz, |
1680 | (char *)ext4fs_indir1_block); | 1646 | (char *)ext4fs_indir1_block); |
1681 | if (status == 0) { | 1647 | if (status == 0) { |
1682 | printf("** DI ext2fs read block (indir 2 1)" | 1648 | printf("** DI ext2fs read block (indir 2 1)" |
1683 | "failed. **\n"); | 1649 | "failed. **\n"); |
1684 | return -1; | 1650 | return -1; |
1685 | } | 1651 | } |
1686 | ext4fs_indir1_blkno = | 1652 | ext4fs_indir1_blkno = |
1687 | __le32_to_cpu(inode->b.blocks.double_indir_block) << | 1653 | __le32_to_cpu(inode->b.blocks.double_indir_block) << |
1688 | log2_blksz; | 1654 | log2_blksz; |
1689 | } | 1655 | } |
1690 | 1656 | ||
1691 | if (ext4fs_indir2_block == NULL) { | 1657 | if (ext4fs_indir2_block == NULL) { |
1692 | ext4fs_indir2_block = zalloc(blksz); | 1658 | ext4fs_indir2_block = zalloc(blksz); |
1693 | if (ext4fs_indir2_block == NULL) { | 1659 | if (ext4fs_indir2_block == NULL) { |
1694 | printf("** DI ext2fs read block (indir 2 2)" | 1660 | printf("** DI ext2fs read block (indir 2 2)" |
1695 | "malloc failed. **\n"); | 1661 | "malloc failed. **\n"); |
1696 | return -1; | 1662 | return -1; |
1697 | } | 1663 | } |
1698 | ext4fs_indir2_size = blksz; | 1664 | ext4fs_indir2_size = blksz; |
1699 | ext4fs_indir2_blkno = -1; | 1665 | ext4fs_indir2_blkno = -1; |
1700 | } | 1666 | } |
1701 | if (blksz != ext4fs_indir2_size) { | 1667 | if (blksz != ext4fs_indir2_size) { |
1702 | free(ext4fs_indir2_block); | 1668 | free(ext4fs_indir2_block); |
1703 | ext4fs_indir2_block = NULL; | 1669 | ext4fs_indir2_block = NULL; |
1704 | ext4fs_indir2_size = 0; | 1670 | ext4fs_indir2_size = 0; |
1705 | ext4fs_indir2_blkno = -1; | 1671 | ext4fs_indir2_blkno = -1; |
1706 | ext4fs_indir2_block = zalloc(blksz); | 1672 | ext4fs_indir2_block = zalloc(blksz); |
1707 | if (ext4fs_indir2_block == NULL) { | 1673 | if (ext4fs_indir2_block == NULL) { |
1708 | printf("** DI ext2fs read block (indir 2 2)" | 1674 | printf("** DI ext2fs read block (indir 2 2)" |
1709 | "malloc failed. **\n"); | 1675 | "malloc failed. **\n"); |
1710 | return -1; | 1676 | return -1; |
1711 | } | 1677 | } |
1712 | ext4fs_indir2_size = blksz; | 1678 | ext4fs_indir2_size = blksz; |
1713 | } | 1679 | } |
1714 | if ((__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) << | 1680 | if ((__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) << |
1715 | log2_blksz) != ext4fs_indir2_blkno) { | 1681 | log2_blksz) != ext4fs_indir2_blkno) { |
1716 | status = ext4fs_devread((lbaint_t)__le32_to_cpu | 1682 | status = ext4fs_devread((lbaint_t)__le32_to_cpu |
1717 | (ext4fs_indir1_block | 1683 | (ext4fs_indir1_block |
1718 | [rblock / | 1684 | [rblock / |
1719 | perblock]) << log2_blksz, 0, | 1685 | perblock]) << log2_blksz, 0, |
1720 | blksz, | 1686 | blksz, |
1721 | (char *)ext4fs_indir2_block); | 1687 | (char *)ext4fs_indir2_block); |
1722 | if (status == 0) { | 1688 | if (status == 0) { |
1723 | printf("** DI ext2fs read block (indir 2 2)" | 1689 | printf("** DI ext2fs read block (indir 2 2)" |
1724 | "failed. **\n"); | 1690 | "failed. **\n"); |
1725 | return -1; | 1691 | return -1; |
1726 | } | 1692 | } |
1727 | ext4fs_indir2_blkno = | 1693 | ext4fs_indir2_blkno = |
1728 | __le32_to_cpu(ext4fs_indir1_block[rblock | 1694 | __le32_to_cpu(ext4fs_indir1_block[rblock |
1729 | / | 1695 | / |
1730 | perblock]) << | 1696 | perblock]) << |
1731 | log2_blksz; | 1697 | log2_blksz; |
1732 | } | 1698 | } |
1733 | blknr = __le32_to_cpu(ext4fs_indir2_block[rblock % perblock]); | 1699 | blknr = __le32_to_cpu(ext4fs_indir2_block[rblock % perblock]); |
1734 | } | 1700 | } |
1735 | /* Tripple indirect. */ | 1701 | /* Tripple indirect. */ |
1736 | else { | 1702 | else { |
1737 | rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 + | 1703 | rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 + |
1738 | (blksz / 4 * blksz / 4)); | 1704 | (blksz / 4 * blksz / 4)); |
1739 | perblock_child = blksz / 4; | 1705 | perblock_child = blksz / 4; |
1740 | perblock_parent = ((blksz / 4) * (blksz / 4)); | 1706 | perblock_parent = ((blksz / 4) * (blksz / 4)); |
1741 | 1707 | ||
1742 | if (ext4fs_indir1_block == NULL) { | 1708 | if (ext4fs_indir1_block == NULL) { |
1743 | ext4fs_indir1_block = zalloc(blksz); | 1709 | ext4fs_indir1_block = zalloc(blksz); |
1744 | if (ext4fs_indir1_block == NULL) { | 1710 | if (ext4fs_indir1_block == NULL) { |
1745 | printf("** TI ext2fs read block (indir 2 1)" | 1711 | printf("** TI ext2fs read block (indir 2 1)" |
1746 | "malloc failed. **\n"); | 1712 | "malloc failed. **\n"); |
1747 | return -1; | 1713 | return -1; |
1748 | } | 1714 | } |
1749 | ext4fs_indir1_size = blksz; | 1715 | ext4fs_indir1_size = blksz; |
1750 | ext4fs_indir1_blkno = -1; | 1716 | ext4fs_indir1_blkno = -1; |
1751 | } | 1717 | } |
1752 | if (blksz != ext4fs_indir1_size) { | 1718 | if (blksz != ext4fs_indir1_size) { |
1753 | free(ext4fs_indir1_block); | 1719 | free(ext4fs_indir1_block); |
1754 | ext4fs_indir1_block = NULL; | 1720 | ext4fs_indir1_block = NULL; |
1755 | ext4fs_indir1_size = 0; | 1721 | ext4fs_indir1_size = 0; |
1756 | ext4fs_indir1_blkno = -1; | 1722 | ext4fs_indir1_blkno = -1; |
1757 | ext4fs_indir1_block = zalloc(blksz); | 1723 | ext4fs_indir1_block = zalloc(blksz); |
1758 | if (ext4fs_indir1_block == NULL) { | 1724 | if (ext4fs_indir1_block == NULL) { |
1759 | printf("** TI ext2fs read block (indir 2 1)" | 1725 | printf("** TI ext2fs read block (indir 2 1)" |
1760 | "malloc failed. **\n"); | 1726 | "malloc failed. **\n"); |
1761 | return -1; | 1727 | return -1; |
1762 | } | 1728 | } |
1763 | ext4fs_indir1_size = blksz; | 1729 | ext4fs_indir1_size = blksz; |
1764 | } | 1730 | } |
1765 | if ((__le32_to_cpu(inode->b.blocks.triple_indir_block) << | 1731 | if ((__le32_to_cpu(inode->b.blocks.triple_indir_block) << |
1766 | log2_blksz) != ext4fs_indir1_blkno) { | 1732 | log2_blksz) != ext4fs_indir1_blkno) { |
1767 | status = ext4fs_devread | 1733 | status = ext4fs_devread |
1768 | ((lbaint_t) | 1734 | ((lbaint_t) |
1769 | __le32_to_cpu(inode->b.blocks.triple_indir_block) | 1735 | __le32_to_cpu(inode->b.blocks.triple_indir_block) |
1770 | << log2_blksz, 0, blksz, | 1736 | << log2_blksz, 0, blksz, |
1771 | (char *)ext4fs_indir1_block); | 1737 | (char *)ext4fs_indir1_block); |
1772 | if (status == 0) { | 1738 | if (status == 0) { |
1773 | printf("** TI ext2fs read block (indir 2 1)" | 1739 | printf("** TI ext2fs read block (indir 2 1)" |
1774 | "failed. **\n"); | 1740 | "failed. **\n"); |
1775 | return -1; | 1741 | return -1; |
1776 | } | 1742 | } |
1777 | ext4fs_indir1_blkno = | 1743 | ext4fs_indir1_blkno = |
1778 | __le32_to_cpu(inode->b.blocks.triple_indir_block) << | 1744 | __le32_to_cpu(inode->b.blocks.triple_indir_block) << |
1779 | log2_blksz; | 1745 | log2_blksz; |
1780 | } | 1746 | } |
1781 | 1747 | ||
1782 | if (ext4fs_indir2_block == NULL) { | 1748 | if (ext4fs_indir2_block == NULL) { |
1783 | ext4fs_indir2_block = zalloc(blksz); | 1749 | ext4fs_indir2_block = zalloc(blksz); |
1784 | if (ext4fs_indir2_block == NULL) { | 1750 | if (ext4fs_indir2_block == NULL) { |
1785 | printf("** TI ext2fs read block (indir 2 2)" | 1751 | printf("** TI ext2fs read block (indir 2 2)" |
1786 | "malloc failed. **\n"); | 1752 | "malloc failed. **\n"); |
1787 | return -1; | 1753 | return -1; |
1788 | } | 1754 | } |
1789 | ext4fs_indir2_size = blksz; | 1755 | ext4fs_indir2_size = blksz; |
1790 | ext4fs_indir2_blkno = -1; | 1756 | ext4fs_indir2_blkno = -1; |
1791 | } | 1757 | } |
1792 | if (blksz != ext4fs_indir2_size) { | 1758 | if (blksz != ext4fs_indir2_size) { |
1793 | free(ext4fs_indir2_block); | 1759 | free(ext4fs_indir2_block); |
1794 | ext4fs_indir2_block = NULL; | 1760 | ext4fs_indir2_block = NULL; |
1795 | ext4fs_indir2_size = 0; | 1761 | ext4fs_indir2_size = 0; |
1796 | ext4fs_indir2_blkno = -1; | 1762 | ext4fs_indir2_blkno = -1; |
1797 | ext4fs_indir2_block = zalloc(blksz); | 1763 | ext4fs_indir2_block = zalloc(blksz); |
1798 | if (ext4fs_indir2_block == NULL) { | 1764 | if (ext4fs_indir2_block == NULL) { |
1799 | printf("** TI ext2fs read block (indir 2 2)" | 1765 | printf("** TI ext2fs read block (indir 2 2)" |
1800 | "malloc failed. **\n"); | 1766 | "malloc failed. **\n"); |
1801 | return -1; | 1767 | return -1; |
1802 | } | 1768 | } |
1803 | ext4fs_indir2_size = blksz; | 1769 | ext4fs_indir2_size = blksz; |
1804 | } | 1770 | } |
1805 | if ((__le32_to_cpu(ext4fs_indir1_block[rblock / | 1771 | if ((__le32_to_cpu(ext4fs_indir1_block[rblock / |
1806 | perblock_parent]) << | 1772 | perblock_parent]) << |
1807 | log2_blksz) | 1773 | log2_blksz) |
1808 | != ext4fs_indir2_blkno) { | 1774 | != ext4fs_indir2_blkno) { |
1809 | status = ext4fs_devread((lbaint_t)__le32_to_cpu | 1775 | status = ext4fs_devread((lbaint_t)__le32_to_cpu |
1810 | (ext4fs_indir1_block | 1776 | (ext4fs_indir1_block |
1811 | [rblock / | 1777 | [rblock / |
1812 | perblock_parent]) << | 1778 | perblock_parent]) << |
1813 | log2_blksz, 0, blksz, | 1779 | log2_blksz, 0, blksz, |
1814 | (char *)ext4fs_indir2_block); | 1780 | (char *)ext4fs_indir2_block); |
1815 | if (status == 0) { | 1781 | if (status == 0) { |
1816 | printf("** TI ext2fs read block (indir 2 2)" | 1782 | printf("** TI ext2fs read block (indir 2 2)" |
1817 | "failed. **\n"); | 1783 | "failed. **\n"); |
1818 | return -1; | 1784 | return -1; |
1819 | } | 1785 | } |
1820 | ext4fs_indir2_blkno = | 1786 | ext4fs_indir2_blkno = |
1821 | __le32_to_cpu(ext4fs_indir1_block[rblock / | 1787 | __le32_to_cpu(ext4fs_indir1_block[rblock / |
1822 | perblock_parent]) | 1788 | perblock_parent]) |
1823 | << log2_blksz; | 1789 | << log2_blksz; |
1824 | } | 1790 | } |
1825 | 1791 | ||
1826 | if (ext4fs_indir3_block == NULL) { | 1792 | if (ext4fs_indir3_block == NULL) { |
1827 | ext4fs_indir3_block = zalloc(blksz); | 1793 | ext4fs_indir3_block = zalloc(blksz); |
1828 | if (ext4fs_indir3_block == NULL) { | 1794 | if (ext4fs_indir3_block == NULL) { |
1829 | printf("** TI ext2fs read block (indir 2 2)" | 1795 | printf("** TI ext2fs read block (indir 2 2)" |
1830 | "malloc failed. **\n"); | 1796 | "malloc failed. **\n"); |
1831 | return -1; | 1797 | return -1; |
1832 | } | 1798 | } |
1833 | ext4fs_indir3_size = blksz; | 1799 | ext4fs_indir3_size = blksz; |
1834 | ext4fs_indir3_blkno = -1; | 1800 | ext4fs_indir3_blkno = -1; |
1835 | } | 1801 | } |
1836 | if (blksz != ext4fs_indir3_size) { | 1802 | if (blksz != ext4fs_indir3_size) { |
1837 | free(ext4fs_indir3_block); | 1803 | free(ext4fs_indir3_block); |
1838 | ext4fs_indir3_block = NULL; | 1804 | ext4fs_indir3_block = NULL; |
1839 | ext4fs_indir3_size = 0; | 1805 | ext4fs_indir3_size = 0; |
1840 | ext4fs_indir3_blkno = -1; | 1806 | ext4fs_indir3_blkno = -1; |
1841 | ext4fs_indir3_block = zalloc(blksz); | 1807 | ext4fs_indir3_block = zalloc(blksz); |
1842 | if (ext4fs_indir3_block == NULL) { | 1808 | if (ext4fs_indir3_block == NULL) { |
1843 | printf("** TI ext2fs read block (indir 2 2)" | 1809 | printf("** TI ext2fs read block (indir 2 2)" |
1844 | "malloc failed. **\n"); | 1810 | "malloc failed. **\n"); |
1845 | return -1; | 1811 | return -1; |
1846 | } | 1812 | } |
1847 | ext4fs_indir3_size = blksz; | 1813 | ext4fs_indir3_size = blksz; |
1848 | } | 1814 | } |
1849 | if ((__le32_to_cpu(ext4fs_indir2_block[rblock | 1815 | if ((__le32_to_cpu(ext4fs_indir2_block[rblock |
1850 | / | 1816 | / |
1851 | perblock_child]) << | 1817 | perblock_child]) << |
1852 | log2_blksz) != ext4fs_indir3_blkno) { | 1818 | log2_blksz) != ext4fs_indir3_blkno) { |
1853 | status = | 1819 | status = |
1854 | ext4fs_devread((lbaint_t)__le32_to_cpu | 1820 | ext4fs_devread((lbaint_t)__le32_to_cpu |
1855 | (ext4fs_indir2_block | 1821 | (ext4fs_indir2_block |
1856 | [(rblock / perblock_child) | 1822 | [(rblock / perblock_child) |
1857 | % (blksz / 4)]) << log2_blksz, 0, | 1823 | % (blksz / 4)]) << log2_blksz, 0, |
1858 | blksz, (char *)ext4fs_indir3_block); | 1824 | blksz, (char *)ext4fs_indir3_block); |
1859 | if (status == 0) { | 1825 | if (status == 0) { |
1860 | printf("** TI ext2fs read block (indir 2 2)" | 1826 | printf("** TI ext2fs read block (indir 2 2)" |
1861 | "failed. **\n"); | 1827 | "failed. **\n"); |
1862 | return -1; | 1828 | return -1; |
1863 | } | 1829 | } |
1864 | ext4fs_indir3_blkno = | 1830 | ext4fs_indir3_blkno = |
1865 | __le32_to_cpu(ext4fs_indir2_block[(rblock / | 1831 | __le32_to_cpu(ext4fs_indir2_block[(rblock / |
1866 | perblock_child) % | 1832 | perblock_child) % |
1867 | (blksz / | 1833 | (blksz / |
1868 | 4)]) << | 1834 | 4)]) << |
1869 | log2_blksz; | 1835 | log2_blksz; |
1870 | } | 1836 | } |
1871 | 1837 | ||
1872 | blknr = __le32_to_cpu(ext4fs_indir3_block | 1838 | blknr = __le32_to_cpu(ext4fs_indir3_block |
1873 | [rblock % perblock_child]); | 1839 | [rblock % perblock_child]); |
1874 | } | 1840 | } |
1875 | debug("read_allocated_block %ld\n", blknr); | 1841 | debug("read_allocated_block %ld\n", blknr); |
1876 | 1842 | ||
1877 | return blknr; | 1843 | return blknr; |
1878 | } | 1844 | } |
1879 | 1845 | ||
1880 | void ext4fs_close(void) | 1846 | void ext4fs_close(void) |
1881 | { | 1847 | { |
1882 | if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) { | 1848 | if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) { |
1883 | ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen); | 1849 | ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen); |
1884 | ext4fs_file = NULL; | 1850 | ext4fs_file = NULL; |
1885 | } | 1851 | } |
1886 | if (ext4fs_root != NULL) { | 1852 | if (ext4fs_root != NULL) { |
1887 | free(ext4fs_root); | 1853 | free(ext4fs_root); |
1888 | ext4fs_root = NULL; | 1854 | ext4fs_root = NULL; |
1889 | } | 1855 | } |
1890 | if (ext4fs_indir1_block != NULL) { | 1856 | if (ext4fs_indir1_block != NULL) { |
1891 | free(ext4fs_indir1_block); | 1857 | free(ext4fs_indir1_block); |
1892 | ext4fs_indir1_block = NULL; | 1858 | ext4fs_indir1_block = NULL; |
1893 | ext4fs_indir1_size = 0; | 1859 | ext4fs_indir1_size = 0; |
1894 | ext4fs_indir1_blkno = -1; | 1860 | ext4fs_indir1_blkno = -1; |
1895 | } | 1861 | } |
1896 | if (ext4fs_indir2_block != NULL) { | 1862 | if (ext4fs_indir2_block != NULL) { |
1897 | free(ext4fs_indir2_block); | 1863 | free(ext4fs_indir2_block); |
1898 | ext4fs_indir2_block = NULL; | 1864 | ext4fs_indir2_block = NULL; |
1899 | ext4fs_indir2_size = 0; | 1865 | ext4fs_indir2_size = 0; |
1900 | ext4fs_indir2_blkno = -1; | 1866 | ext4fs_indir2_blkno = -1; |
1901 | } | 1867 | } |
1902 | if (ext4fs_indir3_block != NULL) { | 1868 | if (ext4fs_indir3_block != NULL) { |
1903 | free(ext4fs_indir3_block); | 1869 | free(ext4fs_indir3_block); |
1904 | ext4fs_indir3_block = NULL; | 1870 | ext4fs_indir3_block = NULL; |
1905 | ext4fs_indir3_size = 0; | 1871 | ext4fs_indir3_size = 0; |
1906 | ext4fs_indir3_blkno = -1; | 1872 | ext4fs_indir3_blkno = -1; |
1907 | } | 1873 | } |
1908 | } | 1874 | } |
1909 | 1875 | ||
1910 | int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, | 1876 | int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, |
1911 | struct ext2fs_node **fnode, int *ftype) | 1877 | struct ext2fs_node **fnode, int *ftype) |
1912 | { | 1878 | { |
1913 | unsigned int fpos = 0; | 1879 | unsigned int fpos = 0; |
1914 | int status; | 1880 | int status; |
1915 | struct ext2fs_node *diro = (struct ext2fs_node *) dir; | 1881 | struct ext2fs_node *diro = (struct ext2fs_node *) dir; |
1916 | 1882 | ||
1917 | #ifdef DEBUG | 1883 | #ifdef DEBUG |
1918 | if (name != NULL) | 1884 | if (name != NULL) |
1919 | printf("Iterate dir %s\n", name); | 1885 | printf("Iterate dir %s\n", name); |
1920 | #endif /* of DEBUG */ | 1886 | #endif /* of DEBUG */ |
1921 | if (!diro->inode_read) { | 1887 | if (!diro->inode_read) { |
1922 | status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); | 1888 | status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); |
1923 | if (status == 0) | 1889 | if (status == 0) |
1924 | return 0; | 1890 | return 0; |
1925 | } | 1891 | } |
1926 | /* Search the file. */ | 1892 | /* Search the file. */ |
1927 | while (fpos < __le32_to_cpu(diro->inode.size)) { | 1893 | while (fpos < __le32_to_cpu(diro->inode.size)) { |
1928 | struct ext2_dirent dirent; | 1894 | struct ext2_dirent dirent; |
1929 | 1895 | ||
1930 | status = ext4fs_read_file(diro, fpos, | 1896 | status = ext4fs_read_file(diro, fpos, |
1931 | sizeof(struct ext2_dirent), | 1897 | sizeof(struct ext2_dirent), |
1932 | (char *) &dirent); | 1898 | (char *) &dirent); |
1933 | if (status < 1) | 1899 | if (status < 1) |
1934 | return 0; | 1900 | return 0; |
1935 | 1901 | ||
1936 | if (dirent.namelen != 0) { | 1902 | if (dirent.namelen != 0) { |
1937 | char filename[dirent.namelen + 1]; | 1903 | char filename[dirent.namelen + 1]; |
1938 | struct ext2fs_node *fdiro; | 1904 | struct ext2fs_node *fdiro; |
1939 | int type = FILETYPE_UNKNOWN; | 1905 | int type = FILETYPE_UNKNOWN; |
1940 | 1906 | ||
1941 | status = ext4fs_read_file(diro, | 1907 | status = ext4fs_read_file(diro, |
1942 | fpos + | 1908 | fpos + |
1943 | sizeof(struct ext2_dirent), | 1909 | sizeof(struct ext2_dirent), |
1944 | dirent.namelen, filename); | 1910 | dirent.namelen, filename); |
1945 | if (status < 1) | 1911 | if (status < 1) |
1946 | return 0; | 1912 | return 0; |
1947 | 1913 | ||
1948 | fdiro = zalloc(sizeof(struct ext2fs_node)); | 1914 | fdiro = zalloc(sizeof(struct ext2fs_node)); |
1949 | if (!fdiro) | 1915 | if (!fdiro) |
1950 | return 0; | 1916 | return 0; |
1951 | 1917 | ||
1952 | fdiro->data = diro->data; | 1918 | fdiro->data = diro->data; |
1953 | fdiro->ino = __le32_to_cpu(dirent.inode); | 1919 | fdiro->ino = __le32_to_cpu(dirent.inode); |
1954 | 1920 | ||
1955 | filename[dirent.namelen] = '\0'; | 1921 | filename[dirent.namelen] = '\0'; |
1956 | 1922 | ||
1957 | if (dirent.filetype != FILETYPE_UNKNOWN) { | 1923 | if (dirent.filetype != FILETYPE_UNKNOWN) { |
1958 | fdiro->inode_read = 0; | 1924 | fdiro->inode_read = 0; |
1959 | 1925 | ||
1960 | if (dirent.filetype == FILETYPE_DIRECTORY) | 1926 | if (dirent.filetype == FILETYPE_DIRECTORY) |
1961 | type = FILETYPE_DIRECTORY; | 1927 | type = FILETYPE_DIRECTORY; |
1962 | else if (dirent.filetype == FILETYPE_SYMLINK) | 1928 | else if (dirent.filetype == FILETYPE_SYMLINK) |
1963 | type = FILETYPE_SYMLINK; | 1929 | type = FILETYPE_SYMLINK; |
1964 | else if (dirent.filetype == FILETYPE_REG) | 1930 | else if (dirent.filetype == FILETYPE_REG) |
1965 | type = FILETYPE_REG; | 1931 | type = FILETYPE_REG; |
1966 | } else { | 1932 | } else { |
1967 | status = ext4fs_read_inode(diro->data, | 1933 | status = ext4fs_read_inode(diro->data, |
1968 | __le32_to_cpu | 1934 | __le32_to_cpu |
1969 | (dirent.inode), | 1935 | (dirent.inode), |
1970 | &fdiro->inode); | 1936 | &fdiro->inode); |
1971 | if (status == 0) { | 1937 | if (status == 0) { |
1972 | free(fdiro); | 1938 | free(fdiro); |
1973 | return 0; | 1939 | return 0; |
1974 | } | 1940 | } |
1975 | fdiro->inode_read = 1; | 1941 | fdiro->inode_read = 1; |
1976 | 1942 | ||
1977 | if ((__le16_to_cpu(fdiro->inode.mode) & | 1943 | if ((__le16_to_cpu(fdiro->inode.mode) & |
1978 | FILETYPE_INO_MASK) == | 1944 | FILETYPE_INO_MASK) == |
1979 | FILETYPE_INO_DIRECTORY) { | 1945 | FILETYPE_INO_DIRECTORY) { |
1980 | type = FILETYPE_DIRECTORY; | 1946 | type = FILETYPE_DIRECTORY; |
1981 | } else if ((__le16_to_cpu(fdiro->inode.mode) | 1947 | } else if ((__le16_to_cpu(fdiro->inode.mode) |
1982 | & FILETYPE_INO_MASK) == | 1948 | & FILETYPE_INO_MASK) == |
1983 | FILETYPE_INO_SYMLINK) { | 1949 | FILETYPE_INO_SYMLINK) { |
1984 | type = FILETYPE_SYMLINK; | 1950 | type = FILETYPE_SYMLINK; |
1985 | } else if ((__le16_to_cpu(fdiro->inode.mode) | 1951 | } else if ((__le16_to_cpu(fdiro->inode.mode) |
1986 | & FILETYPE_INO_MASK) == | 1952 | & FILETYPE_INO_MASK) == |
1987 | FILETYPE_INO_REG) { | 1953 | FILETYPE_INO_REG) { |
1988 | type = FILETYPE_REG; | 1954 | type = FILETYPE_REG; |
1989 | } | 1955 | } |
1990 | } | 1956 | } |
1991 | #ifdef DEBUG | 1957 | #ifdef DEBUG |
1992 | printf("iterate >%s<\n", filename); | 1958 | printf("iterate >%s<\n", filename); |
1993 | #endif /* of DEBUG */ | 1959 | #endif /* of DEBUG */ |
1994 | if ((name != NULL) && (fnode != NULL) | 1960 | if ((name != NULL) && (fnode != NULL) |
1995 | && (ftype != NULL)) { | 1961 | && (ftype != NULL)) { |
1996 | if (strcmp(filename, name) == 0) { | 1962 | if (strcmp(filename, name) == 0) { |
1997 | *ftype = type; | 1963 | *ftype = type; |
1998 | *fnode = fdiro; | 1964 | *fnode = fdiro; |
1999 | return 1; | 1965 | return 1; |
2000 | } | 1966 | } |
2001 | } else { | 1967 | } else { |
2002 | if (fdiro->inode_read == 0) { | 1968 | if (fdiro->inode_read == 0) { |
2003 | status = ext4fs_read_inode(diro->data, | 1969 | status = ext4fs_read_inode(diro->data, |
2004 | __le32_to_cpu( | 1970 | __le32_to_cpu( |
2005 | dirent.inode), | 1971 | dirent.inode), |
2006 | &fdiro->inode); | 1972 | &fdiro->inode); |
2007 | if (status == 0) { | 1973 | if (status == 0) { |
2008 | free(fdiro); | 1974 | free(fdiro); |
2009 | return 0; | 1975 | return 0; |
2010 | } | 1976 | } |
2011 | fdiro->inode_read = 1; | 1977 | fdiro->inode_read = 1; |
2012 | } | 1978 | } |
2013 | switch (type) { | 1979 | switch (type) { |
2014 | case FILETYPE_DIRECTORY: | 1980 | case FILETYPE_DIRECTORY: |
2015 | printf("<DIR> "); | 1981 | printf("<DIR> "); |
2016 | break; | 1982 | break; |
2017 | case FILETYPE_SYMLINK: | 1983 | case FILETYPE_SYMLINK: |
2018 | printf("<SYM> "); | 1984 | printf("<SYM> "); |
2019 | break; | 1985 | break; |
2020 | case FILETYPE_REG: | 1986 | case FILETYPE_REG: |
2021 | printf(" "); | 1987 | printf(" "); |
2022 | break; | 1988 | break; |
2023 | default: | 1989 | default: |
2024 | printf("< ? > "); | 1990 | printf("< ? > "); |
2025 | break; | 1991 | break; |
2026 | } | 1992 | } |
2027 | printf("%10d %s\n", | 1993 | printf("%10d %s\n", |
2028 | __le32_to_cpu(fdiro->inode.size), | 1994 | __le32_to_cpu(fdiro->inode.size), |
2029 | filename); | 1995 | filename); |
2030 | } | 1996 | } |
2031 | free(fdiro); | 1997 | free(fdiro); |
2032 | } | 1998 | } |
2033 | fpos += __le16_to_cpu(dirent.direntlen); | 1999 | fpos += __le16_to_cpu(dirent.direntlen); |
2034 | } | 2000 | } |
2035 | return 0; | 2001 | return 0; |
2036 | } | 2002 | } |
2037 | 2003 | ||
2038 | static char *ext4fs_read_symlink(struct ext2fs_node *node) | 2004 | static char *ext4fs_read_symlink(struct ext2fs_node *node) |
2039 | { | 2005 | { |
2040 | char *symlink; | 2006 | char *symlink; |
2041 | struct ext2fs_node *diro = node; | 2007 | struct ext2fs_node *diro = node; |
2042 | int status; | 2008 | int status; |
2043 | 2009 | ||
2044 | if (!diro->inode_read) { | 2010 | if (!diro->inode_read) { |
2045 | status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); | 2011 | status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); |
2046 | if (status == 0) | 2012 | if (status == 0) |
2047 | return 0; | 2013 | return 0; |
2048 | } | 2014 | } |
2049 | symlink = zalloc(__le32_to_cpu(diro->inode.size) + 1); | 2015 | symlink = zalloc(__le32_to_cpu(diro->inode.size) + 1); |
2050 | if (!symlink) | 2016 | if (!symlink) |
2051 | return 0; | 2017 | return 0; |
2052 | 2018 | ||
2053 | if (__le32_to_cpu(diro->inode.size) <= 60) { | 2019 | if (__le32_to_cpu(diro->inode.size) <= 60) { |
2054 | strncpy(symlink, diro->inode.b.symlink, | 2020 | strncpy(symlink, diro->inode.b.symlink, |
2055 | __le32_to_cpu(diro->inode.size)); | 2021 | __le32_to_cpu(diro->inode.size)); |
2056 | } else { | 2022 | } else { |
2057 | status = ext4fs_read_file(diro, 0, | 2023 | status = ext4fs_read_file(diro, 0, |
2058 | __le32_to_cpu(diro->inode.size), | 2024 | __le32_to_cpu(diro->inode.size), |
2059 | symlink); | 2025 | symlink); |
2060 | if (status == 0) { | 2026 | if (status == 0) { |
2061 | free(symlink); | 2027 | free(symlink); |
2062 | return 0; | 2028 | return 0; |
2063 | } | 2029 | } |
2064 | } | 2030 | } |
2065 | symlink[__le32_to_cpu(diro->inode.size)] = '\0'; | 2031 | symlink[__le32_to_cpu(diro->inode.size)] = '\0'; |
2066 | return symlink; | 2032 | return symlink; |
2067 | } | 2033 | } |
2068 | 2034 | ||
2069 | static int ext4fs_find_file1(const char *currpath, | 2035 | static int ext4fs_find_file1(const char *currpath, |
2070 | struct ext2fs_node *currroot, | 2036 | struct ext2fs_node *currroot, |
2071 | struct ext2fs_node **currfound, int *foundtype) | 2037 | struct ext2fs_node **currfound, int *foundtype) |
2072 | { | 2038 | { |
2073 | char fpath[strlen(currpath) + 1]; | 2039 | char fpath[strlen(currpath) + 1]; |
2074 | char *name = fpath; | 2040 | char *name = fpath; |
2075 | char *next; | 2041 | char *next; |
2076 | int status; | 2042 | int status; |
2077 | int type = FILETYPE_DIRECTORY; | 2043 | int type = FILETYPE_DIRECTORY; |
2078 | struct ext2fs_node *currnode = currroot; | 2044 | struct ext2fs_node *currnode = currroot; |
2079 | struct ext2fs_node *oldnode = currroot; | 2045 | struct ext2fs_node *oldnode = currroot; |
2080 | 2046 | ||
2081 | strncpy(fpath, currpath, strlen(currpath) + 1); | 2047 | strncpy(fpath, currpath, strlen(currpath) + 1); |
2082 | 2048 | ||
2083 | /* Remove all leading slashes. */ | 2049 | /* Remove all leading slashes. */ |
2084 | while (*name == '/') | 2050 | while (*name == '/') |
2085 | name++; | 2051 | name++; |
2086 | 2052 | ||
2087 | if (!*name) { | 2053 | if (!*name) { |
2088 | *currfound = currnode; | 2054 | *currfound = currnode; |
2089 | return 1; | 2055 | return 1; |
2090 | } | 2056 | } |
2091 | 2057 | ||
2092 | for (;;) { | 2058 | for (;;) { |
2093 | int found; | 2059 | int found; |
2094 | 2060 | ||
2095 | /* Extract the actual part from the pathname. */ | 2061 | /* Extract the actual part from the pathname. */ |
2096 | next = strchr(name, '/'); | 2062 | next = strchr(name, '/'); |
2097 | if (next) { | 2063 | if (next) { |
2098 | /* Remove all leading slashes. */ | 2064 | /* Remove all leading slashes. */ |
2099 | while (*next == '/') | 2065 | while (*next == '/') |
2100 | *(next++) = '\0'; | 2066 | *(next++) = '\0'; |
2101 | } | 2067 | } |
2102 | 2068 | ||
2103 | if (type != FILETYPE_DIRECTORY) { | 2069 | if (type != FILETYPE_DIRECTORY) { |
2104 | ext4fs_free_node(currnode, currroot); | 2070 | ext4fs_free_node(currnode, currroot); |
2105 | return 0; | 2071 | return 0; |
2106 | } | 2072 | } |
2107 | 2073 | ||
2108 | oldnode = currnode; | 2074 | oldnode = currnode; |
2109 | 2075 | ||
2110 | /* Iterate over the directory. */ | 2076 | /* Iterate over the directory. */ |
2111 | found = ext4fs_iterate_dir(currnode, name, &currnode, &type); | 2077 | found = ext4fs_iterate_dir(currnode, name, &currnode, &type); |
2112 | if (found == 0) | 2078 | if (found == 0) |
2113 | return 0; | 2079 | return 0; |
2114 | 2080 | ||
2115 | if (found == -1) | 2081 | if (found == -1) |
2116 | break; | 2082 | break; |
2117 | 2083 | ||
2118 | /* Read in the symlink and follow it. */ | 2084 | /* Read in the symlink and follow it. */ |
2119 | if (type == FILETYPE_SYMLINK) { | 2085 | if (type == FILETYPE_SYMLINK) { |
2120 | char *symlink; | 2086 | char *symlink; |
2121 | 2087 | ||
2122 | /* Test if the symlink does not loop. */ | 2088 | /* Test if the symlink does not loop. */ |
2123 | if (++symlinknest == 8) { | 2089 | if (++symlinknest == 8) { |
2124 | ext4fs_free_node(currnode, currroot); | 2090 | ext4fs_free_node(currnode, currroot); |
2125 | ext4fs_free_node(oldnode, currroot); | 2091 | ext4fs_free_node(oldnode, currroot); |
2126 | return 0; | 2092 | return 0; |
2127 | } | 2093 | } |
2128 | 2094 | ||
2129 | symlink = ext4fs_read_symlink(currnode); | 2095 | symlink = ext4fs_read_symlink(currnode); |
2130 | ext4fs_free_node(currnode, currroot); | 2096 | ext4fs_free_node(currnode, currroot); |
2131 | 2097 | ||
2132 | if (!symlink) { | 2098 | if (!symlink) { |
2133 | ext4fs_free_node(oldnode, currroot); | 2099 | ext4fs_free_node(oldnode, currroot); |
2134 | return 0; | 2100 | return 0; |
2135 | } | 2101 | } |
2136 | 2102 | ||
2137 | debug("Got symlink >%s<\n", symlink); | 2103 | debug("Got symlink >%s<\n", symlink); |
2138 | 2104 | ||
2139 | if (symlink[0] == '/') { | 2105 | if (symlink[0] == '/') { |
2140 | ext4fs_free_node(oldnode, currroot); | 2106 | ext4fs_free_node(oldnode, currroot); |
2141 | oldnode = &ext4fs_root->diropen; | 2107 | oldnode = &ext4fs_root->diropen; |
2142 | } | 2108 | } |
2143 | 2109 | ||
2144 | /* Lookup the node the symlink points to. */ | 2110 | /* Lookup the node the symlink points to. */ |
2145 | status = ext4fs_find_file1(symlink, oldnode, | 2111 | status = ext4fs_find_file1(symlink, oldnode, |
2146 | &currnode, &type); | 2112 | &currnode, &type); |
2147 | 2113 | ||
2148 | free(symlink); | 2114 | free(symlink); |
2149 | 2115 | ||
2150 | if (status == 0) { | 2116 | if (status == 0) { |
2151 | ext4fs_free_node(oldnode, currroot); | 2117 | ext4fs_free_node(oldnode, currroot); |
2152 | return 0; | 2118 | return 0; |
2153 | } | 2119 | } |
2154 | } | 2120 | } |
2155 | 2121 | ||
2156 | ext4fs_free_node(oldnode, currroot); | 2122 | ext4fs_free_node(oldnode, currroot); |
2157 | 2123 | ||
2158 | /* Found the node! */ | 2124 | /* Found the node! */ |
2159 | if (!next || *next == '\0') { | 2125 | if (!next || *next == '\0') { |
2160 | *currfound = currnode; | 2126 | *currfound = currnode; |
2161 | *foundtype = type; | 2127 | *foundtype = type; |
2162 | return 1; | 2128 | return 1; |
2163 | } | 2129 | } |
2164 | name = next; | 2130 | name = next; |
2165 | } | 2131 | } |
2166 | return -1; | 2132 | return -1; |
2167 | } | 2133 | } |
2168 | 2134 | ||
2169 | int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode, | 2135 | int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode, |
2170 | struct ext2fs_node **foundnode, int expecttype) | 2136 | struct ext2fs_node **foundnode, int expecttype) |
2171 | { | 2137 | { |
2172 | int status; | 2138 | int status; |
2173 | int foundtype = FILETYPE_DIRECTORY; | 2139 | int foundtype = FILETYPE_DIRECTORY; |
2174 | 2140 | ||
2175 | symlinknest = 0; | 2141 | symlinknest = 0; |
2176 | if (!path) | 2142 | if (!path) |
2177 | return 0; | 2143 | return 0; |
2178 | 2144 | ||
2179 | status = ext4fs_find_file1(path, rootnode, foundnode, &foundtype); | 2145 | status = ext4fs_find_file1(path, rootnode, foundnode, &foundtype); |
2180 | if (status == 0) | 2146 | if (status == 0) |
2181 | return 0; | 2147 | return 0; |
2182 | 2148 | ||
2183 | /* Check if the node that was found was of the expected type. */ | 2149 | /* Check if the node that was found was of the expected type. */ |
2184 | if ((expecttype == FILETYPE_REG) && (foundtype != expecttype)) | 2150 | if ((expecttype == FILETYPE_REG) && (foundtype != expecttype)) |
2185 | return 0; | 2151 | return 0; |
2186 | else if ((expecttype == FILETYPE_DIRECTORY) | 2152 | else if ((expecttype == FILETYPE_DIRECTORY) |
2187 | && (foundtype != expecttype)) | 2153 | && (foundtype != expecttype)) |
2188 | return 0; | 2154 | return 0; |
2189 | 2155 | ||
2190 | return 1; | 2156 | return 1; |
2191 | } | 2157 | } |
2192 | 2158 | ||
2193 | int ext4fs_open(const char *filename) | 2159 | int ext4fs_open(const char *filename) |
2194 | { | 2160 | { |
2195 | struct ext2fs_node *fdiro = NULL; | 2161 | struct ext2fs_node *fdiro = NULL; |
2196 | int status; | 2162 | int status; |
2197 | int len; | 2163 | int len; |
2198 | 2164 | ||
2199 | if (ext4fs_root == NULL) | 2165 | if (ext4fs_root == NULL) |
2200 | return -1; | 2166 | return -1; |
2201 | 2167 | ||
2202 | ext4fs_file = NULL; | 2168 | ext4fs_file = NULL; |
2203 | status = ext4fs_find_file(filename, &ext4fs_root->diropen, &fdiro, | 2169 | status = ext4fs_find_file(filename, &ext4fs_root->diropen, &fdiro, |
2204 | FILETYPE_REG); | 2170 | FILETYPE_REG); |
2205 | if (status == 0) | 2171 | if (status == 0) |
2206 | goto fail; | 2172 | goto fail; |
2207 | 2173 | ||
2208 | if (!fdiro->inode_read) { | 2174 | if (!fdiro->inode_read) { |
2209 | status = ext4fs_read_inode(fdiro->data, fdiro->ino, | 2175 | status = ext4fs_read_inode(fdiro->data, fdiro->ino, |
2210 | &fdiro->inode); | 2176 | &fdiro->inode); |
2211 | if (status == 0) | 2177 | if (status == 0) |
2212 | goto fail; | 2178 | goto fail; |
2213 | } | 2179 | } |
2214 | len = __le32_to_cpu(fdiro->inode.size); | 2180 | len = __le32_to_cpu(fdiro->inode.size); |
2215 | ext4fs_file = fdiro; | 2181 | ext4fs_file = fdiro; |
2216 | 2182 | ||
2217 | return len; | 2183 | return len; |
2218 | fail: | 2184 | fail: |
2219 | ext4fs_free_node(fdiro, &ext4fs_root->diropen); | 2185 | ext4fs_free_node(fdiro, &ext4fs_root->diropen); |
2220 | 2186 | ||
2221 | return -1; | 2187 | return -1; |
2222 | } | 2188 | } |
2223 | 2189 | ||
2224 | int ext4fs_mount(unsigned part_length) | 2190 | int ext4fs_mount(unsigned part_length) |
2225 | { | 2191 | { |
2226 | struct ext2_data *data; | 2192 | struct ext2_data *data; |
2227 | int status; | 2193 | int status; |
2228 | struct ext_filesystem *fs = get_fs(); | 2194 | struct ext_filesystem *fs = get_fs(); |
2229 | data = zalloc(SUPERBLOCK_SIZE); | 2195 | data = zalloc(SUPERBLOCK_SIZE); |
fs/ext4/ext4_common.h
1 | /* | 1 | /* |
2 | * (C) Copyright 2011 - 2012 Samsung Electronics | 2 | * (C) Copyright 2011 - 2012 Samsung Electronics |
3 | * EXT4 filesystem implementation in Uboot by | 3 | * EXT4 filesystem implementation in Uboot by |
4 | * Uma Shankar <uma.shankar@samsung.com> | 4 | * Uma Shankar <uma.shankar@samsung.com> |
5 | * Manjunatha C Achar <a.manjunatha@samsung.com> | 5 | * Manjunatha C Achar <a.manjunatha@samsung.com> |
6 | * | 6 | * |
7 | * ext4ls and ext4load : based on ext2 ls load support in Uboot. | 7 | * ext4ls and ext4load : based on ext2 ls load support in Uboot. |
8 | * | 8 | * |
9 | * (C) Copyright 2004 | 9 | * (C) Copyright 2004 |
10 | * esd gmbh <www.esd-electronics.com> | 10 | * esd gmbh <www.esd-electronics.com> |
11 | * Reinhard Arlt <reinhard.arlt@esd-electronics.com> | 11 | * Reinhard Arlt <reinhard.arlt@esd-electronics.com> |
12 | * | 12 | * |
13 | * based on code from grub2 fs/ext2.c and fs/fshelp.c by | 13 | * based on code from grub2 fs/ext2.c and fs/fshelp.c by |
14 | * GRUB -- GRand Unified Bootloader | 14 | * GRUB -- GRand Unified Bootloader |
15 | * Copyright (C) 2003, 2004 Free Software Foundation, Inc. | 15 | * Copyright (C) 2003, 2004 Free Software Foundation, Inc. |
16 | * | 16 | * |
17 | * ext4write : Based on generic ext4 protocol. | 17 | * ext4write : Based on generic ext4 protocol. |
18 | * | 18 | * |
19 | * SPDX-License-Identifier: GPL-2.0+ | 19 | * SPDX-License-Identifier: GPL-2.0+ |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #ifndef __EXT4_COMMON__ | 22 | #ifndef __EXT4_COMMON__ |
23 | #define __EXT4_COMMON__ | 23 | #define __EXT4_COMMON__ |
24 | #include <ext_common.h> | 24 | #include <ext_common.h> |
25 | #include <ext4fs.h> | 25 | #include <ext4fs.h> |
26 | #include <malloc.h> | 26 | #include <malloc.h> |
27 | #include <asm/errno.h> | 27 | #include <asm/errno.h> |
28 | #if defined(CONFIG_EXT4_WRITE) | 28 | #if defined(CONFIG_EXT4_WRITE) |
29 | #include "ext4_journal.h" | 29 | #include "ext4_journal.h" |
30 | #include "crc16.h" | 30 | #include "crc16.h" |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #define YES 1 | 33 | #define YES 1 |
34 | #define NO 0 | 34 | #define NO 0 |
35 | #define RECOVER 1 | 35 | #define RECOVER 1 |
36 | #define SCAN 0 | 36 | #define SCAN 0 |
37 | 37 | ||
38 | #define S_IFLNK 0120000 /* symbolic link */ | 38 | #define S_IFLNK 0120000 /* symbolic link */ |
39 | #define BLOCK_NO_ONE 1 | 39 | #define BLOCK_NO_ONE 1 |
40 | #define SUPERBLOCK_START (2 * 512) | 40 | #define SUPERBLOCK_START (2 * 512) |
41 | #define SUPERBLOCK_SIZE 1024 | 41 | #define SUPERBLOCK_SIZE 1024 |
42 | #define F_FILE 1 | 42 | #define F_FILE 1 |
43 | 43 | ||
44 | static inline void *zalloc(size_t size) | 44 | static inline void *zalloc(size_t size) |
45 | { | 45 | { |
46 | void *p = memalign(ARCH_DMA_MINALIGN, size); | 46 | void *p = memalign(ARCH_DMA_MINALIGN, size); |
47 | memset(p, 0, size); | 47 | memset(p, 0, size); |
48 | return p; | 48 | return p; |
49 | } | 49 | } |
50 | 50 | ||
51 | int ext4fs_read_inode(struct ext2_data *data, int ino, | 51 | int ext4fs_read_inode(struct ext2_data *data, int ino, |
52 | struct ext2_inode *inode); | 52 | struct ext2_inode *inode); |
53 | int ext4fs_read_file(struct ext2fs_node *node, int pos, | 53 | int ext4fs_read_file(struct ext2fs_node *node, int pos, |
54 | unsigned int len, char *buf); | 54 | unsigned int len, char *buf); |
55 | int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode, | 55 | int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode, |
56 | struct ext2fs_node **foundnode, int expecttype); | 56 | struct ext2fs_node **foundnode, int expecttype); |
57 | int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, | 57 | int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, |
58 | struct ext2fs_node **fnode, int *ftype); | 58 | struct ext2fs_node **fnode, int *ftype); |
59 | 59 | ||
60 | int ext4fs_build_extent_cache(struct ext2_inode *inode); | ||
61 | void ext4fs_free_extent_cache(void); | ||
62 | |||
63 | #if defined(CONFIG_EXT4_WRITE) | 60 | #if defined(CONFIG_EXT4_WRITE) |
64 | uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n); | 61 | uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n); |
65 | int ext4fs_checksum_update(unsigned int i); | 62 | int ext4fs_checksum_update(unsigned int i); |
66 | int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags); | 63 | int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags); |
67 | void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type); | 64 | void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type); |
68 | long int ext4fs_get_new_blk_no(void); | 65 | long int ext4fs_get_new_blk_no(void); |
69 | int ext4fs_get_new_inode_no(void); | 66 | int ext4fs_get_new_inode_no(void); |
70 | void ext4fs_reset_block_bmap(long int blockno, unsigned char *buffer, | 67 | void ext4fs_reset_block_bmap(long int blockno, unsigned char *buffer, |
71 | int index); | 68 | int index); |
72 | int ext4fs_set_block_bmap(long int blockno, unsigned char *buffer, int index); | 69 | int ext4fs_set_block_bmap(long int blockno, unsigned char *buffer, int index); |
73 | int ext4fs_set_inode_bmap(int inode_no, unsigned char *buffer, int index); | 70 | int ext4fs_set_inode_bmap(int inode_no, unsigned char *buffer, int index); |
74 | void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index); | 71 | void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index); |
75 | int ext4fs_iget(int inode_no, struct ext2_inode *inode); | 72 | int ext4fs_iget(int inode_no, struct ext2_inode *inode); |
76 | void ext4fs_allocate_blocks(struct ext2_inode *file_inode, | 73 | void ext4fs_allocate_blocks(struct ext2_inode *file_inode, |
77 | unsigned int total_remaining_blocks, | 74 | unsigned int total_remaining_blocks, |
78 | unsigned int *total_no_of_block); | 75 | unsigned int *total_no_of_block); |
79 | void put_ext4(uint64_t off, void *buf, uint32_t size); | 76 | void put_ext4(uint64_t off, void *buf, uint32_t size); |
80 | #endif | 77 | #endif |
81 | #endif | 78 | #endif |
82 | 79 |
fs/ext4/ext4fs.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2011 - 2012 Samsung Electronics | 2 | * (C) Copyright 2011 - 2012 Samsung Electronics |
3 | * EXT4 filesystem implementation in Uboot by | 3 | * EXT4 filesystem implementation in Uboot by |
4 | * Uma Shankar <uma.shankar@samsung.com> | 4 | * Uma Shankar <uma.shankar@samsung.com> |
5 | * Manjunatha C Achar <a.manjunatha@samsung.com> | 5 | * Manjunatha C Achar <a.manjunatha@samsung.com> |
6 | * | 6 | * |
7 | * ext4ls and ext4load : Based on ext2 ls and load support in Uboot. | 7 | * ext4ls and ext4load : Based on ext2 ls and load support in Uboot. |
8 | * Ext4 read optimization taken from Open-Moko | 8 | * Ext4 read optimization taken from Open-Moko |
9 | * Qi bootloader | 9 | * Qi bootloader |
10 | * | 10 | * |
11 | * (C) Copyright 2004 | 11 | * (C) Copyright 2004 |
12 | * esd gmbh <www.esd-electronics.com> | 12 | * esd gmbh <www.esd-electronics.com> |
13 | * Reinhard Arlt <reinhard.arlt@esd-electronics.com> | 13 | * Reinhard Arlt <reinhard.arlt@esd-electronics.com> |
14 | * | 14 | * |
15 | * based on code from grub2 fs/ext2.c and fs/fshelp.c by | 15 | * based on code from grub2 fs/ext2.c and fs/fshelp.c by |
16 | * GRUB -- GRand Unified Bootloader | 16 | * GRUB -- GRand Unified Bootloader |
17 | * Copyright (C) 2003, 2004 Free Software Foundation, Inc. | 17 | * Copyright (C) 2003, 2004 Free Software Foundation, Inc. |
18 | * | 18 | * |
19 | * ext4write : Based on generic ext4 protocol. | 19 | * ext4write : Based on generic ext4 protocol. |
20 | * | 20 | * |
21 | * SPDX-License-Identifier: GPL-2.0+ | 21 | * SPDX-License-Identifier: GPL-2.0+ |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <common.h> | 24 | #include <common.h> |
25 | #include <ext_common.h> | 25 | #include <ext_common.h> |
26 | #include <ext4fs.h> | 26 | #include <ext4fs.h> |
27 | #include "ext4_common.h" | 27 | #include "ext4_common.h" |
28 | 28 | ||
29 | int ext4fs_symlinknest; | 29 | int ext4fs_symlinknest; |
30 | struct ext_filesystem ext_fs; | 30 | struct ext_filesystem ext_fs; |
31 | 31 | ||
32 | struct ext_filesystem *get_fs(void) | 32 | struct ext_filesystem *get_fs(void) |
33 | { | 33 | { |
34 | return &ext_fs; | 34 | return &ext_fs; |
35 | } | 35 | } |
36 | 36 | ||
37 | void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot) | 37 | void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot) |
38 | { | 38 | { |
39 | if ((node != &ext4fs_root->diropen) && (node != currroot)) | 39 | if ((node != &ext4fs_root->diropen) && (node != currroot)) |
40 | free(node); | 40 | free(node); |
41 | } | 41 | } |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * Taken from openmoko-kernel mailing list: By Andy green | 44 | * Taken from openmoko-kernel mailing list: By Andy green |
45 | * Optimized read file API : collects and defers contiguous sector | 45 | * Optimized read file API : collects and defers contiguous sector |
46 | * reads into one potentially more efficient larger sequential read action | 46 | * reads into one potentially more efficient larger sequential read action |
47 | */ | 47 | */ |
48 | int ext4fs_read_file(struct ext2fs_node *node, int pos, | 48 | int ext4fs_read_file(struct ext2fs_node *node, int pos, |
49 | unsigned int len, char *buf) | 49 | unsigned int len, char *buf) |
50 | { | 50 | { |
51 | struct ext_filesystem *fs = get_fs(); | 51 | struct ext_filesystem *fs = get_fs(); |
52 | int i; | 52 | int i; |
53 | lbaint_t blockcnt; | 53 | lbaint_t blockcnt; |
54 | int log2blksz = fs->dev_desc->log2blksz; | 54 | int log2blksz = fs->dev_desc->log2blksz; |
55 | int log2_fs_blocksize = LOG2_BLOCK_SIZE(node->data) - log2blksz; | 55 | int log2_fs_blocksize = LOG2_BLOCK_SIZE(node->data) - log2blksz; |
56 | int blocksize = (1 << (log2_fs_blocksize + log2blksz)); | 56 | int blocksize = (1 << (log2_fs_blocksize + log2blksz)); |
57 | unsigned int filesize = __le32_to_cpu(node->inode.size); | 57 | unsigned int filesize = __le32_to_cpu(node->inode.size); |
58 | lbaint_t previous_block_number = -1; | 58 | lbaint_t previous_block_number = -1; |
59 | lbaint_t delayed_start = 0; | 59 | lbaint_t delayed_start = 0; |
60 | lbaint_t delayed_extent = 0; | 60 | lbaint_t delayed_extent = 0; |
61 | lbaint_t delayed_skipfirst = 0; | 61 | lbaint_t delayed_skipfirst = 0; |
62 | lbaint_t delayed_next = 0; | 62 | lbaint_t delayed_next = 0; |
63 | char *delayed_buf = NULL; | 63 | char *delayed_buf = NULL; |
64 | short status; | 64 | short status; |
65 | 65 | ||
66 | if (le32_to_cpu(node->inode.flags) & EXT4_EXTENTS_FL) { | ||
67 | if (ext4fs_build_extent_cache(&node->inode)) { | ||
68 | printf("Error building extent cache!\n"); | ||
69 | len = -1; | ||
70 | goto out_exit; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | /* Adjust len so it we can't read past the end of the file. */ | 66 | /* Adjust len so it we can't read past the end of the file. */ |
75 | if (len > filesize) | 67 | if (len > filesize) |
76 | len = filesize; | 68 | len = filesize; |
77 | 69 | ||
78 | blockcnt = ((len + pos) + blocksize - 1) / blocksize; | 70 | blockcnt = ((len + pos) + blocksize - 1) / blocksize; |
79 | 71 | ||
80 | for (i = pos / blocksize; i < blockcnt; i++) { | 72 | for (i = pos / blocksize; i < blockcnt; i++) { |
81 | lbaint_t blknr; | 73 | lbaint_t blknr; |
82 | int blockoff = pos % blocksize; | 74 | int blockoff = pos % blocksize; |
83 | int blockend = blocksize; | 75 | int blockend = blocksize; |
84 | int skipfirst = 0; | 76 | int skipfirst = 0; |
85 | blknr = read_allocated_block(&(node->inode), i); | 77 | blknr = read_allocated_block(&(node->inode), i); |
86 | if (blknr < 0) { | 78 | if (blknr < 0) |
87 | len = -1; | 79 | return -1; |
88 | goto out_exit; | ||
89 | } | ||
90 | 80 | ||
91 | blknr = blknr << log2_fs_blocksize; | 81 | blknr = blknr << log2_fs_blocksize; |
92 | 82 | ||
93 | /* Last block. */ | 83 | /* Last block. */ |
94 | if (i == blockcnt - 1) { | 84 | if (i == blockcnt - 1) { |
95 | blockend = (len + pos) % blocksize; | 85 | blockend = (len + pos) % blocksize; |
96 | 86 | ||
97 | /* The last portion is exactly blocksize. */ | 87 | /* The last portion is exactly blocksize. */ |
98 | if (!blockend) | 88 | if (!blockend) |
99 | blockend = blocksize; | 89 | blockend = blocksize; |
100 | } | 90 | } |
101 | 91 | ||
102 | /* First block. */ | 92 | /* First block. */ |
103 | if (i == pos / blocksize) { | 93 | if (i == pos / blocksize) { |
104 | skipfirst = blockoff; | 94 | skipfirst = blockoff; |
105 | blockend -= skipfirst; | 95 | blockend -= skipfirst; |
106 | } | 96 | } |
107 | if (blknr) { | 97 | if (blknr) { |
108 | int status; | 98 | int status; |
109 | 99 | ||
110 | if (previous_block_number != -1) { | 100 | if (previous_block_number != -1) { |
111 | if (delayed_next == blknr) { | 101 | if (delayed_next == blknr) { |
112 | delayed_extent += blockend; | 102 | delayed_extent += blockend; |
113 | delayed_next += blockend >> log2blksz; | 103 | delayed_next += blockend >> log2blksz; |
114 | } else { /* spill */ | 104 | } else { /* spill */ |
115 | status = ext4fs_devread(delayed_start, | 105 | status = ext4fs_devread(delayed_start, |
116 | delayed_skipfirst, | 106 | delayed_skipfirst, |
117 | delayed_extent, | 107 | delayed_extent, |
118 | delayed_buf); | 108 | delayed_buf); |
119 | if (status == 0) { | 109 | if (status == 0) |
120 | len = -1; | 110 | return -1; |
121 | goto out_exit; | ||
122 | } | ||
123 | previous_block_number = blknr; | 111 | previous_block_number = blknr; |
124 | delayed_start = blknr; | 112 | delayed_start = blknr; |
125 | delayed_extent = blockend; | 113 | delayed_extent = blockend; |
126 | delayed_skipfirst = skipfirst; | 114 | delayed_skipfirst = skipfirst; |
127 | delayed_buf = buf; | 115 | delayed_buf = buf; |
128 | delayed_next = blknr + | 116 | delayed_next = blknr + |
129 | (blockend >> log2blksz); | 117 | (blockend >> log2blksz); |
130 | } | 118 | } |
131 | } else { | 119 | } else { |
132 | previous_block_number = blknr; | 120 | previous_block_number = blknr; |
133 | delayed_start = blknr; | 121 | delayed_start = blknr; |
134 | delayed_extent = blockend; | 122 | delayed_extent = blockend; |
135 | delayed_skipfirst = skipfirst; | 123 | delayed_skipfirst = skipfirst; |
136 | delayed_buf = buf; | 124 | delayed_buf = buf; |
137 | delayed_next = blknr + | 125 | delayed_next = blknr + |
138 | (blockend >> log2blksz); | 126 | (blockend >> log2blksz); |
139 | } | 127 | } |
140 | } else { | 128 | } else { |
141 | if (previous_block_number != -1) { | 129 | if (previous_block_number != -1) { |
142 | /* spill */ | 130 | /* spill */ |
143 | status = ext4fs_devread(delayed_start, | 131 | status = ext4fs_devread(delayed_start, |
144 | delayed_skipfirst, | 132 | delayed_skipfirst, |
145 | delayed_extent, | 133 | delayed_extent, |
146 | delayed_buf); | 134 | delayed_buf); |
147 | if (status == 0) { | 135 | if (status == 0) |
148 | len = -1; | 136 | return -1; |
149 | goto out_exit; | ||
150 | } | ||
151 | previous_block_number = -1; | 137 | previous_block_number = -1; |
152 | } | 138 | } |
153 | memset(buf, 0, blocksize - skipfirst); | 139 | memset(buf, 0, blocksize - skipfirst); |
154 | } | 140 | } |
155 | buf += blocksize - skipfirst; | 141 | buf += blocksize - skipfirst; |
156 | } | 142 | } |
157 | if (previous_block_number != -1) { | 143 | if (previous_block_number != -1) { |
158 | /* spill */ | 144 | /* spill */ |
159 | status = ext4fs_devread(delayed_start, | 145 | status = ext4fs_devread(delayed_start, |
160 | delayed_skipfirst, delayed_extent, | 146 | delayed_skipfirst, delayed_extent, |
161 | delayed_buf); | 147 | delayed_buf); |
162 | if (status == 0) { | 148 | if (status == 0) |
163 | len = -1; | 149 | return -1; |
164 | goto out_exit; | ||
165 | } | ||
166 | previous_block_number = -1; | 150 | previous_block_number = -1; |
167 | } | 151 | } |
168 | |||
169 | |||
170 | out_exit: | ||
171 | ext4fs_free_extent_cache(); | ||
172 | 152 | ||
173 | return len; | 153 | return len; |
174 | } | 154 | } |
175 | 155 | ||
176 | int ext4fs_ls(const char *dirname) | 156 | int ext4fs_ls(const char *dirname) |
177 | { | 157 | { |
178 | struct ext2fs_node *dirnode; | 158 | struct ext2fs_node *dirnode; |
179 | int status; | 159 | int status; |
180 | 160 | ||
181 | if (dirname == NULL) | 161 | if (dirname == NULL) |
182 | return 0; | 162 | return 0; |
183 | 163 | ||
184 | status = ext4fs_find_file(dirname, &ext4fs_root->diropen, &dirnode, | 164 | status = ext4fs_find_file(dirname, &ext4fs_root->diropen, &dirnode, |
185 | FILETYPE_DIRECTORY); | 165 | FILETYPE_DIRECTORY); |
186 | if (status != 1) { | 166 | if (status != 1) { |
187 | printf("** Can not find directory. **\n"); | 167 | printf("** Can not find directory. **\n"); |
188 | return 1; | 168 | return 1; |
189 | } | 169 | } |
190 | 170 | ||
191 | ext4fs_iterate_dir(dirnode, NULL, NULL, NULL); | 171 | ext4fs_iterate_dir(dirnode, NULL, NULL, NULL); |
192 | ext4fs_free_node(dirnode, &ext4fs_root->diropen); | 172 | ext4fs_free_node(dirnode, &ext4fs_root->diropen); |
193 | 173 | ||
194 | return 0; | 174 | return 0; |
195 | } | 175 | } |
196 | 176 | ||
197 | int ext4fs_exists(const char *filename) | 177 | int ext4fs_exists(const char *filename) |
198 | { | 178 | { |
199 | int file_len; | 179 | int file_len; |
200 | 180 | ||
201 | file_len = ext4fs_open(filename); | 181 | file_len = ext4fs_open(filename); |
202 | return file_len >= 0; | 182 | return file_len >= 0; |
203 | } | 183 | } |
204 | 184 | ||
205 | int ext4fs_read(char *buf, unsigned len) | 185 | int ext4fs_read(char *buf, unsigned len) |
206 | { | 186 | { |
207 | if (ext4fs_root == NULL || ext4fs_file == NULL) | 187 | if (ext4fs_root == NULL || ext4fs_file == NULL) |
208 | return 0; | 188 | return 0; |
209 | 189 | ||
210 | return ext4fs_read_file(ext4fs_file, 0, len, buf); | 190 | return ext4fs_read_file(ext4fs_file, 0, len, buf); |
211 | } | 191 | } |
212 | 192 | ||
213 | int ext4fs_probe(block_dev_desc_t *fs_dev_desc, | 193 | int ext4fs_probe(block_dev_desc_t *fs_dev_desc, |
214 | disk_partition_t *fs_partition) | 194 | disk_partition_t *fs_partition) |
215 | { | 195 | { |
216 | ext4fs_set_blk_dev(fs_dev_desc, fs_partition); | 196 | ext4fs_set_blk_dev(fs_dev_desc, fs_partition); |
217 | 197 | ||
218 | if (!ext4fs_mount(fs_partition->size)) { | 198 | if (!ext4fs_mount(fs_partition->size)) { |
219 | ext4fs_close(); | 199 | ext4fs_close(); |
220 | return -1; | 200 | return -1; |
221 | } | 201 | } |
222 | 202 | ||
223 | return 0; | 203 | return 0; |
224 | } | 204 | } |
225 | 205 | ||
226 | int ext4_read_file(const char *filename, void *buf, int offset, int len) | 206 | int ext4_read_file(const char *filename, void *buf, int offset, int len) |
227 | { | 207 | { |
228 | int file_len; | 208 | int file_len; |
229 | int len_read; | 209 | int len_read; |
230 | 210 | ||
231 | if (offset != 0) { | 211 | if (offset != 0) { |
232 | printf("** Cannot support non-zero offset **\n"); | 212 | printf("** Cannot support non-zero offset **\n"); |
233 | return -1; | 213 | return -1; |
234 | } | 214 | } |
235 | 215 | ||
236 | file_len = ext4fs_open(filename); | 216 | file_len = ext4fs_open(filename); |
237 | if (file_len < 0) { | 217 | if (file_len < 0) { |
238 | printf("** File not found %s **\n", filename); | 218 | printf("** File not found %s **\n", filename); |
239 | return -1; | 219 | return -1; |
240 | } | 220 | } |
241 | 221 | ||
242 | if (len == 0) | 222 | if (len == 0) |
243 | len = file_len; | 223 | len = file_len; |
244 | 224 | ||
245 | len_read = ext4fs_read(buf, len); | 225 | len_read = ext4fs_read(buf, len); |
246 | 226 | ||
247 | return len_read; | 227 | return len_read; |
248 | } | 228 | } |
249 | 229 |