diff --git a/lsvmutils/ext2.c b/lsvmutils/ext2.c index 4bfc071..e2161f2 100644 --- a/lsvmutils/ext2.c +++ b/lsvmutils/ext2.c @@ -140,6 +140,59 @@ static void _HexDump( typedef unsigned long ssize_t; #endif +static ssize_t _ReadPartialBlock( + Blkdev* dev, + UINTN blkno, + size_t offset, + size_t size, + void* data) +{ + UINT8 blk[BLKDEV_BLKSIZE]; + UINT32 off; /* offset into this block */ + UINT32 len; /* bytes to read from this block */ + + if (!size) + return 0; + + if (dev->GetN(dev, blkno, 1, blk) != 0) + return -1; + + off = offset % BLKDEV_BLKSIZE; + len = _Min(BLKDEV_BLKSIZE - off, size); + Memcpy(data, &blk[off], len); + return len; +} + +static ssize_t _WritePartialBlock( + Blkdev* dev, + UINTN blkno, + ssize_t offset, + size_t size, + const void* data) +{ + UINT8 blk[BLKDEV_BLKSIZE]; + UINT32 off; /* offset into this block */ + UINT32 len; /* bytes to read from this block */ + + if (!size) + return 0; + + /* Fetch the block */ + if (dev->GetN(dev, blkno, 1, blk) != 0) + return -1; + + /* Replace the specified data in the block. */ + off = offset % BLKDEV_BLKSIZE; + len = _Min(BLKDEV_BLKSIZE - off, size); + Memcpy(&blk[off], data, len); + + /* Rewrite the block */ + if (dev->PutN(dev, blkno, 1, blk) != 0) + return -1; + + return len; +} + static ssize_t _Read( Blkdev* dev, size_t offset, @@ -147,40 +200,44 @@ static ssize_t _Read( size_t size) { UINT32 blkno; - UINT32 i; + UINT32 nblocks; UINT32 rem; UINT8* ptr; + ssize_t bytesRead; if (!dev || !data) return -1; blkno = offset / BLKDEV_BLKSIZE; + rem = size; + ptr = data; - for (i = blkno, rem = size, ptr = (UINT8*)data; rem; i++) + /* Handle the special case if offset is unaligned to the sector. */ + if (offset % BLKDEV_BLKSIZE != 0) { - UINT8 blk[BLKDEV_BLKSIZE]; - UINT32 off; /* offset into this block */ - UINT32 len; /* bytes to read from this block */ - - if (dev->Get(dev, i, blk) != 0) + bytesRead = _ReadPartialBlock(dev, blkno, offset, rem, ptr); + if (bytesRead < 0) return -1; - /* If first block */ - if (i == blkno) - off = offset % BLKDEV_BLKSIZE; - else - off = 0; - - len = BLKDEV_BLKSIZE - off; - - if (len > rem) - len = rem; - - Memcpy(ptr, &blk[off], len); - rem -= len; - ptr += len; + blkno++; + rem -= bytesRead; + ptr += bytesRead; } + /* Read the remaining full blocks. */ + nblocks = rem / BLKDEV_BLKSIZE; + if (dev->GetN(dev, blkno, nblocks, ptr) != 0) + return -1; + + blkno += nblocks; + rem -= nblocks * BLKDEV_BLKSIZE; + ptr += nblocks * BLKDEV_BLKSIZE; + + /* Read the last partial block if needed. */ + bytesRead = _ReadPartialBlock(dev, blkno, 0, rem, ptr); + if (bytesRead < 0) + return -1; + return size; } @@ -191,45 +248,44 @@ static ssize_t _Write( size_t size) { UINT32 blkno; - UINT32 i; + UINT32 nblocks; UINT32 rem; - UINT8* ptr; + const UINT8* ptr; + ssize_t bytesWritten; if (!dev || !data) return -1; blkno = offset / BLKDEV_BLKSIZE; + rem = size; + ptr = data; - for (i = blkno, rem = size, ptr = (UINT8*)data; rem; i++) + /* Handle the special case if offset is not aligned to sector. */ + if (offset % BLKDEV_BLKSIZE != 0) { - UINT8 blk[BLKDEV_BLKSIZE]; - UINT32 off; /* offset into this block */ - UINT32 len; /* bytes to write from this block */ - - /* Fetch the block */ - if (dev->Get(dev, i, blk) != 0) + bytesWritten = _WritePartialBlock(dev, blkno, offset, rem, ptr); + if (bytesWritten < 0) return -1; - /* If first block */ - if (i == blkno) - off = offset % BLKDEV_BLKSIZE; - else - off = 0; - - len = BLKDEV_BLKSIZE - off; - - if (len > rem) - len = rem; - - Memcpy(&blk[off], ptr, len); - rem -= len; - ptr += len; - - /* Rewrite the block */ - if (dev->Put(dev, i, blk) != 0) - return -1; + blkno++; + rem -= bytesWritten; + ptr += bytesWritten; } + /* Write the remaining blocks full blocks. */ + nblocks = rem / BLKDEV_BLKSIZE; + if (dev->PutN(dev, blkno, nblocks, ptr) != 0) + return -1; + + blkno += nblocks; + rem -= nblocks * BLKDEV_BLKSIZE; + ptr += nblocks * BLKDEV_BLKSIZE; + + /* Write the partial block if needed. */ + bytesWritten = _WritePartialBlock(dev, blkno, 0, rem, ptr); + if (bytesWritten < 0) + return -1; + return size; } @@ -3774,7 +3830,7 @@ EXT2Err EXT2Rm( /* Truncate the file first */ if (EXT2_IFERR(err = EXT2Trunc(ext2, path))) { - goto done; + GOTO(done); } /* Split the path */