diff --git a/xsnap/sources/xsnap-worker.c b/xsnap/sources/xsnap-worker.c index 8d9e63d..cb9616e 100644 --- a/xsnap/sources/xsnap-worker.c +++ b/xsnap/sources/xsnap-worker.c @@ -93,6 +93,11 @@ xsCallback gxSnapshotCallbacks[mxSnapshotCallbackCount] = { // fx_clearTimer, }; +typedef struct { + FILE *file; + int size; +} SnapshotStream; + static int fxSnapshotRead(void* stream, void* address, size_t size) { return (fread(address, size, 1, stream) == 1) ? 0 : errno; @@ -100,7 +105,10 @@ static int fxSnapshotRead(void* stream, void* address, size_t size) static int fxSnapshotWrite(void* stream, void* address, size_t size) { - return (fwrite(address, size, 1, stream) == 1) ? 0 : errno; + SnapshotStream* snapshotStream = stream; + size_t written = fwrite(address, size, 1, snapshotStream->file); + snapshotStream->size += size * written; + return (written == 1) ? 0 : errno; } #if mxInstrument @@ -331,7 +339,18 @@ int main(int argc, char* argv[]) } xsInitializeSharedCluster(); if (argr) { - snapshot.stream = fopen(argv[argr], "rb"); + char *path = argv[argr]; + if (path[0] == '@') { + int fd = atoi(path + 1); + int tmpfd = dup(fd); + if (tmpfd < 0) { + snapshot.stream = NULL; + } else { + snapshot.stream = fdopen(tmpfd, "rb"); + } + } else { + snapshot.stream = fopen(path, "rb"); + } if (snapshot.stream) { machine = xsReadSnapshot(&snapshot, "xsnap", NULL); fclose(snapshot.stream); @@ -528,10 +547,24 @@ int main(int argc, char* argv[]) fxTestRecord(mxTestRecordParam, nsbuf + 1, nslen - 1); #endif path = nsbuf + 1; - snapshot.stream = fopen(path, "wb"); - if (snapshot.stream) { + SnapshotStream stream; + if (path[0] == '@') { + int fd = atoi(path + 1); + int tmpfd = dup(fd); + if (tmpfd < 0) { + stream.file = NULL; + } else { + stream.file = fdopen(tmpfd, "ab"); + } + } else { + stream.file = fopen(path, "wb"); + } + stream.size = 0; + if (stream.file) { + snapshot.stream = &stream; fxWriteSnapshot(machine, &snapshot); - fclose(snapshot.stream); + snapshot.stream = NULL; + fclose(stream.file); } else snapshot.error = errno; @@ -541,7 +574,10 @@ int main(int argc, char* argv[]) c_exit(E_IO_ERROR); } if (snapshot.error == 0) { - int writeError = fxWriteOkay(toParent, meterIndex, machine, "", 0); + // Allows us to format up to 999,999,999,999 bytes (1TiB - 1) + char fsize[13]; + int fsizeLength = snprintf(fsize, sizeof(fsize), "%d", stream.size); + int writeError = fxWriteOkay(toParent, meterIndex, machine, fsize, fsizeLength); if (writeError != 0) { fprintf(stderr, "%s\n", fxWriteNetStringError(writeError)); c_exit(E_IO_ERROR); @@ -810,7 +846,7 @@ static int fxWriteOkay(FILE* outStream, xsUnsignedValue meterIndex, xsMachine *t char numeral64[] = "12345678901234567890"; // big enough for 64bit numeral char prefix[8 + sizeof fmt + 8 * sizeof numeral64 + sizeof timestampBuffer]; // Prepend the meter usage to the reply. - snprintf(prefix, sizeof(prefix) - 1, fmt, + snprintf(prefix, sizeof(prefix), fmt, fxGetCurrentHeapCount(the), meterIndex, the->allocatedSpace, tsbuf); return fxWriteNetString(outStream, prefix, buf, length);