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