From 05521dc5c5a6b571016fde335e5a91e00e48ab1b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig <hch@cloudius-systems.com> Date: Thu, 17 Jan 2013 19:55:05 +0100 Subject: [PATCH] add misc routines from musl --- libc/build.mak | 16 +++++-- libc/misc/a64l.c | 26 ++++++++++++ libc/misc/basename.c | 14 +++++++ libc/misc/dirname.c | 14 +++++++ libc/misc/ffs.c | 7 ++++ libc/misc/get_current_dir_name.c | 16 +++++++ libc/misc/gethostid.c | 4 ++ libc/misc/getopt.c | 72 ++++++++++++++++++++++++++++++++ libc/misc/getopt_long.c | 59 ++++++++++++++++++++++++++ libc/misc/getresgid.c | 8 ++++ libc/misc/getresuid.c | 8 ++++ libc/misc/getsubopt.c | 23 ++++++++++ libc/misc/setdomainname.c | 8 ++++ 13 files changed, 272 insertions(+), 3 deletions(-) create mode 100644 libc/misc/a64l.c create mode 100644 libc/misc/basename.c create mode 100644 libc/misc/dirname.c create mode 100644 libc/misc/ffs.c create mode 100644 libc/misc/get_current_dir_name.c create mode 100644 libc/misc/gethostid.c create mode 100644 libc/misc/getopt.c create mode 100644 libc/misc/getopt_long.c create mode 100644 libc/misc/getresgid.c create mode 100644 libc/misc/getresuid.c create mode 100644 libc/misc/getsubopt.c create mode 100644 libc/misc/setdomainname.c diff --git a/libc/build.mak b/libc/build.mak index 926cdbaf2..d1bf4dd08 100644 --- a/libc/build.mak +++ b/libc/build.mak @@ -1,7 +1,5 @@ libc := -libc += getopt.o - libc += ctype/__ctype_b_loc.o libc += ctype/__ctype_get_mb_cur_max.o libc += ctype/__ctype_tolower_loc.o @@ -99,6 +97,19 @@ libc += locale/wcsxfrm_l.o libc += locale/wctrans_l.o libc += locale/wctype_l.o +libc += misc/a64l.o +libc += misc/basename.o +libc += misc/dirname.o +libc += misc/ffs.o +libc += misc/get_current_dir_name.o +libc += misc/gethostid.o +libc += misc/getopt.o +libc += misc/getopt_long.o +libc += misc/getresuid.o +libc += misc/getresgid.o +libc += misc/getsubopt.o +libc += misc/setdomainname.o + libc += multibyte/btowc.o libc += multibyte/internal.o libc += multibyte/mblen.o @@ -224,4 +235,3 @@ libc += time.o libc += signal.o libc += mman.o libc += qsort.o - diff --git a/libc/misc/a64l.c b/libc/misc/a64l.c new file mode 100644 index 000000000..86aeefe0d --- /dev/null +++ b/libc/misc/a64l.c @@ -0,0 +1,26 @@ +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +static const char digits[] = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +long a64l(const char *s) +{ + int e; + uint32_t x = 0; + for (e=0; e<36 && *s; e+=6, s++) + x |= (strchr(digits, *s)-digits)<<e; + return x; +} + +char *l64a(long x0) +{ + static char s[7]; + char *p; + uint32_t x = x0; + for (p=s; x; p++, x>>=6) + *p = digits[x&63]; + *p = 0; + return s; +} diff --git a/libc/misc/basename.c b/libc/misc/basename.c new file mode 100644 index 000000000..5713598a2 --- /dev/null +++ b/libc/misc/basename.c @@ -0,0 +1,14 @@ +#include <string.h> +#include "libc.h" + +char *basename(char *s) +{ + size_t i; + if (!s || !*s) return "."; + i = strlen(s)-1; + for (; i&&s[i]=='/'; i--) s[i] = 0; + for (; i&&s[i-1]!='/'; i--); + return s+i; +} + +weak_alias(basename, __xpg_basename); diff --git a/libc/misc/dirname.c b/libc/misc/dirname.c new file mode 100644 index 000000000..dd570883d --- /dev/null +++ b/libc/misc/dirname.c @@ -0,0 +1,14 @@ +#include <string.h> +#include <libgen.h> + +char *dirname(char *s) +{ + size_t i; + if (!s || !*s) return "."; + i = strlen(s)-1; + for (; s[i]=='/'; i--) if (!i) return "/"; + for (; s[i]!='/'; i--) if (!i) return "."; + for (; s[i]=='/'; i--) if (!i) return "/"; + s[i+1] = 0; + return s; +} diff --git a/libc/misc/ffs.c b/libc/misc/ffs.c new file mode 100644 index 000000000..673ce5a97 --- /dev/null +++ b/libc/misc/ffs.c @@ -0,0 +1,7 @@ +#include <strings.h> +#include "atomic.h" + +int ffs(int i) +{ + return i ? a_ctz_l(i)+1 : 0; +} diff --git a/libc/misc/get_current_dir_name.c b/libc/misc/get_current_dir_name.c new file mode 100644 index 000000000..e0f463b5c --- /dev/null +++ b/libc/misc/get_current_dir_name.c @@ -0,0 +1,16 @@ +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <unistd.h> +#include <sys/stat.h> + +char *get_current_dir_name(void) { + struct stat a, b; + char buf[PATH_MAX]; + char *res = getenv("PWD"); + if (res && *res && !stat(res, &a) && !stat(".", &b) + && (a.st_dev == b.st_dev) && (a.st_ino == b.st_ino)) + return strdup(res); + if(!getcwd(buf, sizeof(buf))) return NULL; + return strdup(buf); +} diff --git a/libc/misc/gethostid.c b/libc/misc/gethostid.c new file mode 100644 index 000000000..ea65611ab --- /dev/null +++ b/libc/misc/gethostid.c @@ -0,0 +1,4 @@ +long gethostid() +{ + return 0; +} diff --git a/libc/misc/getopt.c b/libc/misc/getopt.c new file mode 100644 index 000000000..35880a090 --- /dev/null +++ b/libc/misc/getopt.c @@ -0,0 +1,72 @@ +#include <unistd.h> +#include <wchar.h> +#include <string.h> +#include <limits.h> +#include <stdlib.h> +#include "libc.h" + +char *optarg; +int optind=1, opterr=1, optopt, __optpos, __optreset=0; + +#define optpos __optpos +weak_alias(__optreset, optreset); + +int getopt(int argc, char * const argv[], const char *optstring) +{ + int i; + wchar_t c, d; + int k, l; + char *optchar; + + if (!optind || __optreset) { + __optreset = 0; + __optpos = 0; + optind = 1; + } + + if (optind >= argc || !argv[optind] || argv[optind][0] != '-' || !argv[optind][1]) + return -1; + if (argv[optind][1] == '-' && !argv[optind][2]) + return optind++, -1; + + if (!optpos) optpos++; + if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) { + k = 1; + c = 0xfffd; /* replacement char */ + } + optchar = argv[optind]+optpos; + optopt = c; + optpos += k; + + if (!argv[optind][optpos]) { + optind++; + optpos = 0; + } + + for (i=0; (l = mbtowc(&d, optstring+i, MB_LEN_MAX)) && d!=c; i+=l>0?l:1); + + if (d != c) { + if (optstring[0] != ':' && opterr) { + write(2, argv[0], strlen(argv[0])); + write(2, ": illegal option: ", 18); + write(2, optchar, k); + write(2, "\n", 1); + } + return '?'; + } + if (optstring[i+1] == ':') { + if (optind >= argc) { + if (optstring[0] == ':') return ':'; + if (opterr) { + write(2, argv[0], strlen(argv[0])); + write(2, ": option requires an argument: ", 31); + write(2, optchar, k); + write(2, "\n", 1); + } + return '?'; + } + optarg = argv[optind++] + optpos; + optpos = 0; + } + return c; +} diff --git a/libc/misc/getopt_long.c b/libc/misc/getopt_long.c new file mode 100644 index 000000000..4ef5a5c7a --- /dev/null +++ b/libc/misc/getopt_long.c @@ -0,0 +1,59 @@ +#define _GNU_SOURCE +#include <stddef.h> +#include <getopt.h> +#include <stdio.h> + +extern int __optpos, __optreset; + +static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly) +{ + if (!optind || __optreset) { + __optreset = 0; + __optpos = 0; + optind = 1; + } + if (optind >= argc || !argv[optind] || argv[optind][0] != '-') return -1; + if ((longonly && argv[optind][1]) || + (argv[optind][1] == '-' && argv[optind][2])) + { + int i; + for (i=0; longopts[i].name; i++) { + const char *name = longopts[i].name; + char *opt = argv[optind]+1; + if (*opt == '-') opt++; + for (; *name && *name == *opt; name++, opt++); + if (*name || (*opt && *opt != '=')) continue; + if (*opt == '=') { + if (!longopts[i].has_arg) continue; + optarg = opt+1; + } else { + if (longopts[i].has_arg == required_argument) { + if (!(optarg = argv[++optind])) + return ':'; + } else optarg = NULL; + } + optind++; + if (idx) *idx = i; + if (longopts[i].flag) { + *longopts[i].flag = longopts[i].val; + return 0; + } + return longopts[i].val; + } + if (argv[optind][1] == '-') { + optind++; + return '?'; + } + } + return getopt(argc, argv, optstring); +} + +int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) +{ + return __getopt_long(argc, argv, optstring, longopts, idx, 0); +} + +int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) +{ + return __getopt_long(argc, argv, optstring, longopts, idx, 1); +} diff --git a/libc/misc/getresgid.c b/libc/misc/getresgid.c new file mode 100644 index 000000000..d00d9a99d --- /dev/null +++ b/libc/misc/getresgid.c @@ -0,0 +1,8 @@ +#define _GNU_SOURCE +#include <unistd.h> +#include "syscall.h" + +int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) +{ + return syscall(SYS_getresgid, rgid, egid, sgid); +} diff --git a/libc/misc/getresuid.c b/libc/misc/getresuid.c new file mode 100644 index 000000000..d75d5d408 --- /dev/null +++ b/libc/misc/getresuid.c @@ -0,0 +1,8 @@ +#define _GNU_SOURCE +#include <unistd.h> +#include "syscall.h" + +int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) +{ + return syscall(SYS_getresuid, ruid, euid, suid); +} diff --git a/libc/misc/getsubopt.c b/libc/misc/getsubopt.c new file mode 100644 index 000000000..dac9bf9ea --- /dev/null +++ b/libc/misc/getsubopt.c @@ -0,0 +1,23 @@ +#include <stdlib.h> +#include <string.h> + +int getsubopt(char **opt, char *const *keys, char **val) +{ + char *s = *opt; + int i; + + *val = NULL; + *opt = strchr(s, ','); + if (*opt) *(*opt)++ = 0; + else *opt = s + strlen(s); + + for (i=0; keys[i]; i++) { + size_t l = strlen(keys[i]); + if (strncmp(keys[i], s, l)) continue; + if (s[l] == '=') + *val = s + l; + else if (s[l]) continue; + return i; + } + return -1; +} diff --git a/libc/misc/setdomainname.c b/libc/misc/setdomainname.c new file mode 100644 index 000000000..22d3f7463 --- /dev/null +++ b/libc/misc/setdomainname.c @@ -0,0 +1,8 @@ +#define _GNU_SOURCE +#include <unistd.h> +#include "syscall.h" + +int setdomainname(const char *name, size_t len) +{ + return syscall(SYS_setdomainname, name, len); +} -- GitLab