mirror of
https://github.com/vgough/encfs.git
synced 2025-01-24 22:58:36 +01:00
Verify open/read/write/truncate returned values
This commit is contained in:
parent
b88da06a08
commit
13ae4de830
@ -195,7 +195,9 @@ int BlockFileIO::write(const IORequest &req) {
|
||||
if (req.offset > fileSize) {
|
||||
// extend file first to fill hole with 0's..
|
||||
const bool forceWrite = false;
|
||||
padFile(fileSize, req.offset, forceWrite);
|
||||
int res = padFile(fileSize, req.offset, forceWrite);
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
|
||||
// check against edge cases where we can just let the base class handle the
|
||||
@ -244,7 +246,10 @@ int BlockFileIO::write(const IORequest &req) {
|
||||
} else {
|
||||
// have to merge with existing block data..
|
||||
blockReq.dataLen = _blockSize;
|
||||
blockReq.dataLen = cacheReadOneBlock(blockReq);
|
||||
if ((blockReq.dataLen = cacheReadOneBlock(blockReq)) < 0) {
|
||||
res = blockReq.dataLen;
|
||||
break;
|
||||
}
|
||||
|
||||
// extend data if necessary..
|
||||
if (partialOffset + toCopy > blockReq.dataLen)
|
||||
@ -274,10 +279,11 @@ int BlockFileIO::write(const IORequest &req) {
|
||||
|
||||
int BlockFileIO::blockSize() const { return _blockSize; }
|
||||
|
||||
void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
|
||||
int BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
|
||||
off_t oldLastBlock = oldSize / _blockSize;
|
||||
off_t newLastBlock = newSize / _blockSize;
|
||||
int newBlockSize = newSize % _blockSize;
|
||||
int res = 0;
|
||||
|
||||
IORequest req;
|
||||
MemBlock mb;
|
||||
@ -296,9 +302,10 @@ void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
|
||||
|
||||
if (outSize) {
|
||||
memset(mb.data, 0, outSize);
|
||||
cacheReadOneBlock(req);
|
||||
req.dataLen = outSize;
|
||||
cacheWriteOneBlock(req);
|
||||
if ((res = cacheReadOneBlock(req)) >= 0) {
|
||||
req.dataLen = outSize;
|
||||
res = cacheWriteOneBlock(req);
|
||||
}
|
||||
}
|
||||
} else
|
||||
VLOG(1) << "optimization: not padding last block";
|
||||
@ -317,33 +324,36 @@ void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
|
||||
if (req.dataLen != 0) {
|
||||
VLOG(1) << "padding block " << oldLastBlock;
|
||||
memset(mb.data, 0, _blockSize);
|
||||
cacheReadOneBlock(req);
|
||||
req.dataLen = _blockSize; // expand to full block size
|
||||
cacheWriteOneBlock(req);
|
||||
if ((res = cacheReadOneBlock(req)) >= 0) {
|
||||
req.dataLen = _blockSize; // expand to full block size
|
||||
res = cacheWriteOneBlock(req);
|
||||
}
|
||||
++oldLastBlock;
|
||||
}
|
||||
|
||||
// 2, pad zero blocks unless holes are allowed
|
||||
if (!_allowHoles) {
|
||||
for (; oldLastBlock != newLastBlock; ++oldLastBlock) {
|
||||
for (; !res && (oldLastBlock != newLastBlock); ++oldLastBlock) {
|
||||
VLOG(1) << "padding block " << oldLastBlock;
|
||||
req.offset = oldLastBlock * _blockSize;
|
||||
req.dataLen = _blockSize;
|
||||
memset(mb.data, 0, req.dataLen);
|
||||
cacheWriteOneBlock(req);
|
||||
res = cacheWriteOneBlock(req);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. only necessary if write is forced and block is non 0 length
|
||||
if (forceWrite && newBlockSize) {
|
||||
if (!res && forceWrite && newBlockSize) {
|
||||
req.offset = newLastBlock * _blockSize;
|
||||
req.dataLen = newBlockSize;
|
||||
memset(mb.data, 0, req.dataLen);
|
||||
cacheWriteOneBlock(req);
|
||||
res = cacheWriteOneBlock(req);
|
||||
}
|
||||
}
|
||||
|
||||
if (mb.data) MemoryPool::release(mb);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int BlockFileIO::truncateBase(off_t size, FileIO *base) {
|
||||
@ -357,10 +367,11 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
|
||||
// states that it will pad with 0's.
|
||||
// do the truncate so that the underlying filesystem can allocate
|
||||
// the space, and then we'll fill it in padFile..
|
||||
if (base) base->truncate(size);
|
||||
if (base) res = base->truncate(size);
|
||||
|
||||
const bool forceWrite = true;
|
||||
padFile(oldSize, size, forceWrite);
|
||||
if (!res)
|
||||
res = padFile(oldSize, size, forceWrite);
|
||||
} else if (size == oldSize) {
|
||||
// the easiest case, but least likely....
|
||||
} else if (partialBlock) {
|
||||
@ -376,19 +387,17 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
|
||||
req.data = mb.data;
|
||||
|
||||
ssize_t rdSz = cacheReadOneBlock(req);
|
||||
if (rdSz < 0)
|
||||
res = rdSz;
|
||||
|
||||
// do the truncate
|
||||
if (base) res = base->truncate(size);
|
||||
else if (base)
|
||||
res = base->truncate(size);
|
||||
|
||||
// write back out partial block
|
||||
req.dataLen = partialBlock;
|
||||
int wrRes = cacheWriteOneBlock(req);
|
||||
|
||||
if ((rdSz < 0) || (wrRes)) {
|
||||
// rwarning - unlikely to ever occur..
|
||||
RLOG(WARNING) << "truncate failure: read " << rdSz
|
||||
<< " bytes, partial block of " << partialBlock;
|
||||
}
|
||||
if (!res)
|
||||
res = cacheWriteOneBlock(req);
|
||||
|
||||
MemoryPool::release(mb);
|
||||
} else {
|
||||
|
@ -49,7 +49,7 @@ class BlockFileIO : public FileIO {
|
||||
|
||||
protected:
|
||||
int truncateBase(off_t size, FileIO *base);
|
||||
void padFile(off_t oldSize, off_t newSize, bool forceWrite);
|
||||
int padFile(off_t oldSize, off_t newSize, bool forceWrite);
|
||||
|
||||
// same as read(), except that the request.offset field is guarenteed to be
|
||||
// block aligned, and the request size will not be larger then 1 block.
|
||||
|
@ -95,20 +95,20 @@ bool CipherFileIO::setIV(uint64_t iv) {
|
||||
} else if (haveHeader) {
|
||||
// we have an old IV, and now a new IV, so we need to update the fileIV
|
||||
// on disk.
|
||||
if (fileIV == 0) {
|
||||
// ensure the file is open for read/write..
|
||||
int newFlags = lastFlags | O_RDWR;
|
||||
int res = base->open(newFlags);
|
||||
if (res < 0) {
|
||||
if (res == -EISDIR) {
|
||||
// duh -- there are no file headers for directories!
|
||||
externalIV = iv;
|
||||
return base->setIV(iv);
|
||||
} else {
|
||||
VLOG(1) << "writeHeader failed to re-open for write";
|
||||
return false;
|
||||
}
|
||||
// ensure the file is open for read/write..
|
||||
int newFlags = lastFlags | O_RDWR;
|
||||
int res = base->open(newFlags);
|
||||
if (res < 0) {
|
||||
if (res == -EISDIR) {
|
||||
// duh -- there are no file headers for directories!
|
||||
externalIV = iv;
|
||||
return base->setIV(iv);
|
||||
} else {
|
||||
VLOG(1) << "setIV failed to re-open for write";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (fileIV == 0) {
|
||||
if (initHeader() < 0)
|
||||
return false;
|
||||
}
|
||||
@ -184,7 +184,9 @@ int CipherFileIO::initHeader() {
|
||||
req.offset = 0;
|
||||
req.data = buf;
|
||||
req.dataLen = 8;
|
||||
base->read(req);
|
||||
ssize_t readSize = base->read(req);
|
||||
if(readSize < 0)
|
||||
return readSize;
|
||||
|
||||
if(!cipher->streamDecode(buf, sizeof(buf), externalIV, key))
|
||||
return -EBADMSG;
|
||||
@ -219,7 +221,9 @@ int CipherFileIO::initHeader() {
|
||||
req.data = buf;
|
||||
req.dataLen = 8;
|
||||
|
||||
base->write(req);
|
||||
int res = base->write(req);
|
||||
if (res)
|
||||
return res;
|
||||
} else {
|
||||
VLOG(1) << "base not writable, IV not written..";
|
||||
}
|
||||
@ -229,15 +233,6 @@ int CipherFileIO::initHeader() {
|
||||
}
|
||||
|
||||
bool CipherFileIO::writeHeader() {
|
||||
if (!base->isWritable()) {
|
||||
// open for write..
|
||||
int newFlags = lastFlags | O_RDWR;
|
||||
if (base->open(newFlags) < 0) {
|
||||
VLOG(1) << "writeHeader failed to re-open for write";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileIV == 0) {
|
||||
RLOG(ERROR) << "Internal error: fileIV == 0 in writeHeader!!!";
|
||||
}
|
||||
@ -257,7 +252,8 @@ bool CipherFileIO::writeHeader() {
|
||||
req.data = buf;
|
||||
req.dataLen = 8;
|
||||
|
||||
base->write(req);
|
||||
if (base->write(req))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -351,7 +347,7 @@ ssize_t CipherFileIO::readOneBlock(const IORequest &req) const {
|
||||
<< readSize;
|
||||
readSize = -EBADMSG;
|
||||
}
|
||||
} else {
|
||||
} else if (readSize == 0) {
|
||||
VLOG(1) << "readSize zero for offset " << req.offset;
|
||||
}
|
||||
|
||||
@ -450,8 +446,11 @@ int CipherFileIO::truncate(off_t size) {
|
||||
if (!base->isWritable()) {
|
||||
// open for write..
|
||||
int newFlags = lastFlags | O_RDWR;
|
||||
if (base->open(newFlags) < 0)
|
||||
VLOG(1) << "writeHeader failed to re-open for write";
|
||||
int res = base->open(newFlags);
|
||||
if (res < 0) {
|
||||
VLOG(1) << "truncate failed to re-open for write";
|
||||
return res;
|
||||
}
|
||||
}
|
||||
int res = initHeader();
|
||||
if (res < 0)
|
||||
@ -462,7 +461,7 @@ int CipherFileIO::truncate(off_t size) {
|
||||
// the wrong size..
|
||||
res = BlockFileIO::truncateBase(size, 0);
|
||||
|
||||
if (res == 0) base->truncate(size + HEADER_SIZE);
|
||||
if (res == 0) res = base->truncate(size + HEADER_SIZE);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ int MACFileIO::truncate(off_t size) {
|
||||
|
||||
int res = BlockFileIO::truncateBase(size, 0);
|
||||
|
||||
if (res == 0) base->truncate(locWithHeader(size, bs, headerSize));
|
||||
if (res == 0) res = base->truncate(locWithHeader(size, bs, headerSize));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user