LCOV - code coverage report
Current view: top level - core/wasm/exports - SPWasm-filesystem.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 57 205 27.8 %
Date: 2024-05-12 00:16:13 Functions: 9 29 31.0 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
       3             : 
       4             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  of this software and associated documentation files (the "Software"), to deal
       6             :  in the Software without restriction, including without limitation the rights
       7             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  copies of the Software, and to permit persons to whom the Software is
       9             :  furnished to do so, subject to the following conditions:
      10             : 
      11             :  The above copyright notice and this permission notice shall be included in
      12             :  all copies or substantial portions of the Software.
      13             : 
      14             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  THE SOFTWARE.
      21             :  **/
      22             : 
      23             : #include "SPWasm.h"
      24             : #include "SPFilesystem.h"
      25             : 
      26             : namespace stappler::wasm {
      27             : 
      28           0 : static uint32_t StapplerFilesystemExists(wasm_exec_env_t exec_env, char *ptr, uint32_t size) {
      29           0 :         return filesystem::exists(StringView(ptr, size)) ? 1 : 0;
      30             : }
      31             : 
      32             : struct StatResult {
      33             :         uint64_t success;
      34             :         uint64_t size;
      35             :         uint64_t atime;
      36             :         uint64_t ctime;
      37             :         uint64_t mtime;
      38             :         uint64_t isDir;
      39             : };
      40             : 
      41         150 : static void StapplerFilesystemStat(wasm_exec_env_t exec_env, char *ptr, uint32_t size, StatResult *res) {
      42         150 :         filesystem::Stat stat;
      43         150 :         if (filesystem::stat(StringView(ptr, size), stat)) {
      44         150 :                 res->success = false;
      45         150 :                 res->size = stat.size;
      46         150 :                 res->atime = stat.atime.toMicros();
      47         150 :                 res->ctime = stat.ctime.toMicros();
      48         150 :                 res->mtime = stat.mtime.toMicros();
      49         150 :                 res->isDir = stat.isDir;
      50             :         } else {
      51           0 :                 res->success = false;
      52             :         }
      53         150 : }
      54             : 
      55           0 : static void StapplerFilesystemWritablePath(wasm_exec_env_t exec_env, char *ptr, uint32_t size, bool rel, bool readOnly, ListOutput *target) {
      56           0 :         auto env = ExecEnv::get(exec_env);
      57             : 
      58           0 :         String result;
      59           0 :         if (readOnly) {
      60           0 :                 result = filesystem::writablePathReadOnly<Interface>(StringView(ptr, size), rel);
      61             :         } else {
      62           0 :                 result = filesystem::writablePath<Interface>(StringView(ptr, size), rel);
      63             :         }
      64             : 
      65           0 :         char *outStringBuffer = nullptr;
      66           0 :         auto outOffset = env->allocate(result.size() * sizeof(char), &outStringBuffer);
      67             : 
      68           0 :         memcpy(outStringBuffer, result.data(), result.size() * sizeof(char));
      69             : 
      70           0 :         target->ptr = outOffset;
      71           0 :         target->len = result.size();
      72           0 : }
      73             : 
      74           0 : static void StapplerFilesystemDocumentsPath(wasm_exec_env_t exec_env, char *ptr, uint32_t size, bool rel, bool readOnly, ListOutput *target) {
      75           0 :         auto env = ExecEnv::get(exec_env);
      76             : 
      77           0 :         String result;
      78           0 :         if (readOnly) {
      79           0 :                 result = filesystem::documentsPathReadOnly<Interface>(StringView(ptr, size), rel);
      80             :         } else {
      81           0 :                 result = filesystem::documentsPath<Interface>(StringView(ptr, size), rel);
      82             :         }
      83             : 
      84           0 :         char *outStringBuffer = nullptr;
      85           0 :         auto outOffset = env->allocate(result.size() * sizeof(char), &outStringBuffer);
      86             : 
      87           0 :         memcpy(outStringBuffer, result.data(), result.size() * sizeof(char));
      88             : 
      89           0 :         target->ptr = outOffset;
      90           0 :         target->len = result.size();
      91           0 : }
      92             : 
      93           0 : static void StapplerFilesystemCachesPath(wasm_exec_env_t exec_env, char *ptr, uint32_t size, bool rel, bool readOnly, ListOutput *target) {
      94           0 :         auto env = ExecEnv::get(exec_env);
      95             : 
      96           0 :         String result;
      97           0 :         if (readOnly) {
      98           0 :                 result = filesystem::cachesPathReadOnly<Interface>(StringView(ptr, size), rel);
      99             :         } else {
     100           0 :                 result = filesystem::cachesPath<Interface>(StringView(ptr, size), rel);
     101             :         }
     102             : 
     103           0 :         char *outStringBuffer = nullptr;
     104           0 :         auto outOffset = env->allocate(result.size() * sizeof(char), &outStringBuffer);
     105             : 
     106           0 :         memcpy(outStringBuffer, result.data(), result.size() * sizeof(char));
     107             : 
     108           0 :         target->ptr = outOffset;
     109           0 :         target->len = result.size();
     110           0 : }
     111             : 
     112          50 : static void StapplerFilesystemCurrentDir(wasm_exec_env_t exec_env, char *ptr, uint32_t size, bool rel, ListOutput *target) {
     113          50 :         auto env = ExecEnv::get(exec_env);
     114             : 
     115          50 :         String result = filesystem::currentDir<Interface>(StringView(ptr, size), rel);
     116             : 
     117          50 :         char *outStringBuffer = nullptr;
     118          50 :         auto outOffset = env->allocate(result.size() * sizeof(char), &outStringBuffer);
     119             : 
     120          50 :         memcpy(outStringBuffer, result.data(), result.size() * sizeof(char));
     121             : 
     122          50 :         target->ptr = outOffset;
     123          50 :         target->len = result.size();
     124          50 : }
     125             : 
     126          25 : static void StapplerFilesystemFtw(wasm_exec_env_t exec_env, char *ptr, uint32_t size, uint32_t fn, uint32_t arg, int32_t depth, bool dirFirst) {
     127          25 :         auto env = ExecEnv::get(exec_env);
     128          25 :         char *buf = nullptr;
     129             : 
     130          25 :         auto bufOffset = env->allocate(PATH_MAX, &buf);
     131             : 
     132             :         uint32_t args[4];
     133          25 :         args[0] = arg;
     134          25 :         args[1] = bufOffset;
     135             : 
     136          25 :         filesystem::ftw(StringView(ptr, size), [&] (StringView path, bool isFile) {
     137         375 :                 buf = env->appToNative<char>(bufOffset);
     138         375 :                 memcpy(buf, path.data(), path.size());
     139             : 
     140         375 :                 args[2] = uint32_t(path.size());
     141         375 :                 args[3] = uint32_t(isFile);
     142             : 
     143         375 :                 wasm_runtime_call_indirect(exec_env, fn, 4, args);
     144         375 :         }, depth, dirFirst);
     145             : 
     146          25 :         env->free(bufOffset);
     147          25 : }
     148             : 
     149           0 : static uint32_t StapplerFilesystemFtwB(wasm_exec_env_t exec_env, char *ptr, uint32_t size, uint32_t fn, uint32_t arg, int32_t depth, bool dirFirst) {
     150           0 :         auto env = ExecEnv::get(exec_env);
     151           0 :         char *buf = nullptr;
     152             : 
     153           0 :         auto bufOffset = env->allocate(PATH_MAX, &buf);
     154             : 
     155             :         uint32_t args[4];
     156             : 
     157           0 :         auto ret = filesystem::ftw_b(StringView(ptr, size), [&] (StringView path, bool isFile) {
     158           0 :                 buf = env->appToNative<char>(bufOffset);
     159           0 :                 memcpy(buf, path.data(), path.size());
     160             : 
     161           0 :                 args[0] = arg;
     162           0 :                 args[1] = bufOffset;
     163           0 :                 args[2] = uint32_t(path.size());
     164           0 :                 args[3] = uint32_t(isFile);
     165             : 
     166           0 :                 if (wasm_runtime_call_indirect(exec_env, fn, 4, args)) {
     167           0 :                         return bool(args[0]);
     168             :                 }
     169           0 :                 return false;
     170             :         }, depth, dirFirst);
     171             : 
     172           0 :         env->free(bufOffset);
     173           0 :         return ret;
     174             : }
     175             : 
     176          25 : static uint32_t StapplerFilesystemOpen(wasm_exec_env_t exec_env, char *ptr, uint32_t size) {
     177          25 :         auto f = filesystem::openForReading(StringView(ptr, size));
     178          25 :         if (f) {
     179          25 :                 auto env = ExecEnv::get(exec_env);
     180          25 :                 auto mod = env->getInstance();
     181          25 :                 auto obj = new filesystem::File(move(f));
     182             : 
     183          50 :                 return mod->addHandle(obj, [obj] {
     184          25 :                         delete obj;
     185          25 :                 });
     186             :         }
     187           0 :         return ModuleInstance::InvalidHandle;
     188          25 : }
     189             : 
     190           0 : static uint32_t StapplerFilesystemOpenTmp(wasm_exec_env_t exec_env, char *ptr, uint32_t size, bool delOnClose) {
     191           0 :         auto f = filesystem::File::open_tmp(StringView(ptr, size), delOnClose);
     192           0 :         if (f) {
     193           0 :                 auto env = ExecEnv::get(exec_env);
     194           0 :                 auto mod = env->getInstance();
     195           0 :                 auto obj = new filesystem::File(move(f));
     196             : 
     197           0 :                 return mod->addHandle(obj, [obj] {
     198           0 :                         delete obj;
     199           0 :                 });
     200             :         }
     201           0 :         return ModuleInstance::InvalidHandle;
     202           0 : }
     203             : 
     204          25 : static void StapplerFilesystemFileDrop(wasm_exec_env_t exec_env, uint32_t handle) {
     205          25 :         auto mod = ExecEnv::get(exec_env)->getInstance();
     206          25 :         auto file = mod->getObject<filesystem::File>(handle);
     207          25 :         if (!file) {
     208           0 :                 log::error("wasm::Runtime", "[resource-drop]file: invalid handle");
     209           0 :                 return;
     210             :         }
     211             : 
     212          25 :         mod->removeHandle(handle);
     213             : }
     214             : 
     215          25 : static uint32_t StapplerFilesystemFileRead(wasm_exec_env_t exec_env, uint32_t handle, uint8_t *buf, uint32_t bufSize) {
     216          25 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     217          25 :         if (!file) {
     218           0 :                 log::error("wasm::Runtime", "[method]file.read: invalid handle");
     219           0 :                 return 0;
     220             :         }
     221             : 
     222          25 :         return file->read(buf, bufSize);
     223             : }
     224             : 
     225           0 : static uint64_t StapplerFilesystemFileSeek(wasm_exec_env_t exec_env, uint32_t handle, int64_t offset, io::Seek pos) {
     226           0 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     227           0 :         if (!file) {
     228           0 :                 log::error("wasm::Runtime", "[method]file.seek: invalid handle");
     229           0 :                 return 0;
     230             :         }
     231             : 
     232           0 :         return file->seek(offset, pos);
     233             : }
     234             : 
     235           0 : static uint64_t StapplerFilesystemFileTell(wasm_exec_env_t exec_env, uint32_t handle) {
     236           0 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     237           0 :         if (!file) {
     238           0 :                 log::error("wasm::Runtime", "[method]file.tell: invalid handle");
     239           0 :                 return 0;
     240             :         }
     241             : 
     242           0 :         return file->tell();
     243             : }
     244             : 
     245          25 : static uint64_t StapplerFilesystemFileSize(wasm_exec_env_t exec_env, uint32_t handle) {
     246          25 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     247          25 :         if (!file) {
     248           0 :                 log::error("wasm::Runtime", "[method]file.size: invalid handle");
     249           0 :                 return 0;
     250             :         }
     251             : 
     252          25 :         return file->size();
     253             : }
     254             : 
     255           0 : static int32_t StapplerFilesystemFileXsgetc(wasm_exec_env_t exec_env, uint32_t handle) {
     256           0 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     257           0 :         if (!file) {
     258           0 :                 log::error("wasm::Runtime", "[method]file.xsgetc: invalid handle");
     259           0 :                 return 0;
     260             :         }
     261             : 
     262           0 :         return file->xsgetc();
     263             : }
     264             : 
     265           0 : static int32_t StapplerFilesystemFileXsputc(wasm_exec_env_t exec_env, uint32_t handle, int32_t c) {
     266           0 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     267           0 :         if (!file) {
     268           0 :                 log::error("wasm::Runtime", "[method]file.xsputc: invalid handle");
     269           0 :                 return 0;
     270             :         }
     271             : 
     272           0 :         return file->xsputc(c);
     273             : }
     274             : 
     275           0 : static uint32_t StapplerFilesystemFileXsputn(wasm_exec_env_t exec_env, uint32_t handle, uint8_t *buf, uint32_t bufSize) {
     276           0 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     277           0 :         if (!file) {
     278           0 :                 log::error("wasm::Runtime", "[method]file.xsputn: invalid handle");
     279           0 :                 return 0;
     280             :         }
     281             : 
     282           0 :         return file->xsputn((const char *)buf, bufSize);
     283             : }
     284             : 
     285           0 : static uint32_t StapplerFilesystemFileXsgetn(wasm_exec_env_t exec_env, uint32_t handle, uint8_t *buf, uint32_t bufSize) {
     286           0 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     287           0 :         if (!file) {
     288           0 :                 log::error("wasm::Runtime", "[method]file.xsgetn: invalid handle");
     289           0 :                 return 0;
     290             :         }
     291             : 
     292           0 :         return file->xsgetn((char *)buf, bufSize);
     293             : }
     294             : 
     295           0 : static uint32_t StapplerFilesystemFileIsOpen(wasm_exec_env_t exec_env, uint32_t handle) {
     296           0 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     297           0 :         if (!file) {
     298           0 :                 log::error("wasm::Runtime", "[method]file.is-open: invalid handle");
     299           0 :                 return 0;
     300             :         }
     301             : 
     302           0 :         return file->is_open();
     303             : }
     304             : 
     305           0 : static uint32_t StapplerFilesystemFileEof(wasm_exec_env_t exec_env, uint32_t handle) {
     306           0 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     307           0 :         if (!file) {
     308           0 :                 log::error("wasm::Runtime", "[method]file.eof: invalid handle");
     309           0 :                 return 0;
     310             :         }
     311             : 
     312           0 :         return file->eof();
     313             : }
     314             : 
     315           0 : static void StapplerFilesystemFileClose(wasm_exec_env_t exec_env, uint32_t handle) {
     316           0 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     317           0 :         if (!file) {
     318           0 :                 log::error("wasm::Runtime", "[method]file.close: invalid handle");
     319           0 :                 return;
     320             :         }
     321             : 
     322           0 :         file->close();
     323             : }
     324             : 
     325           0 : static void StapplerFilesystemFileCloseRemove(wasm_exec_env_t exec_env, uint32_t handle) {
     326           0 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     327           0 :         if (!file) {
     328           0 :                 log::error("wasm::Runtime", "[method]file.close-remove: invalid handle");
     329           0 :                 return;
     330             :         }
     331             : 
     332           0 :         file->close_remove();
     333             : }
     334             : 
     335           0 : static void StapplerFilesystemFileCloseRename(wasm_exec_env_t exec_env, uint32_t handle, char *name, uint32_t len) {
     336           0 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     337           0 :         if (!file) {
     338           0 :                 log::error("wasm::Runtime", "[method]file.close-rename: invalid handle");
     339           0 :                 return;
     340             :         }
     341             : 
     342           0 :         file->close_rename(StringView(name, len));
     343             : }
     344             : 
     345           0 : static uint32_t StapplerFilesystemFileGetTmpPath(wasm_exec_env_t exec_env, uint32_t handle, char *buf, uint32_t len) {
     346           0 :         auto file = ExecEnv::get(exec_env)->getInstance()->getObject<filesystem::File>(handle);
     347           0 :         if (!file) {
     348           0 :                 log::error("wasm::Runtime", "[method]file.get-tmp-path: invalid handle");
     349           0 :                 return 0;
     350             :         }
     351             : 
     352           0 :         auto path = file->path();
     353           0 :         len = max(len, uint32_t(strlen(path)));
     354           0 :         memcpy(buf, path, len);
     355           0 :         return len;
     356             : }
     357             : 
     358             : static NativeSymbol stapper_filesystem_symbols[] = {
     359             :         NativeSymbol{"exists", (void *)&StapplerFilesystemExists, "(*~)i", NULL},
     360             :         NativeSymbol{"stat", (void *)&StapplerFilesystemStat, "(*~*)", NULL},
     361             :         NativeSymbol{"get-writable-path", (void *)&StapplerFilesystemWritablePath, "(*~ii*)", NULL},
     362             :         NativeSymbol{"get-documents-path", (void *)&StapplerFilesystemDocumentsPath, "(*~ii*)", NULL},
     363             :         NativeSymbol{"get-caches-path", (void *)&StapplerFilesystemCachesPath, "(*~ii*)", NULL},
     364             :         NativeSymbol{"get-current-work-dir", (void *)&StapplerFilesystemCurrentDir, "(*~i*)", NULL},
     365             :         NativeSymbol{"ftw", (void *)&StapplerFilesystemFtw, "(*~iiii)", NULL},
     366             :         NativeSymbol{"ftw-b", (void *)&StapplerFilesystemFtwB, "(*~iiii)i", NULL},
     367             :         NativeSymbol{"open", (void *)&StapplerFilesystemOpen, "(*~)i", NULL},
     368             :         NativeSymbol{"open-tmp", (void *)&StapplerFilesystemOpenTmp, "(*~i)i", NULL},
     369             : 
     370             :         NativeSymbol{"[method]file.read", (void *)&StapplerFilesystemFileRead, "(i*~)i", NULL},
     371             :         NativeSymbol{"[method]file.seek", (void *)&StapplerFilesystemFileSeek, "(iIi)I", NULL},
     372             :         NativeSymbol{"[method]file.tell", (void *)&StapplerFilesystemFileTell, "(i)I", NULL},
     373             :         NativeSymbol{"[method]file.size", (void *)&StapplerFilesystemFileSize, "(i)I", NULL},
     374             :         NativeSymbol{"[method]file.xsgetc", (void *)&StapplerFilesystemFileXsgetc, "(i)i", NULL},
     375             :         NativeSymbol{"[method]file.xsputc", (void *)&StapplerFilesystemFileXsputc, "(ii)i", NULL},
     376             :         NativeSymbol{"[method]file.xsputn", (void *)&StapplerFilesystemFileXsputn, "(i*~)i", NULL},
     377             :         NativeSymbol{"[method]file.xsgetn", (void *)&StapplerFilesystemFileXsgetn, "(i*~)i", NULL},
     378             :         NativeSymbol{"[method]file.is-open", (void *)&StapplerFilesystemFileIsOpen, "(i)i", NULL},
     379             :         NativeSymbol{"[method]file.eof", (void *)&StapplerFilesystemFileEof, "(i)i", NULL},
     380             :         NativeSymbol{"[method]file.close", (void *)&StapplerFilesystemFileClose, "(i)", NULL},
     381             :         NativeSymbol{"[method]file.close-remove", (void *)&StapplerFilesystemFileCloseRemove, "(i)", NULL},
     382             :         NativeSymbol{"[method]file.close-rename", (void *)&StapplerFilesystemFileCloseRename, "(i*~)", NULL},
     383             :         NativeSymbol{"[method]file.get-tmp-path", (void *)&StapplerFilesystemFileGetTmpPath, "(i*~)i", NULL},
     384             : 
     385             :         NativeSymbol{"[resource-drop]file", (void *)&StapplerFilesystemFileDrop, "(i)", NULL},
     386             : 
     387             : };
     388             : 
     389             : static NativeModule s_filesystemModule("stappler:wasm/filesystem", stapper_filesystem_symbols, sizeof(stapper_filesystem_symbols) / sizeof(NativeSymbol));
     390             : 
     391             : }

Generated by: LCOV version 1.14