static volatile unsigned cached_columns = 0;
static volatile unsigned cached_lines = 0;
-#define procfs_file_alloca(pid, field) \
- ({ \
- pid_t _pid_ = (pid); \
- char *_r_; \
- _r_ = alloca(sizeof("/proc/") -1 + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
- sprintf(_r_, "/proc/%lu/" field, (unsigned long) _pid_); \
- _r_; \
- })
-
size_t page_size(void) {
static __thread size_t pgsz = 0;
long r;
int safe_atod(const char *s, double *ret_d) {
char *x = NULL;
- double d;
+ double d = 0;
assert(s);
assert(ret_d);
- errno = 0;
- d = strtod(s, &x);
+ RUN_WITH_LOCALE(LC_NUMERIC_MASK, "C") {
+ errno = 0;
+ d = strtod(s, &x);
+ }
if (!x || x == s || *x || errno)
return errno ? -errno : -EINVAL;
return 0;
}
+int get_process_capeff(pid_t pid, char **capeff) {
+ const char *p;
+ _cleanup_free_ char *status = NULL;
+ char *t = NULL;
+ int r;
+
+ assert(capeff);
+ assert(pid >= 0);
+
+ if (pid == 0)
+ p = "/proc/self/status";
+ else
+ p = procfs_file_alloca(pid, "status");
+
+ r = read_full_file(p, &status, NULL);
+ if (r < 0)
+ return r;
+
+ t = strstr(status, "\nCapEff:\t");
+ if (!t)
+ return -ENOENT;
+
+ for (t += strlen("\nCapEff:\t"); t[0] == '0'; t++)
+ continue;
+
+ if (t[0] == '\n')
+ t--;
+
+ *capeff = strndup(t, strchr(t, '\n') - t);
+ if (!*capeff)
+ return -ENOMEM;
+
+ return 0;
+}
int get_process_exe(pid_t pid, char **name) {
const char *p;
+ char *d;
+ int r;
assert(pid >= 0);
assert(name);
else
p = procfs_file_alloca(pid, "exe");
- return readlink_malloc(p, name);
+ r = readlink_malloc(p, name);
+ if (r < 0)
+ return r;
+
+ d = endswith(*name, " (deleted)");
+ if (d)
+ *d = '\0';
+
+ return 0;
}
static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
}
int readlink_and_make_absolute(const char *p, char **r) {
- char *target, *k;
+ _cleanup_free_ char *target = NULL;
+ char *k;
int j;
assert(p);
assert(r);
- if ((j = readlink_malloc(p, &target)) < 0)
+ j = readlink_malloc(p, &target);
+ if (j < 0)
return j;
k = file_in_same_dir(p, target);
- free(target);
-
if (!k)
return -ENOMEM;
return t;
}
-static bool ignore_file_allow_backup(const char *filename) {
+_pure_ static bool ignore_file_allow_backup(const char *filename) {
assert(filename);
return
return 0;
}
-static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
+_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
unsigned i;
assert(n_fdset == 0 || fdset);
"cifs\0"
"smbfs\0"
"ncpfs\0"
+ "ncp\0"
"nfs\0"
"nfs4\0"
"gfs\0"
* https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
*/
+ assert(!(mode & O_CREAT));
+
for (;;) {
- fd = open(name, mode);
+ fd = open(name, mode, 0);
if (fd >= 0)
break;
int parse_bytes(const char *t, off_t *bytes) {
static const struct {
const char *suffix;
- off_t factor;
+ unsigned long long factor;
} table[] = {
{ "B", 1 },
{ "K", 1024ULL },
};
const char *p;
- off_t r = 0;
+ unsigned long long r = 0;
assert(t);
assert(bytes);
for (i = 0; i < ELEMENTSOF(table); i++)
if (startswith(e, table[i].suffix)) {
- r += (off_t) l * table[i].factor;
+ unsigned long long tmp;
+ if ((unsigned long long) l > ULLONG_MAX / table[i].factor)
+ return -ERANGE;
+ tmp = l * table[i].factor;
+ if (tmp > ULLONG_MAX - r)
+ return -ERANGE;
+
+ r += tmp;
+ if ((unsigned long long) (off_t) r != r)
+ return -ERANGE;
+
p = e + strlen(table[i].suffix);
break;
}
if (i >= ELEMENTSOF(table))
return -EINVAL;
- } while (*p != 0);
+ } while (*p);
*bytes = r;
return ret;
}
-static int is_temporary_fs(struct statfs *s) {
+_pure_ static int is_temporary_fs(struct statfs *s) {
assert(s);
return
F_TYPE_CMP(s->f_type, TMPFS_MAGIC) ||
r = new0(char, new_length+1);
if (!r)
- return r;
+ return NULL;
x = (new_length * percent) / 100;
int nfd;
DIR *d;
- nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
+ assert(!(flags & O_CREAT));
+
+ nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
if (nfd < 0)
return NULL;
return true;
}
-char* hostname_cleanup(char *s) {
+char* hostname_cleanup(char *s, bool lowercase) {
char *p, *d;
bool dot;
for (p = s, d = s, dot = true; *p; p++) {
if (*p == '.') {
- if (dot || p[1] == 0)
+ if (dot)
continue;
+ *(d++) = '.';
dot = true;
- } else
+ } else if (hostname_valid_char(*p)) {
+ *(d++) = lowercase ? tolower(*p) : *p;
dot = false;
+ }
- if (hostname_valid_char(*p))
- *(d++) = *p;
}
- *d = 0;
+ if (dot && d > s)
+ d[-1] = 0;
+ else
+ *d = 0;
+
strshorten(s, HOST_NAME_MAX);
return s;
int glob_exists(const char *path) {
_cleanup_globfree_ glob_t g = {};
- int r, k;
+ int k;
assert(path);
k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
if (k == GLOB_NOMATCH)
- r = 0;
+ return 0;
else if (k == GLOB_NOSPACE)
- r = -ENOMEM;
+ return -ENOMEM;
else if (k == 0)
- r = !strv_isempty(g.gl_pathv);
+ return !strv_isempty(g.gl_pathv);
else
- r = errno ? -errno : -EIO;
+ return errno ? -errno : -EIO;
+}
- return r;
+int glob_extend(char ***strv, const char *path) {
+ _cleanup_globfree_ glob_t g = {};
+ int k;
+ char **p;
+
+ errno = 0;
+ k = glob(optarg, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
+
+ if (k == GLOB_NOMATCH)
+ return -ENOENT;
+ else if (k == GLOB_NOSPACE)
+ return -ENOMEM;
+ else if (k != 0 || strv_isempty(g.gl_pathv))
+ return errno ? -errno : -EIO;
+
+ STRV_FOREACH(p, g.gl_pathv) {
+ k = strv_extend(strv, *p);
+ if (k < 0)
+ break;
+ }
+
+ return k;
}
int dirent_ensure_type(DIR *d, struct dirent *de) {
return r;
}
-int can_sleep(const char *type) {
- char *w, *state;
- size_t l, k;
- int r;
- _cleanup_free_ char *p = NULL;
-
- assert(type);
-
- /* If /sys is read-only we cannot sleep */
- if (access("/sys/power/state", W_OK) < 0)
- return false;
-
- r = read_one_line_file("/sys/power/state", &p);
- if (r < 0)
- return false;
-
- k = strlen(type);
- FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
- if (l == k && memcmp(w, type, l) == 0)
- return true;
-
- return false;
-}
-
-int can_sleep_disk(const char *type) {
- char *w, *state;
- size_t l, k;
- int r;
- _cleanup_free_ char *p = NULL;
-
- assert(type);
-
- /* If /sys is read-only we cannot sleep */
- if (access("/sys/power/state", W_OK) < 0 ||
- access("/sys/power/disk", W_OK) < 0)
- return false;
-
- r = read_one_line_file("/sys/power/disk", &p);
- if (r < 0)
- return false;
-
- k = strlen(type);
- FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) {
- if (l == k && memcmp(w, type, l) == 0)
- return true;
-
- if (l == k + 2 && w[0] == '[' && memcmp(w + 1, type, l - 2) == 0 && w[l-1] == ']')
- return true;
- }
-
- return false;
-}
-
bool is_valid_documentation_url(const char *url) {
assert(url);
goto out;
}
- /* For LC_CTYPE=="C" return true,
- * because CTYPE is effectly unset and
- * everything defaults to UTF-8 nowadays. */
-
+ /* For LC_CTYPE=="C" return true, because CTYPE is effectly
+ * unset and everything can do to UTF-8 nowadays. */
set = setlocale(LC_CTYPE, NULL);
if (!set) {
cached_answer = true;
goto out;
}
- cached_answer = streq(set, "C");
+ /* Check result, but ignore the result if C was set
+ * explicitly. */
+ cached_answer =
+ streq(set, "C") &&
+ !getenv("LC_ALL") &&
+ !getenv("LC_CTYPE") &&
+ !getenv("LANG");
out:
- return (bool)cached_answer;
+ return (bool) cached_answer;
}
const char *draw_special_char(DrawSpecialChar ch) {
int create_tmp_dir(char template[], char** dir_name) {
int r = 0;
- char *d, *dt;
+ char *d = NULL, *dt;
assert(dir_name);
*allocated = a;
return q;
}
+
+bool id128_is_valid(const char *s) {
+ size_t i, l;
+
+ l = strlen(s);
+ if (l == 32) {
+
+ /* Simple formatted 128bit hex string */
+
+ for (i = 0; i < l; i++) {
+ char c = s[i];
+
+ if (!(c >= '0' && c <= '9') &&
+ !(c >= 'a' && c <= 'z') &&
+ !(c >= 'A' && c <= 'Z'))
+ return false;
+ }
+
+ } else if (l == 36) {
+
+ /* Formatted UUID */
+
+ for (i = 0; i < l; i++) {
+ char c = s[i];
+
+ if ((i == 8 || i == 13 || i == 18 || i == 23)) {
+ if (c != '-')
+ return false;
+ } else {
+ if (!(c >= '0' && c <= '9') &&
+ !(c >= 'a' && c <= 'z') &&
+ !(c >= 'A' && c <= 'Z'))
+ return false;
+ }
+ }
+
+ } else
+ return false;
+
+ return true;
+}
+
+void parse_user_at_host(char *arg, char **user, char **host) {
+ assert(arg);
+ assert(user);
+ assert(host);
+
+ *host = strchr(arg, '@');
+ if (*host == NULL)
+ *host = arg;
+ else {
+ *host[0]++ = '\0';
+ *user = arg;
+ }
+}
+
+int split_pair(const char *s, const char *sep, char **l, char **r) {
+ char *x, *a, *b;
+
+ assert(s);
+ assert(sep);
+ assert(l);
+ assert(r);
+
+ if (isempty(sep))
+ return -EINVAL;
+
+ x = strstr(s, sep);
+ if (!x)
+ return -EINVAL;
+
+ a = strndup(s, x - s);
+ if (!a)
+ return -ENOMEM;
+
+ b = strdup(x + strlen(sep));
+ if (!b) {
+ free(a);
+ return -ENOMEM;
+ }
+
+ *l = a;
+ *r = b;
+
+ return 0;
+}