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