block.c revision f6e22234d60d71a19b598a257de6355ffa1e999e
13cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher/* 23cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * Squashfs - a compressed read only filesystem for Linux 33cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * 43cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 53cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * Phillip Lougher <phillip@lougher.demon.co.uk> 63cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * 73cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * This program is free software; you can redistribute it and/or 83cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * modify it under the terms of the GNU General Public License 93cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * as published by the Free Software Foundation; either version 2, 103cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * or (at your option) any later version. 113cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * 123cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * This program is distributed in the hope that it will be useful, 133cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * but WITHOUT ANY WARRANTY; without even the implied warranty of 143cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 153cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * GNU General Public License for more details. 163cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * 173cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * You should have received a copy of the GNU General Public License 183cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * along with this program; if not, write to the Free Software 193cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 203cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * 213cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher * block.c 223cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher */ 233cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 24c6893b04297e3a4c3eaaf4560563cfe87e9a6b56plougher#include <linux/fs.h> 25c6893b04297e3a4c3eaaf4560563cfe87e9a6b56plougher#include <linux/vfs.h> 26c6893b04297e3a4c3eaaf4560563cfe87e9a6b56plougher#include <linux/slab.h> 27c6893b04297e3a4c3eaaf4560563cfe87e9a6b56plougher#include <linux/mutex.h> 28c6893b04297e3a4c3eaaf4560563cfe87e9a6b56plougher#include <linux/string.h> 29e10248a420914a7c6092fc02b803cf3dac5b432dplougher#include <linux/buffer_head.h> 30c6893b04297e3a4c3eaaf4560563cfe87e9a6b56plougher#include <linux/zlib.h> 31e10248a420914a7c6092fc02b803cf3dac5b432dplougher#include <linux/squashfs_fs.h> 323cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher#include <linux/squashfs_fs_sb.h> 333cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher#include <linux/squashfs_fs_i.h> 343cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 353cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher#include "squashfs.h" 36e10248a420914a7c6092fc02b803cf3dac5b432dplougher 373cb299277b04dfdb6fe21768b8f83dec1f4014b6plougherstatic struct buffer_head *get_block_length(struct super_block *s, 38f6e22234d60d71a19b598a257de6355ffa1e999eplougher int *cur_index, int *offset, unsigned int *length) 393cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher{ 403cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher struct squashfs_sb_info *msblk = s->s_fs_info; 413cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher struct buffer_head *bh; 423cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 4356d24bf18e169cc9de1499e63a99809b8fed08fbplougher bh = sb_bread(s, *cur_index); 4456d24bf18e169cc9de1499e63a99809b8fed08fbplougher if (bh == NULL) 453cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto out; 463cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 473cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (msblk->devblksize - *offset == 1) { 48f6e22234d60d71a19b598a257de6355ffa1e999eplougher *length = (unsigned char) bh->b_data[*offset]; 493cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher brelse(bh); 5056d24bf18e169cc9de1499e63a99809b8fed08fbplougher bh = sb_bread(s, ++(*cur_index)); 5156d24bf18e169cc9de1499e63a99809b8fed08fbplougher if (bh == NULL) 523cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto out; 53f6e22234d60d71a19b598a257de6355ffa1e999eplougher *length |= (unsigned char) bh->b_data[0] << 8; 543cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher *offset = 1; 553cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } else { 56f6e22234d60d71a19b598a257de6355ffa1e999eplougher *length = (unsigned char) bh->b_data[*offset] | 57f6e22234d60d71a19b598a257de6355ffa1e999eplougher (unsigned char) bh->b_data[*offset + 1] << 8; 583cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher *offset += 2; 593cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 603cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 613cb299277b04dfdb6fe21768b8f83dec1f4014b6plougherout: 62f6e22234d60d71a19b598a257de6355ffa1e999eplougher return bh; 633cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher} 643cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 653cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 66f6e22234d60d71a19b598a257de6355ffa1e999eplougher 67283a23fa5fff9cab6eb5f04e5c9d876cec74d908plougherunsigned int squashfs_read_data(struct super_block *s, void *buffer, 683cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher long long index, unsigned int length, 693cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher long long *next_index, int srclength) 703cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher{ 713cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher struct squashfs_sb_info *msblk = s->s_fs_info; 723cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher struct buffer_head **bh; 733cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); 743cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher unsigned int cur_index = index >> msblk->devblksize_log2; 7556d24bf18e169cc9de1499e63a99809b8fed08fbplougher int bytes, avail, b = 0, k = 0; 763cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher unsigned int compressed; 773cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher unsigned int c_byte = length; 783cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 79b000fa80a6a742b279c61398287698f837cbb14aplougher bh = kmalloc(((msblk->block_size >> msblk->devblksize_log2) + 1) * 8056d24bf18e169cc9de1499e63a99809b8fed08fbplougher sizeof(struct buffer_head *), GFP_KERNEL); 813cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (bh == NULL) 823cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto read_failure; 833cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 843cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (c_byte) { 853cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher bytes = -offset; 863cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); 873cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); 883cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 8956d24bf18e169cc9de1499e63a99809b8fed08fbplougher TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", 90f6e22234d60d71a19b598a257de6355ffa1e999eplougher index, compressed ? "" : "un", c_byte, srclength); 913cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 9256d24bf18e169cc9de1499e63a99809b8fed08fbplougher if (c_byte > srclength || index < 0 || 9356d24bf18e169cc9de1499e63a99809b8fed08fbplougher (index + c_byte) > msblk->bytes_used) 943cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto read_failure; 953cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 963cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher for (b = 0; bytes < (int) c_byte; b++, cur_index++) { 973cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher bh[b] = sb_getblk(s, cur_index); 983cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (bh[b] == NULL) 993cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto block_release; 1003cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher bytes += msblk->devblksize; 1013cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 1023cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher ll_rw_block(READ, b, bh); 1033cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } else { 104b000fa80a6a742b279c61398287698f837cbb14aplougher if (index < 0 || (index + 2) > msblk->bytes_used) 1053cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto read_failure; 1063cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1073cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); 1083cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (bh[0] == NULL) 1093cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto read_failure; 1103cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher b = 1; 1113cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1123cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher bytes = msblk->devblksize - offset; 1133cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher compressed = SQUASHFS_COMPRESSED(c_byte); 1143cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 1153cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 11656d24bf18e169cc9de1499e63a99809b8fed08fbplougher TRACE("Block @ 0x%llx, %scompressed size %d\n", index, 117f6e22234d60d71a19b598a257de6355ffa1e999eplougher compressed ? "" : "un", c_byte); 1183cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 119b000fa80a6a742b279c61398287698f837cbb14aplougher if (c_byte > srclength || (index + c_byte) > msblk->bytes_used) 1203cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto block_release; 1213cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1223cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher for (; bytes < c_byte; b++) { 1233cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher bh[b] = sb_getblk(s, ++cur_index); 1243cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (bh[b] == NULL) 1253cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto block_release; 1263cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher bytes += msblk->devblksize; 1273cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 1283cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher ll_rw_block(READ, b - 1, bh + 1); 1293cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 1303cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1313cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (compressed) { 1323cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher int zlib_err = 0; 1333cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1343cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher /* 13556d24bf18e169cc9de1499e63a99809b8fed08fbplougher * uncompress block 13656d24bf18e169cc9de1499e63a99809b8fed08fbplougher */ 1373cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1383cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher mutex_lock(&msblk->read_data_mutex); 1393cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1403cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher msblk->stream.next_out = buffer; 1413cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher msblk->stream.avail_out = srclength; 1423cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1433cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher for (bytes = 0; k < b; k++) { 14456d24bf18e169cc9de1499e63a99809b8fed08fbplougher avail = min(c_byte - bytes, msblk->devblksize - offset); 1453cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1463cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher wait_on_buffer(bh[k]); 1473cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (!buffer_uptodate(bh[k])) 1483cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto release_mutex; 1493cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1503cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher msblk->stream.next_in = bh[k]->b_data + offset; 15156d24bf18e169cc9de1499e63a99809b8fed08fbplougher msblk->stream.avail_in = avail; 1523cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1533cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (k == 0) { 1543cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher zlib_err = zlib_inflateInit(&msblk->stream); 1553cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (zlib_err != Z_OK) { 15656d24bf18e169cc9de1499e63a99809b8fed08fbplougher ERROR("zlib_inflateInit returned" 15756d24bf18e169cc9de1499e63a99809b8fed08fbplougher " unexpected result 0x%x," 15856d24bf18e169cc9de1499e63a99809b8fed08fbplougher " srclength %d\n", zlib_err, 15956d24bf18e169cc9de1499e63a99809b8fed08fbplougher srclength); 1603cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto release_mutex; 1613cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 1623cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 16356d24bf18e169cc9de1499e63a99809b8fed08fbplougher if (avail == 0) { 1643cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher offset = 0; 1653cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher brelse(bh[k]); 1663cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher continue; 1673cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 1683cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 1693cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1703cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); 1713cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { 17256d24bf18e169cc9de1499e63a99809b8fed08fbplougher ERROR("zlib_inflate returned unexpected result" 17356d24bf18e169cc9de1499e63a99809b8fed08fbplougher " 0x%x, srclength %d, avail_in %d," 17456d24bf18e169cc9de1499e63a99809b8fed08fbplougher " avail_out %d\n", zlib_err, srclength, 17556d24bf18e169cc9de1499e63a99809b8fed08fbplougher msblk->stream.avail_in, 17656d24bf18e169cc9de1499e63a99809b8fed08fbplougher msblk->stream.avail_out); 1773cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto release_mutex; 1783cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 1793cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 18056d24bf18e169cc9de1499e63a99809b8fed08fbplougher bytes += avail; 1813cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher offset = 0; 1823cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher brelse(bh[k]); 1833cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 1843cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1853cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (zlib_err != Z_STREAM_END) 1863cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto release_mutex; 1873cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 1883cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher zlib_err = zlib_inflateEnd(&msblk->stream); 1893cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (zlib_err != Z_OK) { 1903cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher ERROR("zlib_inflateEnd returned unexpected result 0x%x," 1913cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher " srclength %d\n", zlib_err, srclength); 1923cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto release_mutex; 1933cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 1943cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher bytes = msblk->stream.total_out; 1953cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher mutex_unlock(&msblk->read_data_mutex); 1963cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } else { 1973cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher int i; 1983cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 19956d24bf18e169cc9de1499e63a99809b8fed08fbplougher for (i = 0; i < b; i++) { 2003cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher wait_on_buffer(bh[i]); 2013cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (!buffer_uptodate(bh[i])) 2023cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto block_release; 2033cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 2043cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 2053cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher for (bytes = 0; k < b; k++) { 20656d24bf18e169cc9de1499e63a99809b8fed08fbplougher avail = min(c_byte - bytes, msblk->devblksize - offset); 2073cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 20856d24bf18e169cc9de1499e63a99809b8fed08fbplougher memcpy(buffer + bytes, bh[k]->b_data + offset, avail); 20956d24bf18e169cc9de1499e63a99809b8fed08fbplougher bytes += avail; 2103cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher offset = 0; 2113cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher brelse(bh[k]); 2123cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 2133cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 2143cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 2153cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (next_index) 216b000fa80a6a742b279c61398287698f837cbb14aplougher *next_index = index + c_byte + (length ? 0 : 2); 2173cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 2183cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher kfree(bh); 2193cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher return bytes; 2203cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 2213cb299277b04dfdb6fe21768b8f83dec1f4014b6plougherrelease_mutex: 2223cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher mutex_unlock(&msblk->read_data_mutex); 2233cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 2243cb299277b04dfdb6fe21768b8f83dec1f4014b6plougherblock_release: 2253cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher for (; k < b; k++) 2263cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher brelse(bh[k]); 2273cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 2283cb299277b04dfdb6fe21768b8f83dec1f4014b6plougherread_failure: 2293cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher ERROR("sb_bread failed reading block 0x%x\n", cur_index); 2303cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher kfree(bh); 2313cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher return 0; 2323cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher} 2333cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 2343cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 2353cb299277b04dfdb6fe21768b8f83dec1f4014b6plougherint squashfs_get_cached_block(struct super_block *s, void *buffer, 2363cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher long long block, unsigned int offset, 2373cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher int length, long long *next_block, 2383cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher unsigned int *next_offset) 2393cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher{ 2403cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher struct squashfs_sb_info *msblk = s->s_fs_info; 2413cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher int bytes, return_length = length; 2423cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher struct squashfs_cache_entry *entry; 2433cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 2443cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); 2453cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 2463cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher while (1) { 2473cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher entry = squashfs_cache_get(s, msblk->block_cache, block, 0); 2483cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher bytes = entry->length - offset; 2493cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 2503cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (entry->error || bytes < 1) { 2513cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher return_length = 0; 2523cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto finish; 2533cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } else if (bytes >= length) { 2543cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (buffer) 2553cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher memcpy(buffer, entry->data + offset, length); 2563cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (entry->length - offset == length) { 2573cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher *next_block = entry->next_index; 2583cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher *next_offset = 0; 2593cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } else { 2603cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher *next_block = block; 2613cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher *next_offset = offset + length; 2623cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 2633cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher goto finish; 2643cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } else { 2653cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher if (buffer) { 2663cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher memcpy(buffer, entry->data + offset, bytes); 267f6e22234d60d71a19b598a257de6355ffa1e999eplougher buffer += bytes; 2683cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 2693cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher block = entry->next_index; 2703cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher squashfs_cache_put(msblk->block_cache, entry); 2713cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher length -= bytes; 2723cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher offset = 0; 2733cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 2743cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher } 2753cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher 2763cb299277b04dfdb6fe21768b8f83dec1f4014b6plougherfinish: 2773cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher squashfs_cache_put(msblk->block_cache, entry); 2783cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher return return_length; 2793cb299277b04dfdb6fe21768b8f83dec1f4014b6plougher} 280