Lines 173-186
out:
Link Here
|
173 |
|
173 |
|
174 |
SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, |
174 |
SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, |
175 |
long long index, unsigned int length, |
175 |
long long index, unsigned int length, |
176 |
long long *next_index) |
176 |
long long *next_index, int srclength) |
177 |
{ |
177 |
{ |
178 |
struct squashfs_sb_info *msblk = s->s_fs_info; |
178 |
struct squashfs_sb_info *msblk = s->s_fs_info; |
|
|
179 |
struct squashfs_super_block *sblk = &msblk->sblk; |
179 |
struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >> |
180 |
struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >> |
180 |
msblk->devblksize_log2) + 2]; |
181 |
msblk->devblksize_log2) + 2]; |
181 |
unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); |
182 |
unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); |
182 |
unsigned int cur_index = index >> msblk->devblksize_log2; |
183 |
unsigned int cur_index = index >> msblk->devblksize_log2; |
183 |
int bytes, avail_bytes, b = 0, k; |
184 |
int bytes, avail_bytes, b = 0, k = 0; |
184 |
char *c_buffer; |
185 |
char *c_buffer; |
185 |
unsigned int compressed; |
186 |
unsigned int compressed; |
186 |
unsigned int c_byte = length; |
187 |
unsigned int c_byte = length; |
Lines 191-198
SQSH_EXTERN unsigned int squashfs_read_d
Link Here
|
191 |
c_buffer = compressed ? msblk->read_data : buffer; |
192 |
c_buffer = compressed ? msblk->read_data : buffer; |
192 |
c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); |
193 |
c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); |
193 |
|
194 |
|
194 |
TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed |
195 |
TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed |
195 |
? "" : "un", (unsigned int) c_byte); |
196 |
? "" : "un", (unsigned int) c_byte, srclength); |
|
|
197 |
|
198 |
if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) |
199 |
goto read_failure; |
196 |
|
200 |
|
197 |
if (!(bh[0] = sb_getblk(s, cur_index))) |
201 |
if (!(bh[0] = sb_getblk(s, cur_index))) |
198 |
goto block_release; |
202 |
goto block_release; |
Lines 204-209
SQSH_EXTERN unsigned int squashfs_read_d
Link Here
|
204 |
} |
208 |
} |
205 |
ll_rw_block(READ, b, bh); |
209 |
ll_rw_block(READ, b, bh); |
206 |
} else { |
210 |
} else { |
|
|
211 |
if (index < 0 || (index + 2) > sblk->bytes_used) |
212 |
goto read_failure; |
213 |
|
207 |
if (!(bh[0] = get_block_length(s, &cur_index, &offset, |
214 |
if (!(bh[0] = get_block_length(s, &cur_index, &offset, |
208 |
&c_byte))) |
215 |
&c_byte))) |
209 |
goto read_failure; |
216 |
goto read_failure; |
Lines 216-221
SQSH_EXTERN unsigned int squashfs_read_d
Link Here
|
216 |
TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed |
223 |
TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed |
217 |
? "" : "un", (unsigned int) c_byte); |
224 |
? "" : "un", (unsigned int) c_byte); |
218 |
|
225 |
|
|
|
226 |
if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) |
227 |
goto read_failure; |
228 |
|
219 |
for (b = 1; bytes < c_byte; b++) { |
229 |
for (b = 1; bytes < c_byte; b++) { |
220 |
if (!(bh[b] = sb_getblk(s, ++cur_index))) |
230 |
if (!(bh[b] = sb_getblk(s, ++cur_index))) |
221 |
goto block_release; |
231 |
goto block_release; |
Lines 227-233
SQSH_EXTERN unsigned int squashfs_read_d
Link Here
|
227 |
if (compressed) |
237 |
if (compressed) |
228 |
down(&msblk->read_data_mutex); |
238 |
down(&msblk->read_data_mutex); |
229 |
|
239 |
|
230 |
for (bytes = 0, k = 0; k < b; k++) { |
240 |
for (bytes = 0; k < b; k++) { |
231 |
avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ? |
241 |
avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ? |
232 |
msblk->devblksize - offset : |
242 |
msblk->devblksize - offset : |
233 |
c_byte - bytes; |
243 |
c_byte - bytes; |
Lines 249-255
SQSH_EXTERN unsigned int squashfs_read_d
Link Here
|
249 |
msblk->stream.next_in = c_buffer; |
259 |
msblk->stream.next_in = c_buffer; |
250 |
msblk->stream.avail_in = c_byte; |
260 |
msblk->stream.avail_in = c_byte; |
251 |
msblk->stream.next_out = buffer; |
261 |
msblk->stream.next_out = buffer; |
252 |
msblk->stream.avail_out = msblk->read_size; |
262 |
msblk->stream.avail_out = srclength; |
253 |
|
263 |
|
254 |
if (((zlib_err = zlib_inflateInit(&msblk->stream)) != Z_OK) || |
264 |
if (((zlib_err = zlib_inflateInit(&msblk->stream)) != Z_OK) || |
255 |
((zlib_err = zlib_inflate(&msblk->stream, Z_FINISH)) |
265 |
((zlib_err = zlib_inflate(&msblk->stream, Z_FINISH)) |
Lines 271-278
SQSH_EXTERN unsigned int squashfs_read_d
Link Here
|
271 |
return bytes; |
281 |
return bytes; |
272 |
|
282 |
|
273 |
block_release: |
283 |
block_release: |
274 |
while (--b >= 0) |
284 |
for (; k < b; k++) |
275 |
brelse(bh[b]); |
285 |
brelse(bh[k]); |
276 |
|
286 |
|
277 |
read_failure: |
287 |
read_failure: |
278 |
ERROR("sb_bread failed reading block 0x%x\n", cur_index); |
288 |
ERROR("sb_bread failed reading block 0x%x\n", cur_index); |
Lines 336-349
SQSH_EXTERN int squashfs_get_cached_bloc
Link Here
|
336 |
msblk->block_cache[i].block = SQUASHFS_USED_BLK; |
346 |
msblk->block_cache[i].block = SQUASHFS_USED_BLK; |
337 |
up(&msblk->block_cache_mutex); |
347 |
up(&msblk->block_cache_mutex); |
338 |
|
348 |
|
339 |
if (!(msblk->block_cache[i].length = |
349 |
msblk->block_cache[i].length = squashfs_read_data(s, |
340 |
squashfs_read_data(s, |
350 |
msblk->block_cache[i].data, block, 0, &next_index, |
341 |
msblk->block_cache[i].data, |
351 |
SQUASHFS_METADATA_SIZE); |
342 |
block, 0, &next_index))) { |
352 |
|
343 |
ERROR("Unable to read cache block [%llx:%x]\n", |
353 |
if (msblk->block_cache[i].length == 0) { |
344 |
block, offset); |
354 |
ERROR("Unable to read cache block [%llx:%x]\n", |
345 |
goto out; |
355 |
block, offset); |
346 |
} |
356 |
down(&msblk->block_cache_mutex); |
|
|
357 |
msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; |
358 |
kfree(msblk->block_cache[i].data); |
359 |
wake_up(&msblk->waitq); |
360 |
up(&msblk->block_cache_mutex); |
361 |
goto out; |
362 |
} |
347 |
|
363 |
|
348 |
down(&msblk->block_cache_mutex); |
364 |
down(&msblk->block_cache_mutex); |
349 |
wake_up(&msblk->waitq); |
365 |
wake_up(&msblk->waitq); |
Lines 357-363
SQSH_EXTERN int squashfs_get_cached_bloc
Link Here
|
357 |
continue; |
373 |
continue; |
358 |
} |
374 |
} |
359 |
|
375 |
|
360 |
if ((bytes = msblk->block_cache[i].length - offset) >= length) { |
376 |
bytes = msblk->block_cache[i].length - offset; |
|
|
377 |
|
378 |
if (bytes < 1) |
379 |
goto out; |
380 |
else if (bytes >= length) { |
361 |
if (buffer) |
381 |
if (buffer) |
362 |
memcpy(buffer, msblk->block_cache[i].data + |
382 |
memcpy(buffer, msblk->block_cache[i].data + |
363 |
offset, length); |
383 |
offset, length); |
Lines 442-447
SQSH_EXTERN struct squashfs_fragment_cac
Link Here
|
442 |
{ |
462 |
{ |
443 |
int i, n; |
463 |
int i, n; |
444 |
struct squashfs_sb_info *msblk = s->s_fs_info; |
464 |
struct squashfs_sb_info *msblk = s->s_fs_info; |
|
|
465 |
struct squashfs_super_block *sblk = &msblk->sblk; |
445 |
|
466 |
|
446 |
while ( 1 ) { |
467 |
while ( 1 ) { |
447 |
down(&msblk->fragment_mutex); |
468 |
down(&msblk->fragment_mutex); |
Lines 487-493
SQSH_EXTERN struct squashfs_fragment_cac
Link Here
|
487 |
|
508 |
|
488 |
if (!(msblk->fragment[i].length = squashfs_read_data(s, |
509 |
if (!(msblk->fragment[i].length = squashfs_read_data(s, |
489 |
msblk->fragment[i].data, |
510 |
msblk->fragment[i].data, |
490 |
start_block, length, NULL))) { |
511 |
start_block, length, NULL, |
|
|
512 |
sblk->block_size))) { |
491 |
ERROR("Unable to read fragment cache block " |
513 |
ERROR("Unable to read fragment cache block " |
492 |
"[%llx]\n", start_block); |
514 |
"[%llx]\n", start_block); |
493 |
msblk->fragment[i].locked = 0; |
515 |
msblk->fragment[i].locked = 0; |
Lines 876-881
static int read_fragment_index_table(str
Link Here
|
876 |
{ |
898 |
{ |
877 |
struct squashfs_sb_info *msblk = s->s_fs_info; |
899 |
struct squashfs_sb_info *msblk = s->s_fs_info; |
878 |
struct squashfs_super_block *sblk = &msblk->sblk; |
900 |
struct squashfs_super_block *sblk = &msblk->sblk; |
|
|
901 |
unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); |
902 |
|
903 |
if (length == 0) |
904 |
return 1; |
879 |
|
905 |
|
880 |
/* Allocate fragment index table */ |
906 |
/* Allocate fragment index table */ |
881 |
if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES |
907 |
if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES |
Lines 884-896
static int read_fragment_index_table(str
Link Here
|
884 |
return 0; |
910 |
return 0; |
885 |
} |
911 |
} |
886 |
|
912 |
|
887 |
if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) && |
913 |
if (!squashfs_read_data(s, (char *) msblk->fragment_index, |
888 |
!squashfs_read_data(s, (char *) |
914 |
sblk->fragment_table_start, length | |
889 |
msblk->fragment_index, |
915 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { |
890 |
sblk->fragment_table_start, |
|
|
891 |
SQUASHFS_FRAGMENT_INDEX_BYTES |
892 |
(sblk->fragments) | |
893 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { |
894 |
ERROR("unable to read fragment index table\n"); |
916 |
ERROR("unable to read fragment index table\n"); |
895 |
return 0; |
917 |
return 0; |
896 |
} |
918 |
} |
Lines 982-990
static int squashfs_fill_super(struct su
Link Here
|
982 |
init_waitqueue_head(&msblk->waitq); |
1004 |
init_waitqueue_head(&msblk->waitq); |
983 |
init_waitqueue_head(&msblk->fragment_wait_queue); |
1005 |
init_waitqueue_head(&msblk->fragment_wait_queue); |
984 |
|
1006 |
|
|
|
1007 |
sblk->bytes_used = sizeof(struct squashfs_super_block); |
985 |
if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, |
1008 |
if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, |
986 |
sizeof(struct squashfs_super_block) | |
1009 |
sizeof(struct squashfs_super_block) | |
987 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { |
1010 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, |
|
|
1011 |
sizeof(struct squashfs_super_block))) { |
988 |
SERROR("unable to read superblock\n"); |
1012 |
SERROR("unable to read superblock\n"); |
989 |
goto failed_mount; |
1013 |
goto failed_mount; |
990 |
} |
1014 |
} |
Lines 1012-1017
static int squashfs_fill_super(struct su
Link Here
|
1012 |
if(!supported_squashfs_filesystem(msblk, silent)) |
1036 |
if(!supported_squashfs_filesystem(msblk, silent)) |
1013 |
goto failed_mount; |
1037 |
goto failed_mount; |
1014 |
|
1038 |
|
|
|
1039 |
/* Check the filesystem does not extend beyond the end of the |
1040 |
block device */ |
1041 |
if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) |
1042 |
goto failed_mount; |
1043 |
|
1044 |
/* Check the root inode for sanity */ |
1045 |
if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) |
1046 |
goto failed_mount; |
1047 |
|
1015 |
TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); |
1048 |
TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); |
1016 |
TRACE("Inodes are %scompressed\n", |
1049 |
TRACE("Inodes are %scompressed\n", |
1017 |
SQUASHFS_UNCOMPRESSED_INODES |
1050 |
SQUASHFS_UNCOMPRESSED_INODES |
Lines 1081-1087
static int squashfs_fill_super(struct su
Link Here
|
1081 |
if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, |
1114 |
if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, |
1082 |
((sblk->no_uids + sblk->no_guids) * |
1115 |
((sblk->no_uids + sblk->no_guids) * |
1083 |
sizeof(unsigned int)) | |
1116 |
sizeof(unsigned int)) | |
1084 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { |
1117 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, |
|
|
1118 |
(sblk->no_uids + sblk->no_guids) * |
1119 |
sizeof(unsigned int))) { |
1085 |
ERROR("unable to read uid/gid table\n"); |
1120 |
ERROR("unable to read uid/gid table\n"); |
1086 |
goto failed_mount; |
1121 |
goto failed_mount; |
1087 |
} |
1122 |
} |
Lines 1092-1098
static int squashfs_fill_super(struct su
Link Here
|
1092 |
if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, |
1127 |
if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, |
1093 |
((sblk->no_uids + sblk->no_guids) * |
1128 |
((sblk->no_uids + sblk->no_guids) * |
1094 |
sizeof(unsigned int)) | |
1129 |
sizeof(unsigned int)) | |
1095 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { |
1130 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, |
|
|
1131 |
(sblk->no_uids + sblk->no_guids) * |
1132 |
sizeof(unsigned int))) { |
1096 |
ERROR("unable to read uid/gid table\n"); |
1133 |
ERROR("unable to read uid/gid table\n"); |
1097 |
goto failed_mount; |
1134 |
goto failed_mount; |
1098 |
} |
1135 |
} |
Lines 1518-1524
static int squashfs_readpage(struct file
Link Here
|
1518 |
down(&msblk->read_page_mutex); |
1555 |
down(&msblk->read_page_mutex); |
1519 |
|
1556 |
|
1520 |
if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page, |
1557 |
if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page, |
1521 |
block, bsize, NULL))) { |
1558 |
block, bsize, NULL, |
|
|
1559 |
msblk->read_size))) { |
1522 |
ERROR("Unable to read page, block %llx, size %x\n", block, |
1560 |
ERROR("Unable to read page, block %llx, size %x\n", block, |
1523 |
bsize); |
1561 |
bsize); |
1524 |
up(&msblk->read_page_mutex); |
1562 |
up(&msblk->read_page_mutex); |
Lines 1618-1632
static int squashfs_readpage4K(struct fi
Link Here
|
1618 |
|
1656 |
|
1619 |
if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> |
1657 |
if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> |
1620 |
PAGE_CACHE_SHIFT)) { |
1658 |
PAGE_CACHE_SHIFT)) { |
1621 |
pageaddr = kmap_atomic(page, KM_USER0); |
|
|
1622 |
block_list = NULL; |
1659 |
block_list = NULL; |
1623 |
goto skip_read; |
1660 |
goto skip_read; |
1624 |
} |
1661 |
} |
1625 |
|
1662 |
|
1626 |
if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) { |
1663 |
if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) { |
1627 |
ERROR("Failed to allocate block_list\n"); |
1664 |
ERROR("Failed to allocate block_list\n"); |
1628 |
pageaddr = kmap_atomic(page, KM_USER0); |
|
|
1629 |
block_list = NULL; |
1630 |
goto skip_read; |
1665 |
goto skip_read; |
1631 |
} |
1666 |
} |
1632 |
|
1667 |
|
Lines 1638-1648
static int squashfs_readpage4K(struct fi
Link Here
|
1638 |
|
1673 |
|
1639 |
down(&msblk->read_page_mutex); |
1674 |
down(&msblk->read_page_mutex); |
1640 |
bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, |
1675 |
bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, |
1641 |
bsize, NULL); |
1676 |
bsize, NULL, msblk->read_size); |
1642 |
pageaddr = kmap_atomic(page, KM_USER0); |
1677 |
if (bytes) { |
1643 |
if (bytes) |
1678 |
pageaddr = kmap_atomic(page, KM_USER0); |
1644 |
memcpy(pageaddr, msblk->read_page, bytes); |
1679 |
memcpy(pageaddr, msblk->read_page, bytes); |
1645 |
else |
1680 |
kunmap_atomic(pageaddr, KM_USER0); |
|
|
1681 |
} else |
1646 |
ERROR("Unable to read page, block %llx, size %x\n", |
1682 |
ERROR("Unable to read page, block %llx, size %x\n", |
1647 |
block, bsize); |
1683 |
block, bsize); |
1648 |
up(&msblk->read_page_mutex); |
1684 |
up(&msblk->read_page_mutex); |
Lines 1652-1662
static int squashfs_readpage4K(struct fi
Link Here
|
1652 |
SQUASHFS_I(inode)-> |
1688 |
SQUASHFS_I(inode)-> |
1653 |
u.s1.fragment_start_block, |
1689 |
u.s1.fragment_start_block, |
1654 |
SQUASHFS_I(inode)-> u.s1.fragment_size); |
1690 |
SQUASHFS_I(inode)-> u.s1.fragment_size); |
1655 |
pageaddr = kmap_atomic(page, KM_USER0); |
|
|
1656 |
if (fragment) { |
1691 |
if (fragment) { |
1657 |
bytes = i_size_read(inode) & (sblk->block_size - 1); |
1692 |
bytes = i_size_read(inode) & (sblk->block_size - 1); |
|
|
1693 |
pageaddr = kmap_atomic(page, KM_USER0); |
1658 |
memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)-> |
1694 |
memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)-> |
1659 |
u.s1.fragment_offset, bytes); |
1695 |
u.s1.fragment_offset, bytes); |
|
|
1696 |
kunmap_atomic(pageaddr, KM_USER0); |
1660 |
release_cached_fragment(msblk, fragment); |
1697 |
release_cached_fragment(msblk, fragment); |
1661 |
} else |
1698 |
} else |
1662 |
ERROR("Unable to read page, block %llx, size %x\n", |
1699 |
ERROR("Unable to read page, block %llx, size %x\n", |
Lines 1666-1671
static int squashfs_readpage4K(struct fi
Link Here
|
1666 |
} |
1703 |
} |
1667 |
|
1704 |
|
1668 |
skip_read: |
1705 |
skip_read: |
|
|
1706 |
pageaddr = kmap_atomic(page, KM_USER0); |
1669 |
memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); |
1707 |
memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); |
1670 |
kunmap_atomic(pageaddr, KM_USER0); |
1708 |
kunmap_atomic(pageaddr, KM_USER0); |
1671 |
flush_dcache_page(page); |
1709 |
flush_dcache_page(page); |