diff options
Diffstat (limited to 'src/user/lib/libc/std/string.c')
-rw-r--r-- | src/user/lib/libc/std/string.c | 113 |
1 files changed, 108 insertions, 5 deletions
diff --git a/src/user/lib/libc/std/string.c b/src/user/lib/libc/std/string.c index 619b8c6..02225a6 100644 --- a/src/user/lib/libc/std/string.c +++ b/src/user/lib/libc/std/string.c @@ -17,7 +17,18 @@ char *strchr(const char *str, int c) { char *strcpy(char *dest, const char *src) { memcpy(dest, src, strlen(src) + 1); - return (char*)src; + return (char*)dest; +} + +char *strncpy(char *dest, const char *src, int n) { + size_t i; + + for (i = 0; i < n && src[i] != '\0'; i++) + dest[i] = src[i]; + for ( ; i < n; i++) + dest[i] = '\0'; + + return dest; } char *strdup(const char *src) { @@ -29,11 +40,10 @@ char *strdup(const char *src) { char *strcat(char *dest, const char *src) { char *dest2 = dest; - dest2 += strlen(dest) - 1; + while (*dest2) dest2++; // move to end of string + while (*src) { - *dest2 = *src; - src++; - dest2++; + *(dest2++) = *(src++); } *dest2 = 0; return dest; @@ -133,6 +143,8 @@ int printf_str_len(const char *format, va_list ap) { va_arg(ap, void*); } else if (*format == 's') { l += strlen(va_arg(ap, const char*)); + } else if (*format == 'c') { + l += 1; } } else { l++; @@ -164,6 +176,10 @@ int vsprintf(char *buf, const char *format, va_list ap) { const char *s = va_arg(ap, const char*); strcpy(end, s); end += strlen(s); + } else if (*format == 'c') { + char k = va_arg(ap, int); + *(end++) = k; + *end = 0; } format++; } else { @@ -173,3 +189,90 @@ int vsprintf(char *buf, const char *format, va_list ap) { *end = 0; return end - buf; } + + +// ****** PATH CONCATENATION FUNCTION ******* + + +void simplify_path(char* p) { + char *it = p; + char *member = it; + while (*it != 0) { + if (*it == '/') { + if (it == member && it != p) { + // two consecutive slashes + char *i = member; + while (1) { + i[0] = i[1]; + if (i[0] == 0) break; + i++; + } + } else { + *it = 0; + if (strcmp(member, ".") == 0) { + char *i = member; + while (1) { + i[0] = i[2]; + if (i[0] == 0) break; + i++; + } + } else if (strcmp(member, "..") == 0) { + *it = '/'; + char* start = member - 2; + char* next = member + 3; + while (start > p && *start != '/') { + start--; + } + start++; + it = member = start; + while (1) { + *start = *next; + if (*start == 0) break; + start++; + next++; + } + } else { + *it = '/'; + it++; + member = it; + } + } + } else { + it++; + } + } +} + +char* path_cat(const char *a, const char *b, int trailing_slash) { + int len, la = strlen(a), lb = strlen(b); + if (b[0] == '/') { + len = lb + 2; + } else { + len = la + lb + 3; + } + char *buf = malloc(len + 1); + if (b[0] == '/') { + memcpy(buf, b, lb); + if (buf[lb-1] != '/') { + buf[lb++] = '/'; + } + buf[lb] = 0; + } else { + memcpy(buf, a, la); + if (buf[la-1] != '/') { + buf[la++] = '/'; + } + memcpy(buf + la, b, lb); + if (buf[la + lb - 1] != '/') { + buf[la + lb] = '/'; + lb++; + } + buf[la + lb] = 0; + } + simplify_path(buf); + if (!trailing_slash) { + int l = strlen(buf); + if (buf[l-1] == '/') buf[l-1] = 0; + } + return buf; +} |