host.c raw

   1  #include <stdlib.h>
   2  #include <string.h>
   3  #include <stdint.h>
   4  #include <unistd.h>
   5  #include <sys/wait.h>
   6  #include <sys/syscall.h>
   7  #include <fcntl.h>
   8  
   9  int32_t mxc_writefile(const char* path, int32_t pathLen, const char* data, int32_t dataLen, uint32_t mode) {
  10      char pbuf[4096];
  11      if (pathLen > 4095) pathLen = 4095;
  12      memcpy(pbuf, path, pathLen);
  13      pbuf[pathLen] = 0;
  14      int fd = syscall(SYS_openat, -100, pbuf, O_WRONLY|O_CREAT|O_TRUNC, mode);
  15      if (fd < 0) return -1;
  16      int32_t written = 0;
  17      while (written < dataLen) {
  18          long n = syscall(SYS_write, fd, data + written, dataLen - written);
  19          if (n <= 0) break;
  20          written += (int32_t)n;
  21      }
  22      syscall(SYS_close, fd);
  23      return written;
  24  }
  25  
  26  int32_t mxc_mkdir(const char* path, int32_t pathLen, uint32_t mode) {
  27      char pbuf[4096];
  28      if (pathLen > 4095) return -1;
  29      int i;
  30      for (i = 1; i <= pathLen; i++) {
  31          if (i == pathLen || path[i] == '/') {
  32              memcpy(pbuf, path, i);
  33              pbuf[i] = 0;
  34              syscall(SYS_mkdirat, -100, pbuf, mode);
  35          }
  36      }
  37      return 0;
  38  }
  39  
  40  int32_t mxc_readfile(const char* path, int32_t pathLen, char* buf, int32_t bufCap) {
  41      char pbuf[4096];
  42      if (pathLen > 4095) pathLen = 4095;
  43      memcpy(pbuf, path, pathLen);
  44      pbuf[pathLen] = 0;
  45      int fd = syscall(SYS_openat, -100, pbuf, O_RDONLY, 0);
  46      if (fd < 0) return -1;
  47      int32_t total = 0;
  48      while (total < bufCap) {
  49          long n = syscall(SYS_read, fd, buf + total, bufCap - total);
  50          if (n <= 0) break;
  51          total += (int32_t)n;
  52      }
  53      syscall(SYS_close, fd);
  54      return total;
  55  }
  56  
  57  int32_t mxc_filesize(const char* path, int32_t pathLen) {
  58      char pbuf[4096];
  59      if (pathLen > 4095) pathLen = 4095;
  60      memcpy(pbuf, path, pathLen);
  61      pbuf[pathLen] = 0;
  62      int fd = syscall(SYS_openat, -100, pbuf, O_RDONLY, 0);
  63      if (fd < 0) return -1;
  64      long size = syscall(SYS_lseek, fd, 0, 2); /* SEEK_END=2 */
  65      syscall(SYS_close, fd);
  66      return (int32_t)size;
  67  }
  68  
  69  int32_t mxc_run(const char** argv, int32_t argc) {
  70      int pid = fork();
  71      if (pid < 0) return -1;
  72      if (pid == 0) {
  73          char* args[64];
  74          int i;
  75          for (i = 0; i < argc && i < 63; i++) args[i] = (char*)argv[i];
  76          args[i] = NULL;
  77          execvp(args[0], args);
  78          _exit(127);
  79      }
  80      int status;
  81      waitpid(pid, &status, 0);
  82      if (WIFEXITED(status)) return WEXITSTATUS(status);
  83      return -1;
  84  }
  85  
  86  struct linux_dirent64 {
  87      uint64_t d_ino;
  88      int64_t  d_off;
  89      uint16_t d_reclen;
  90      uint8_t  d_type;
  91      char     d_name[];
  92  };
  93  
  94  int32_t mxc_listdir(const char* dir, int32_t dirLen, char* buf, int32_t bufCap) {
  95      char dbuf[4096];
  96      if (dirLen > 4095) dirLen = 4095;
  97      memcpy(dbuf, dir, dirLen);
  98      dbuf[dirLen] = 0;
  99      int fd = syscall(SYS_openat, -100, dbuf, 0x10000, 0); /* AT_FDCWD=-100, O_RDONLY|O_DIRECTORY */
 100      if (fd < 0) return 0;
 101      int32_t pos = 0;
 102      char dbytes[4096];
 103      for (;;) {
 104          long nread = syscall(SYS_getdents64, fd, dbytes, sizeof(dbytes));
 105          if (nread <= 0) break;
 106          long offset = 0;
 107          while (offset < nread) {
 108              struct linux_dirent64* ent = (struct linux_dirent64*)(dbytes + offset);
 109              char* name = ent->d_name;
 110              if (!(name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))) {
 111                  int32_t nlen = (int32_t)strlen(name);
 112                  if (pos + nlen + 1 <= bufCap) {
 113                      memcpy(buf + pos, name, nlen);
 114                      pos += nlen;
 115                      buf[pos] = 0;
 116                      pos++;
 117                  }
 118              }
 119              offset += ent->d_reclen;
 120          }
 121      }
 122      syscall(SYS_close, fd);
 123      return pos;
 124  }
 125  
 126  int32_t mxc_getenv(const char* name, int32_t nameLen, char* buf, int32_t bufCap) {
 127      char nbuf[256];
 128      if (nameLen > 255) nameLen = 255;
 129      memcpy(nbuf, name, nameLen);
 130      nbuf[nameLen] = 0;
 131      const char* val = getenv(nbuf);
 132      if (!val) return 0;
 133      int32_t vlen = (int32_t)strlen(val);
 134      if (vlen > bufCap) vlen = bufCap;
 135      memcpy(buf, val, vlen);
 136      return vlen;
 137  }
 138