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