summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--UPSTREAM.notes9
-rw-r--r--src/libudev/missing.h2
-rw-r--r--src/libudev/util.c107
-rw-r--r--src/libudev/util.h1
-rw-r--r--src/udev/label.c2
-rw-r--r--src/udev/mkdir.c72
6 files changed, 148 insertions, 45 deletions
diff --git a/UPSTREAM.notes b/UPSTREAM.notes
index f95149833e..12c1359393 100644
--- a/UPSTREAM.notes
+++ b/UPSTREAM.notes
@@ -8,3 +8,12 @@
commit edeb68c53f1cdc452016b4c8512586a70b1262e3. Upstream has moved this functionality
to systemd-tmpfilesd since kmod v14 now exports static node info in tmpfiles.d format.
We wish to retain this functionality in udevd.
+
+2013-07-10
+
+ * Add "hwdb: allow list of lookup keys per given record"
+ * Bring src/udev/mkdir.c in line with upstreams use of *_internal() with prefix
+ * Import format_timespan() from upstream's src/shared/time-util.c. Note: our
+ src/libudev/util.c is derived from upstream's src/shared/util.c minus unneeded functions
+ plus three functions from src/shared/time-util.c: now(), timespec_load() and
+ timespan().
diff --git a/src/libudev/missing.h b/src/libudev/missing.h
index aa578d1fe0..a2ca518948 100644
--- a/src/libudev/missing.h
+++ b/src/libudev/missing.h
@@ -139,7 +139,7 @@ static inline int fanotify_init(unsigned int flags, unsigned int event_f_flags)
static inline int fanotify_mark(int fanotify_fd, unsigned int flags, uint64_t mask,
int dfd, const char *pathname) {
#if defined _MIPS_SIM && _MIPS_SIM == _MIPS_SIM_ABI32 || defined __powerpc__ && !defined __powerpc64__ \
- || defined __arm__ && !defined __aarch64__
+ || defined __arm__ && !defined __aarch64__
union {
uint64_t _64;
uint32_t _32[2];
diff --git a/src/libudev/util.c b/src/libudev/util.c
index e447f89647..f625cfe99b 100644
--- a/src/libudev/util.c
+++ b/src/libudev/util.c
@@ -127,6 +127,113 @@ usec_t timespec_load(const struct timespec *ts) {
(usec_t) ts->tv_nsec / NSEC_PER_USEC;
}
+char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
+ static const struct {
+ const char *suffix;
+ usec_t usec;
+ } table[] = {
+ { "y", USEC_PER_YEAR },
+ { "month", USEC_PER_MONTH },
+ { "w", USEC_PER_WEEK },
+ { "d", USEC_PER_DAY },
+ { "h", USEC_PER_HOUR },
+ { "min", USEC_PER_MINUTE },
+ { "s", USEC_PER_SEC },
+ { "ms", USEC_PER_MSEC },
+ { "us", 1 },
+ };
+
+ unsigned i;
+ char *p = buf;
+ bool something = false;
+
+ assert(buf);
+ assert(l > 0);
+
+ if (t == (usec_t) -1)
+ return NULL;
+
+ if (t <= 0) {
+ snprintf(p, l, "0");
+ p[l-1] = 0;
+ return p;
+ }
+
+ /* The result of this function can be parsed with parse_sec */
+
+ for (i = 0; i < ELEMENTSOF(table); i++) {
+ int k;
+ size_t n;
+ bool done = false;
+ usec_t a, b;
+
+ if (t <= 0)
+ break;
+
+ if (t < accuracy && something)
+ break;
+
+ if (t < table[i].usec)
+ continue;
+
+ if (l <= 1)
+ break;
+
+ a = t / table[i].usec;
+ b = t % table[i].usec;
+
+ /* Let's see if we should shows this in dot notation */
+ if (t < USEC_PER_MINUTE && b > 0) {
+ usec_t cc;
+ int j;
+
+ j = 0;
+ for (cc = table[i].usec; cc > 1; cc /= 10)
+ j++;
+
+ for (cc = accuracy; cc > 1; cc /= 10) {
+ b /= 10;
+ j--;
+ }
+
+ if (j > 0) {
+ k = snprintf(p, l,
+ "%s%llu.%0*llu%s",
+ p > buf ? " " : "",
+ (unsigned long long) a,
+ j,
+ (unsigned long long) b,
+ table[i].suffix);
+
+ t = 0;
+ done = true;
+ }
+ }
+
+ /* No? Then let's show it normally */
+ if (!done) {
+ k = snprintf(p, l,
+ "%s%llu%s",
+ p > buf ? " " : "",
+ (unsigned long long) a,
+ table[i].suffix);
+
+ t = b;
+ }
+
+ n = MIN((size_t) k, l);
+
+ l -= n;
+ p += n;
+
+ something = true;
+ }
+
+ *p = 0;
+
+ return buf;
+}
+
char* endswith(const char *s, const char *postfix) {
size_t sl, pl;
diff --git a/src/libudev/util.h b/src/libudev/util.h
index 2ac6f59c49..60b300da3c 100644
--- a/src/libudev/util.h
+++ b/src/libudev/util.h
@@ -84,6 +84,7 @@ union dirent_storage {
usec_t now(clockid_t clock);
usec_t timespec_load(const struct timespec *ts);
+char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy);
size_t page_size(void);
#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
diff --git a/src/udev/label.c b/src/udev/label.c
index 1ab40f4bba..1e4d01113a 100644
--- a/src/udev/label.c
+++ b/src/udev/label.c
@@ -85,7 +85,7 @@ int label_init(const char *prefix) {
l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.",
- format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp),
+ format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0),
(l+1023)/1024);
}
#endif
diff --git a/src/udev/mkdir.c b/src/udev/mkdir.c
index b9920ec207..c775bfa0c3 100644
--- a/src/udev/mkdir.c
+++ b/src/udev/mkdir.c
@@ -26,54 +26,47 @@
#include <stdlib.h>
#include <stdio.h>
-#include "mkdir.h"
#include "label.h"
#include "util.h"
+#include "mkdir.h"
-static int makedir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, bool apply) {
+static int is_dir(const char* path) {
struct stat st;
- if (label_mkdir(path, mode, apply) >= 0)
- if (chmod_and_chown(path, mode, uid, gid) < 0)
- return -errno;
-
- if (lstat(path, &st) < 0)
- return -errno;
-
- if ((st.st_mode & 0777) != mode ||
- st.st_uid != uid ||
- st.st_gid != gid ||
- !S_ISDIR(st.st_mode)) {
- errno = EEXIST;
+ if (stat(path, &st) < 0)
return -errno;
- }
- return 0;
+ return S_ISDIR(st.st_mode);
}
-static int makedir_parents(const char *path, mode_t mode, bool apply) {
- struct stat st;
+static int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, bool apply) {
const char *p, *e;
+ int r;
assert(path);
+ if (prefix && !path_startswith(path, prefix))
+ return -ENOTDIR;
+
/* return immediately if directory exists */
e = strrchr(path, '/');
if (!e)
return -EINVAL;
+
+ if (e == path)
+ return 0;
+
p = strndupa(path, e - path);
- if (stat(p, &st) >= 0) {
- if ((st.st_mode & S_IFMT) == S_IFDIR)
- return 0;
- else
- return -ENOTDIR;
- }
+ r = is_dir(p);
+ if (r > 0)
+ return 0;
+ if (r == 0)
+ return -ENOTDIR;
/* create every parent directory in the path, except the last component */
p = path + strspn(path, "/");
for (;;) {
- int r;
- char *t;
+ char t[strlen(path) + 1];
e = p + strcspn(p, "/");
p = e + strspn(e, "/");
@@ -83,39 +76,32 @@ static int makedir_parents(const char *path, mode_t mode, bool apply) {
if (*p == 0)
return 0;
- t = strndup(path, e - path);
- if (!t)
- return -ENOMEM;
+ memcpy(t, path, e - path);
+ t[e-path] = 0;
- r = label_mkdir(t, mode, apply);
- free(t);
+ if (prefix && path_startswith(prefix, t))
+ continue;
+ r = label_mkdir(t, mode, apply);
if (r < 0 && errno != EEXIST)
return -errno;
}
}
int mkdir_parents(const char *path, mode_t mode) {
- return makedir_parents(path, mode, false);
+ return mkdir_parents_internal(NULL, path, mode, false);
}
int mkdir_parents_label(const char *path, mode_t mode) {
- return makedir_parents(path, mode, true);
-}
-
-static int is_dir(const char* path) {
- struct stat st;
- if (stat(path, &st) < 0)
- return -errno;
- return S_ISDIR(st.st_mode);
+ return mkdir_parents_internal(NULL, path, mode, true);
}
-static int makedir_p(const char *path, mode_t mode, bool apply) {
+static int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, bool apply) {
int r;
/* Like mkdir -p */
- r = makedir_parents(path, mode, apply);
+ r = mkdir_parents_internal(prefix, path, mode, apply);
if (r < 0)
return r;
@@ -127,5 +113,5 @@ static int makedir_p(const char *path, mode_t mode, bool apply) {
}
int mkdir_p(const char *path, mode_t mode) {
- return makedir_p(path, mode, false);
+ return mkdir_p_internal(NULL, path, mode, false);
}