Break out utils to separate file
This commit is contained in:
@@ -8,6 +8,8 @@ bin_PROGRAMS = build-root
|
|||||||
|
|
||||||
build_root_SOURCES = \
|
build_root_SOURCES = \
|
||||||
build-root.c \
|
build-root.c \
|
||||||
|
utils.h \
|
||||||
|
utils.c \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
build_root_CFLAGS = $(AM_CFLAGS)
|
build_root_CFLAGS = $(AM_CFLAGS)
|
||||||
|
334
build-root.c
334
build-root.c
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
@@ -18,53 +18,28 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <dirent.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <grp.h>
|
||||||
#include <linux/loop.h>
|
#include <linux/loop.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <poll.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/syscall.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/eventfd.h>
|
#include <sys/eventfd.h>
|
||||||
#include <sys/signalfd.h>
|
#include <sys/signalfd.h>
|
||||||
#include <sys/capability.h>
|
#include <sys/capability.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <grp.h>
|
|
||||||
|
|
||||||
#if 0
|
#include "utils.h"
|
||||||
#define __debug__(x) printf x
|
|
||||||
#else
|
|
||||||
#define __debug__(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
|
|
||||||
|
|
||||||
#define TRUE 1
|
|
||||||
#define FALSE 0
|
|
||||||
typedef int bool;
|
|
||||||
|
|
||||||
#define READ_END 0
|
|
||||||
#define WRITE_END 1
|
|
||||||
|
|
||||||
/* Globals to avoid having to use getuid(), since the uid/gid changes during runtime */
|
/* Globals to avoid having to use getuid(), since the uid/gid changes during runtime */
|
||||||
static uid_t uid;
|
static uid_t uid;
|
||||||
@@ -73,290 +48,6 @@ static bool is_privileged;
|
|||||||
static const char *argv0;
|
static const char *argv0;
|
||||||
static int proc_fd = -1;
|
static int proc_fd = -1;
|
||||||
|
|
||||||
static void
|
|
||||||
strfreev (char **str_array)
|
|
||||||
{
|
|
||||||
if (str_array)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; str_array[i] != NULL; i++)
|
|
||||||
free (str_array[i]);
|
|
||||||
|
|
||||||
free (str_array);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
cleanup_freep (void *p)
|
|
||||||
{
|
|
||||||
void **pp = (void**)p;
|
|
||||||
if (*pp)
|
|
||||||
free (*pp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
cleanup_strvp (void *p)
|
|
||||||
{
|
|
||||||
void **pp = (void**)p;
|
|
||||||
strfreev (*pp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
cleanup_fdp (int *fdp)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
assert (fdp);
|
|
||||||
|
|
||||||
fd = *fdp;
|
|
||||||
if (fd != -1)
|
|
||||||
(void) close (fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define cleanup_free __attribute__((cleanup(cleanup_freep)))
|
|
||||||
#define cleanup_fd __attribute__((cleanup(cleanup_fdp)))
|
|
||||||
#define cleanup_strv __attribute__((cleanup(cleanup_strvp)))
|
|
||||||
|
|
||||||
static inline void *
|
|
||||||
steal_pointer (void *pp)
|
|
||||||
{
|
|
||||||
void **ptr = (void **) pp;
|
|
||||||
void *ref;
|
|
||||||
|
|
||||||
ref = *ptr;
|
|
||||||
*ptr = NULL;
|
|
||||||
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* type safety */
|
|
||||||
#define steal_pointer(pp) \
|
|
||||||
(0 ? (*(pp)) : (steal_pointer) (pp))
|
|
||||||
|
|
||||||
static void
|
|
||||||
die_with_error (const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
int errsv;
|
|
||||||
|
|
||||||
errsv = errno;
|
|
||||||
|
|
||||||
va_start (args, format);
|
|
||||||
vfprintf (stderr, format, args);
|
|
||||||
va_end (args);
|
|
||||||
|
|
||||||
fprintf (stderr, ": %s\n", strerror (errsv));
|
|
||||||
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
die (const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start (args, format);
|
|
||||||
vfprintf (stderr, format, args);
|
|
||||||
va_end (args);
|
|
||||||
|
|
||||||
fprintf (stderr, "\n");
|
|
||||||
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
die_oom (void)
|
|
||||||
{
|
|
||||||
die ("Out of memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
xmalloc (size_t size)
|
|
||||||
{
|
|
||||||
void *res = malloc (size);
|
|
||||||
if (res == NULL)
|
|
||||||
die_oom ();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
xcalloc (size_t size)
|
|
||||||
{
|
|
||||||
void *res = calloc (1, size);
|
|
||||||
if (res == NULL)
|
|
||||||
die_oom ();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
xrealloc (void *ptr, size_t size)
|
|
||||||
{
|
|
||||||
void *res = realloc (ptr, size);
|
|
||||||
if (size != 0 && res == NULL)
|
|
||||||
die_oom ();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
xstrdup (const char *str)
|
|
||||||
{
|
|
||||||
char *res;
|
|
||||||
|
|
||||||
assert (str != NULL);
|
|
||||||
|
|
||||||
res = strdup (str);
|
|
||||||
if (res == NULL)
|
|
||||||
die_oom ();
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
xsetenv (const char *name, const char *value, int overwrite)
|
|
||||||
{
|
|
||||||
if (setenv (name, value, overwrite))
|
|
||||||
die ("setenv failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
xunsetenv (const char *name)
|
|
||||||
{
|
|
||||||
if (unsetenv(name))
|
|
||||||
die ("unsetenv failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
strconcat (const char *s1,
|
|
||||||
const char *s2)
|
|
||||||
{
|
|
||||||
size_t len = 0;
|
|
||||||
char *res;
|
|
||||||
|
|
||||||
if (s1)
|
|
||||||
len += strlen (s1);
|
|
||||||
if (s2)
|
|
||||||
len += strlen (s2);
|
|
||||||
|
|
||||||
res = xmalloc (len + 1);
|
|
||||||
*res = 0;
|
|
||||||
if (s1)
|
|
||||||
strcat (res, s1);
|
|
||||||
if (s2)
|
|
||||||
strcat (res, s2);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
strconcat3 (const char *s1,
|
|
||||||
const char *s2,
|
|
||||||
const char *s3)
|
|
||||||
{
|
|
||||||
size_t len = 0;
|
|
||||||
char *res;
|
|
||||||
|
|
||||||
if (s1)
|
|
||||||
len += strlen (s1);
|
|
||||||
if (s2)
|
|
||||||
len += strlen (s2);
|
|
||||||
if (s3)
|
|
||||||
len += strlen (s3);
|
|
||||||
|
|
||||||
res = xmalloc (len + 1);
|
|
||||||
*res = 0;
|
|
||||||
if (s1)
|
|
||||||
strcat (res, s1);
|
|
||||||
if (s2)
|
|
||||||
strcat (res, s2);
|
|
||||||
if (s3)
|
|
||||||
strcat (res, s3);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char*
|
|
||||||
strdup_printf (const char *format,
|
|
||||||
...)
|
|
||||||
{
|
|
||||||
char *buffer = NULL;
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start (args, format);
|
|
||||||
vasprintf (&buffer, format, args);
|
|
||||||
va_end (args);
|
|
||||||
|
|
||||||
if (buffer == NULL)
|
|
||||||
die_oom ();
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
fdwalk (int (*cb)(void *data, int fd), void *data)
|
|
||||||
{
|
|
||||||
int open_max;
|
|
||||||
int fd;
|
|
||||||
int dfd;
|
|
||||||
int res = 0;
|
|
||||||
DIR *d;
|
|
||||||
|
|
||||||
dfd = openat (proc_fd, "self/fd", O_DIRECTORY | O_PATH);
|
|
||||||
if (dfd == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if ((d = fdopendir (dfd)))
|
|
||||||
{
|
|
||||||
struct dirent *de;
|
|
||||||
|
|
||||||
while ((de = readdir (d)))
|
|
||||||
{
|
|
||||||
long l;
|
|
||||||
char *e = NULL;
|
|
||||||
|
|
||||||
if (de->d_name[0] == '.')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
l = strtol (de->d_name, &e, 10);
|
|
||||||
if (errno != 0 || !e || *e)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
fd = (int) l;
|
|
||||||
|
|
||||||
if ((long) fd != l)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (fd == dirfd (d))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((res = cb (data, fd)) != 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir (d);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
open_max = sysconf (_SC_OPEN_MAX);
|
|
||||||
|
|
||||||
for (fd = 0; fd < open_max; fd++)
|
|
||||||
if ((res = cb (data, fd)) != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int raw_clone(unsigned long flags, void *child_stack) {
|
|
||||||
#if defined(__s390__) || defined(__CRIS__)
|
|
||||||
/* On s390 and cris the order of the first and second arguments
|
|
||||||
* of the raw clone() system call is reversed. */
|
|
||||||
return (int) syscall(__NR_clone, child_stack, flags);
|
|
||||||
#else
|
|
||||||
return (int) syscall(__NR_clone, flags, child_stack);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage ()
|
usage ()
|
||||||
{
|
{
|
||||||
@@ -367,17 +58,6 @@ usage ()
|
|||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
pivot_root (const char * new_root, const char * put_old)
|
|
||||||
{
|
|
||||||
#ifdef __NR_pivot_root
|
|
||||||
return syscall(__NR_pivot_root, new_root, put_old);
|
|
||||||
#else
|
|
||||||
errno = ENOSYS;
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BIND_READONLY = (1<<0),
|
BIND_READONLY = (1<<0),
|
||||||
BIND_PRIVATE = (1<<1),
|
BIND_PRIVATE = (1<<1),
|
||||||
@@ -1110,7 +790,7 @@ monitor_child (int event_fd)
|
|||||||
|
|
||||||
/* Close all extra fds in the monitoring process.
|
/* Close all extra fds in the monitoring process.
|
||||||
Any passed in fds have been passed on to the child anyway. */
|
Any passed in fds have been passed on to the child anyway. */
|
||||||
fdwalk (close_extra_fds, dont_close);
|
fdwalk (proc_fd, close_extra_fds, dont_close);
|
||||||
|
|
||||||
sigemptyset (&mask);
|
sigemptyset (&mask);
|
||||||
sigaddset (&mask, SIGCHLD);
|
sigaddset (&mask, SIGCHLD);
|
||||||
@@ -1654,7 +1334,7 @@ main (int argc,
|
|||||||
Any passed in fds have been passed on to the child anyway. */
|
Any passed in fds have been passed on to the child anyway. */
|
||||||
{
|
{
|
||||||
int dont_close[] = { event_fd, sync_fd, -1 };
|
int dont_close[] = { event_fd, sync_fd, -1 };
|
||||||
fdwalk (close_extra_fds, dont_close);
|
fdwalk (proc_fd, close_extra_fds, dont_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
return do_init (event_fd, pid);
|
return do_init (event_fd, pid);
|
||||||
|
272
utils.c
Normal file
272
utils.c
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
/* build-root
|
||||||
|
* Copyright (C) 2016 Alexander Larsson
|
||||||
|
*
|
||||||
|
* This program 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 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
die_with_error (const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
int errsv;
|
||||||
|
|
||||||
|
errsv = errno;
|
||||||
|
|
||||||
|
va_start (args, format);
|
||||||
|
vfprintf (stderr, format, args);
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
fprintf (stderr, ": %s\n", strerror (errsv));
|
||||||
|
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
die (const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start (args, format);
|
||||||
|
vfprintf (stderr, format, args);
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
fprintf (stderr, "\n");
|
||||||
|
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
die_oom (void)
|
||||||
|
{
|
||||||
|
die ("Out of memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
xmalloc (size_t size)
|
||||||
|
{
|
||||||
|
void *res = malloc (size);
|
||||||
|
if (res == NULL)
|
||||||
|
die_oom ();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
xcalloc (size_t size)
|
||||||
|
{
|
||||||
|
void *res = calloc (1, size);
|
||||||
|
if (res == NULL)
|
||||||
|
die_oom ();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
xrealloc (void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
void *res = realloc (ptr, size);
|
||||||
|
if (size != 0 && res == NULL)
|
||||||
|
die_oom ();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
xstrdup (const char *str)
|
||||||
|
{
|
||||||
|
char *res;
|
||||||
|
|
||||||
|
assert (str != NULL);
|
||||||
|
|
||||||
|
res = strdup (str);
|
||||||
|
if (res == NULL)
|
||||||
|
die_oom ();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
strfreev (char **str_array)
|
||||||
|
{
|
||||||
|
if (str_array)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; str_array[i] != NULL; i++)
|
||||||
|
free (str_array[i]);
|
||||||
|
|
||||||
|
free (str_array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xsetenv (const char *name, const char *value, int overwrite)
|
||||||
|
{
|
||||||
|
if (setenv (name, value, overwrite))
|
||||||
|
die ("setenv failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xunsetenv (const char *name)
|
||||||
|
{
|
||||||
|
if (unsetenv(name))
|
||||||
|
die ("unsetenv failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
strconcat (const char *s1,
|
||||||
|
const char *s2)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
char *res;
|
||||||
|
|
||||||
|
if (s1)
|
||||||
|
len += strlen (s1);
|
||||||
|
if (s2)
|
||||||
|
len += strlen (s2);
|
||||||
|
|
||||||
|
res = xmalloc (len + 1);
|
||||||
|
*res = 0;
|
||||||
|
if (s1)
|
||||||
|
strcat (res, s1);
|
||||||
|
if (s2)
|
||||||
|
strcat (res, s2);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
strconcat3 (const char *s1,
|
||||||
|
const char *s2,
|
||||||
|
const char *s3)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
char *res;
|
||||||
|
|
||||||
|
if (s1)
|
||||||
|
len += strlen (s1);
|
||||||
|
if (s2)
|
||||||
|
len += strlen (s2);
|
||||||
|
if (s3)
|
||||||
|
len += strlen (s3);
|
||||||
|
|
||||||
|
res = xmalloc (len + 1);
|
||||||
|
*res = 0;
|
||||||
|
if (s1)
|
||||||
|
strcat (res, s1);
|
||||||
|
if (s2)
|
||||||
|
strcat (res, s2);
|
||||||
|
if (s3)
|
||||||
|
strcat (res, s3);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
strdup_printf (const char *format,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
char *buffer = NULL;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start (args, format);
|
||||||
|
vasprintf (&buffer, format, args);
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
die_oom ();
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fdwalk (int proc_fd, int (*cb)(void *data, int fd), void *data)
|
||||||
|
{
|
||||||
|
int open_max;
|
||||||
|
int fd;
|
||||||
|
int dfd;
|
||||||
|
int res = 0;
|
||||||
|
DIR *d;
|
||||||
|
|
||||||
|
dfd = openat (proc_fd, "self/fd", O_DIRECTORY | O_PATH);
|
||||||
|
if (dfd == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ((d = fdopendir (dfd)))
|
||||||
|
{
|
||||||
|
struct dirent *de;
|
||||||
|
|
||||||
|
while ((de = readdir (d)))
|
||||||
|
{
|
||||||
|
long l;
|
||||||
|
char *e = NULL;
|
||||||
|
|
||||||
|
if (de->d_name[0] == '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
l = strtol (de->d_name, &e, 10);
|
||||||
|
if (errno != 0 || !e || *e)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fd = (int) l;
|
||||||
|
|
||||||
|
if ((long) fd != l)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (fd == dirfd (d))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((res = cb (data, fd)) != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir (d);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
open_max = sysconf (_SC_OPEN_MAX);
|
||||||
|
|
||||||
|
for (fd = 0; fd < open_max; fd++)
|
||||||
|
if ((res = cb (data, fd)) != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
raw_clone (unsigned long flags,
|
||||||
|
void *child_stack)
|
||||||
|
{
|
||||||
|
#if defined(__s390__) || defined(__CRIS__)
|
||||||
|
/* On s390 and cris the order of the first and second arguments
|
||||||
|
* of the raw clone() system call is reversed. */
|
||||||
|
return (int) syscall(__NR_clone, child_stack, flags);
|
||||||
|
#else
|
||||||
|
return (int) syscall(__NR_clone, flags, child_stack);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pivot_root (const char * new_root, const char * put_old)
|
||||||
|
{
|
||||||
|
#ifdef __NR_pivot_root
|
||||||
|
return syscall(__NR_pivot_root, new_root, put_old);
|
||||||
|
#else
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
128
utils.h
Normal file
128
utils.h
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/* build-root
|
||||||
|
* Copyright (C) 2016 Alexander Larsson
|
||||||
|
*
|
||||||
|
* This program 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 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UTILS_H__
|
||||||
|
#define __UTILS_H__
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define __debug__(x) printf x
|
||||||
|
#else
|
||||||
|
#define __debug__(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
|
||||||
|
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
typedef int bool;
|
||||||
|
|
||||||
|
#define PIPE_READ_END 0
|
||||||
|
#define PIPE_WRITE_END 1
|
||||||
|
|
||||||
|
void strfreev (char **str_array);
|
||||||
|
void die_with_error (const char *format,
|
||||||
|
...);
|
||||||
|
void die (const char *format,
|
||||||
|
...);
|
||||||
|
void die_oom (void);
|
||||||
|
void *xmalloc (size_t size);
|
||||||
|
void *xcalloc (size_t size);
|
||||||
|
void *xrealloc (void *ptr,
|
||||||
|
size_t size);
|
||||||
|
char *xstrdup (const char *str);
|
||||||
|
void xsetenv (const char *name,
|
||||||
|
const char *value,
|
||||||
|
int overwrite);
|
||||||
|
void xunsetenv (const char *name);
|
||||||
|
char *strconcat (const char *s1,
|
||||||
|
const char *s2);
|
||||||
|
char *strconcat3 (const char *s1,
|
||||||
|
const char *s2,
|
||||||
|
const char *s3);
|
||||||
|
char* strdup_printf (const char *format,
|
||||||
|
...);
|
||||||
|
int fdwalk (int proc_fd,
|
||||||
|
int (*cb)(void *data, int fd),
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
/* syscall wrappers */
|
||||||
|
int raw_clone (unsigned long flags,
|
||||||
|
void *child_stack);
|
||||||
|
int pivot_root (const char *new_root,
|
||||||
|
const char *put_old);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
cleanup_freep (void *p)
|
||||||
|
{
|
||||||
|
void **pp = (void**)p;
|
||||||
|
if (*pp)
|
||||||
|
free (*pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
cleanup_strvp (void *p)
|
||||||
|
{
|
||||||
|
void **pp = (void**)p;
|
||||||
|
strfreev (*pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
cleanup_fdp (int *fdp)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
assert (fdp);
|
||||||
|
|
||||||
|
fd = *fdp;
|
||||||
|
if (fd != -1)
|
||||||
|
(void) close (fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define cleanup_free __attribute__((cleanup(cleanup_freep)))
|
||||||
|
#define cleanup_fd __attribute__((cleanup(cleanup_fdp)))
|
||||||
|
#define cleanup_strv __attribute__((cleanup(cleanup_strvp)))
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
steal_pointer (void *pp)
|
||||||
|
{
|
||||||
|
void **ptr = (void **) pp;
|
||||||
|
void *ref;
|
||||||
|
|
||||||
|
ref = *ptr;
|
||||||
|
*ptr = NULL;
|
||||||
|
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* type safety */
|
||||||
|
#define steal_pointer(pp) \
|
||||||
|
(0 ? (*(pp)) : (steal_pointer) (pp))
|
||||||
|
|
||||||
|
#endif /* __UTILS_H__ */
|
Reference in New Issue
Block a user