summaryrefslogtreecommitdiff
path: root/tools/common.c
diff options
context:
space:
mode:
authorVladimir Azarov <avm@intermediate-node.net>2024-11-05 20:24:40 +0100
committerVladimir Azarov <avm@intermediate-node.net>2024-11-05 21:49:55 +0100
commitf777f6a9450d2bd5fc7ec531e6fb69f79942499a (patch)
treedc33cd941f49708274a74548862ba7b133013c55 /tools/common.c
parent3972268b97b789a8212ea9bc7d1b9ce9905a68d8 (diff)
Musl make
Diffstat (limited to 'tools/common.c')
-rw-r--r--tools/common.c313
1 files changed, 253 insertions, 60 deletions
diff --git a/tools/common.c b/tools/common.c
index 00f7d3c..8156bec 100644
--- a/tools/common.c
+++ b/tools/common.c
@@ -50,6 +50,16 @@ int open(char *fname, int flags, int mode)
flags|o_largefile, mode));
}
+int chdir(char *path)
+{
+ return sysret(__syscall1(__NR_chdir, (long)path));
+}
+
+int getdents64(int fd, char *buf, int size)
+{
+ return sysret(__syscall3(__NR_getdents64, fd, (long)buf, size));
+}
+
int stat(char *fname, struct stat *st)
{
return sysret(__syscall2(__NR_stat, (long)fname, (long)st));
@@ -60,6 +70,21 @@ int fstat(int fd, struct stat *st)
return sysret(__syscall2(__NR_fstat, (long)fd, (long)st));
}
+int access(char *path, int mode)
+{
+ return sysret(__syscall2(__NR_access, (long)path, mode));
+}
+
+int dup2(int oldfd, int newfd)
+{
+ return sysret(__syscall2(__NR_dup2, oldfd, newfd));
+}
+
+int pipe(int *fds)
+{
+ return sysret(__syscall1(__NR_pipe, (long)fds));
+}
+
int close(int fd)
{
return sysret(__syscall1(__NR_close, fd));
@@ -69,7 +94,7 @@ void *mmap(char *addr, unsigned long length, int prot, int flags, int fd,
unsigned long offset)
{
return (void*)sysret(__syscall6(__NR_mmap, (long)addr, length,
- prot, flags, fd, offset));
+ prot, flags, fd, offset));
}
int munmap(char *addr, int length)
@@ -79,11 +104,72 @@ int munmap(char *addr, int length)
#define MREMAP_MAYMOVE 1
-int mremap(void *old_addr, unsigned long old_size, unsigned long new_size,
+void *mremap(void *old_addr, unsigned long old_size, unsigned long new_size,
int flags, void *new_addr)
{
- return sysret(__syscall5(__NR_mremap, (long)old_addr, old_size,
- new_size, flags, (long)new_addr));
+ return (void *)sysret(__syscall5(__NR_mremap, (long)old_addr,
+ old_size, new_size, flags, (long)new_addr));
+}
+
+int fork()
+{
+ return sysret(__syscall0(__NR_fork));
+}
+
+int wait4(int pid, int *wstatus, int options, void *rusage)
+{
+ return sysret(__syscall6(__NR_wait4, pid, (long)wstatus, options,
+ (long)rusage, 0, 0));
+}
+
+int execve(char *path, char **argv, char **envp)
+{
+ return sysret(__syscall3(__NR_execve, (long)path, (long)argv,
+ (long)envp));
+}
+
+int getrusage(int who, struct rusage *rusage)
+{
+ return sysret(__syscall2(__NR_getrusage, who, (long)rusage));
+}
+
+enum {
+ dirbuf_size = 16 * 1024
+};
+
+int opendir(struct dir *dir, char *path)
+{
+ dir->fd = open(path, O_RDONLY|O_DIRECTORY, 0);
+ if (dir->fd == -1)
+ return 0;
+
+ dir->buf = malloc(dirbuf_size);
+ dir->cur = dir->buf;
+ dir->end = dir->cur;
+ dir->path = path;
+ return 1;
+}
+
+void closedir(struct dir *dir)
+{
+ close(dir->fd);
+}
+
+struct dirent *readdir(struct dir *dir)
+{
+ struct dirent *tmp;
+ if (dir->cur == dir->end) {
+ int r = getdents64(dir->fd, dir->buf, dirbuf_size);
+ if (r == -1)
+ syscall_error(dir->path);
+ if (r == 0)
+ return NULL;
+ dir->cur = dir->buf;
+ dir->end = dir->buf + r;
+ }
+ tmp = (struct dirent *)dir->cur;
+ dir->cur += tmp->dsize;
+ return tmp;
}
int strzlen(char *s)
@@ -94,6 +180,14 @@ int strzlen(char *s)
return s - sc;
}
+struct str *debug2str(char *s)
+{
+ static struct str str;
+ str.start = s;
+ str.end = str.start + strzlen(s);
+ return &str;
+}
+
int strzeq(char *s1, char *s2)
{
for (; *s1 && *s1 == *s2; ++s1, ++s2)
@@ -104,15 +198,32 @@ int strzeq(char *s1, char *s2)
int streq(struct str *s1, struct str *s2)
{
int i;
+ char * restrict tmp1, * restrict tmp2;
if (s1->end - s1->start != s2->end - s2->start)
return 0;
+
+ tmp1 = s1->start;
+ tmp2 = s2->start;
for (i = 0; s1->start + i < s1->end; ++i) {
- if (s1->start[i] != s2->start[i])
+ if (tmp1[i] != tmp2[i])
return 0;
}
return 1;
}
+int strge(struct str *s1, struct str *s2)
+{
+ char *tmp1 =s1->start, *tmp2 = s2->start;
+ for (;; ++tmp1, ++tmp2) {
+ if (tmp1 == s1->end)
+ return tmp2 == s2->end;
+ if (tmp2 == s2->end)
+ return 1;
+ if (*tmp1 != *tmp2)
+ return *tmp1 > *tmp2;
+ }
+}
+
void memmove(char *dest, char *src, int len)
{
int i;
@@ -125,11 +236,11 @@ void memmove(char *dest, char *src, int len)
}
}
-void memcpy(void *dest, void *src, int len)
+void memcpy(void * restrict dest, void * restrict src, int len)
{
- int i;
char *d = dest;
char *s = src;
+ int i;
for (i = 0; i < len; ++i)
d[i] = s[i];
}
@@ -141,6 +252,18 @@ void memset(void *dest, char c, int len)
*tmp = c;
}
+int memeq(void *m1, void *m2, int len)
+{
+ char *s1 = m1;
+ char *s2 = m2;
+ int i;
+ for (i = 0; i < len; ++i) {
+ if (s1[i] != s2[i])
+ return 0;
+ }
+ return 1;
+}
+
#define E(e, s) [e] = s,
char *estrings[256] = {
@@ -156,12 +279,6 @@ void perror(char *s)
eprintf("%s: %s\n", s, estrings[idx]);
}
-void syscall_error(char *fname)
-{
- perror(fname);
- hexit(1);
-}
-
enum {
buflen = 32 * 1024
};
@@ -175,9 +292,12 @@ struct iobuf {
struct iobuf stdout = { 1 };
struct iobuf stderr = { 2 };
-static void flush(struct iobuf *buf)
+void flush(struct iobuf *buf)
{
- int ret = write(buf->fd, buf->buf, buf->len);
+ int ret;
+ if (buf->len == 0)
+ return;
+ ret = write(buf->fd, buf->buf, buf->len);
if (ret != buf->len) {
write(2, _S("some stdout/stderr error\n"));
exit(3);
@@ -185,6 +305,12 @@ static void flush(struct iobuf *buf)
buf->len = 0;
}
+void syscall_error(char *fname)
+{
+ perror(fname);
+ hexit(1);
+}
+
static void putchar(struct iobuf *buf, char c)
{
if (buf->len == buflen)
@@ -204,7 +330,7 @@ void hexit(int code)
}
static void print_int(struct iobuf *buf, int nsigned, int byte4,
- unsigned long n)
+ unsigned long n, int size)
{
char tmpbuf[64];
char *p = tmpbuf;
@@ -238,6 +364,10 @@ static void print_int(struct iobuf *buf, int nsigned, int byte4,
*p = k % 10 + '0';
++p;
}
+ if (p - tmpbuf < size) {
+ for (; p < tmpbuf + size; ++p)
+ *p = '0';
+ }
for (--p;; --p) {
putchar(buf, *p);
if (p == tmpbuf)
@@ -258,30 +388,38 @@ void print_str(struct iobuf *buf, struct str *s)
putchar(buf, *tmp);
}
-static void format(struct iobuf *buf, char c, va_list vl)
+static void format(struct iobuf *buf, char c, int size, va_list vl)
{
switch(c) {
unsigned long arg;
case '%':
+ if (size != -1)
+ goto size_err;
putchar(buf, '%');
break;
case 'd':
case 'u':
arg = va_arg(vl, unsigned int);
- print_int(buf, c == 'd', 1, arg);
+ print_int(buf, c == 'd', 1, arg, size);
break;
case 'D':
case 'U':
arg = va_arg(vl, unsigned long);
- print_int(buf, c == 'D', 0, arg);
+ print_int(buf, c == 'D', 0, arg, size);
break;
case 's':
+ if (size != -1)
+ goto size_err;
print_strz(buf, va_arg(vl, char*));
break;
case 'S':
+ if (size != -1)
+ goto size_err;
print_str(buf, va_arg(vl, struct str *));
break;
case 'c':
+ if (size != -1)
+ goto size_err;
arg = va_arg(vl, int);
putchar(buf, arg);
break;
@@ -289,23 +427,35 @@ static void format(struct iobuf *buf, char c, va_list vl)
write(2, _S("printf: unexpected format option \n"));
hexit(2);
}
+ return;
+size_err:
+ write(2, _S("printf: %c: size not applicable\n"));
+ hexit(2);
}
static void __printf(struct iobuf *buf, char *s, va_list vl)
{
for (; *s; ++s) {
if (*s == '%') {
- if (s[1] == 0) {
- write(2, _S("printf: nothing comes after '%'"));
- hexit(2);
+ int size = -1;
+ if (s[1] == 0)
+ goto zero_err;
+ if (s[1] >= '0' && s[1] <= '9') {
+ size = s[1] - '0';
+ ++s;
}
- format(buf, s[1], vl);
+ if (s[1] == 0)
+ goto zero_err;
+ format(buf, s[1], size, vl);
++s;
} else {
putchar(buf, *s);
}
}
return;
+zero_err:
+ write(2, _S("printf: nothing specifier after '%'"));
+ hexit(2);
}
void printf(char *fmt, ...)
@@ -318,8 +468,6 @@ void printf(char *fmt, ...)
void evprintf(char *fmt, va_list vl)
{
- print_strz(&stderr, progname);
- print_strz(&stderr, ": ");
__printf(&stderr, fmt, vl);
}
@@ -331,38 +479,56 @@ void eprintf(char *fmt, ...)
va_end(vl);
}
-/* Memory management */
+void error(char *fmt, ...)
+{
+ va_list vl;
+ va_start(vl, fmt);
-struct mem_buffer {
- char *cur, *end;
- char *saved;
-};
+ print_strz(&stderr, progname);
+ print_strz(&stderr, ": ");
+ evprintf(fmt, vl);
+
+ va_end(vl);
+ print_strz(&stderr, "\n");
+ hexit(1);
+}
+
+/* Memory management */
-static struct mem_buffer mem_buf;
+struct heap heap;
-static void mem_buffer_init()
+void heap_offset_save()
{
- mem_buf.cur = mem_buf.end = brk(NULL);
- mem_buf.saved = NULL;
+ if (heap.snum == heap_saves_max)
+ error("heap: offset stack is full");
+ heap.saved[heap.snum] = heap.a.cur;
+ ++heap.snum;
}
-void save_heap_offset()
+void heap_offset_remove()
{
- if (mem_buf.saved != NULL) {
- eprintf("mem_buffer: offset already saved\n");
- hexit(2);
+ if (heap.snum == 0) {
+ error("heap: offset stack is empty");
}
- mem_buf.saved = mem_buf.cur;
+ --heap.snum;
}
-void restore_heap_offset()
+void heap_offset_restore()
{
- if (mem_buf.saved == NULL) {
- eprintf("mem_buffer: no offset was saved\n");
- hexit(2);
- }
- mem_buf.cur = mem_buf.saved;
- mem_buf.saved = NULL;
+ if (heap.snum == 0)
+ error("mem_buffer: no offset was saved\n");
+ heap.a.cur = heap.saved[heap.snum - 1];
+ --heap.snum;
+ heap.last_alloc = NULL;
+}
+
+void *mem_alloc(int size)
+{
+ void *tmp = mmap(NULL, size, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANON, -1, 0);
+ if (tmp == (void*)-1)
+ syscall_error("mmap");
+ return tmp;
}
static int get_alignment(int n)
@@ -378,7 +544,7 @@ static int get_alignment(int n)
return 1;
}
-static void mem_buf_grow(int size)
+static void heap_grow(struct arena *a, int size)
{
char *tmp;
if (size < 128*1024) {
@@ -388,31 +554,58 @@ static void mem_buf_grow(int size)
size &= -4096;
}
/*printf("Growing (%d)\n", size);*/
- tmp = brk(mem_buf.end + size);
- if (tmp == mem_buf.end) {
- eprintf("mem_buf: unable to allocate memory\n");
- hexit(1);
- }
- mem_buf.end = tmp;
+ tmp = brk(a->end + size);
+ if (tmp == a->end)
+ error("heap: unable to grow");
+ a->end = tmp;
+}
+
+static void heap_init()
+{
+ heap.a.start = heap.a.cur = heap.a.end = brk(NULL);
+ heap.a.grow = heap_grow;
+
+ heap.snum = 0;
+ heap.last_alloc = NULL;
}
#define ALIGN(v, align) \
(void*)(((unsigned long)(v) + (align) - 1ul) & -(align))
-void *malloc(int size)
+void *amalloc(struct arena *a, int size)
{
int align = get_alignment(size);
- char *tmp = ALIGN(mem_buf.cur, align);
- int diff = tmp + size - mem_buf.end;
+ char *tmp = ALIGN(a->cur, align);
+ int diff = tmp + size - a->end;
if (diff > 0)
- mem_buf_grow(diff);
+ a->grow(a, diff);
+
+ a->cur = tmp + size;
+
+ return tmp;
+}
- mem_buf.cur = tmp + size;
+void *malloc(int size)
+{
+ void *tmp = amalloc(&heap.a, size);
+ heap.last_alloc = tmp;
return tmp;
}
-int main(int argc, char **argv, char **envp);
+void realloc(void *p, int newsize)
+{
+ int diff;
+ if (heap.last_alloc != p)
+ error("realloc: not a previously allocated region");
+ diff = heap.last_alloc + newsize - heap.a.end;
+ if (diff > 0)
+ heap.a.grow(&heap.a, diff);
+
+ heap.a.cur = heap.last_alloc + newsize;
+}
+
+extern int main(int argc, char **argv, char **envp);
void _start_c(unsigned long *p)
{
@@ -421,7 +614,7 @@ void _start_c(unsigned long *p)
char **envp = argv + argc + 1;
progname = argv[0];
- mem_buffer_init();
+ heap_init();
hexit(main(argc, argv, envp));
}