New upstream version 2017.10

This commit is contained in:
Simon McVittie committed 2017-08-29 15:42:08 +01:00
commit 592e798794
140 files changed
+4813 -1216

No files matched your search

+5 -3
View File
@@ -187,11 +187,12 @@ text_percent_internal (const char *text,
const guint n_spaces = sizeof (spaces) - 1;
const guint ncolumns = glnx_console_columns ();
const guint bar_min = 10;
const guint input_textlen = text ? strlen (text) : 0;
if (text && !*text)
text = NULL;
const guint input_textlen = text ? strlen (text) : 0;
if (percentage == current_percent
&& g_strcmp0 (text, current_text) == 0)
return;
@@ -221,7 +222,8 @@ text_percent_internal (const char *text,
if (percentage == -1)
{
fwrite (text, 1, input_textlen, stdout);
if (text != NULL)
fwrite (text, 1, input_textlen, stdout);
/* Overwrite remaining space, if any */
if (ncolumns > input_textlen)
@@ -273,7 +275,7 @@ void
glnx_console_progress_text_percent (const char *text,
guint percentage)
{
g_return_if_fail (percentage >= 0 && percentage <= 100);
g_return_if_fail (percentage <= 100);
text_percent_internal (text, percentage);
}
+1 -1
View File
@@ -83,7 +83,7 @@ typedef struct GLnxRealDirfdIterator GLnxRealDirfdIterator;
/**
* glnx_dirfd_iterator_init_at:
* @dfd: File descriptor, may be AT_FDCWD or -1
* @path: Path, may be relative to @df
* @path: Path, may be relative to @dfd
* @follow: If %TRUE and the last component of @path is a symlink, follow it
* @out_dfd_iter: (out caller-allocates): A directory iterator, will be initialized
* @error: Error
+104 -42
View File
@@ -31,9 +31,6 @@
#include <sys/ioctl.h>
#include <sys/sendfile.h>
#include <errno.h>
/* See linux.git/fs/btrfs/ioctl.h */
#define BTRFS_IOCTL_MAGIC 0x94
#define BTRFS_IOC_CLONE _IOW(BTRFS_IOCTL_MAGIC, 9, int)
#include <glnx-fdio.h>
#include <glnx-dirfd.h>
@@ -43,6 +40,11 @@
#include <glnx-local-alloc.h>
#include <glnx-missing.h>
/* The standardized version of BTRFS_IOC_CLONE */
#ifndef FICLONE
#define FICLONE _IOW(0x94, 9, int)
#endif
/* 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 (hence works correctly on signed
@@ -654,13 +656,6 @@ copy_symlink_at (int src_dfd,
* conveniently fit in with the rest of libglnx.
*/
static int btrfs_reflink(int infd, int outfd) {
g_return_val_if_fail(infd >= 0, -1);
g_return_val_if_fail(outfd >= 0, -1);
return ioctl (outfd, BTRFS_IOC_CLONE, infd);
}
/* Like write(), but loop until @nbytes are written, or an error
* occurs.
*
@@ -703,8 +698,10 @@ glnx_loop_write(int fd, const void *buf, size_t nbytes)
return 0;
}
/* Read from @fdf until EOF, writing to @fdt. If @try_reflink is %TRUE,
* attempt to use any "reflink" functionality; see e.g. https://lwn.net/Articles/331808/
/* Read from @fdf until EOF, writing to @fdt. If max_bytes is -1, a full-file
* clone will be attempted. Otherwise Linux copy_file_range(), sendfile()
* syscall will be attempted. If none of those work, this function will do a
* plain read()/write() loop.
*
* The file descriptor @fdf must refer to a regular file.
*
@@ -712,58 +709,123 @@ glnx_loop_write(int fd, const void *buf, size_t nbytes)
* On error, this function returns `-1` and @errno will be set.
*/
int
glnx_regfile_copy_bytes (int fdf, int fdt, off_t max_bytes, gboolean try_reflink)
glnx_regfile_copy_bytes (int fdf, int fdt, off_t max_bytes)
{
bool try_sendfile = true;
int r;
/* Last updates from systemd as of commit 6bda23dd6aaba50cf8e3e6024248cf736cc443ca */
static int have_cfr = -1; /* -1 means unknown */
bool try_cfr = have_cfr != 0;
static int have_sendfile = -1; /* -1 means unknown */
bool try_sendfile = have_sendfile != 0;
g_return_val_if_fail (fdf >= 0, -1);
g_return_val_if_fail (fdt >= 0, -1);
g_return_val_if_fail (max_bytes >= -1, -1);
/* Try btrfs reflinks first. */
if (try_reflink && max_bytes == (off_t) -1)
/* If we've requested to copy the whole range, try a full-file clone first.
*/
if (max_bytes == (off_t) -1)
{
r = btrfs_reflink(fdf, fdt);
if (r >= 0)
if (ioctl (fdt, FICLONE, fdf) == 0)
return 0;
/* Fall through */
struct stat stbuf;
/* Gather the size so we can provide the whole thing at once to
* copy_file_range() or sendfile().
*/
if (fstat (fdf, &stbuf) < 0)
return -1;
max_bytes = stbuf.st_size;
}
while (TRUE)
{
size_t m = COPY_BUFFER_SIZE;
ssize_t n;
if (max_bytes != (off_t) -1)
/* First, try copy_file_range(). Note this is an inlined version of
* try_copy_file_range() from systemd upstream, which works better since
* we use POSIX errno style.
*/
if (try_cfr)
{
if ((off_t) m > max_bytes)
m = (size_t) max_bytes;
}
/* First try sendfile(), unless we already tried */
if (try_sendfile)
{
n = sendfile (fdt, fdf, NULL, m);
n = copy_file_range (fdf, NULL, fdt, NULL, max_bytes, 0u);
if (n < 0)
{
if (errno != EINVAL && errno != ENOSYS)
if (errno == ENOSYS)
{
/* No cfr in kernel, mark as permanently unavailable
* and fall through to sendfile().
*/
have_cfr = 0;
try_cfr = false;
}
else if (errno == EXDEV)
/* We won't try cfr again for this run, but let's be
* conservative and not mark it as available/unavailable until
* we know for sure.
*/
try_cfr = false;
else
return -1;
try_sendfile = false;
/* use fallback below */
}
else if (n == 0) /* EOF */
break;
else if (n > 0)
/* Succcess! */
goto next;
else
{
/* cfr worked, mark it as available */
if (have_cfr == -1)
have_cfr = 1;
if (n == 0) /* EOF */
break;
else
/* Success! */
goto next;
}
}
/* Next try sendfile(); this version is also changed from systemd upstream
* to match the same logic we have for copy_file_range().
*/
if (try_sendfile)
{
n = sendfile (fdt, fdf, NULL, max_bytes);
if (n < 0)
{
if (G_IN_SET (errno, EINVAL, ENOSYS))
{
/* No sendfile(), or it doesn't work on regular files.
* Mark it as permanently unavailable, and fall through
* to plain read()/write().
*/
have_sendfile = 0;
try_sendfile = false;
}
else
return -1;
}
else
{
/* sendfile() worked, mark it as available */
if (have_sendfile == -1)
have_sendfile = 1;
if (n == 0) /* EOF */
break;
else if (n > 0)
/* Succcess! */
goto next;
}
}
/* As a fallback just copy bits by hand */
{ char buf[m];
{ size_t m = COPY_BUFFER_SIZE;
if (max_bytes != (off_t) -1)
{
if ((off_t) m > max_bytes)
m = (size_t) max_bytes;
}
char buf[m];
n = read (fdf, buf, m);
n = TEMP_FAILURE_RETRY (read (fdf, buf, m));
if (n < 0)
return -1;
if (n == 0) /* EOF */
@@ -776,7 +838,7 @@ glnx_regfile_copy_bytes (int fdf, int fdt, off_t max_bytes, gboolean try_reflink
next:
if (max_bytes != (off_t) -1)
{
g_assert(max_bytes >= n);
g_assert_cmpint (max_bytes, >=, n);
max_bytes -= n;
if (max_bytes == 0)
break;
@@ -867,7 +929,7 @@ glnx_file_copy_at (int src_dfd,
goto out;
}
r = glnx_regfile_copy_bytes (src_fd, dest_fd, (off_t) -1, TRUE);
r = glnx_regfile_copy_bytes (src_fd, dest_fd, (off_t) -1);
if (r < 0)
{
glnx_set_error_from_errno (error);
+1 -1
View File
@@ -170,7 +170,7 @@ int
glnx_loop_write (int fd, const void *buf, size_t nbytes);
int
glnx_regfile_copy_bytes (int fdf, int fdt, off_t max_bytes, gboolean try_reflink);
glnx_regfile_copy_bytes (int fdf, int fdt, off_t max_bytes);
typedef enum {
GLNX_FILE_COPY_OVERWRITE = (1 << 0),
+10 -160
View File
@@ -25,30 +25,6 @@
G_BEGIN_DECLS
#define GLNX_DEFINE_CLEANUP_FUNCTION(Type, name, func) \
static inline void name (void *v) \
{ \
func (*(Type*)v); \
}
#define GLNX_DEFINE_CLEANUP_FUNCTION0(Type, name, func) \
static inline void name (void *v) \
{ \
if (*(Type*)v) \
func (*(Type*)v); \
}
/**
* glnx_free:
*
* Call g_free() on a variable location when it goes out of scope.
*/
#define glnx_free __attribute__ ((cleanup(glnx_local_free)))
#ifdef GLNX_GSYSTEM_COMPAT
#define gs_free __attribute__ ((cleanup(glnx_local_free)))
#endif
GLNX_DEFINE_CLEANUP_FUNCTION(void*, glnx_local_free, g_free)
/**
* glnx_unref_object:
*
@@ -57,141 +33,14 @@ GLNX_DEFINE_CLEANUP_FUNCTION(void*, glnx_local_free, g_free)
* %NULL.
*/
#define glnx_unref_object __attribute__ ((cleanup(glnx_local_obj_unref)))
#ifdef GLNX_GSYSTEM_COMPAT
#define gs_unref_object __attribute__ ((cleanup(glnx_local_obj_unref)))
#endif
GLNX_DEFINE_CLEANUP_FUNCTION0(GObject*, glnx_local_obj_unref, g_object_unref)
/**
* glnx_unref_variant:
*
* Call g_variant_unref() on a variable location when it goes out of
* scope. Note that unlike g_variant_unref(), the variable may be
* %NULL.
*/
#define glnx_unref_variant __attribute__ ((cleanup(glnx_local_variant_unref)))
#ifdef GLNX_GSYSTEM_COMPAT
#define gs_unref_variant __attribute__ ((cleanup(glnx_local_variant_unref)))
#endif
GLNX_DEFINE_CLEANUP_FUNCTION0(GVariant*, glnx_local_variant_unref, g_variant_unref)
/**
* glnx_free_variant_iter:
*
* Call g_variant_iter_free() on a variable location when it goes out of
* scope.
*/
#define glnx_free_variant_iter __attribute__ ((cleanup(glnx_local_variant_iter_free)))
GLNX_DEFINE_CLEANUP_FUNCTION0(GVariantIter*, glnx_local_variant_iter_free, g_variant_iter_free)
/**
* glnx_free_variant_builder:
*
* Call g_variant_builder_unref() on a variable location when it goes out of
* scope.
*/
#define glnx_unref_variant_builder __attribute__ ((cleanup(glnx_local_variant_builder_unref)))
GLNX_DEFINE_CLEANUP_FUNCTION0(GVariantBuilder*, glnx_local_variant_builder_unref, g_variant_builder_unref)
/**
* glnx_unref_array:
*
* Call g_array_unref() on a variable location when it goes out of
* scope. Note that unlike g_array_unref(), the variable may be
* %NULL.
*/
#define glnx_unref_array __attribute__ ((cleanup(glnx_local_array_unref)))
GLNX_DEFINE_CLEANUP_FUNCTION0(GArray*, glnx_local_array_unref, g_array_unref)
/**
* glnx_unref_ptrarray:
*
* Call g_ptr_array_unref() on a variable location when it goes out of
* scope. Note that unlike g_ptr_array_unref(), the variable may be
* %NULL.
*/
#define glnx_unref_ptrarray __attribute__ ((cleanup(glnx_local_ptrarray_unref)))
#ifdef GLNX_GSYSTEM_COMPAT
#define gs_unref_ptrarray __attribute__ ((cleanup(glnx_local_ptrarray_unref)))
#endif
GLNX_DEFINE_CLEANUP_FUNCTION0(GPtrArray*, glnx_local_ptrarray_unref, g_ptr_array_unref)
/**
* glnx_unref_hashtable:
*
* Call g_hash_table_unref() on a variable location when it goes out
* of scope. Note that unlike g_hash_table_unref(), the variable may
* be %NULL.
*/
#define glnx_unref_hashtable __attribute__ ((cleanup(glnx_local_hashtable_unref)))
#ifdef GLNX_GSYSTEM_COMPAT
#define gs_unref_hashtable __attribute__ ((cleanup(glnx_local_hashtable_unref)))
#endif
GLNX_DEFINE_CLEANUP_FUNCTION0(GHashTable*, glnx_local_hashtable_unref, g_hash_table_unref)
/**
* glnx_free_list:
*
* Call g_list_free() on a variable location when it goes out
* of scope.
*/
#define glnx_free_list __attribute__ ((cleanup(glnx_local_free_list)))
GLNX_DEFINE_CLEANUP_FUNCTION(GList*, glnx_local_free_list, g_list_free)
/**
* glnx_free_slist:
*
* Call g_slist_free() on a variable location when it goes out
* of scope.
*/
#define glnx_free_slist __attribute__ ((cleanup(glnx_local_free_slist)))
GLNX_DEFINE_CLEANUP_FUNCTION(GSList*, glnx_local_free_slist, g_slist_free)
/**
* glnx_free_checksum:
*
* Call g_checksum_free() on a variable location when it goes out
* of scope. Note that unlike g_checksum_free(), the variable may
* be %NULL.
*/
#define glnx_free_checksum __attribute__ ((cleanup(glnx_local_checksum_free)))
GLNX_DEFINE_CLEANUP_FUNCTION0(GChecksum*, glnx_local_checksum_free, g_checksum_free)
/**
* glnx_unref_bytes:
*
* Call g_bytes_unref() on a variable location when it goes out
* of scope. Note that unlike g_bytes_unref(), the variable may
* be %NULL.
*/
#define glnx_unref_bytes __attribute__ ((cleanup(glnx_local_bytes_unref)))
GLNX_DEFINE_CLEANUP_FUNCTION0(GBytes*, glnx_local_bytes_unref, g_bytes_unref)
/**
* glnx_strfreev:
*
* Call g_strfreev() on a variable location when it goes out of scope.
*/
#define glnx_strfreev __attribute__ ((cleanup(glnx_local_strfreev)))
GLNX_DEFINE_CLEANUP_FUNCTION(char**, glnx_local_strfreev, g_strfreev)
/**
* glnx_free_error:
*
* Call g_error_free() on a variable location when it goes out of scope.
*/
#define glnx_free_error __attribute__ ((cleanup(glnx_local_free_error)))
GLNX_DEFINE_CLEANUP_FUNCTION0(GError*, glnx_local_free_error, g_error_free)
/**
* glnx_unref_keyfile:
*
* Call g_key_file_unref() on a variable location when it goes out of scope.
*/
#define glnx_unref_keyfile __attribute__ ((cleanup(glnx_local_keyfile_unref)))
GLNX_DEFINE_CLEANUP_FUNCTION0(GKeyFile*, glnx_local_keyfile_unref, g_key_file_unref)
static inline void
glnx_local_obj_unref (void *v)
{
GObject *o = *(GObject **)v;
if (o)
g_object_unref (o);
}
#define glnx_unref_object __attribute__ ((cleanup(glnx_local_obj_unref)))
static inline void
glnx_cleanup_close_fdp (int *fdp)
@@ -204,7 +53,8 @@ glnx_cleanup_close_fdp (int *fdp)
if (fd >= 0)
{
errsv = errno;
(void) close (fd);
if (close (fd) < 0)
g_assert (errno != EBADF);
errno = errsv;
}
}
+41
View File
@@ -52,3 +52,44 @@ static inline int renameat2(int oldfd, const char *oldname, int newfd, const cha
# endif
}
#endif
/* Copied from systemd git:
commit 6bda23dd6aaba50cf8e3e6024248cf736cc443ca
Author: Yu Watanabe <watanabe.yu+github@gmail.com>
AuthorDate: Thu Jul 27 20:22:54 2017 +0900
Commit: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
CommitDate: Thu Jul 27 07:22:54 2017 -0400
*/
#if !HAVE_DECL_COPY_FILE_RANGE
# ifndef __NR_copy_file_range
# if defined(__x86_64__)
# define __NR_copy_file_range 326
# elif defined(__i386__)
# define __NR_copy_file_range 377
# elif defined __s390__
# define __NR_copy_file_range 375
# elif defined __arm__
# define __NR_copy_file_range 391
# elif defined __aarch64__
# define __NR_copy_file_range 285
# elif defined __powerpc__
# define __NR_copy_file_range 379
# elif defined __arc__
# define __NR_copy_file_range 285
# else
# warning "__NR_copy_file_range not defined for your architecture"
# endif
# endif
static inline ssize_t copy_file_range(int fd_in, loff_t *off_in,
int fd_out, loff_t *off_out,
size_t len,
unsigned int flags) {
# ifdef __NR_copy_file_range
return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags);
# else
errno = ENOSYS;
return -1;
# endif
}
#endif
+2 -2
View File
@@ -145,8 +145,8 @@ get_xattrs_impl (const char *path,
{
gboolean ret = FALSE;
ssize_t bytes_read, real_size;
glnx_free char *xattr_names = NULL;
glnx_free char *xattr_names_canonical = NULL;
g_autofree char *xattr_names = NULL;
g_autofree char *xattr_names_canonical = NULL;
GVariantBuilder builder;
gboolean builder_initialized = FALSE;
g_autoptr(GVariant) ret_xattrs = NULL;