dracut-install: make use of _cleanup_* macros

master
Harald Hoyer 2013-04-29 11:35:23 +02:00
parent 26a077fc7e
commit 3ed08d1e4d
3 changed files with 282 additions and 136 deletions

View File

@ -62,6 +62,10 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
static size_t dir_len(char const *file)
{
size_t length;

if(!file)
return 0;

/* Strip the basename and any redundant slashes before it. */
for (length = strlen(file)-1; 0 < length; length--)
if (file[length] == '/' && file[length-1] != '/')
@ -73,20 +77,22 @@ static char *convert_abs_rel(const char *from, const char *target)
{
/* we use the 4*MAXPATHLEN, which should not overrun */
char relative_from[MAXPATHLEN * 4];
char *realtarget = NULL;
char *p, *q;
_cleanup_free_ char *realtarget = NULL;
_cleanup_free_ char *target_dir_p = NULL, *realpath_p = NULL;
const char *realfrom = from;
int level = 0, fromlevel = 0, targetlevel = 0;
int l, i, rl;
int dirlen;

p = strdup(target);
dirlen = dir_len(p);
p[dirlen] = '\0';
q = realpath(p, NULL);
target_dir_p = strdup(target);
if (!target_dir_p)
return strdup(from);

if (q == NULL) {
free(p);
dirlen = dir_len(target_dir_p);
target_dir_p[dirlen] = '\0';
realpath_p = realpath(target_dir_p, NULL);

if (realpath_p == NULL) {
log_warning("convert_abs_rel(): target '%s' directory has no realpath.", target);
return strdup(from);
}
@ -95,11 +101,9 @@ static char *convert_abs_rel(const char *from, const char *target)
* character - need to skip all leading /'s */
rl = strlen(target);
for (i = dirlen+1; i < rl; ++i)
if (p[i] != '/')
if (target_dir_p[i] != '/')
break;
asprintf(&realtarget, "%s/%s", q, &p[i]);
free(p);
free(q);
asprintf(&realtarget, "%s/%s", realpath_p, &target_dir_p[i]);

/* now calculate the relative path from <from> to <target> and
store it in <relative_from>
@ -122,8 +126,6 @@ static char *convert_abs_rel(const char *from, const char *target)
if (realtarget[i] == '/')
level++;

free(realtarget);

/* add "../" to the relative_from path, until the common pathname is
reached */
for (i = level; i < targetlevel; i++) {
@ -155,18 +157,16 @@ static char *convert_abs_rel(const char *from, const char *target)
static int ln_r(const char *src, const char *dst)
{
int ret;
const char *points_to = convert_abs_rel(src, dst);
_cleanup_free_ const char *points_to = convert_abs_rel(src, dst);

log_info("ln -s '%s' '%s'", points_to, dst);
ret = symlink(points_to, dst);

if (ret != 0) {
log_error("ERROR: ln -s '%s' '%s': %m", points_to, dst);
free((char *)points_to);
return 1;
}

free((char *)points_to);

return 0;
}

@ -186,11 +186,11 @@ static bool use_clone = true;
static int cp(const char *src, const char *dst)
{
int pid;
int ret;
int ret = 0;

if (use_clone) {
struct stat sb;
int dest_desc, source_desc;
_cleanup_close_ int dest_desc = -1, source_desc = -1;

if (lstat(src, &sb) != 0)
goto normal_copy;
@ -207,12 +207,11 @@ static int cp(const char *src, const char *dst)
(sb.st_mode) & (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO));

if (dest_desc < 0) {
close(source_desc);
goto normal_copy;
}

ret = clone_file(dest_desc, source_desc);
close(source_desc);

if (ret == 0) {
struct timeval tv[2];
if (fchown(dest_desc, sb.st_uid, sb.st_gid) != 0)
@ -222,11 +221,10 @@ static int cp(const char *src, const char *dst)
tv[1].tv_sec = sb.st_mtime;
tv[1].tv_usec = 0;
futimes(dest_desc, tv);
close(dest_desc);
return ret;
}
close(dest_desc);

dest_desc = -1;
/* clone did not work, remove the file */
unlink(dst);
/* do not try clone again */
@ -243,10 +241,11 @@ static int cp(const char *src, const char *dst)
while (waitpid(pid, &ret, 0) < 0) {
if (errno != EINTR) {
ret = -1;
log_error("Failed: cp --reflink=auto --sparse=auto --preserve=mode,timestamps -fL %s %s", src, dst);
break;
}
}

log_debug("cp ret = %d", ret);
return ret;
}

@ -256,15 +255,17 @@ static int resolve_deps(const char *src)

char *buf = malloc(LINE_MAX);
size_t linesize = LINE_MAX;
FILE *fptr;
char *cmd;
_cleanup_pclose_ FILE *fptr = NULL;
_cleanup_free_ char *cmd = NULL;

if (strstr(src, ".so") == 0) {
int fd;
_cleanup_close_ int fd = -1;
fd = open(src, O_RDONLY | O_CLOEXEC);
if (fd < 0)
return -errno;

read(fd, buf, LINE_MAX);
buf[LINE_MAX - 1] = '\0';
close(fd);
if (buf[0] == '#' && buf[1] == '!') {
/* we have a shebang */
char *p, *q;
@ -280,7 +281,11 @@ static int resolve_deps(const char *src)
}

/* run ldd */
asprintf(&cmd, "ldd %s 2>&1", src);
ret = asprintf(&cmd, "ldd %s 2>&1", src);
if (ret < 0)
return ret;
ret = 0;

fptr = popen(cmd, "r");

while (!feof(fptr)) {
@ -336,7 +341,6 @@ static int resolve_deps(const char *src)
}
}
}
pclose(fptr);

return ret;
}
@ -344,10 +348,14 @@ static int resolve_deps(const char *src)
/* Install ".<filename>.hmac" file for FIPS self-checks */
static int hmac_install(const char *src, const char *dst, const char *hmacpath)
{
char *srcpath = strdup(src);
char *dstpath = strdup(dst);
char *srchmacname = NULL;
char *dsthmacname = NULL;
_cleanup_free_ char *srcpath = strdup(src);
_cleanup_free_ char *dstpath = strdup(dst);
_cleanup_free_ char *srchmacname = NULL;
_cleanup_free_ char *dsthmacname = NULL;

if (!(srcpath && dstpath))
return -ENOMEM;

size_t dlen = dir_len(src);

if (endswith(src, ".hmac"))
@ -371,22 +379,18 @@ static int hmac_install(const char *src, const char *dst, const char *hmacpath)
}
log_debug("hmac cp '%s' '%s')", srchmacname, dsthmacname);
dracut_install(srchmacname, dsthmacname, false, false, true);
free(dsthmacname);
free(srchmacname);
free(srcpath);
free(dstpath);
return 0;
}

static int dracut_install(const char *src, const char *dst, bool isdir, bool resolvedeps, bool hashdst)
{
struct stat sb, db;
char *dname = NULL;
char *fulldstpath = NULL;
char *fulldstdir = NULL;
_cleanup_free_ char *fulldstpath = NULL;
_cleanup_free_ char *fulldstdir = NULL;
int ret;
bool src_exists = true;
char *i, *existing;
char *i = NULL;
char *existing;

log_debug("dracut_install('%s', '%s')", src, dst);

@ -419,6 +423,9 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
}

i = strdup(dst);
if (!i)
return -ENOMEM;

hashmap_put(items, i, i);

asprintf(&fulldstpath, "%s%s", destrootdir, dst);
@ -437,7 +444,6 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
} else
log_debug("'%s' already exists", fulldstpath);

