From 5b81eca96f1463bc1719f0a77b9c3606282f836a Mon Sep 17 00:00:00 2001 From: GillesDuvert Date: Wed, 16 Aug 2023 00:33:48 +0200 Subject: [PATCH] permits to read and write save/restore files of size > 2 GB (64 bit pointers). Probably NOT working on big-endian cpus. Untested on 32 bit architecture. --- src/saverestore.cpp | 102 ++++++++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 42 deletions(-) diff --git a/src/saverestore.cpp b/src/saverestore.cpp index 9e3f68c31..978228f5b 100644 --- a/src/saverestore.cpp +++ b/src/saverestore.cpp @@ -102,7 +102,19 @@ enum { #define xdr_uint64_t xdr_u_int64_t #endif - //this is the routined used by IDL as per the documentation. +// relaces xdr_getpos and setpos by these local functions that return 32 or 64 bits addresses ( "long int") depending on architecture. +// Will permit to read and write files larger than 2^32 bytes (issue #1551) on 64 bits machines. Probably uncomplete support for 32 bit machines though. +long int xdr_get_gdl_pos(XDR *x){ + long int where=ftell(save_fid); +// std::cerr<<"getpos: "< (p)) && xdr_float(xdrs, reinterpret_cast (p) + 1)); @@ -136,7 +148,7 @@ enum { } } - inline uint32_t writeNewRecordHeader(XDR *xdrs, int code){ + inline uint64_t writeNewRecordHeader(XDR *xdrs, int code){ int32_t rectype=code; xdr_int32_t(xdrs, &rectype); //-16 uint32_t ptrs0=0; @@ -145,49 +157,55 @@ enum { xdr_uint32_t(xdrs, &ptrs1); //-8 int32_t UnknownLong=0; xdr_int32_t(xdrs, &UnknownLong); - return xdr_getpos(xdrs); //end of header + return xdr_get_gdl_pos(xdrs); //end of header } - inline uint32_t updateNewRecordHeader(XDR *xdrs, uint32_t cur) { - uint32_t next = xdr_getpos(xdrs); + inline uint64_t updateNewRecordHeader(XDR *xdrs, uint64_t cur) { + uint64_t next = xdr_get_gdl_pos(xdrs); + std::cerr<<"updateNewRecordHeader : was at "<(var), isObject); } - uint32_t writeNormalVariable(XDR *xdrs, std::string varName, BaseGDL* var, int varflags=0x0) { + uint64_t writeNormalVariable(XDR *xdrs, std::string varName, BaseGDL* var, int varflags=0x0) { bool isSysVar=false; bool readonly=false; if (varflags & 0x02) //defines a system variable. @@ -1292,7 +1310,7 @@ enum { readonly = true; } const char* varname=varName.c_str(); - uint32_t cur=writeNewRecordHeader(xdrs, isSysVar?SYSTEM_VARIABLE:VARIABLE); + uint64_t cur=writeNewRecordHeader(xdrs, isSysVar?SYSTEM_VARIABLE:VARIABLE); xdr_string(xdrs, (char**)&varname, 2048); if (var==NULL) return updateNewRecordHeader(xdrs, cur); //unexistent var if (DEBUG_SAVERESTORE) std::cerr<<"Writing normal Variable "<Interpreter()->CallStack(); int32_t curlevnum = callStack.size(); DSubUD* pro = static_cast (callStack[curlevnum - 1]->GetPro()); DCommon* c=pro->Common(commonname); int32_t ncommonvars = c->NVar(); - if (ncommonvars < 1) return xdr_getpos(xdrs); - uint32_t cur = writeNewRecordHeader(xdrs, COMMONBLOCK); //COMMON + if (ncommonvars < 1) return xdr_get_gdl_pos(xdrs); + uint64_t cur = writeNewRecordHeader(xdrs, COMMONBLOCK); //COMMON xdr_int32_t(xdrs, &ncommonvars); char* name = (char*)commonname.c_str(); u_int len=c->Name().size(); @@ -2022,7 +2040,7 @@ enum { } for (int i = 0; i < ncommonvars; ++i) lens[i] = c->VarName(i).size(); for (int i = 0; i < ncommonvars; ++i) xdr_string(xdrs, &varnames[i], lens[i]); - uint32_t next = updateNewRecordHeader(xdrs, cur); + uint64_t next = updateNewRecordHeader(xdrs, cur); if (DEBUG_SAVERESTORE) std::cerr<