diff options
Diffstat (limited to 'tools/common.c')
-rw-r--r-- | tools/common.c | 313 |
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)); } |