mirror of
https://github.com/AuxXxilium/kmod.git
synced 2024-11-23 15:00:52 +07:00
Move generic util functions to shared directory
This commit is contained in:
parent
8b7189bc25
commit
96573a0220
@ -43,7 +43,11 @@ LIBKMOD_REVISION=8
|
||||
LIBKMOD_AGE=2
|
||||
|
||||
noinst_LTLIBRARIES = libkmod/libkmod-util.la
|
||||
libkmod_libkmod_util_la_SOURCES = libkmod/libkmod-hash.c \
|
||||
libkmod_libkmod_util_la_SOURCES = shared/macro.h \
|
||||
shared/missing.h\
|
||||
shared/util.c \
|
||||
shared/util.h \
|
||||
libkmod/libkmod-hash.c \
|
||||
libkmod/libkmod-hash.h \
|
||||
libkmod/libkmod-array.c \
|
||||
libkmod/libkmod-array.h \
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <shared/util.h>
|
||||
|
||||
#include "libkmod.h"
|
||||
#include "libkmod-internal.h"
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <shared/util.h>
|
||||
|
||||
#include "libkmod.h"
|
||||
#include "libkmod-internal.h"
|
||||
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <shared/util.h>
|
||||
|
||||
#include "libkmod.h"
|
||||
#include "libkmod-internal.h"
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <shared/util.h>
|
||||
|
||||
#include "libkmod.h"
|
||||
#include "libkmod-hash.h"
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <shared/macro.h>
|
||||
#include <shared/util.h>
|
||||
|
||||
#include "libkmod-internal.h"
|
||||
#include "libkmod-index.h"
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include <linux/module.h>
|
||||
#endif
|
||||
|
||||
#include <shared/util.h>
|
||||
|
||||
#include "libkmod.h"
|
||||
#include "libkmod-internal.h"
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <shared/missing.h>
|
||||
#include <shared/util.h>
|
||||
|
||||
#include "libkmod-internal.h"
|
||||
|
||||
|
@ -20,88 +20,29 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <shared/util.h>
|
||||
|
||||
#include "libkmod.h"
|
||||
#include "libkmod-internal.h"
|
||||
|
||||
/*
|
||||
* Read one logical line from a configuration file.
|
||||
*
|
||||
* Line endings may be escaped with backslashes, to form one logical line from
|
||||
* several physical lines. No end of line character(s) are included in the
|
||||
* result.
|
||||
*
|
||||
* If linenum is not NULL, it is incremented by the number of physical lines
|
||||
* which have been read.
|
||||
*/
|
||||
char *getline_wrapped(FILE *fp, unsigned int *linenum)
|
||||
{
|
||||
int size = 256;
|
||||
int i = 0, n = 0;
|
||||
_cleanup_free_ char *buf = malloc(size);
|
||||
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
for(;;) {
|
||||
int ch = getc_unlocked(fp);
|
||||
|
||||
switch(ch) {
|
||||
case EOF:
|
||||
if (i == 0)
|
||||
return NULL;
|
||||
/* else fall through */
|
||||
|
||||
case '\n':
|
||||
n++;
|
||||
|
||||
{
|
||||
char *ret;
|
||||
if (i == size) {
|
||||
ret = realloc(buf, size + 1);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
} else
|
||||
ret = buf;
|
||||
ret[i] = '\0';
|
||||
buf = NULL;
|
||||
if (linenum)
|
||||
*linenum += n;
|
||||
return ret;
|
||||
}
|
||||
|
||||
case '\\':
|
||||
ch = getc_unlocked(fp);
|
||||
|
||||
if (ch == '\n') {
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
/* else fall through */
|
||||
|
||||
default:
|
||||
buf[i++] = ch;
|
||||
|
||||
if (i == size) {
|
||||
char *tmp;
|
||||
size *= 2;
|
||||
tmp = realloc(buf, size);
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
buf = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const struct kmod_ext kmod_exts[] = {
|
||||
{".ko", sizeof(".ko") - 1},
|
||||
#ifdef ENABLE_ZLIB
|
||||
{".ko.gz", sizeof(".ko.gz") - 1},
|
||||
#endif
|
||||
#ifdef ENABLE_XZ
|
||||
{".ko.xz", sizeof(".ko.xz") - 1},
|
||||
#endif
|
||||
{ }
|
||||
};
|
||||
|
||||
inline int alias_normalize(const char *alias, char buf[PATH_MAX], size_t *len)
|
||||
{
|
||||
@ -176,232 +117,6 @@ char *path_to_modname(const char *path, char buf[PATH_MAX], size_t *len)
|
||||
return modname_normalize(modname, buf, len);
|
||||
}
|
||||
|
||||
inline void *memdup(const void *p, size_t n)
|
||||
{
|
||||
void *r = malloc(n);
|
||||
|
||||
if (r == NULL)
|
||||
return NULL;
|
||||
|
||||
return memcpy(r, p, n);
|
||||
}
|
||||
|
||||
ssize_t read_str_safe(int fd, char *buf, size_t buflen)
|
||||
{
|
||||
size_t todo = buflen - 1;
|
||||
size_t done = 0;
|
||||
|
||||
do {
|
||||
ssize_t r = read(fd, buf + done, todo);
|
||||
|
||||
if (r == 0)
|
||||
break;
|
||||
else if (r > 0) {
|
||||
todo -= r;
|
||||
done += r;
|
||||
} else {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK ||
|
||||
errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
return -errno;
|
||||
}
|
||||
} while (todo > 0);
|
||||
|
||||
buf[done] = '\0';
|
||||
return done;
|
||||
}
|
||||
|
||||
ssize_t write_str_safe(int fd, const char *buf, size_t buflen)
|
||||
{
|
||||
size_t todo = buflen;
|
||||
size_t done = 0;
|
||||
|
||||
do {
|
||||
ssize_t r = write(fd, buf + done, todo);
|
||||
|
||||
if (r == 0)
|
||||
break;
|
||||
else if (r > 0) {
|
||||
todo -= r;
|
||||
done += r;
|
||||
} else {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK ||
|
||||
errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
return -errno;
|
||||
}
|
||||
} while (todo > 0);
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
int read_str_long(int fd, long *value, int base)
|
||||
{
|
||||
char buf[32], *end;
|
||||
long v;
|
||||
int err;
|
||||
|
||||
*value = 0;
|
||||
err = read_str_safe(fd, buf, sizeof(buf));
|
||||
if (err < 0)
|
||||
return err;
|
||||
errno = 0;
|
||||
v = strtol(buf, &end, base);
|
||||
if (end == buf || !isspace(*end))
|
||||
return -EINVAL;
|
||||
|
||||
*value = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_str_ulong(int fd, unsigned long *value, int base)
|
||||
{
|
||||
char buf[32], *end;
|
||||
long v;
|
||||
int err;
|
||||
|
||||
*value = 0;
|
||||
err = read_str_safe(fd, buf, sizeof(buf));
|
||||
if (err < 0)
|
||||
return err;
|
||||
errno = 0;
|
||||
v = strtoul(buf, &end, base);
|
||||
if (end == buf || !isspace(*end))
|
||||
return -EINVAL;
|
||||
*value = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *strchr_replace(char *s, int c, char r)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = s; *p != '\0'; p++)
|
||||
if (*p == c)
|
||||
*p = r;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
bool path_is_absolute(const char *p)
|
||||
{
|
||||
assert(p != NULL);
|
||||
|
||||
return p[0] == '/';
|
||||
}
|
||||
|
||||
char *path_make_absolute_cwd(const char *p)
|
||||
{
|
||||
_cleanup_free_ char *cwd = NULL;
|
||||
size_t plen, cwdlen;
|
||||
char *r;
|
||||
|
||||
if (path_is_absolute(p))
|
||||
return strdup(p);
|
||||
|
||||
cwd = get_current_dir_name();
|
||||
if (!cwd)
|
||||
return NULL;
|
||||
|
||||
plen = strlen(p);
|
||||
cwdlen = strlen(cwd);
|
||||
|
||||
/* cwd + '/' + p + '\0' */
|
||||
r = realloc(cwd, cwdlen + 1 + plen + 1);
|
||||
if (r == NULL)
|
||||
return NULL;
|
||||
|
||||
cwd = NULL;
|
||||
r[cwdlen] = '/';
|
||||
memcpy(&r[cwdlen + 1], p, plen + 1);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int is_dir(const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(path, &st) >= 0)
|
||||
return S_ISDIR(st.st_mode);
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
int mkdir_p(const char *path, int len, mode_t mode)
|
||||
{
|
||||
char *start, *end;
|
||||
|
||||
start = strndupa(path, len);
|
||||
end = start + len;
|
||||
|
||||
/*
|
||||
* scan backwards, replacing '/' with '\0' while the component doesn't
|
||||
* exist
|
||||
*/
|
||||
for (;;) {
|
||||
int r = is_dir(start);
|
||||
if (r > 0) {
|
||||
end += strlen(end);
|
||||
|
||||
if (end == start + len)
|
||||
return 0;
|
||||
|
||||
/* end != start, since it would be caught on the first
|
||||
* iteration */
|
||||
*end = '/';
|
||||
break;
|
||||
} else if (r == 0)
|
||||
return -ENOTDIR;
|
||||
|
||||
if (end == start)
|
||||
break;
|
||||
|
||||
*end = '\0';
|
||||
|
||||
/* Find the next component, backwards, discarding extra '/'*/
|
||||
while (end > start && *end != '/')
|
||||
end--;
|
||||
|
||||
while (end > start && *(end - 1) == '/')
|
||||
end--;
|
||||
}
|
||||
|
||||
for (; end < start + len;) {
|
||||
if (mkdir(start, mode) < 0 && errno != EEXIST)
|
||||
return -errno;
|
||||
|
||||
end += strlen(end);
|
||||
*end = '/';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mkdir_parents(const char *path, mode_t mode)
|
||||
{
|
||||
char *end = strrchr(path, '/');
|
||||
|
||||
/* no parent directories */
|
||||
if (end == NULL)
|
||||
return 0;
|
||||
|
||||
return mkdir_p(path, end - path, mode);
|
||||
}
|
||||
|
||||
const struct kmod_ext kmod_exts[] = {
|
||||
{".ko", sizeof(".ko") - 1},
|
||||
#ifdef ENABLE_ZLIB
|
||||
{".ko.gz", sizeof(".ko.gz") - 1},
|
||||
#endif
|
||||
#ifdef ENABLE_XZ
|
||||
{".ko.xz", sizeof(".ko.xz") - 1},
|
||||
#endif
|
||||
{ }
|
||||
};
|
||||
|
||||
bool path_ends_with_kmod_ext(const char *path, size_t len)
|
||||
{
|
||||
const struct kmod_ext *eitr;
|
||||
@ -415,20 +130,3 @@ bool path_ends_with_kmod_ext(const char *path, size_t len)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define USEC_PER_SEC 1000000ULL
|
||||
#define NSEC_PER_USEC 1000ULL
|
||||
unsigned long long ts_usec(const struct timespec *ts)
|
||||
{
|
||||
return (unsigned long long) ts->tv_sec * USEC_PER_SEC +
|
||||
(unsigned long long) ts->tv_nsec / NSEC_PER_USEC;
|
||||
}
|
||||
|
||||
unsigned long long stat_mstamp(const struct stat *st)
|
||||
{
|
||||
#ifdef HAVE_STRUCT_STAT_ST_MTIM
|
||||
return ts_usec(&st->st_mtim);
|
||||
#else
|
||||
return (unsigned long long) st->st_mtime;
|
||||
#endif
|
||||
}
|
||||
|
@ -2,64 +2,18 @@
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <shared/macro.h>
|
||||
|
||||
char *getline_wrapped(FILE *fp, unsigned int *linenum) __attribute__((nonnull(1)));
|
||||
#define streq(a, b) (strcmp((a), (b)) == 0)
|
||||
#define strstartswith(a, b) (strncmp(a, b, strlen(b)) == 0)
|
||||
void *memdup(const void *p, size_t n) __attribute__((nonnull(1)));
|
||||
|
||||
ssize_t read_str_safe(int fd, char *buf, size_t buflen) _must_check_ __attribute__((nonnull(2)));
|
||||
ssize_t write_str_safe(int fd, const char *buf, size_t buflen) __attribute__((nonnull(2)));
|
||||
int read_str_long(int fd, long *value, int base) _must_check_ __attribute__((nonnull(2)));
|
||||
int read_str_ulong(int fd, unsigned long *value, int base) _must_check_ __attribute__((nonnull(2)));
|
||||
char *strchr_replace(char *s, int c, char r);
|
||||
bool path_is_absolute(const char *p) _must_check_ __attribute__((nonnull(1)));
|
||||
char *path_make_absolute_cwd(const char *p) _must_check_ __attribute__((nonnull(1)));
|
||||
int mkdir_p(const char *path, int len, mode_t mode);
|
||||
int mkdir_parents(const char *path, mode_t mode);
|
||||
int alias_normalize(const char *alias, char buf[PATH_MAX], size_t *len) _must_check_ __attribute__((nonnull(1,2)));
|
||||
char *modname_normalize(const char *modname, char buf[PATH_MAX], size_t *len) __attribute__((nonnull(1, 2)));
|
||||
char *path_to_modname(const char *path, char buf[PATH_MAX], size_t *len) __attribute__((nonnull(2)));
|
||||
#define KMOD_EXT_UNC 0
|
||||
|
||||
extern const struct kmod_ext {
|
||||
const char *ext;
|
||||
size_t len;
|
||||
} kmod_exts[];
|
||||
#define KMOD_EXT_UNC 0
|
||||
|
||||
int alias_normalize(const char *alias, char buf[PATH_MAX], size_t *len) _must_check_ __attribute__((nonnull(1,2)));
|
||||
char *modname_normalize(const char *modname, char buf[PATH_MAX], size_t *len) __attribute__((nonnull(1, 2)));
|
||||
char *path_to_modname(const char *path, char buf[PATH_MAX], size_t *len) __attribute__((nonnull(2)));
|
||||
bool path_ends_with_kmod_ext(const char *path, size_t len) __attribute__((nonnull(1)));
|
||||
|
||||
unsigned long long stat_mstamp(const struct stat *st);
|
||||
unsigned long long ts_usec(const struct timespec *ts);
|
||||
|
||||
#define get_unaligned(ptr) \
|
||||
({ \
|
||||
struct __attribute__((packed)) { \
|
||||
typeof(*(ptr)) __v; \
|
||||
} *__p = (typeof(__p)) (ptr); \
|
||||
__p->__v; \
|
||||
})
|
||||
|
||||
#define put_unaligned(val, ptr) \
|
||||
do { \
|
||||
struct __attribute__((packed)) { \
|
||||
typeof(*(ptr)) __v; \
|
||||
} *__p = (typeof(__p)) (ptr); \
|
||||
__p->__v = (val); \
|
||||
} while(0)
|
||||
|
||||
static _always_inline_ unsigned int ALIGN_POWER2(unsigned int u)
|
||||
{
|
||||
return 1 << ((sizeof(u) * 8) - __builtin_clz(u - 1));
|
||||
}
|
||||
|
||||
static inline void freep(void *p) {
|
||||
free(*(void**) p);
|
||||
}
|
||||
|
||||
#define _cleanup_free_ _cleanup_(freep)
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <shared/util.h>
|
||||
|
||||
#include "libkmod.h"
|
||||
#include "libkmod-internal.h"
|
||||
#include "libkmod-index.h"
|
||||
|
5
shared/.gitignore
vendored
Normal file
5
shared/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.dirstamp
|
||||
.deps/
|
||||
.libs/
|
||||
*.la
|
||||
*.lo
|
345
shared/util.c
Normal file
345
shared/util.c
Normal file
@ -0,0 +1,345 @@
|
||||
/*
|
||||
* kmod - interface to kernel module operations
|
||||
*
|
||||
* Copyright (C) 2011-2013 ProFUSION embedded systems
|
||||
* Copyright (C) 2012 Lucas De Marchi <lucas.de.marchi@gmail.com>
|
||||
* Copyright (C) 2013-2014 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <shared/util.h>
|
||||
|
||||
#define USEC_PER_SEC 1000000ULL
|
||||
#define NSEC_PER_USEC 1000ULL
|
||||
|
||||
/* string handling functions and memory allocations */
|
||||
/* ************************************************************************ */
|
||||
|
||||
void *memdup(const void *p, size_t n)
|
||||
{
|
||||
void *r = malloc(n);
|
||||
|
||||
if (r == NULL)
|
||||
return NULL;
|
||||
|
||||
return memcpy(r, p, n);
|
||||
}
|
||||
|
||||
char *strchr_replace(char *s, int c, char r)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = s; *p != '\0'; p++) {
|
||||
if (*p == c)
|
||||
*p = r;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* read-like and fread-like functions */
|
||||
/* ************************************************************************ */
|
||||
ssize_t read_str_safe(int fd, char *buf, size_t buflen)
|
||||
{
|
||||
size_t todo = buflen - 1;
|
||||
size_t done = 0;
|
||||
|
||||
do {
|
||||
ssize_t r = read(fd, buf + done, todo);
|
||||
|
||||
if (r == 0)
|
||||
break;
|
||||
else if (r > 0) {
|
||||
todo -= r;
|
||||
done += r;
|
||||
} else {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK ||
|
||||
errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
return -errno;
|
||||
}
|
||||
} while (todo > 0);
|
||||
|
||||
buf[done] = '\0';
|
||||
return done;
|
||||
}
|
||||
|
||||
ssize_t write_str_safe(int fd, const char *buf, size_t buflen)
|
||||
{
|
||||
size_t todo = buflen;
|
||||
size_t done = 0;
|
||||
|
||||
do {
|
||||
ssize_t r = write(fd, buf + done, todo);
|
||||
|
||||
if (r == 0)
|
||||
break;
|
||||
else if (r > 0) {
|
||||
todo -= r;
|
||||
done += r;
|
||||
} else {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK ||
|
||||
errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
return -errno;
|
||||
}
|
||||
} while (todo > 0);
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
int read_str_long(int fd, long *value, int base)
|
||||
{
|
||||
char buf[32], *end;
|
||||
long v;
|
||||
int err;
|
||||
|
||||
*value = 0;
|
||||
err = read_str_safe(fd, buf, sizeof(buf));
|
||||
if (err < 0)
|
||||
return err;
|
||||
errno = 0;
|
||||
v = strtol(buf, &end, base);
|
||||
if (end == buf || !isspace(*end))
|
||||
return -EINVAL;
|
||||
|
||||
*value = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_str_ulong(int fd, unsigned long *value, int base)
|
||||
{
|
||||
char buf[32], *end;
|
||||
long v;
|
||||
int err;
|
||||
|
||||
*value = 0;
|
||||
err = read_str_safe(fd, buf, sizeof(buf));
|
||||
if (err < 0)
|
||||
return err;
|
||||
errno = 0;
|
||||
v = strtoul(buf, &end, base);
|
||||
if (end == buf || !isspace(*end))
|
||||
return -EINVAL;
|
||||
*value = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read one logical line from a configuration file.
|
||||
*
|
||||
* Line endings may be escaped with backslashes, to form one logical line from
|
||||
* several physical lines. No end of line character(s) are included in the
|
||||
* result.
|
||||
*
|
||||
* If linenum is not NULL, it is incremented by the number of physical lines
|
||||
* which have been read.
|
||||
*/
|
||||
char *getline_wrapped(FILE *fp, unsigned int *linenum)
|
||||
{
|
||||
int size = 256;
|
||||
int i = 0, n = 0;
|
||||
_cleanup_free_ char *buf = malloc(size);
|
||||
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
for(;;) {
|
||||
int ch = getc_unlocked(fp);
|
||||
|
||||
switch(ch) {
|
||||
case EOF:
|
||||
if (i == 0)
|
||||
return NULL;
|
||||
/* else fall through */
|
||||
|
||||
case '\n':
|
||||
n++;
|
||||
|
||||
{
|
||||
char *ret;
|
||||
if (i == size) {
|
||||
ret = realloc(buf, size + 1);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
} else
|
||||
ret = buf;
|
||||
ret[i] = '\0';
|
||||
buf = NULL;
|
||||
if (linenum)
|
||||
*linenum += n;
|
||||
return ret;
|
||||
}
|
||||
|
||||
case '\\':
|
||||
ch = getc_unlocked(fp);
|
||||
|
||||
if (ch == '\n') {
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
/* else fall through */
|
||||
|
||||
default:
|
||||
buf[i++] = ch;
|
||||
|
||||
if (i == size) {
|
||||
char *tmp;
|
||||
size *= 2;
|
||||
tmp = realloc(buf, size);
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
buf = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* path handling functions */
|
||||
/* ************************************************************************ */
|
||||
|
||||
bool path_is_absolute(const char *p)
|
||||
{
|
||||
assert(p != NULL);
|
||||
|
||||
return p[0] == '/';
|
||||
}
|
||||
|
||||
char *path_make_absolute_cwd(const char *p)
|
||||
{
|
||||
_cleanup_free_ char *cwd = NULL;
|
||||
size_t plen, cwdlen;
|
||||
char *r;
|
||||
|
||||
if (path_is_absolute(p))
|
||||
return strdup(p);
|
||||
|
||||
cwd = get_current_dir_name();
|
||||
if (!cwd)
|
||||
return NULL;
|
||||
|
||||
plen = strlen(p);
|
||||
cwdlen = strlen(cwd);
|
||||
|
||||
/* cwd + '/' + p + '\0' */
|
||||
r = realloc(cwd, cwdlen + 1 + plen + 1);
|
||||
if (r == NULL)
|
||||
return NULL;
|
||||
|
||||
cwd = NULL;
|
||||
r[cwdlen] = '/';
|
||||
memcpy(&r[cwdlen + 1], p, plen + 1);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int is_dir(const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(path, &st) >= 0)
|
||||
return S_ISDIR(st.st_mode);
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
int mkdir_p(const char *path, int len, mode_t mode)
|
||||
{
|
||||
char *start, *end;
|
||||
|
||||
start = strndupa(path, len);
|
||||
end = start + len;
|
||||
|
||||
/*
|
||||
* scan backwards, replacing '/' with '\0' while the component doesn't
|
||||
* exist
|
||||
*/
|
||||
for (;;) {
|
||||
int r = is_dir(start);
|
||||
if (r > 0) {
|
||||
end += strlen(end);
|
||||
|
||||
if (end == start + len)
|
||||
return 0;
|
||||
|
||||
/* end != start, since it would be caught on the first
|
||||
* iteration */
|
||||
*end = '/';
|
||||
break;
|
||||
} else if (r == 0)
|
||||
return -ENOTDIR;
|
||||
|
||||
if (end == start)
|
||||
break;
|
||||
|
||||
*end = '\0';
|
||||
|
||||
/* Find the next component, backwards, discarding extra '/'*/
|
||||
while (end > start && *end != '/')
|
||||
end--;
|
||||
|
||||
while (end > start && *(end - 1) == '/')
|
||||
end--;
|
||||
}
|
||||
|
||||
for (; end < start + len;) {
|
||||
if (mkdir(start, mode) < 0 && errno != EEXIST)
|
||||
return -errno;
|
||||
|
||||
end += strlen(end);
|
||||
*end = '/';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mkdir_parents(const char *path, mode_t mode)
|
||||
{
|
||||
char *end = strrchr(path, '/');
|
||||
|
||||
/* no parent directories */
|
||||
if (end == NULL)
|
||||
return 0;
|
||||
|
||||
return mkdir_p(path, end - path, mode);
|
||||
}
|
||||
|
||||
unsigned long long ts_usec(const struct timespec *ts)
|
||||
{
|
||||
return (unsigned long long) ts->tv_sec * USEC_PER_SEC +
|
||||
(unsigned long long) ts->tv_nsec / NSEC_PER_USEC;
|
||||
}
|
||||
|
||||
unsigned long long stat_mstamp(const struct stat *st)
|
||||
{
|
||||
#ifdef HAVE_STRUCT_STAT_ST_MTIM
|
||||
return ts_usec(&st->st_mtim);
|
||||
#else
|
||||
return (unsigned long long) st->st_mtime;
|
||||
#endif
|
||||
}
|
64
shared/util.h
Normal file
64
shared/util.h
Normal file
@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <shared/macro.h>
|
||||
|
||||
/* string handling functions and memory allocations */
|
||||
/* ************************************************************************ */
|
||||
#define streq(a, b) (strcmp((a), (b)) == 0)
|
||||
#define strstartswith(a, b) (strncmp(a, b, strlen(b)) == 0)
|
||||
char *strchr_replace(char *s, int c, char r);
|
||||
void *memdup(const void *p, size_t n) __attribute__((nonnull(1)));
|
||||
|
||||
/* read-like and fread-like functions */
|
||||
/* ************************************************************************ */
|
||||
ssize_t read_str_safe(int fd, char *buf, size_t buflen) _must_check_ __attribute__((nonnull(2)));
|
||||
ssize_t write_str_safe(int fd, const char *buf, size_t buflen) __attribute__((nonnull(2)));
|
||||
int read_str_long(int fd, long *value, int base) _must_check_ __attribute__((nonnull(2)));
|
||||
int read_str_ulong(int fd, unsigned long *value, int base) _must_check_ __attribute__((nonnull(2)));
|
||||
char *getline_wrapped(FILE *fp, unsigned int *linenum) __attribute__((nonnull(1)));
|
||||
|
||||
/* path handling functions */
|
||||
/* ************************************************************************ */
|
||||
bool path_is_absolute(const char *p) _must_check_ __attribute__((nonnull(1)));
|
||||
char *path_make_absolute_cwd(const char *p) _must_check_ __attribute__((nonnull(1)));
|
||||
int mkdir_p(const char *path, int len, mode_t mode);
|
||||
int mkdir_parents(const char *path, mode_t mode);
|
||||
unsigned long long stat_mstamp(const struct stat *st);
|
||||
unsigned long long ts_usec(const struct timespec *ts);
|
||||
|
||||
/* endianess and alignments */
|
||||
/* ************************************************************************ */
|
||||
#define get_unaligned(ptr) \
|
||||
({ \
|
||||
struct __attribute__((packed)) { \
|
||||
typeof(*(ptr)) __v; \
|
||||
} *__p = (typeof(__p)) (ptr); \
|
||||
__p->__v; \
|
||||
})
|
||||
|
||||
#define put_unaligned(val, ptr) \
|
||||
do { \
|
||||
struct __attribute__((packed)) { \
|
||||
typeof(*(ptr)) __v; \
|
||||
} *__p = (typeof(__p)) (ptr); \
|
||||
__p->__v = (val); \
|
||||
} while(0)
|
||||
|
||||
static _always_inline_ unsigned int ALIGN_POWER2(unsigned int u)
|
||||
{
|
||||
return 1 << ((sizeof(u) * 8) - __builtin_clz(u - 1));
|
||||
}
|
||||
|
||||
/* misc */
|
||||
/* ************************************************************************ */
|
||||
static inline void freep(void *p) {
|
||||
free(*(void**) p);
|
||||
}
|
||||
#define _cleanup_free_ _cleanup_(freep)
|
@ -40,6 +40,8 @@
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <shared/util.h>
|
||||
|
||||
/* kmod_elf_get_section() is not exported, we need the private header */
|
||||
#include <libkmod-internal.h>
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <string.h>
|
||||
#include <libkmod.h>
|
||||
|
||||
#include <shared/util.h>
|
||||
|
||||
#include "libkmod-util.h"
|
||||
#include "testsuite.h"
|
||||
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <shared/util.h>
|
||||
|
||||
#include "libkmod-util.h"
|
||||
#include "testsuite.h"
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "libkmod-util.h"
|
||||
|
||||
#include <shared/macro.h>
|
||||
#include <shared/util.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -30,7 +30,8 @@
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include "libkmod-util.h"
|
||||
|
||||
#include <shared/util.h>
|
||||
|
||||
#include "kmod.h"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user