VFiles for abstract file operations, used at first in patches
Jeffrey Pfau jeffrey@endrift.com
Wed, 16 Jul 2014 01:31:10 -0700
7 files changed,
136 insertions(+),
38 deletions(-)
M
src/gba/gba-thread.c
→
src/gba/gba-thread.c
@@ -7,6 +7,7 @@
#include "debugger/debugger.h" #include "util/patch.h" +#include "util/vfile.h" #include <signal.h>@@ -114,7 +115,7 @@ if (threadContext->biosFd >= 0) {
GBALoadBIOS(&gba, threadContext->biosFd); } - if (threadContext->patchFd >= 0 && loadPatch(threadContext->patchFd, &patch)) { + if (threadContext->patchFd >= 0 && loadPatch(VFileFromFD(threadContext->patchFd), &patch)) { GBAApplyPatch(&gba, &patch); } }
M
src/util/patch-ips.c
→
src/util/patch-ips.c
@@ -1,15 +1,16 @@
#include "util/patch-ips.h" #include "util/patch.h" +#include "util/vfile.h" static size_t _IPSOutputSize(struct Patch* patch, size_t inSize); static bool _IPSApplyPatch(struct Patch* patch, void* out, size_t outSize); bool loadPatchIPS(struct Patch* patch) { - lseek(patch->patchfd, 0, SEEK_SET); + patch->vf->seek(patch->vf, 0, SEEK_SET); char buffer[5]; - if (read(patch->patchfd, buffer, 5) != 5) { + if (patch->vf->read(patch->vf, buffer, 5) != 5) { return false; }@@ -17,8 +18,8 @@ if (memcmp(buffer, "PATCH", 5) != 0) {
return false; } - lseek(patch->patchfd, -3, SEEK_END); - if (read(patch->patchfd, buffer, 3) != 3) { + patch->vf->seek(patch->vf, -3, SEEK_END); + if (patch->vf->read(patch->vf, buffer, 3) != 3) { return false; }@@ -37,7 +38,7 @@ return inSize;
} bool _IPSApplyPatch(struct Patch* patch, void* out, size_t outSize) { - if (lseek(patch->patchfd, 5, SEEK_SET) != 5) { + if (patch->vf->seek(patch->vf, 5, SEEK_SET) != 5) { return false; } uint8_t* buf = out;@@ -46,7 +47,7 @@ while (true) {
uint32_t offset = 0; uint16_t size = 0; - if (read(patch->patchfd, &offset, 3) != 3) { + if (patch->vf->read(patch->vf, &offset, 3) != 3) { return false; }@@ -55,17 +56,17 @@ return true;
} offset = (offset >> 16) | (offset & 0xFF00) | ((offset << 16) & 0xFF0000); - if (read(patch->patchfd, &size, 2) != 2) { + if (patch->vf->read(patch->vf, &size, 2) != 2) { return false; } if (!size) { // RLE chunk - if (read(patch->patchfd, &size, 2) != 2) { + if (patch->vf->read(patch->vf, &size, 2) != 2) { return false; } size = (size >> 8) | (size << 8); uint8_t byte; - if (read(patch->patchfd, &byte, 1) != 1) { + if (patch->vf->read(patch->vf, &byte, 1) != 1) { return false; } if (offset + size > outSize) {@@ -77,7 +78,7 @@ size = (size >> 8) | (size << 8);
if (offset + size > outSize) { return false; } - if (read(patch->patchfd, &buf[offset], size) != size) { + if (patch->vf->read(patch->vf, &buf[offset], size) != size) { return false; } }
M
src/util/patch-ups.c
→
src/util/patch-ups.c
@@ -2,6 +2,7 @@ #include "util/patch-ips.h"
#include "util/crc32.h" #include "util/patch.h" +#include "util/vfile.h" enum { IN_CHECKSUM = -12,@@ -13,13 +14,13 @@ };
static size_t _UPSOutputSize(struct Patch* patch, size_t inSize); static bool _UPSApplyPatch(struct Patch* patch, void* out, size_t outSize); -static size_t _UPSDecodeLength(int fd); +static size_t _UPSDecodeLength(struct VFile* vf); bool loadPatchUPS(struct Patch* patch) { - lseek(patch->patchfd, 0, SEEK_SET); + patch->vf->seek(patch->vf, 0, SEEK_SET); char buffer[BUFFER_SIZE]; - if (read(patch->patchfd, buffer, 4) != 4) { + if (patch->vf->read(patch->vf, buffer, 4) != 4) { return false; }@@ -27,24 +28,24 @@ if (memcmp(buffer, "UPS1", 4) != 0) {
return false; } - size_t filesize = lseek(patch->patchfd, 0, SEEK_END); + size_t filesize = patch->vf->seek(patch->vf, 0, SEEK_END); uint32_t goodCrc32; - lseek(patch->patchfd, PATCH_CHECKSUM, SEEK_END); - if (read(patch->patchfd, &goodCrc32, 4) != 4) { + patch->vf->seek(patch->vf, PATCH_CHECKSUM, SEEK_END); + if (patch->vf->read(patch->vf, &goodCrc32, 4) != 4) { return false; } size_t blocksize; size_t alreadyRead = 0; - lseek(patch->patchfd, 0, SEEK_SET); + patch->vf->seek(patch->vf, 0, SEEK_SET); uint32_t crc = 0; while (alreadyRead < filesize + PATCH_CHECKSUM) { size_t toRead = sizeof(buffer); if (toRead + alreadyRead > filesize + PATCH_CHECKSUM) { toRead = filesize + PATCH_CHECKSUM - alreadyRead; } - blocksize = read(patch->patchfd, buffer, toRead); + blocksize = patch->vf->read(patch->vf, buffer, toRead); alreadyRead += blocksize; crc = updateCrc32(crc, buffer, blocksize); if (blocksize < toRead) {@@ -63,20 +64,20 @@ }
size_t _UPSOutputSize(struct Patch* patch, size_t inSize) { UNUSED(inSize); - lseek(patch->patchfd, 4, SEEK_SET); - if (_UPSDecodeLength(patch->patchfd) != inSize) { + patch->vf->seek(patch->vf, 4, SEEK_SET); + if (_UPSDecodeLength(patch->vf) != inSize) { return 0; } - return _UPSDecodeLength(patch->patchfd); + return _UPSDecodeLength(patch->vf); } bool _UPSApplyPatch(struct Patch* patch, void* out, size_t outSize) { // TODO: Input checksum - size_t filesize = lseek(patch->patchfd, 0, SEEK_END); - lseek(patch->patchfd, 4, SEEK_SET); - _UPSDecodeLength(patch->patchfd); // Discard input size - if (_UPSDecodeLength(patch->patchfd) != outSize) { + size_t filesize = patch->vf->seek(patch->vf, 0, SEEK_END); + patch->vf->seek(patch->vf, 4, SEEK_SET); + _UPSDecodeLength(patch->vf); // Discard input size + if (_UPSDecodeLength(patch->vf) != outSize) { return false; }@@ -84,11 +85,11 @@ size_t offset = 0;
size_t alreadyRead = 0; uint8_t* buf = out; while (alreadyRead < filesize + IN_CHECKSUM) { - offset += _UPSDecodeLength(patch->patchfd); + offset += _UPSDecodeLength(patch->vf); uint8_t byte; while (true) { - if (read(patch->patchfd, &byte, 1) != 1) { + if (patch->vf->read(patch->vf, &byte, 1) != 1) { return false; } buf[offset] ^= byte;@@ -97,28 +98,28 @@ if (!byte) {
break; } } - alreadyRead = lseek(patch->patchfd, 0, SEEK_CUR); + alreadyRead = patch->vf->seek(patch->vf, 0, SEEK_CUR); } uint32_t goodCrc32; - lseek(patch->patchfd, OUT_CHECKSUM, SEEK_END); - if (read(patch->patchfd, &goodCrc32, 4) != 4) { + patch->vf->seek(patch->vf, OUT_CHECKSUM, SEEK_END); + if (patch->vf->read(patch->vf, &goodCrc32, 4) != 4) { return false; } - lseek(patch->patchfd, 0, SEEK_SET); + patch->vf->seek(patch->vf, 0, SEEK_SET); if (crc32(out, outSize) != goodCrc32) { return false; } return true; } -size_t _UPSDecodeLength(int fd) { +size_t _UPSDecodeLength(struct VFile* vf) { size_t shift = 1; size_t value = 0; uint8_t byte; while (true) { - if (read(fd, &byte, 1) != 1) { + if (vf->read(vf, &byte, 1) != 1) { break; } value += (byte & 0x7f) * shift;
M
src/util/patch.c
→
src/util/patch.c
@@ -3,8 +3,8 @@
#include "util/patch-ips.h" #include "util/patch-ups.h" -bool loadPatch(int patchfd, struct Patch* patch) { - patch->patchfd = patchfd; +bool loadPatch(struct VFile* vf, struct Patch* patch) { + patch->vf = vf; if (loadPatchIPS(patch)) { return true;
M
src/util/patch.h
→
src/util/patch.h
@@ -3,13 +3,15 @@ #define PATCH_H
#include "common.h" +struct VFile; + struct Patch { - int patchfd; + struct VFile* vf; size_t (*outputSize)(struct Patch* patch, size_t inSize); bool (*applyPatch)(struct Patch* patch, void* out, size_t outSize); }; -bool loadPatch(int patchfd, struct Patch* patch); +bool loadPatch(struct VFile* vf, struct Patch* patch); #endif
A
src/util/vfile.c
@@ -0,0 +1,76 @@
+#include "util/vfile.h" + +#include <fcntl.h> + +struct VFileFD { + struct VFile d; + int fd; +}; + +static bool _vfdClose(struct VFile* vf); +static size_t _vfdSeek(struct VFile* vf, off_t offset, int whence); +static size_t _vfdRead(struct VFile* vf, void* buffer, size_t size); +static size_t _vfdReadline(struct VFile* vf, char* buffer, size_t size); +static size_t _vfdWrite(struct VFile* vf, void* buffer, size_t size); + +struct VFile* VFileOpen(const char* path, int flags) { + int fd = open(path, flags); + return VFileFromFD(fd); +} + +struct VFile* VFileFromFD(int fd) { + if (fd < 0) { + return 0; + } + + struct VFileFD* vfd = malloc(sizeof(struct VFileFD)); + if (!vfd) { + return 0; + } + + vfd->fd = fd; + vfd->d.close = _vfdClose; + vfd->d.seek = _vfdSeek; + vfd->d.read = _vfdRead; + vfd->d.readline = _vfdReadline; + vfd->d.write = _vfdWrite; + + return &vfd->d; +} + +bool _vfdClose(struct VFile* vf) { + struct VFileFD* vfd = (struct VFileFD*) vf; + if (close(vfd->fd) < 0) { + return false; + } + free(vfd); + return true; +} + +size_t _vfdSeek(struct VFile* vf, off_t offset, int whence) { + struct VFileFD* vfd = (struct VFileFD*) vf; + return lseek(vfd->fd, offset, whence); +} + +size_t _vfdRead(struct VFile* vf, void* buffer, size_t size) { + struct VFileFD* vfd = (struct VFileFD*) vf; + return read(vfd->fd, buffer, size); +} + +size_t _vfdReadline(struct VFile* vf, char* buffer, size_t size) { + struct VFileFD* vfd = (struct VFileFD*) vf; + size_t bytesRead = 0; + while (bytesRead < size - 1) { + size_t newRead = read(vfd->fd, &buffer[bytesRead], 1); + bytesRead += newRead; + if (!newRead || buffer[bytesRead] == '\n') { + break; + } + } + return buffer[bytesRead] = '\0'; +} + +size_t _vfdWrite(struct VFile* vf, void* buffer, size_t size) { + struct VFileFD* vfd = (struct VFileFD*) vf; + return write(vfd->fd, buffer, size); +}
A
src/util/vfile.h
@@ -0,0 +1,17 @@
+#ifndef VFILE_H +#define VFILE_H + +#include "common.h" + +struct VFile { + bool (*close)(struct VFile* vf); + size_t (*seek)(struct VFile* vf, off_t offset, int whence); + size_t (*read)(struct VFile* vf, void* buffer, size_t size); + size_t (*readline)(struct VFile* vf, char* buffer, size_t size); + size_t (*write)(struct VFile* vf, void* buffer, size_t size); +}; + +struct VFile* VFileOpen(const char* path, int flags); +struct VFile* VFileFromFD(int fd); + +#endif