|
|
|
@ -95,10 +95,12 @@ extern "C" {
|
|
|
|
|
|
|
|
|
|
#ifdef DO_USER_XATTR_COPYING
|
|
|
|
|
|
|
|
|
|
//#include <stdio.h> // For stderr, (v)fprintf (already included above)
|
|
|
|
|
#ifdef HAVE_ATTR__ATTR_COPY_FILE
|
|
|
|
|
|
|
|
|
|
//#include <stdio.h> // For stderr, vsnprintf (already included above)
|
|
|
|
|
//#include <errno.h> // For errno (already included above)
|
|
|
|
|
//#include <stdlib.h> // For free (already included above)
|
|
|
|
|
//#include <string.h> // For strerror, strdup, and strcmp (already implicitly included above)
|
|
|
|
|
//#include <string.h> // For strerror, strdup, and strncmp (already implicitly included above)
|
|
|
|
|
#include <stdarg.h> // For va_start and va_end
|
|
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
@ -110,17 +112,53 @@ extern "C" {
|
|
|
|
|
* Optional error handler for attr_copy_file(). CTX is the error
|
|
|
|
|
* context passed to attr_copy_file(), ERR is the errno value
|
|
|
|
|
* that occurred. FMT and the rest are printf style arguments.
|
|
|
|
|
*
|
|
|
|
|
* No action is taken beyond logging. Errors commonly occur when copying
|
|
|
|
|
* files to filesystems that don't support extended attributes (such as
|
|
|
|
|
* /tmp on Linux).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
error(struct error_context *ctx, const char *fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
if (vfprintf(stderr, fmt, ap))
|
|
|
|
|
fprintf(stderr, ": ");
|
|
|
|
|
fprintf(stderr, "%s\n", strerror(errno));
|
|
|
|
|
va_end(ap);
|
|
|
|
|
// Original sample code:
|
|
|
|
|
// va_list ap;
|
|
|
|
|
//
|
|
|
|
|
// va_start(ap, fmt);
|
|
|
|
|
// if (vfprintf(stderr, fmt, ap))
|
|
|
|
|
// fprintf(stderr, ": ");
|
|
|
|
|
// fprintf(stderr, "%s\n", strerror(errno));
|
|
|
|
|
// va_end(ap);
|
|
|
|
|
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
// Save a copy in case it gets clobbered (shouldn't be needed)
|
|
|
|
|
int our_errno = errno;
|
|
|
|
|
|
|
|
|
|
// Get length of formatted string (may be 0)
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
int len = vsnprintf(nullptr, 0, fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
|
|
if ( len ) {
|
|
|
|
|
// There's a prefix string, output it
|
|
|
|
|
char* buffer = (char*)malloc(len+1);
|
|
|
|
|
if ( buffer ) {
|
|
|
|
|
// Buffer allocated, write the error to it
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
vsnprintf(&buffer[0], len+1, fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
// Write message to log
|
|
|
|
|
kdDebug(7007) << "Error in attr_copy_file: " << buffer << ": " << strerror(our_errno) << endl;
|
|
|
|
|
} else {
|
|
|
|
|
// Buffer allocation failed, just log what we can
|
|
|
|
|
kdDebug(7007) << "Error in attr_copy_file: " << strerror(our_errno) << endl;
|
|
|
|
|
}
|
|
|
|
|
free(buffer);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
// No prefix string, just log the error code
|
|
|
|
|
kdDebug(7007) << "Error in attr_copy_file: " << strerror(our_errno) << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -130,18 +168,18 @@ error(struct error_context *ctx, const char *fmt, ...)
|
|
|
|
|
static const char *
|
|
|
|
|
quote(struct error_context *ctx, const char *pathname)
|
|
|
|
|
{
|
|
|
|
|
char *pn = strdup(pathname), *p;
|
|
|
|
|
pathname = strdup(pathname);
|
|
|
|
|
for (p = pn; *p != '\0'; p++)
|
|
|
|
|
if (*p & 0x80)
|
|
|
|
|
*p='?';
|
|
|
|
|
return pn;
|
|
|
|
|
char *pn = strdup(pathname), *p;
|
|
|
|
|
pathname = strdup(pathname);
|
|
|
|
|
for (p = pn; *p != '\0'; p++)
|
|
|
|
|
if (*p & 0x80)
|
|
|
|
|
*p='?';
|
|
|
|
|
return pn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
quote_free(struct error_context *ctx, const char *name)
|
|
|
|
|
{
|
|
|
|
|
free((void *)name);
|
|
|
|
|
free((void *)name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -150,20 +188,33 @@ quote_free(struct error_context *ctx, const char *name)
|
|
|
|
|
struct error_context ctx = { error, quote, quote_free };
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Optional attribute filter for attr_copy_file(). This example
|
|
|
|
|
* excludes all attributes other than extended user attributes.
|
|
|
|
|
* Optional attribute filter for attr_copy_file(). This example
|
|
|
|
|
* excludes all attributes other than extended user attributes
|
|
|
|
|
* (those prefixed with "user.").
|
|
|
|
|
*
|
|
|
|
|
* Returns 0 if the attribute should be copied, non-zero otherwise
|
|
|
|
|
*
|
|
|
|
|
* If this function is not specified then the default behaviour of
|
|
|
|
|
* attr_copy_file is to copy all attributes except for ACLs (as listed
|
|
|
|
|
* in /etc/xattr.conf; all patterns that match are skipped).
|
|
|
|
|
*
|
|
|
|
|
* This function isn't used by the current code.
|
|
|
|
|
*/
|
|
|
|
|
static int is_user_attr(const char *name, struct error_context *ctx)
|
|
|
|
|
{
|
|
|
|
|
// Note that non-Linux systems (including Solaris and Darwin/OSX) may
|
|
|
|
|
// use a different naming scheme for user attributes. AFAIK FreeBSD
|
|
|
|
|
// and NetBSD do support the "user" namespace.
|
|
|
|
|
return strcmp(name, "user.") == 0;
|
|
|
|
|
// Note that non-Linux systems (including Solaris and Darwin/OSX) may
|
|
|
|
|
// use a different naming scheme for user attributes. AFAIK FreeBSD
|
|
|
|
|
// and NetBSD do support the "user" namespace.
|
|
|
|
|
return strncmp(name, "user.", 5) == 0;
|
|
|
|
|
|
|
|
|
|
// If this function is not specified in the call to attr_copy_file then the
|
|
|
|
|
// default behavior is to use the following heuristic instead (see above):
|
|
|
|
|
// return attr_copy_action(name, ctx) == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* USE_XATTR */
|
|
|
|
|
#endif /* HAVE_ATTR__ATTR_COPY_FILE */
|
|
|
|
|
|
|
|
|
|
#endif /* DO_USER_XATTR_COPYING */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -2049,11 +2100,18 @@ void FileCopyJob::slotResult( TDEIO::Job *job)
|
|
|
|
|
m_copyJob = 0;
|
|
|
|
|
|
|
|
|
|
#ifdef DO_USER_XATTR_COPYING
|
|
|
|
|
#ifdef HAVE_ATTR__ATTR_COPY_FILE
|
|
|
|
|
{
|
|
|
|
|
// Copy extended attributes (added AKH 2017-11-26)
|
|
|
|
|
attr_copy_file(TQFile::encodeName(m_src.path()), TQFile::encodeName(m_dest.path()), NULL, &ctx);
|
|
|
|
|
// Copy extended attributes (added AKH 2017-11-26)
|
|
|
|
|
// Returned error code (0 on success, -1 on failure) is ignored
|
|
|
|
|
int err = attr_copy_file(TQFile::encodeName(m_src.path()), TQFile::encodeName(m_dest.path()), NULL, &ctx);
|
|
|
|
|
|
|
|
|
|
// The same but using the attribute name filter function defined above (is_user_attr)
|
|
|
|
|
//int err = attr_copy_file(TQFile::encodeName(m_src.path()), TQFile::encodeName(m_dest.path()), is_user_attr, &ctx);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#endif /* HAVE_ATTR__ATTR_COPY_FILE */
|
|
|
|
|
#endif /* DO_USER_XATTR_COPYING */
|
|
|
|
|
|
|
|
|
|
if (m_move)
|
|
|
|
|
{
|
|
|
|
|