free(fulldstpath);
/* dst does already exist */
return ret;
}
@ -449,6 +455,8 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
ret = stat(fulldstdir, &db);

if (ret < 0) {
_cleanup_free_ char *dname = NULL;

if (errno != ENOENT) {
log_error("ERROR: stat '%s': %m", fulldstdir);
return 1;
@ -456,35 +464,34 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
/* create destination directory */
log_debug("dest dir '%s' does not exist", fulldstdir);
dname = strdup(dst);
if (!dname)
return 1;

dname[dir_len(dname)] = '\0';
ret = dracut_install(dname, dname, true, false, true);

free(dname);

if (ret != 0) {
log_error("ERROR: failed to create directory '%s'", fulldstdir);
free(fulldstdir);
return 1;
}
}

free(fulldstdir);

if (isdir && !src_exists) {
log_info("mkdir '%s'", fulldstpath);
return mkdir(fulldstpath, 0755);
ret = mkdir(fulldstpath, 0755);
return ret;
}

/* ready to install src */

if (S_ISDIR(sb.st_mode)) {
log_info("mkdir '%s'", fulldstpath);
return mkdir(fulldstpath, sb.st_mode | S_IWUSR);
ret = mkdir(fulldstpath, sb.st_mode | S_IWUSR);
return ret;
}

if (S_ISLNK(sb.st_mode)) {
char *abspath;
char *absdestpath = NULL;
_cleanup_free_ char *abspath = NULL;

abspath = realpath(src, NULL);

@ -502,15 +509,13 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
}

if (lstat(fulldstpath, &sb) != 0) {
_cleanup_free_ char *absdestpath = NULL;

asprintf(&absdestpath, "%s%s", destrootdir, abspath);

ln_r(absdestpath, fulldstpath);

free(absdestpath);
}

free(abspath);
if (arg_hmac) {
/* copy .hmac files also */
hmac_install(src, dst, NULL);
@ -528,8 +533,12 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
}
}

