diff --git a/meshcore/agentcore.c b/meshcore/agentcore.c index 7ed381a..f4ea110 100644 --- a/meshcore/agentcore.c +++ b/meshcore/agentcore.c @@ -2470,6 +2470,59 @@ void MeshServer_SendAgentInfo(MeshAgentHostContainer* agent, ILibWebClient_State if (agent->serverAuthState == 3) { MeshServer_ServerAuthenticated(WebStateObject, agent); } } +void MeshServer_selfupdate_continue(MeshAgentHostContainer *agent) +{ + +#ifdef WIN32 + agent->performSelfUpdate = 1; +#else + // Set performSelfUpdate to the startupType, on Linux is this important: 1 = systemd, 2 = upstart, 3 = sysv-init + int len = ILibSimpleDataStore_Get(agent->masterDb, "StartupType", ILibScratchPad, sizeof(ILibScratchPad)); + if (len > 0) { agent->performSelfUpdate = atoi(ILibScratchPad); } + if (agent->performSelfUpdate == 0) { agent->performSelfUpdate = 999; } // Never allow this value to be zero. +#endif + + if (duk_peval_string_noresult(agent->meshCoreCtx, "require('service-manager').manager.getService('meshagentDiagnostic').start();") == 0) + { + if (agent->logUpdate != 0) + { + ILIBLOGMESSSAGE("SelfUpdate -> Starting Secondary Agent, to assist with self update"); + } + } + else + { + if (agent->logUpdate != 0) + { + ILIBLOGMESSSAGE("SelfUpdate -> Secondary Agent unavailable to assist with self update"); + } + } + + // Everything looks good, lets perform the update + if (agent->logUpdate != 0) + { + char tmp[255]; + sprintf_s(tmp, sizeof(tmp), "SelfUpdate -> Stopping Chain (%d)", agent->performSelfUpdate); + ILIBLOGMESSSAGE(tmp); + } + ILibStopChain(agent->chain); +} +duk_ret_t MeshServer_selfupdate_unzip_complete(duk_context *ctx) +{ + duk_eval_string(ctx, "require('MeshAgent')"); // [MeshAgent] + MeshAgentHostContainer *agent = (MeshAgentHostContainer*)Duktape_GetPointerProperty(ctx, -1, MESH_AGENT_PTR); + if (agent->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Updated successfully unzipped..."); } + MeshServer_selfupdate_continue(agent); + return(0); +} +duk_ret_t MeshServer_selfupdate_unzip_error(duk_context *ctx) +{ + duk_eval_string(ctx, "require('MeshAgent')"); // [MeshAgent] + MeshAgentHostContainer *agent = (MeshAgentHostContainer*)Duktape_GetPointerProperty(ctx, -1, MESH_AGENT_PTR); + duk_push_sprintf(ctx, "SelfUpdate -> FAILED to unzip update: %s", (char*)duk_safe_to_string(ctx, 0)); + if (agent->logUpdate != 0) { ILIBLOGMESSSAGE(duk_safe_to_string(ctx, -1)); } + return(0); +} + // Process MeshCentral server commands. void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAgentHostContainer *agent, char *cmd, int cmdLen) { @@ -2915,54 +2968,64 @@ void MeshServer_ProcessCommand(ILibWebClient_StateObject WebStateObject, MeshAge if ((GenerateSHA384FileHash(updateFilePath, updateFileHash) == 0) && (memcmp(updateFileHash, cm->coreModuleHash, sizeof(cm->coreModuleHash)) == 0)) { //printf("UPDATE: End OK\r\n"); + int updateTop = duk_get_top(agent->meshCoreCtx); if (agent->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Download Complete... Hash verified"); } if (agent->fakeUpdate != 0) { int fsz; char *fsc; - fsz = ILibReadFileFromDiskEx(&fsc, agent->exePath); + sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s.zip", agent->exePath); + fsz = ILibReadFileFromDiskEx(&fsc, ILibScratchPad); + if (fsz == 0) + { + fsz = ILibReadFileFromDiskEx(&fsc, agent->exePath); + if (agent->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Overriding update with same version..."); } + } + else + { + if (agent->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Overriding update with provided zip..."); } + } ILibWriteStringToDiskEx(updateFilePath, fsc, fsz); - if (agent->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Overriding update with same version..."); } } if (agent->fakeUpdate != 0 || agent->forceUpdate != 0) { ILibSimpleDataStore_Put(agent->masterDb, "disableUpdate", "1"); if (agent->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Disabling future updates..."); } } -#ifdef WIN32 - agent->performSelfUpdate = 1; -#else - // Set performSelfUpdate to the startupType, on Linux is this important: 1 = systemd, 2 = upstart, 3 = sysv-init - int len = ILibSimpleDataStore_Get(agent->masterDb, "StartupType", ILibScratchPad, sizeof(ILibScratchPad)); - if (len > 0) { agent->performSelfUpdate = atoi(ILibScratchPad); } - if (agent->performSelfUpdate == 0) { agent->performSelfUpdate = 999; } // Never allow this value to be zero. -#endif - if (duk_peval_string_noresult(agent->meshCoreCtx, "require('service-manager').manager.getService('meshagentDiagnostic').start();") == 0) + duk_eval_string(agent->meshCoreCtx, "require('zip-reader')"); // [reader] + duk_prepare_method_call(agent->meshCoreCtx, -1, "isZip"); // [reader][isZip][this] + duk_push_string(agent->meshCoreCtx, updateFilePath); // [reader][isZip][this][path] + duk_pcall_method(agent->meshCoreCtx, 1); // [reader][boolean] + if (duk_to_boolean(agent->meshCoreCtx, -1)) { - if (agent->logUpdate != 0) + // Update File is zipped + if (agent->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Unzipping update..."); } + duk_eval_string(agent->meshCoreCtx, "require('update-helper')"); // [helper] + duk_prepare_method_call(agent->meshCoreCtx, -1, "start"); // [helper][start][this] + duk_push_string(agent->meshCoreCtx, updateFilePath); // [helper][start][this][path] + if (duk_pcall_method(agent->meshCoreCtx, 1) == 0) // [helper][promise] { - ILIBLOGMESSSAGE("SelfUpdate -> Starting Secondary Agent, to assist with self update"); + duk_prepare_method_call(agent->meshCoreCtx, -1, "then"); // [helper][promise][then][this] + duk_push_c_function(agent->meshCoreCtx, MeshServer_selfupdate_unzip_complete, DUK_VARARGS);//..][res] + duk_push_c_function(agent->meshCoreCtx, MeshServer_selfupdate_unzip_error, DUK_VARARGS);//[this][res][rej] + duk_pcall_method(agent->meshCoreCtx, 2); } - } - else - { - if (agent->logUpdate != 0) + else { - ILIBLOGMESSSAGE("SelfUpdate -> Secondary Agent unavailable to assist with self update"); + if (agent->logUpdate != 0) + { + sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "SelfUpdate -> Error Unzipping: %s", duk_safe_to_string(agent->meshCoreCtx, -1)); + ILIBLOGMESSSAGE(ILibScratchPad); + } } + duk_set_top(agent->meshCoreCtx, updateTop); // ... + break; // Break out here, and continue when finished unzipping (or in the case of error, abort) } - - - // Everything looks good, lets perform the update - if (agent->logUpdate != 0) - { - char tmp[255]; - sprintf_s(tmp, sizeof(tmp), "SelfUpdate -> Stopping Chain (%d)", agent->performSelfUpdate); - ILIBLOGMESSSAGE(tmp); - } - ILibStopChain(agent->chain); - } else + duk_set_top(agent->meshCoreCtx, updateTop); // ... + MeshServer_selfupdate_continue(agent); + } + else { // Hash check failed, delete the file and do nothing. On next server reconnect, we will try again. if (agent->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Download Complete... Hash FAILED, aborting update..."); } diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c index 17de517..bb055c0 100644 --- a/microscript/ILibDuktape_Polyfills.c +++ b/microscript/ILibDuktape_Polyfills.c @@ -2291,11 +2291,13 @@ void ILibDuktape_Polyfills_JS_Init(duk_context *ctx) duk_peval_string_noresult(ctx, "addCompressedModule('identifiers', Buffer.from('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', 'base64'));"); // zip-reader, refer to modules/zip-reader.js - duk_peval_string_noresult(ctx, "addCompressedModule('zip-reader', Buffer.from('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', 'base64'));"); + duk_peval_string_noresult(ctx, "addCompressedModule('zip-reader', Buffer.from('eJzVG/1T20b2d2b4Hza5mVpujDE2oS0+2iMYrkwJZDC5TC9lMrK0wgJZ0kmrAs1wf/u9t7uSVquVZJLeD6XTGPbjvbfv+71db3+7uXEUxY+Jf7NkZDwaj8hpyGhAjqIkjhKb+VG4ubG5ceY7NEypS7LQpQlhS0oOY9uBDzkzIP+iSQqryXg4IhYueCmnXvanmxuPUUZW9iMJI0aylAIEPyWeH1BCHxwaM+KHxIlWceDboUPJvc+WHIuEMdzc+FVCiBbMhsU2LI/hL09dRmyG1BL4WTIW729v39/fD21O6TBKbrYDsS7dPjs9Oj6fH28BtbjjfRjQNCUJ/U/mJ3DMxSOxYyDGsRdAYmDfkygh9k1CYY5FSOx94jM/vBmQNPLYvZ3QzQ3XT1niLzJW4VNOGpxXXQCcskPy8nBOTucvyZvD+el8sLnx4fTq54v3V+TD4eXl4fnV6fGcXFySo4vz2enV6cU5/HVCDs9/Jb+cns8GhAKXAAt9iBOkHkj0kYPUBXbNKa2g9yJBThpTx/d8Bw4V3mT2DSU30e80CeEsJKbJyk9RiikQ525uBP7KZ1wJ0vqJAMm325sbv9sJOb44ml2SA7Izwv/Gr/emYlyMTiZ7kx/Gu9/LwbMTHNz7bjLe/e71eIrsx+E4iQA5hSkpBasnh3p9udPN4oA+qCuAn9Re9frDGZ/iwLwsdJBkAkJ37k6iAOh+Z7Ol5dKU9Tc3PgsF8T1iAQIHODeMA5sBg1bk4ID07v1wMu71xSq5GH9wO+DGj2EKbGZWbxsw30Z+aPV++41TieuexAcNUroODNwpgWzrMPDQLLoDblc3tdBNfiIIkuwTBVwJbWFzFgugw3Tpe8zKV90vwR4tORXQ8AZs8EeyU+cEB/LqgFjrE0JeaThzpEIU1otCpF4K/KAPYCrp/DF0LETW75eLFTrwp7pvdef6SblNwfFUMPZJURH6wBLbYefwacWabgxjGrpgFjkr4GijPvlM4mEaZYlDh04QpRS4ByOfwADxt4SyLAmnqvxCgA0cL8HFUVywnGu10Il4iCQLdQVuPYu1iGP611FrB/xJFNChH3rRjtU7FkIA3sCB4DTcTuUOljzWsBntWsNgM2dp0fppa8JTp0CKt1ZFa6Q8C9jiF1gpHA8XmwR4Q9mcD1oojRwILI0yFmdM9VpcVR1Yy+gHCCNU7sNzDEDBvMC+SYEV94seeaoBGob2Ck1YkXk5VzrRuDYXgSj4qXsDUhiAVWcRahCG5xxYflig2CEvDkhlLudm4og9SFyLtVbhIrt7R5dH5AglSjwb/I/bU/lfk4EiY66Niv2qsAt1UNgnTxH7MbUKruD8UyVq/OHHMXUvFrfUAZgY/0u/wFF8EnOnM+ByD1ZvAVhQxaG6sTdVN3Ao6HXxU85gPLbQ/G8fMJ3IEWk8E/tPZvnmj7cP10PPVZixAOx3VeUXJAxd6vkhfZdEENbZI2fPgPQw50pBAxQkoLn7dY0wSA/JBWkAMR+vp/UpXxuDI1o+P1zJhX51iYZAinsYZ+nSUnZ99K+FZmkYnkyaQiz4NLn+vioUVOaD8tSowBxDTQQ5UJUcXHmNIAo9U0EXnkBFoLgHIxrOQPCH5IDUMFVCJbFe4DqMRGyZRPfE6mFS7UWQoIHtlF5KkdhUHUMQCGGI+TYmjkgeD26Ngtcc9nkE9UGx94XJYrmDupcZm9UpdMymqaqEzjIL78BPBaAJ/fp6AwgDne/sNN2+WiaZiCscZh7NX8HQ4pGBLejU5z+KmsC/k3FOUz7etA+yGSFB1OKLXwzUt5ygQCx35+rALYIT0IRWoCbr4O7Ajz+c8VYbrpJSvhYFngVBy4an5qkyqfgCUqtE8M/nU9Ew3ExYt/xEujezmb2m9NY/iIHap0F9DPy/HahW9UxzWlOduljBT4/K0Xb4doX788UD0oEqHKwryejXcRnDv8rk1P9DD3MtFOnG3kwOL88KgSjaVZRqI/LNN1WJVdxHfWdei/WbfdnXakDhDZt0bw0YJZ9yLSF/Fb9EV1gMuYnth42BpoWIhmGDYmqJkSEkDxeZ59HkbeRiLrpjWKDqhinJE2tyxfJs4I5pRW5ajQtaBIPzIuaODDOxnWlFm1oLVIRVaxNUKrA89aHuVtFCEgXZjOZzkL1+Jh/enF7N98nWzusqTxW8/EgydcOPqTaF/mHuh3dqNlgMWjRJBiIRuYQh+JULab1UbGz1EA5PbgoQZWZDPh5fXorUB7Dg+DUk/gXqYUoDb/iJLz2jHtNVpnEh2Too0bVv4nmdJc40TLH7ao2U4/YNlWjDufFne5vMopCSD2XvlXtf3pXkfZZFEDl39Y2FEyrPoCW8LVh1rkNiObs4PyZ4AOyaXmErOwG1Seq1q0I5JM1vo4QSNK6WUADGY4yCBk9g9k4NJwAKCvTkKuLUd58VNOwSbIamyO8SgFAqjaUDrTxu4kW1DYLyk8LhRYnnYgtEaMx+joL/NSAi0O3riCHy7Y5+2CM/iY/6vClqV5heaO0anK+6gSZj5+rPPQ7Tl4CK2sHPvGdQcwva3Fd5h53c7pCm96chm4zPjq1RH1X/7ORSP6qm4v+kIU3sgLzLkjhKKTkJbNme06Du7AHUvVoGoYFT6kXylrJl5DYD+74L2AkkQufYBTuTCtEEadxJF+89dsOpk6SLSjpJrsMgziK+YHvrQAfKJbGz26/U5QbqFNtjkUw0kUarAXuzSXRt6GsFsR49aybbdn6w4bX9Um7pTQQK0zfvzf3Bn86NBnxgCD7aaSMAfvrI81LINl6RyahZLZsVzVR0NOEzua2aSzJtNXqmKITwLHPVhsBsaueqQZUonry0gTlURFPjTs4C2PZG8MIOgFgLhdRhtmd4JiIORf6hRCNFAh0gyNaPRRcL0lWkERu69bhWT6XXj1+Vc01GkO+UOlQjGAUtBjWRVcRbv56oNDwrnUjZHj8MAjXKlKP8ykHcpJjvAbpvkgxawXuUJWRguBNk8LfV28dbIexclrN4VSGROPeQ+sj7HzE5VYPvuqm+jj5ldsLSDz5b8quor0Bf/qG3u8vOOHY95SWEVZoQKNkAFtyKrq3IOFJuhOm0GLjlA7fTqozxOMppID8UZ1n7frB2YJU32QKfJIQ3mJYr47KlsEV2+lO91hFXPtLWNReiXGGqeLRVsszUS0x+JVJeGPCbiraLX1ZeqRbtDb7po3+t1WqK6ig3Rto9QZc1fSoNR7Ty03EleatPo5BWjZa1EtRW7pcbjwv5u+eHfrqkWtrOAfH7Z/4b/JIFLNWdlmha1+48y2Oba1sVpODyZ4JXEvtEoZ9faFeVtrqP0jurPyyuTKuXJJZprX7Z0wxvKMwOF6y3Hq9BXahhKiHOWbvgnh1eHcrrBCk4nZ9lzwyiAEqVtz47i1tlSx42ALVjM+ujc63j0GqSeiX4PATF1IC04lpTxpzHYJprZhEah49DF591OVmS0JCRvD9jUmj0ARoFRUpRnKlp4x8mg7byaWPMbQiucrM5xspJw0X7/zFo4Pm4ceaM4H9oCyTndDfMeVN3700u8NleFDOms5Ya2DDfXgebb1FNcIayP1duMOaVWF+SS97RwSyxonuIAZmJHupMOm5jeTeu5LB68knI1xTYdWhQZm5Nxmg3avFJ3KJZ01CBdkD94qq9GZbMtVuo6oL0Xj1hO6zxuAPWmZ0y8jZy8Ukkf+hIrvyVGSA/5c7o2QBnNmsD2EWh6FCc+DRwn9unMFQqXTVKVbX7WJKUDomC4cHfa78TgBFuSud2zlJvyKK5SDhrHZUvoBakoVE4BhLhf2/cHXBbVZS3Sef2Kg5yyscl6b0lfejV6H/qDhlGnyTrccXdyhhUWaq6SG3q616UNBPWdKfxbDFpha+x5DUQoLJQYQzPYitvd0Raa0yziwdUL2p5WK2eqLzOQ5j8IWkOwZiAiKdZhnus6sMvbUH5FrWCmP4O+Q4iP8Zfjlc+Y5ijAQ85EZXnS5hh/beaX+VZQvEs9an+uI2LK7bZsnzT9n/KQjjzH2MaYa2DCHl9KopNwytUXrQ3vgHmANpLQfGYkLsb9TmUqdQxPRDTe2Y0rD3YTJnNSmqGabWpJS423dquCGrUYtdA1zJwQcwGoQ8vPl3OLs7Pfl3nta1CIQKVZYiRls+kuI4BN+alMj2e0dRJ/JhFSW9QmKwgsDTTUeG7CkUFsI5bcUX497Oys9wkPqt9Svm0QYa08j1De4/JFPD7aOhHs0vUVqStaJTe4nOwBBzHcZLAsetvtVUi25K7PNBO69uo17oJ3KBhE+Qy7bvGpl3yEXDlZnV3b0B29/A5eBnAlXjbddlwBE4HE9IZ6KcDqvEoU+D9mhnVI6f88k9zZrLbdREDI2/90F9lq6+4ZYKRMtcwPRhtS5zfPyNxXoeS56Sp67Bn7QR6PFoDGveUz85+x18OuSMNXocD+NW0JAQVPWTye1RpM8TJOjKC5HotiJyvk86LSRip3EzYrBnabp2X67k4UD50cvrrBVPHp0z4yEF9umFX/iP6fPhvy/V59ZJnv0kfWyCo9WoLjN02GCKZNO8EPrfs9KCiVeKE8eZSPyt3dA3FYdv2xDFTCAI173rS9EOLVEWrS4sClQiAj3+84tci2DSmP5WgmVqYExq+EaFXN+LdV6QnB3zkWemBeEej9Vv8SuiS1wQHZDyaEp/8nVTShil59cpvzxssgURnXDX72CJ+v6/nFpDC8q86Pru4PMF0lMzxJgpDzfHRLO8voXvwlTdbHiTghIoWKBbjxidFGvStpp91NhMI+Okd+ZvwVII1XbHbCOY8Wy1AHYHupkwixW+98m/+un7qNCOs+1kjwquIAZKwG20zpp16qDSi4rfDJhRG0MKqx/qbik4szXxLl1EWuGSB33AuvF0jZhH56ghNzzi4iZber6mEbzhhpa5voIW/X1DRwG8mdqjfZMp/TPevFZ+TQ608aCi9kWmuxgNZLrV0mUbaOWX9tUVgCo9XIuyXJEBxkRea1SLcT//tx1oVjn6ps9wEXzfhX0HN61j+wrZf+bppdwnaSxaFOvIvoKU8Y9MfYahLyselOmz+AgVhI/8EJORjpYrsG1lfdlg8t1RXnvSU2A7ILr5pF4A/jq75JenD65EyuCMHd98og2M5OJoog5N8cLflW15JVn55UBVlwWwpzVXkZmC79CGOEn6H8lm+z0p4jOMy3hcfoLH/Az9eiek=', 'base64'));"); // zip-writer, refer to modules/zip-writer.js duk_peval_string_noresult(ctx, "addCompressedModule('zip-writer', Buffer.from('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', 'base64'));"); + // update-helper, refer to modules/update-helper.js + duk_peval_string_noresult(ctx, "addCompressedModule('update-helper', Buffer.from('eJytVd9v2zYQfheg/+GaF8mdK2d5jNEHL00xY4UzREmDdhgCWjrJzGSSI6m6XuD/fUdRtiX/QPcwvYgi77777rs7avQ2DG6kWmteLixcXV5dwlRYrOBGaiU1s1yKMAiDTzxDYTCHWuSowS4QJopl9GpPhvAZtSFruEouIXYGF+3RxWAcBmtZw5KtQUgLtUFC4AYKXiHg9wyVBS4gk0tVcSYyhBW3iyZKi5GEwZcWQc4tI2NG5oq+iq4ZMOvYAj0La9X1aLRarRLWME2kLkeVtzOjT9Ob21l6+47YOo9HUaExoPHvmmtKc74GpohMxuZEsWIrkBpYqZHOrHRkV5pbLsohGFnYFdMYBjk3VvN5bXs6balRvl0DUooJuJikME0v4JdJOk2HYfA0ffj17vEBnib395PZw/Q2hbt7uLmbfZg+TO9m9PURJrMv8Nt09mEISCpRFPyutGNPFLlTEHOSK0XshS+kp2MUZrzgGSUlypqVCKX8hlpQLqBQL7lxVTRELg+Dii+5bZrAHGdEQd6OnHjfmAalJbkivN9qGEftVuTKHwZFLTIHBMYybeNa5czi78wuBmHw6kvmcDRawhC42iLGO8eYkhySwcsAXpv+SZ5pp4loxruNl2bjZQwbF9fB8gLiNztW/3D1TiOjXKJBws1XrrpcHDRRaJDjwdita92EtvS18YCtActPJN2Dd4su+vi0f0Kiin2ez95jgRXVIyZAhfnAe7ZCbcVS/7dUW7l80MTNp0kqFCVN45v38PNgb9ah4h7VAMbRo6BuxMx1eCbpJhHWuGkhwGbao24k97SRskoS/+7hZr/EyuDZwFav+xsH555cjsZ2y1QYKk9GNbD4RIOMqaX1slMr+Ami51p4etGQZCwqVppriFbzqC/YAVv3ZMxmC4hx8ENqZ/M/EBZPnW27U/2Ajs8/cW1CIqjxyVPPhM794rSRFHHUcCVJ9t2267KDbPymC7sbqCPlWpcSbVuDbu/9cfnnIFFcYezjn2mQIx02rfAHkxUfj1GvfQ7q0++WWlRc/JWuRXZipE+7uD/UR8rjwOmwt/4r3EkGfbAzAjX92GvHo1TtmT7z2p7V3Rc2yqXYz/ZOfR92Lz92rtcmlG+H3a24v2rDYOP2lzKvK0zoSpHauvvr1f8+rv0LNmT4L6QVhQk=', 'base64'));"); #ifndef _NOHECI duk_peval_string_noresult(ctx, "addCompressedModule('heci', Buffer.from('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', 'base64'));"); diff --git a/microscript/ILibDuktape_fs.c b/microscript/ILibDuktape_fs.c index 9fa033d..2f5c252 100644 --- a/microscript/ILibDuktape_fs.c +++ b/microscript/ILibDuktape_fs.c @@ -407,21 +407,33 @@ duk_ret_t ILibDuktape_fs_openSync(duk_context *ctx) } duk_ret_t ILibDuktape_fs_readSync(duk_context *ctx) { + int narg = (int)duk_get_top(ctx); + if (narg > 3) + { + // Convert to Options Format + duk_push_this(ctx); // [fs] + duk_prepare_method_call(ctx, -1, "readSync"); // [fs][readSync][this] + duk_dup(ctx, 0); duk_dup(ctx, 1); // [fs][readSync][this][fd][buffer] + duk_push_object(ctx); // [fs][readSync][this][fd][buffer][options] + duk_dup(ctx, 2); duk_put_prop_string(ctx, -2, "offset"); + duk_dup(ctx, 3); duk_put_prop_string(ctx, -2, "length"); + duk_dup(ctx, 4); duk_put_prop_string(ctx, -2, "position"); + duk_call_method(ctx, 3); + return(1); + } + duk_size_t bufferSize; char *buffer = Duktape_GetBuffer(ctx, 1, &bufferSize); - int offset = duk_require_int(ctx, 2); - int length = duk_require_int(ctx, 3); + int offset = Duktape_GetIntPropertyValue(ctx, 2, "offset", 0); + int length = Duktape_GetIntPropertyValue(ctx, 2, "length", (int)bufferSize); + int position = Duktape_GetIntPropertyValue(ctx, 2, "position", -1); int bytesRead; FILE *f = ILibDuktape_fs_getFilePtr(ctx, duk_require_int(ctx, 0)); if (length > (int)bufferSize) { return(ILibDuktape_Error(ctx, "fs.readSync(): Buffer of size: %llu bytes, but attempting to read %d bytes", (uint64_t)bufferSize, length)); } - if (f != NULL) { - if (duk_is_number(ctx, 4)) - { - fseek(f, duk_require_int(ctx, 4), SEEK_SET); - } + if (position >= 0) { fseek(f, position, SEEK_SET); } bytesRead = (int)fread(buffer + offset, 1, length, f); duk_push_int(ctx, bytesRead); return 1; @@ -2319,7 +2331,7 @@ void ILibDuktape_fs_PUSH(duk_context *ctx, void *chain) ILibDuktape_CreateInstanceMethod(ctx, "closeSync", ILibDuktape_fs_closeSync, 1); ILibDuktape_CreateInstanceMethod(ctx, "openSync", ILibDuktape_fs_openSync, DUK_VARARGS); - ILibDuktape_CreateInstanceMethod(ctx, "readSync", ILibDuktape_fs_readSync, 5); + ILibDuktape_CreateInstanceMethod(ctx, "readSync", ILibDuktape_fs_readSync, DUK_VARARGS); ILibDuktape_CreateInstanceMethod(ctx, "writeSync", ILibDuktape_fs_writeSync, DUK_VARARGS); ILibDuktape_CreateInstanceMethod(ctx, "read", ILibDuktape_fs_read, DUK_VARARGS); ILibDuktape_CreateInstanceMethod(ctx, "write", ILibDuktape_fs_write, DUK_VARARGS); diff --git a/modules/zip-reader.js b/modules/zip-reader.js index 8eec086..4dc7a93 100644 --- a/modules/zip-reader.js +++ b/modules/zip-reader.js @@ -438,4 +438,19 @@ function read(path) return(ret); } -module.exports = { read: read }; \ No newline at end of file +function isZip(path) +{ + if (require('fs').statSync(path).size < 30) { return (false); } + var fd = require('fs').openSync(path, 'rb'); + var jsFile = Buffer.alloc(4); + var bytesRead = require('fs').readSync(fd, jsFile, { position: 0 }); + require('fs').closeSync(fd); + + if (bytesRead == 4 && jsFile[0] == 0x50 && jsFile[1] == 0x4B && jsFile[2] == 0x03 && jsFile[3] == 0x04) + { + return (true); + } + return (false); +} + +module.exports = { read: read, isZip: isZip }; \ No newline at end of file