mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
121 lines
2.6 KiB
C
121 lines
2.6 KiB
C
|
|
#ifdef HAVE_MEMMEM
|
|
#define _GNU_SOURCE
|
|
#include <string.h>
|
|
#endif
|
|
#include <assert.h>
|
|
#ifndef WIN32
|
|
#include <pwd.h>
|
|
#endif
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <limits.h>
|
|
|
|
|
|
#include "util.h"
|
|
#include "jv.h"
|
|
|
|
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 */
|
|
}
|
|
|