log_debug("dracut_install ret = %d", ret);
log_info("cp '%s' '%s'", src, fulldstpath);
ret += cp(src, fulldstpath);

log_debug("dracut_install ret = %d", ret);

return ret;
}

@ -540,49 +549,49 @@ static void item_free(char *i)
}

static void usage(int status)
{
/* */
printf("\
Usage: %s -D DESTROOTDIR [OPTION]... -a SOURCE...\n\
or: %s -D DESTROOTDIR [OPTION]... SOURCE DEST\n\
\n\
Install SOURCE to DEST in DESTROOTDIR with all needed dependencies.\n\
\n\
-D --destrootdir Install all files to DESTROOTDIR as the root\n\
-a --all Install all SOURCE arguments to DESTROOTDIR\n\
-o --optional If SOURCE does not exist, do not fail\n\
-d --dir SOURCE is a directory\n\
-l --ldd Also install shebang executables and libraries\n\
-R --resolvelazy Only install shebang executables and libraries for all SOURCE files\n\
-H --fips Also install all '.SOURCE.hmac' files\n\
-v --verbose Show more output\n\
--debug Show debug output\n\
--version Show package version\n\
-h --help Show this help\n\
\n\
Example:\n\
# mkdir -p /var/tmp/test-root\n\
# %s -D /var/tmp/test-root --ldd -a sh tr\n\
# tree /var/tmp/test-root\n\
/var/tmp/test-root\n\
|-- lib64 -> usr/lib64\n\
`-- usr\n\
|-- bin\n\
| |-- bash\n\
| |-- sh -> bash\n\
| `-- tr\n\
`-- lib64\n\
|-- ld-2.15.90.so\n\
|-- ld-linux-x86-64.so.2 -> ld-2.15.90.so\n\
|-- libc-2.15.90.so\n\
|-- libc.so\n\
|-- libc.so.6 -> libc-2.15.90.so\n\
|-- libdl-2.15.90.so\n\
|-- libdl.so -> libdl-2.15.90.so\n\
|-- libdl.so.2 -> libdl-2.15.90.so\n\
|-- libtinfo.so.5 -> libtinfo.so.5.9\n\
`-- libtinfo.so.5.9\n\
", program_invocation_short_name, program_invocation_short_name, program_invocation_short_name);
{
/* */
printf("Usage: %s -D DESTROOTDIR [OPTION]... -a SOURCE...\n"
"or: %s -D DESTROOTDIR [OPTION]... SOURCE DEST\n"
"\n"
"Install SOURCE to DEST in DESTROOTDIR with all needed dependencies.\n"
"\n"
" -D --destrootdir Install all files to DESTROOTDIR as the root\n"
" -a --all Install all SOURCE arguments to DESTROOTDIR\n"
" -o --optional If SOURCE does not exist, do not fail\n"
" -d --dir SOURCE is a directory\n"
" -l --ldd Also install shebang executables and libraries\n"
" -R --resolvelazy Only install shebang executables and libraries\n"
" for all SOURCE files\n"
" -H --fips Also install all '.SOURCE.hmac' files\n"
" -v --verbose Show more output\n"
" --debug Show debug output\n"
" --version Show package version\n"
" -h --help Show this help\n"
"\n"
"Example:\n"
"# mkdir -p /var/tmp/test-root\n"
"# %s -D /var/tmp/test-root --ldd -a sh tr\n"
"# tree /var/tmp/test-root\n"
"/var/tmp/test-root\n"
"|-- lib64 -> usr/lib64\n"
"`-- usr\n"
" |-- bin\n"
" | |-- bash\n"
" | |-- sh -> bash\n"
" | `-- tr\n"
" `-- lib64\n"
" |-- ld-2.15.90.so\n"
" |-- ld-linux-x86-64.so.2 -> ld-2.15.90.so\n"
" |-- libc-2.15.90.so\n"
" |-- libc.so\n"
" |-- libc.so.6 -> libc-2.15.90.so\n"
" |-- libdl-2.15.90.so\n"
" |-- libdl.so -> libdl-2.15.90.so\n"
" |-- libdl.so.2 -> libdl-2.15.90.so\n"
" |-- libtinfo.so.5 -> libtinfo.so.5.9\n"
" `-- libtinfo.so.5.9\n"
, program_invocation_short_name, program_invocation_short_name, program_invocation_short_name);
exit(status);
}

@ -595,7 +604,7 @@ static int parse_argv(int argc, char *argv[])
ARG_DEBUG
};

