New upstream version 2017.13
This commit is contained in:
commit
8f7f43a65b
174 files changed
+5474
-2244
No files matched your search
@@ -53,7 +53,7 @@ libglnx_la_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags)
|
||||
libglnx_la_LDFLAGS = -avoid-version -Bsymbolic-functions -export-symbols-regex "^glnx_" -no-undefined -export-dynamic
|
||||
libglnx_la_LIBADD = $(libglnx_libs)
|
||||
|
||||
libglnx_tests = test-libglnx-xattrs test-libglnx-fdio test-libglnx-errors test-libglnx-macros
|
||||
libglnx_tests = test-libglnx-xattrs test-libglnx-fdio test-libglnx-errors test-libglnx-macros test-libglnx-shutil
|
||||
TESTS += $(libglnx_tests)
|
||||
|
||||
check_PROGRAMS += $(libglnx_tests)
|
||||
@@ -72,3 +72,7 @@ test_libglnx_errors_LDADD = $(libglnx_libs) libglnx.la
|
||||
test_libglnx_macros_SOURCES = libglnx/tests/test-libglnx-macros.c
|
||||
test_libglnx_macros_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags)
|
||||
test_libglnx_macros_LDADD = $(libglnx_libs) libglnx.la
|
||||
|
||||
test_libglnx_shutil_SOURCES = libglnx/tests/test-libglnx-shutil.c
|
||||
test_libglnx_shutil_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags)
|
||||
test_libglnx_shutil_LDADD = $(libglnx_libs) libglnx.la
|
||||
+1
-1
@@ -37,7 +37,7 @@ applicable.
|
||||
|
||||
For local allocation macros, you should start using the `g_auto`
|
||||
macros from GLib. A backport is included in libglnx. There are a few
|
||||
APIs not defined in GLib yet, such as `glnx_fd_close`.
|
||||
APIs not defined in GLib yet, such as `glnx_autofd`.
|
||||
|
||||
`gs_transfer_out_value` is replaced by `g_steal_pointer`.
|
||||
|
||||
|
||||
+10
-18
@@ -99,7 +99,7 @@ glnx_dirfd_iterator_init_at (int dfd,
|
||||
GLnxDirFdIterator *out_dfd_iter,
|
||||
GError **error)
|
||||
{
|
||||
glnx_fd_close int fd = -1;
|
||||
glnx_autofd int fd = -1;
|
||||
if (!glnx_opendirat (dfd, path, follow, &fd, error))
|
||||
return FALSE;
|
||||
|
||||
@@ -190,15 +190,12 @@ glnx_dirfd_iterator_next_dent_ensure_dtype (GLnxDirFdIterator *dfd_iter,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
struct dirent *ret_dent;
|
||||
|
||||
g_return_val_if_fail (out_dent, FALSE);
|
||||
|
||||
if (!glnx_dirfd_iterator_next_dent (dfd_iter, out_dent, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
ret_dent = *out_dent;
|
||||
|
||||
struct dirent *ret_dent = *out_dent;
|
||||
if (ret_dent)
|
||||
{
|
||||
|
||||
@@ -265,20 +262,16 @@ glnx_fdrel_abspath (int dfd,
|
||||
void
|
||||
glnx_gen_temp_name (gchar *tmpl)
|
||||
{
|
||||
size_t len;
|
||||
char *XXXXXX;
|
||||
int i;
|
||||
g_return_if_fail (tmpl != NULL);
|
||||
const size_t len = strlen (tmpl);
|
||||
g_return_if_fail (len >= 6);
|
||||
|
||||
static const char letters[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
static const int NLETTERS = sizeof (letters) - 1;
|
||||
|
||||
g_return_if_fail (tmpl != NULL);
|
||||
len = strlen (tmpl);
|
||||
g_return_if_fail (len >= 6);
|
||||
|
||||
XXXXXX = tmpl + (len - 6);
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
char *XXXXXX = tmpl + (len - 6);
|
||||
for (int i = 0; i < 6; i++)
|
||||
XXXXXX[i] = letters[g_random_int_range(0, NLETTERS)];
|
||||
}
|
||||
|
||||
@@ -326,7 +319,7 @@ glnx_mkdtempat (int dfd, const char *tmpl, int mode,
|
||||
}
|
||||
|
||||
/* And open it */
|
||||
glnx_fd_close int ret_dfd = -1;
|
||||
glnx_autofd int ret_dfd = -1;
|
||||
if (!glnx_opendirat (dfd, path, FALSE, &ret_dfd, error))
|
||||
{
|
||||
/* If we fail to open, let's try to clean up */
|
||||
@@ -382,8 +375,7 @@ _glnx_tmpdir_free (GLnxTmpDir *tmpd,
|
||||
if (!(tmpd && tmpd->initialized))
|
||||
return TRUE;
|
||||
g_assert_cmpint (tmpd->fd, !=, -1);
|
||||
(void) close (tmpd->fd);
|
||||
tmpd->fd = -1;
|
||||
glnx_close_fd (&tmpd->fd);
|
||||
g_assert (tmpd->path);
|
||||
g_assert_cmpint (tmpd->src_dfd, !=, -1);
|
||||
g_autofree char *path = tmpd->path; /* Take ownership */
|
||||
|
||||
+43
-46
@@ -141,7 +141,14 @@ glnx_renameat2_exchange (int olddirfd, const char *oldpath,
|
||||
#endif
|
||||
|
||||
/* Fallback */
|
||||
{ const char *old_tmp_name = glnx_strjoina (oldpath, ".XXXXXX");
|
||||
{ char *old_tmp_name_buf = glnx_strjoina (oldpath, ".XXXXXX");
|
||||
/* This obviously isn't race-free, but doing better gets tricky, since if
|
||||
* we're here the kernel isn't likely to support RENAME_NOREPLACE either.
|
||||
* Anyways, upgrade the kernel. Failing that, avoid use of this function in
|
||||
* shared subdirectories like /tmp.
|
||||
*/
|
||||
glnx_gen_temp_name (old_tmp_name_buf);
|
||||
const char *old_tmp_name = old_tmp_name_buf;
|
||||
|
||||
/* Move old out of the way */
|
||||
if (renameat (olddirfd, oldpath, olddirfd, old_tmp_name) < 0)
|
||||
@@ -168,11 +175,7 @@ glnx_tmpfile_clear (GLnxTmpfile *tmpf)
|
||||
return;
|
||||
if (!tmpf->initialized)
|
||||
return;
|
||||
if (tmpf->fd != -1)
|
||||
{
|
||||
if (close (tmpf->fd) < 0)
|
||||
g_assert (errno != EBADF);
|
||||
}
|
||||
glnx_close_fd (&tmpf->fd);
|
||||
/* If ->path is set, we're likely aborting due to an error. Clean it up */
|
||||
if (tmpf->path)
|
||||
{
|
||||
@@ -188,9 +191,8 @@ open_tmpfile_core (int dfd, const char *subpath,
|
||||
GLnxTmpfile *out_tmpf,
|
||||
GError **error)
|
||||
{
|
||||
/* Picked this to match mkstemp() */
|
||||
const guint mode = 0600;
|
||||
glnx_fd_close int fd = -1;
|
||||
int count;
|
||||
|
||||
dfd = glnx_dirfd_canonicalize (dfd);
|
||||
|
||||
@@ -201,33 +203,35 @@ open_tmpfile_core (int dfd, const char *subpath,
|
||||
* link_tmpfile() below to rename the result after writing the file
|
||||
* in full. */
|
||||
#if defined(O_TMPFILE) && !defined(DISABLE_OTMPFILE) && !defined(ENABLE_WRPSEUDO_COMPAT)
|
||||
fd = openat (dfd, subpath, O_TMPFILE|flags, mode);
|
||||
if (fd == -1 && !(G_IN_SET(errno, ENOSYS, EISDIR, EOPNOTSUPP)))
|
||||
return glnx_throw_errno_prefix (error, "open(O_TMPFILE)");
|
||||
if (fd != -1)
|
||||
{
|
||||
/* Workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=17523
|
||||
* See also https://github.com/ostreedev/ostree/issues/991
|
||||
*/
|
||||
if (fchmod (fd, mode) < 0)
|
||||
return glnx_throw_errno_prefix (error, "fchmod");
|
||||
out_tmpf->initialized = TRUE;
|
||||
out_tmpf->src_dfd = dfd; /* Copied; caller must keep open */
|
||||
out_tmpf->fd = glnx_steal_fd (&fd);
|
||||
out_tmpf->path = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
{
|
||||
glnx_autofd int fd = openat (dfd, subpath, O_TMPFILE|flags, mode);
|
||||
if (fd == -1 && !(G_IN_SET(errno, ENOSYS, EISDIR, EOPNOTSUPP)))
|
||||
return glnx_throw_errno_prefix (error, "open(O_TMPFILE)");
|
||||
if (fd != -1)
|
||||
{
|
||||
/* Workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=17523
|
||||
* See also https://github.com/ostreedev/ostree/issues/991
|
||||
*/
|
||||
if (fchmod (fd, mode) < 0)
|
||||
return glnx_throw_errno_prefix (error, "fchmod");
|
||||
out_tmpf->initialized = TRUE;
|
||||
out_tmpf->src_dfd = dfd; /* Copied; caller must keep open */
|
||||
out_tmpf->fd = glnx_steal_fd (&fd);
|
||||
out_tmpf->path = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
/* Fallthrough */
|
||||
#endif
|
||||
|
||||
const guint count_max = 100;
|
||||
{ g_autofree char *tmp = g_strconcat (subpath, "/tmp.XXXXXX", NULL);
|
||||
const guint count_max = 100;
|
||||
|
||||
for (count = 0; count < count_max; count++)
|
||||
for (int count = 0; count < count_max; count++)
|
||||
{
|
||||
glnx_gen_temp_name (tmp);
|
||||
|
||||
fd = openat (dfd, tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, mode);
|
||||
glnx_autofd int fd = openat (dfd, tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, mode);
|
||||
if (fd < 0)
|
||||
{
|
||||
if (errno == EEXIST)
|
||||
@@ -246,7 +250,7 @@ open_tmpfile_core (int dfd, const char *subpath,
|
||||
}
|
||||
}
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS,
|
||||
"Exhausted %u attempts to create temporary file", count);
|
||||
"Exhausted %u attempts to create temporary file", count_max);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -356,9 +360,9 @@ glnx_link_tmpfile_at (GLnxTmpfile *tmpf,
|
||||
char *dnbuf = strdupa (target);
|
||||
const char *dn = dirname (dnbuf);
|
||||
char *tmpname_buf = glnx_strjoina (dn, "/tmp.XXXXXX");
|
||||
guint count;
|
||||
const guint count_max = 100;
|
||||
|
||||
const guint count_max = 100;
|
||||
guint count;
|
||||
for (count = 0; count < count_max; count++)
|
||||
{
|
||||
glnx_gen_temp_name (tmpname_buf);
|
||||
@@ -569,7 +573,7 @@ glnx_file_get_contents_utf8_at (int dfd,
|
||||
{
|
||||
dfd = glnx_dirfd_canonicalize (dfd);
|
||||
|
||||
glnx_fd_close int fd = -1;
|
||||
glnx_autofd int fd = -1;
|
||||
if (!glnx_openat_rdonly (dfd, subpath, TRUE, &fd, error))
|
||||
return NULL;
|
||||
|
||||
@@ -599,17 +603,13 @@ glnx_readlinkat_malloc (int dfd,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
size_t l = 100;
|
||||
|
||||
dfd = glnx_dirfd_canonicalize (dfd);
|
||||
|
||||
size_t l = 100;
|
||||
for (;;)
|
||||
{
|
||||
g_autofree char *c = NULL;
|
||||
ssize_t n;
|
||||
|
||||
c = g_malloc (l);
|
||||
n = TEMP_FAILURE_RETRY (readlinkat (dfd, subpath, c, l-1));
|
||||
g_autofree char *c = g_malloc (l);
|
||||
ssize_t n = TEMP_FAILURE_RETRY (readlinkat (dfd, subpath, c, l-1));
|
||||
if (n < 0)
|
||||
return glnx_null_throw_errno_prefix (error, "readlinkat");
|
||||
|
||||
@@ -679,18 +679,15 @@ copy_symlink_at (int src_dfd,
|
||||
int
|
||||
glnx_loop_write(int fd, const void *buf, size_t nbytes)
|
||||
{
|
||||
const uint8_t *p = buf;
|
||||
|
||||
g_return_val_if_fail(fd >= 0, -1);
|
||||
g_return_val_if_fail(buf, -1);
|
||||
g_return_val_if_fail (fd >= 0, -1);
|
||||
g_return_val_if_fail (buf, -1);
|
||||
|
||||
errno = 0;
|
||||
|
||||
const uint8_t *p = buf;
|
||||
while (nbytes > 0)
|
||||
{
|
||||
ssize_t k;
|
||||
|
||||
k = write(fd, p, nbytes);
|
||||
ssize_t k = write(fd, p, nbytes);
|
||||
if (k < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
@@ -926,7 +923,7 @@ glnx_file_copy_at (int src_dfd,
|
||||
|
||||
/* Regular file path below here */
|
||||
|
||||
glnx_fd_close int src_fd = -1;
|
||||
glnx_autofd int src_fd = -1;
|
||||
if (!glnx_openat_rdonly (src_dfd, src_subpath, FALSE, &src_fd, error))
|
||||
return FALSE;
|
||||
|
||||
|
||||
+5
-8
@@ -299,7 +299,7 @@ glnx_fstatat (int dfd,
|
||||
* glnx_fstatat_allow_noent:
|
||||
* @dfd: Directory FD to stat beneath
|
||||
* @path: Path to stat beneath @dfd
|
||||
* @buf: (out caller-allocates): Return location for stat details
|
||||
* @buf: (out caller-allocates) (allow-none): Return location for stat details
|
||||
* @flags: Flags to pass to fstatat()
|
||||
* @error: Return location for a #GError, or %NULL
|
||||
*
|
||||
@@ -318,15 +318,12 @@ glnx_fstatat_allow_noent (int dfd,
|
||||
int flags,
|
||||
GError **error)
|
||||
{
|
||||
if (TEMP_FAILURE_RETRY (fstatat (dfd, path, out_buf, flags)) != 0)
|
||||
G_GNUC_UNUSED struct stat unused_stbuf;
|
||||
if (TEMP_FAILURE_RETRY (fstatat (dfd, path, out_buf ? out_buf : &unused_stbuf, flags)) != 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
{
|
||||
int errsv = errno;
|
||||
(void) glnx_throw_errno_prefix (error, "fstatat(%s)", path);
|
||||
errno = errsv;
|
||||
return FALSE;
|
||||
}
|
||||
return glnx_throw_errno_prefix (error, "fstatat(%s)", path);
|
||||
/* Note we preserve errno as ENOENT */
|
||||
}
|
||||
else
|
||||
errno = 0;
|
||||
|
||||
+27
-13
@@ -42,14 +42,30 @@ glnx_local_obj_unref (void *v)
|
||||
}
|
||||
#define glnx_unref_object __attribute__ ((cleanup(glnx_local_obj_unref)))
|
||||
|
||||
static inline void
|
||||
glnx_cleanup_close_fdp (int *fdp)
|
||||
static inline int
|
||||
glnx_steal_fd (int *fdp)
|
||||
{
|
||||
int fd, errsv;
|
||||
int fd = *fdp;
|
||||
*fdp = -1;
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* glnx_close_fd:
|
||||
* @fdp: Pointer to fd
|
||||
*
|
||||
* Effectively `close (glnx_steal_fd (&fd))`. Also
|
||||
* asserts that `close()` did not raise `EBADF` - encountering
|
||||
* that error is usually a critical bug in the program.
|
||||
*/
|
||||
static inline void
|
||||
glnx_close_fd (int *fdp)
|
||||
{
|
||||
int errsv;
|
||||
|
||||
g_assert (fdp);
|
||||
|
||||
fd = *fdp;
|
||||
int fd = glnx_steal_fd (fdp);
|
||||
if (fd >= 0)
|
||||
{
|
||||
errsv = errno;
|
||||
@@ -62,16 +78,14 @@ glnx_cleanup_close_fdp (int *fdp)
|
||||
/**
|
||||
* glnx_fd_close:
|
||||
*
|
||||
* Deprecated in favor of `glnx_autofd`.
|
||||
*/
|
||||
#define glnx_fd_close __attribute__((cleanup(glnx_close_fd)))
|
||||
/**
|
||||
* glnx_autofd:
|
||||
*
|
||||
* Call close() on a variable location when it goes out of scope.
|
||||
*/
|
||||
#define glnx_fd_close __attribute__((cleanup(glnx_cleanup_close_fdp)))
|
||||
|
||||
static inline int
|
||||
glnx_steal_fd (int *fdp)
|
||||
{
|
||||
int fd = *fdp;
|
||||
*fdp = -1;
|
||||
return fd;
|
||||
}
|
||||
#define glnx_autofd __attribute__((cleanup(glnx_close_fd)))
|
||||
|
||||
G_END_DECLS
|
||||
@@ -61,7 +61,7 @@
|
||||
*/
|
||||
gboolean
|
||||
glnx_make_lock_file(int dfd, const char *p, int operation, GLnxLockFile *out_lock, GError **error) {
|
||||
glnx_fd_close int fd = -1;
|
||||
glnx_autofd int fd = -1;
|
||||
g_autofree char *t = NULL;
|
||||
int r;
|
||||
|
||||
@@ -119,8 +119,7 @@ glnx_make_lock_file(int dfd, const char *p, int operation, GLnxLockFile *out_loc
|
||||
if (st.st_nlink > 0)
|
||||
break;
|
||||
|
||||
(void) close(fd);
|
||||
fd = -1;
|
||||
glnx_close_fd (&fd);
|
||||
}
|
||||
|
||||
/* Note that if this is not AT_FDCWD, the caller takes responsibility
|
||||
@@ -174,9 +173,7 @@ void glnx_release_lock_file(GLnxLockFile *f) {
|
||||
f->path = NULL;
|
||||
}
|
||||
|
||||
if (f->fd != -1)
|
||||
(void) close (f->fd);
|
||||
f->fd = -1;
|
||||
glnx_close_fd (&f->fd);
|
||||
f->operation = 0;
|
||||
f->initialized = FALSE;
|
||||
}
|
||||
@@ -18,7 +18,18 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
/* Missing glibc definitions to access certain kernel APIs */
|
||||
/* Missing glibc definitions to access certain kernel APIs.
|
||||
This file is last updated from systemd git:
|
||||
|
||||
commit 71e5200f94b22589922704aa4abdf95d4fe2e528
|
||||
Author: Daniel Mack <daniel@zonque.org>
|
||||
AuthorDate: Tue Oct 18 17:57:10 2016 +0200
|
||||
Commit: Lennart Poettering <lennart@poettering.net>
|
||||
CommitDate: Fri Sep 22 15:24:54 2017 +0200
|
||||
|
||||
Add abstraction model for BPF programs
|
||||
*/
|
||||
|
||||
|
||||
#if !HAVE_DECL_RENAMEAT2
|
||||
# ifndef __NR_renameat2
|
||||
@@ -26,6 +37,8 @@
|
||||
# define __NR_renameat2 316
|
||||
# elif defined __arm__
|
||||
# define __NR_renameat2 382
|
||||
# elif defined __aarch64__
|
||||
# define __NR_renameat2 276
|
||||
# elif defined _MIPS_SIM
|
||||
# if _MIPS_SIM == _MIPS_SIM_ABI32
|
||||
# define __NR_renameat2 4351
|
||||
@@ -38,6 +51,12 @@
|
||||
# endif
|
||||
# elif defined __i386__
|
||||
# define __NR_renameat2 353
|
||||
# elif defined __powerpc64__
|
||||
# define __NR_renameat2 357
|
||||
# elif defined __s390__ || defined __s390x__
|
||||
# define __NR_renameat2 347
|
||||
# elif defined __arc__
|
||||
# define __NR_renameat2 276
|
||||
# else
|
||||
# warning "__NR_renameat2 unknown for your architecture"
|
||||
# endif
|
||||
@@ -53,6 +72,45 @@ static inline int renameat2(int oldfd, const char *oldname, int newfd, const cha
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_MEMFD_CREATE
|
||||
# ifndef __NR_memfd_create
|
||||
# if defined __x86_64__
|
||||
# define __NR_memfd_create 319
|
||||
# elif defined __arm__
|
||||
# define __NR_memfd_create 385
|
||||
# elif defined __aarch64__
|
||||
# define __NR_memfd_create 279
|
||||
# elif defined __s390__
|
||||
# define __NR_memfd_create 350
|
||||
# elif defined _MIPS_SIM
|
||||
# if _MIPS_SIM == _MIPS_SIM_ABI32
|
||||
# define __NR_memfd_create 4354
|
||||
# endif
|
||||
# if _MIPS_SIM == _MIPS_SIM_NABI32
|
||||
# define __NR_memfd_create 6318
|
||||
# endif
|
||||
# if _MIPS_SIM == _MIPS_SIM_ABI64
|
||||
# define __NR_memfd_create 5314
|
||||
# endif
|
||||
# elif defined __i386__
|
||||
# define __NR_memfd_create 356
|
||||
# elif defined __arc__
|
||||
# define __NR_memfd_create 279
|
||||
# else
|
||||
# warning "__NR_memfd_create unknown for your architecture"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
static inline int memfd_create(const char *name, unsigned int flags) {
|
||||
# ifdef __NR_memfd_create
|
||||
return syscall(__NR_memfd_create, name, flags);
|
||||
# else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Copied from systemd git:
|
||||
commit 6bda23dd6aaba50cf8e3e6024248cf736cc443ca
|
||||
Author: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
|
||||
+47
-7
@@ -19,7 +19,17 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
/* Missing glibc definitions to access certain kernel APIs */
|
||||
/* Missing glibc definitions to access certain kernel APIs.
|
||||
This file is last updated from systemd git:
|
||||
|
||||
commit 71e5200f94b22589922704aa4abdf95d4fe2e528
|
||||
Author: Daniel Mack <daniel@zonque.org>
|
||||
AuthorDate: Tue Oct 18 17:57:10 2016 +0200
|
||||
Commit: Lennart Poettering <lennart@poettering.net>
|
||||
CommitDate: Fri Sep 22 15:24:54 2017 +0200
|
||||
|
||||
Add abstraction model for BPF programs
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -29,22 +39,30 @@
|
||||
#include <uchar.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
/* The precise definition of __O_TMPFILE is arch specific, so let's
|
||||
* just define this on x86 where we know the value. */
|
||||
/* The precise definition of __O_TMPFILE is arch specific; use the
|
||||
* values defined by the kernel (note: some are hexa, some are octal,
|
||||
* duplicated as-is from the kernel definitions):
|
||||
* - alpha, parisc, sparc: each has a specific value;
|
||||
* - others: they use the "generic" value.
|
||||
*/
|
||||
|
||||
#ifndef __O_TMPFILE
|
||||
#if defined(__alpha__)
|
||||
#define __O_TMPFILE 0100000000
|
||||
#elif defined(__parisc__) || defined(__hppa__)
|
||||
#define __O_TMPFILE 0400000000
|
||||
#elif defined(__sparc__) || defined(__sparc64__)
|
||||
#define __O_TMPFILE 0x2000000
|
||||
#else
|
||||
#define __O_TMPFILE 020000000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* a horrid kludge trying to make sure that this will fail on old kernels */
|
||||
#ifndef O_TMPFILE
|
||||
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef RENAME_NOREPLACE
|
||||
#define RENAME_NOREPLACE (1 << 0)
|
||||
#endif
|
||||
@@ -52,4 +70,26 @@
|
||||
#define RENAME_EXCHANGE (1 << 1)
|
||||
#endif
|
||||
|
||||
#ifndef F_LINUX_SPECIFIC_BASE
|
||||
#define F_LINUX_SPECIFIC_BASE 1024
|
||||
#endif
|
||||
|
||||
#ifndef F_ADD_SEALS
|
||||
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
|
||||
#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
|
||||
|
||||
#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
|
||||
#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
|
||||
#define F_SEAL_GROW 0x0004 /* prevent file from growing */
|
||||
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||
#endif
|
||||
|
||||
#ifndef MFD_ALLOW_SEALING
|
||||
#define MFD_ALLOW_SEALING 0x0002U
|
||||
#endif
|
||||
|
||||
#ifndef MFD_CLOEXEC
|
||||
#define MFD_CLOEXEC 0x0001U
|
||||
#endif
|
||||
|
||||
#include "glnx-missing-syscall.h"
|
||||
@@ -84,14 +84,12 @@ glnx_shutil_rm_rf_at (int dfd,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
glnx_fd_close int target_dfd = -1;
|
||||
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
|
||||
|
||||
dfd = glnx_dirfd_canonicalize (dfd);
|
||||
|
||||
|
||||
/* With O_NOFOLLOW first */
|
||||
target_dfd = openat (dfd, path,
|
||||
O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
|
||||
glnx_autofd int target_dfd =
|
||||
openat (dfd, path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
|
||||
|
||||
if (target_dfd == -1)
|
||||
{
|
||||
@@ -110,6 +108,7 @@ glnx_shutil_rm_rf_at (int dfd,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
|
||||
if (!glnx_dirfd_iterator_init_take_fd (&target_dfd, &dfd_iter, error))
|
||||
return FALSE;
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#include <glnx-macros.h>
|
||||
#include <glnx-missing.h>
|
||||
#include <glnx-local-alloc.h>
|
||||
#include <glnx-backport-autocleanups.h>
|
||||
#include <glnx-backports.h>
|
||||
|
||||
+1
-3
@@ -1,8 +1,6 @@
|
||||
AC_DEFUN([LIBGLNX_CONFIGURE],
|
||||
[
|
||||
AC_CHECK_DECLS([
|
||||
renameat2,
|
||||
],
|
||||
AC_CHECK_DECLS([renameat2, memfd_create],
|
||||
[], [], [[
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -32,8 +32,8 @@ static gboolean
|
||||
renameat_test_setup (int *out_srcfd, int *out_destfd,
|
||||
GError **error)
|
||||
{
|
||||
glnx_fd_close int srcfd = -1;
|
||||
glnx_fd_close int destfd = -1;
|
||||
glnx_autofd int srcfd = -1;
|
||||
glnx_autofd int destfd = -1;
|
||||
|
||||
(void) glnx_shutil_rm_rf_at (AT_FDCWD, "srcdir", NULL, NULL);
|
||||
if (mkdir ("srcdir", 0755) < 0)
|
||||
@@ -62,8 +62,8 @@ static void
|
||||
test_renameat2_noreplace (void)
|
||||
{
|
||||
_GLNX_TEST_DECLARE_ERROR(local_error, error);
|
||||
glnx_fd_close int srcfd = -1;
|
||||
glnx_fd_close int destfd = -1;
|
||||
glnx_autofd int srcfd = -1;
|
||||
glnx_autofd int destfd = -1;
|
||||
struct stat stbuf;
|
||||
|
||||
if (!renameat_test_setup (&srcfd, &destfd, error))
|
||||
@@ -92,8 +92,8 @@ test_renameat2_exchange (void)
|
||||
{
|
||||
_GLNX_TEST_DECLARE_ERROR(local_error, error);
|
||||
|
||||
glnx_fd_close int srcfd = -1;
|
||||
glnx_fd_close int destfd = -1;
|
||||
glnx_autofd int srcfd = -1;
|
||||
glnx_autofd int destfd = -1;
|
||||
if (!renameat_test_setup (&srcfd, &destfd, error))
|
||||
return;
|
||||
|
||||
@@ -161,13 +161,22 @@ test_fstatat (void)
|
||||
return;
|
||||
g_assert_cmpint (errno, ==, ENOENT);
|
||||
g_assert_no_error (local_error);
|
||||
|
||||
/* test NULL parameter for stat */
|
||||
if (!glnx_fstatat_allow_noent (AT_FDCWD, ".", NULL, 0, error))
|
||||
return;
|
||||
g_assert_cmpint (errno, ==, 0);
|
||||
g_assert_no_error (local_error);
|
||||
if (!glnx_fstatat_allow_noent (AT_FDCWD, "nosuchfile", NULL, 0, error))
|
||||
return;
|
||||
g_assert_cmpint (errno, ==, ENOENT);
|
||||
g_assert_no_error (local_error);
|
||||
}
|
||||
|
||||
static void
|
||||
test_filecopy (void)
|
||||
{
|
||||
_GLNX_TEST_DECLARE_ERROR(local_error, error);
|
||||
g_auto(GLnxTmpfile) tmpf = { 0, };
|
||||
const char foo[] = "foo";
|
||||
struct stat stbuf;
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright © 2017 Endless Mobile, Inc.
|
||||
*
|
||||
* 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 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libglnx.h"
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <err.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libglnx-testlib.h"
|
||||
|
||||
static void
|
||||
test_mkdir_p_enoent (void)
|
||||
{
|
||||
_GLNX_TEST_DECLARE_ERROR(local_error, error);
|
||||
glnx_autofd int dfd = -1;
|
||||
|
||||
if (!glnx_ensure_dir (AT_FDCWD, "test", 0755, error))
|
||||
return;
|
||||
if (!glnx_opendirat (AT_FDCWD, "test", FALSE, &dfd, error))
|
||||
return;
|
||||
if (rmdir ("test") < 0)
|
||||
return (void) glnx_throw_errno_prefix (error, "rmdir(%s)", "test");
|
||||
|
||||
/* This should fail with ENOENT. */
|
||||
glnx_shutil_mkdir_p_at (dfd, "blah/baz", 0755, NULL, error);
|
||||
g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
|
||||
g_clear_error (&local_error);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/mkdir-p/enoent", test_mkdir_p_enoent);
|
||||
|
||||
ret = g_test_run();
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -82,7 +82,7 @@ do_write_run (GLnxDirFdIterator *dfd_iter, GError **error)
|
||||
{
|
||||
guint32 randname_v = g_random_int ();
|
||||
g_autofree char *randname = g_strdup_printf ("file%u", randname_v);
|
||||
glnx_fd_close int fd = -1;
|
||||
glnx_autofd int fd = -1;
|
||||
|
||||
again:
|
||||
fd = openat (dfd_iter->fd, randname, O_CREAT | O_EXCL, 0644);
|
||||
@@ -113,7 +113,7 @@ do_write_run (GLnxDirFdIterator *dfd_iter, GError **error)
|
||||
if (!dent)
|
||||
break;
|
||||
|
||||
glnx_fd_close int fd = -1;
|
||||
glnx_autofd int fd = -1;
|
||||
if (!glnx_openat_rdonly (dfd_iter->fd, dent->d_name, FALSE, &fd, error))
|
||||
return FALSE;
|
||||
|
||||
@@ -157,7 +157,7 @@ do_read_run (GLnxDirFdIterator *dfd_iter,
|
||||
if (!dent)
|
||||
break;
|
||||
|
||||
glnx_fd_close int fd = -1;
|
||||
glnx_autofd int fd = -1;
|
||||
if (!glnx_openat_rdonly (dfd_iter->fd, dent->d_name, FALSE, &fd, error))
|
||||
return FALSE;
|
||||
|
||||
|
||||
Reference in new issue
Block a user