| |
| #ifdef HAVE_MEMMEM |
| #define _GNU_SOURCE |
| #endif |
| |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <assert.h> |
| #include <fcntl.h> |
| #include <limits.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #ifndef WIN32 |
| #include <pwd.h> |
| #endif |
| |
| |
| #include "util.h" |
| #include "jv.h" |
| |
| #ifndef HAVE_MKSTEMP |
| int mkstemp(char *template) { |
| size_t len = strlen(template); |
| int tries=5; |
| int fd; |
| |
| // mktemp() truncates template when it fails |
| char *s = alloca(len + 1); |
| assert(s != NULL); |
| strcpy(s, template); |
| |
| do { |
| // Restore template |
| strcpy(template, s); |
| (void) mktemp(template); |
| fd = open(template, O_CREAT | O_EXCL | O_RDWR, 0600); |
| } while (fd == -1 && tries-- > 0); |
| return fd; |
| } |
| #endif |
| |
| jv expand_path(jv path) { |
| assert(jv_get_kind(path) == JV_KIND_STRING); |
| const char *pstr = jv_string_value(path); |
| jv ret = path; |
| if (jv_string_length_bytes(jv_copy(path)) > 1 && pstr[0] == '~' && pstr[1] == '/') { |
| jv home = get_home(); |
| if (jv_is_valid(home)) { |
| ret = jv_string_fmt("%s/%s",jv_string_value(home),pstr+2); |
| jv_free(home); |
| } else { |
| jv emsg = jv_invalid_get_msg(home); |
| ret = jv_invalid_with_msg(jv_string_fmt("Could not expand %s. (%s)", pstr, jv_string_value(emsg))); |
| jv_free(emsg); |
| } |
| jv_free(path); |
| } |
| return ret; |
| } |
| |
| jv get_home() { |
| jv ret; |
| char *home = getenv("HOME"); |
| if (!home) { |
| #ifndef WIN32 |
| struct passwd* pwd = getpwuid(getuid()); |
| if (pwd) |
| ret = jv_string(pwd->pw_dir); |
| else |
| ret = jv_invalid_with_msg(jv_string("Could not find home directory.")); |
| #else |
| home = getenv("USERPROFILE"); |
| if (!home) { |
| char *hd = getenv("HOMEDRIVE"); |
| if (!hd) hd = ""; |
| home = getenv("HOMEPATH"); |
| if (!home) { |
| ret = jv_invalid_with_msg(jv_string("Could not find home directory.")); |
| } else { |
| ret = jv_string_fmt("%s%s",hd,home); |
| } |
| } else { |
| ret = jv_string(home); |
| } |
| #endif |
| } else { |
| ret = jv_string(home); |
| } |
| return ret; |
| } |
| |
| |
| jv jq_realpath(jv path) { |
| int path_max; |
| char *buf = NULL; |
| #ifdef _PC_PATH_MAX |
| path_max = pathconf(jv_string_value(path),_PC_PATH_MAX); |
| #else |
| path_max = PATH_MAX; |
| #endif |
| if (path_max > 0) { |
| buf = malloc(sizeof(char) * path_max); |
| } |
| #ifdef WIN32 |
| char *tmp = _fullpath(buf, jv_string_value(path), path_max); |
| #else |
| char *tmp = realpath(jv_string_value(path), buf); |
| #endif |
| if (tmp == NULL) { |
| free(buf); |
| return path; |
| } |
| jv_free(path); |
| path = jv_string(tmp); |
| free(tmp); |
| return path; |
| } |
| |
| const void *_jq_memmem(const void *haystack, size_t haystacklen, |
| const void *needle, size_t needlelen) { |
| #ifdef HAVE_MEMMEM |
| return (const void*)memmem(haystack, haystacklen, needle, needlelen); |
| #else |
| const char *h = haystack; |
| const char *n = needle; |
| size_t hi, hi2, ni; |
| |
| if (haystacklen < needlelen || haystacklen == 0) |
| return NULL; |
| for (hi = 0; hi < (haystacklen - needlelen + 1); hi++) { |
| for (ni = 0, hi2 = hi; ni < needlelen; ni++, hi2++) { |
| if (h[hi2] != n[ni]) |
| goto not_this; |
| } |
| |
| return &h[hi]; |
| |
| not_this: |
| continue; |
| } |
| return NULL; |
| #endif /* !HAVE_MEMMEM */ |
| } |
| |