static const struct option const options[] = {
static struct option const options[] = {
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, ARG_VERSION},
{"dir", no_argument, NULL, 'd'},
@ -691,7 +700,7 @@ static int resolve_lazy(int argc, char **argv)

static char *find_binary(const char *src)
{
char *path;
_cleanup_free_ char *path = NULL;
char *p, *q;
bool end = false;
char *newsrc = NULL;
@ -703,6 +712,12 @@ static char *find_binary(const char *src)
}
path = strdup(path);
p = path;

if (path == NULL) {
log_error("Out of memory!");
exit(EXIT_FAILURE);
}

log_debug("PATH=%s", path);

do {
@ -716,6 +731,11 @@ static char *find_binary(const char *src)
*q = '\0';

asprintf(&newsrc, "%s/%s", p, src);
if (newsrc == NULL) {
log_error("Out of memory!");
exit(EXIT_FAILURE);
}

p = q + 1;

if (stat(newsrc, &sb) != 0) {
@ -729,9 +749,9 @@ static char *find_binary(const char *src)

} while (!end);

free(path);
if (newsrc)
log_debug("find_binary(%s) == %s", src, newsrc);

return newsrc;
}

@ -773,22 +793,20 @@ static int install_all(int argc, char **argv)
log_debug("Handle '%s'", argv[i]);

if (strchr(argv[i], '/') == NULL) {
char *newsrc = find_binary(argv[i]);
_cleanup_free_ char *newsrc = find_binary(argv[i]);
if (newsrc) {
log_debug("dracut_install '%s'", newsrc);
ret = dracut_install(newsrc, newsrc, arg_createdir, arg_resolvedeps, true);
if (ret == 0) {
log_debug("dracut_install '%s' OK", newsrc);
}
free(newsrc);
} else {
ret = -1;
}

} else {
char *dest = strdup(argv[i]);
_cleanup_free_ char *dest = strdup(argv[i]);
ret = dracut_install(argv[i], dest, arg_createdir, arg_resolvedeps, true);
free(dest);
}

if ((ret != 0) && (!arg_optional)) {

View File

@ -1,7 +1,6 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/

#ifndef foomacrohfoo
#define foomacrohfoo
#pragma once

/***
This file is part of systemd.
@ -45,16 +44,38 @@
#define _hidden_ __attribute__ ((visibility("hidden")))
#define _weakref_(x) __attribute__((weakref(#x)))
#define _introspect_(x) __attribute__((section("introspect." x)))
#define _alignas_(x) __attribute__((aligned(__alignof(x))))
#define _cleanup_(x) __attribute__((cleanup(x)))

/* automake test harness */
#define EXIT_TEST_SKIP 77

#define XSTRINGIFY(x) #x
#define STRINGIFY(x) XSTRINGIFY(x)

/* Rounds up */
#define ALIGN(l) ALIGN_TO((l), sizeof(void*))

#define ALIGN4(l) (((l) + 3) & ~3)
#define ALIGN8(l) (((l) + 7) & ~7)

#if __SIZEOF_POINTER__ == 8
#define ALIGN(l) ALIGN8(l)
#elif __SIZEOF_POINTER__ == 4
#define ALIGN(l) ALIGN4(l)
#else
#error "Wut? Pointers are neither 4 nor 8 bytes long?"
#endif

#define ALIGN_PTR(p) ((void*) ALIGN((unsigned long) p))
#define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) p))
#define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) p))

static inline size_t ALIGN_TO(size_t l, size_t ali) {
return ((l + ali - 1) & ~(ali - 1));
}

#define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) p))

#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))

/*
@ -64,34 +85,35 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})

#ifndef MAX
#define MAX(a,b) \
__extension__ ({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
_a > _b ? _a : _b; \
#define container_of(ptr, type, member) \
__extension__ ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) ); \
})
#endif

#define MAX3(a,b,c) \
MAX(MAX(a,b),c)
#undef MAX
#define MAX(a,b) \
__extension__ ({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
_a > _b ? _a : _b; \
})

#ifndef MIN
#define MAX3(x,y,z) \
__extension__ ({ \
typeof(x) _c = MAX(x,y); \
MAX(_c, z); \
})

#undef MIN
#define MIN(a,b) \
__extension__ ({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
_a < _b ? _a : _b; \
})
#endif

#define MIN3(a,b,c) \
MIN(MIN(a,b),c)

#ifndef CLAMP
#define CLAMP(x, low, high) \
__extension__ ({ \
typeof(x) _x = (x); \
@ -99,6 +121,7 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
typeof(high) _high = (high); \
((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \
})
#endif

#define assert_se(expr) \
do { \
@ -119,14 +142,21 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
log_assert_failed_unreachable(t, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
} while (false)

#define assert_cc(expr) \
do { \
switch (0) { \
case 0: \
case !!(expr): \
; \
} \
#if defined(static_assert)
#define assert_cc(expr) \
do { \
static_assert(expr, #expr); \
} while (false)
#else
#define assert_cc(expr) \
do { \
switch (0) { \
case 0: \
case !!(expr): \
; \
} \
} while (false)
#endif

#define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
#define UINT_TO_PTR(u) ((void*) ((uintptr_t) (u)))
@ -149,6 +179,8 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
#define memzero(x,l) (memset((x), 0, (l)))
#define zero(x) (memzero(&(x), sizeof(x)))

#define CHAR_TO_STR(x) ((char[2]) { x, 0 })

#define char_array_0(x) x[sizeof(x)-1] = 0;

#define IOVEC_SET_STRING(i, s) \
@ -187,6 +219,66 @@ static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
return k;
}

#include "log.h"
#define VA_FORMAT_ADVANCE(format, ap) \
do { \
int _argtypes[128]; \
size_t _i, _k; \
_k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \
assert(_k < ELEMENTSOF(_argtypes)); \
for (_i = 0; _i < _k; _i++) { \
if (_argtypes[_i] & PA_FLAG_PTR) { \
(void) va_arg(ap, void*); \
continue; \
} \
\
switch (_argtypes[_i]) { \
case PA_INT: \
case PA_INT|PA_FLAG_SHORT: \
case PA_CHAR: \
(void) va_arg(ap, int); \
break; \
case PA_INT|PA_FLAG_LONG: \
(void) va_arg(ap, long int); \
break; \
case PA_INT|PA_FLAG_LONG_LONG: \
(void) va_arg(ap, long long int); \
break; \
case PA_WCHAR: \
(void) va_arg(ap, wchar_t); \
break; \
case PA_WSTRING: \
case PA_STRING: \
case PA_POINTER: \
(void) va_arg(ap, void*); \
break; \
case PA_FLOAT: \
case PA_DOUBLE: \
(void) va_arg(ap, double); \
break; \
case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: \
(void) va_arg(ap, long double); \
break; \
default: \
assert_not_reached("Unknown format string argument."); \
} \
} \
} while(false)

#endif
/* Because statfs.t_type can be int on some architecures, we have to cast
* the const magic to the type, otherwise the compiler warns about
* signed/unsigned comparison, because the magic can be 32 bit unsigned.
*/
#define F_TYPE_CMP(a, b) (a == (typeof(a)) b)


/* Returns the number of chars needed to format variables of the
* specified type as a decimal string. Adds in extra space for a
* negative '-' prefix. */

#define DECIMAL_STR_MAX(type) \
(1+(sizeof(type) <= 1 ? 3 : \
sizeof(type) <= 2 ? 5 : \
sizeof(type) <= 4 ? 10 : \
sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))

#include "log.h"

View File

@ -507,6 +507,42 @@ void* memdup(const void *p, size_t l);

int is_kernel_thread(pid_t pid);

static inline void freep(void *p) {
free(*(void**) p);
}

static inline void fclosep(FILE **f) {
if (*f)
fclose(*f);
}

static inline void pclosep(FILE **f) {
if (*f)
pclose(*f);
}

static inline void closep(int *fd) {
if (*fd >= 0)
close_nointr_nofail(*fd);
}

static inline void closedirp(DIR **d) {
if (*d)
closedir(*d);
}

static inline void umaskp(mode_t *u) {
umask(*u);
}

#define _cleanup_free_ _cleanup_(freep)
#define _cleanup_fclose_ _cleanup_(fclosep)
#define _cleanup_pclose_ _cleanup_(pclosep)
#define _cleanup_close_ _cleanup_(closep)
#define _cleanup_closedir_ _cleanup_(closedirp)
#define _cleanup_umask_ _cleanup_(umaskp)
#define _cleanup_globfree_ _cleanup_(globfree)

int fd_inc_sndbuf(int fd, size_t n);
int fd_inc_rcvbuf(int fd, size_t n);