|
|
@ -97,10 +97,10 @@ extern "C" {
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_ATTR__ATTR_COPY_FILE
|
|
|
|
#ifdef HAVE_ATTR__ATTR_COPY_FILE
|
|
|
|
|
|
|
|
|
|
|
|
//#include <stdio.h> // For stderr, vsnprintf (already included above)
|
|
|
|
//#include <stdio.h> // For vsnprintf (already included above)
|
|
|
|
//#include <errno.h> // For errno (already included above)
|
|
|
|
//#include <errno.h> // For errno (already included above)
|
|
|
|
//#include <stdlib.h> // For free (already included above)
|
|
|
|
//#include <stdlib.h> // For malloc and free (already included above)
|
|
|
|
//#include <string.h> // For strerror, strdup, and strncmp (already implicitly included above)
|
|
|
|
//#include <string.h> // For strerror and strncmp (already implicitly included above)
|
|
|
|
#include <stdarg.h> // For va_start and va_end
|
|
|
|
#include <stdarg.h> // For va_start and va_end
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
extern "C" {
|
|
|
@ -131,24 +131,32 @@ error(struct error_context *ctx, const char *fmt, ...)
|
|
|
|
|
|
|
|
|
|
|
|
va_list ap;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
|
|
// Save a copy in case it gets clobbered (shouldn't be needed)
|
|
|
|
// Save a copy since it may get clobbered
|
|
|
|
int our_errno = errno;
|
|
|
|
int our_errno = errno;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( fmt ) {
|
|
|
|
|
|
|
|
// Format string was supplied
|
|
|
|
|
|
|
|
|
|
|
|
// Get length of formatted string (may be 0)
|
|
|
|
// Get length of formatted string (may be 0)
|
|
|
|
va_start(ap, fmt);
|
|
|
|
va_start(ap, fmt);
|
|
|
|
int len = vsnprintf(nullptr, 0, fmt, ap);
|
|
|
|
int len = vsnprintf(nullptr, 0, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
|
|
|
|
if ( len ) {
|
|
|
|
if ( len > 0 ) {
|
|
|
|
// There's a prefix string, output it
|
|
|
|
// There's a prefix string, output it
|
|
|
|
char* buffer = (char*)malloc(len+1);
|
|
|
|
char* buffer = (char*)malloc(len+1);
|
|
|
|
if ( buffer ) {
|
|
|
|
if ( buffer ) {
|
|
|
|
// Buffer allocated, write the error to it
|
|
|
|
// Buffer allocated, write the error to it
|
|
|
|
va_start(ap, fmt);
|
|
|
|
va_start(ap, fmt);
|
|
|
|
vsnprintf(&buffer[0], len+1, fmt, ap);
|
|
|
|
int written = vsnprintf(&buffer[0], len+1, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if ( written > 0 ) {
|
|
|
|
// Write message to log
|
|
|
|
// Write message to log
|
|
|
|
kdDebug(7007) << "Error in attr_copy_file: " << buffer << ": " << strerror(our_errno) << endl;
|
|
|
|
kdDebug(7007) << "Error in attr_copy_file: " << buffer << ": " << strerror(our_errno) << endl;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// vsnprintf failed or returned an empty string, just log what we can
|
|
|
|
|
|
|
|
kdDebug(7007) << "Error in attr_copy_file: " << strerror(our_errno) << endl;
|
|
|
|
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// Buffer allocation failed, just log what we can
|
|
|
|
// Buffer allocation failed, just log what we can
|
|
|
|
kdDebug(7007) << "Error in attr_copy_file: " << strerror(our_errno) << endl;
|
|
|
|
kdDebug(7007) << "Error in attr_copy_file: " << strerror(our_errno) << endl;
|
|
|
@ -159,33 +167,16 @@ error(struct error_context *ctx, const char *fmt, ...)
|
|
|
|
// No prefix string, just log the error code
|
|
|
|
// No prefix string, just log the error code
|
|
|
|
kdDebug(7007) << "Error in attr_copy_file: " << strerror(our_errno) << endl;
|
|
|
|
kdDebug(7007) << "Error in attr_copy_file: " << strerror(our_errno) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// No format string, just log the error code
|
|
|
|
/*
|
|
|
|
kdDebug(7007) << "Error in attr_copy_file: " << strerror(our_errno) << endl;
|
|
|
|
* Optional handler for quoting path names in error messages.
|
|
|
|
}
|
|
|
|
* (This is a very stupid example!)
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
|
|
quote_free(struct error_context *ctx, const char *name)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
free((void *)name);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* The error context we pass to attr_copy_file().
|
|
|
|
* The error context we pass to attr_copy_file().
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
struct error_context ctx = { error, quote, quote_free };
|
|
|
|
struct error_context ctx = { error, NULL, NULL };
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Optional attribute filter for attr_copy_file(). This example
|
|
|
|
* Optional attribute filter for attr_copy_file(). This example
|
|
|
@ -205,7 +196,14 @@ static int is_user_attr(const char *name, struct error_context *ctx)
|
|
|
|
// Note that non-Linux systems (including Solaris and Darwin/OSX) may
|
|
|
|
// Note that non-Linux systems (including Solaris and Darwin/OSX) may
|
|
|
|
// use a different naming scheme for user attributes. AFAIK FreeBSD
|
|
|
|
// use a different naming scheme for user attributes. AFAIK FreeBSD
|
|
|
|
// and NetBSD do support the "user" namespace.
|
|
|
|
// and NetBSD do support the "user" namespace.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( name ) {
|
|
|
|
|
|
|
|
// Name is not a null pointer
|
|
|
|
return strncmp(name, "user.", 5) == 0;
|
|
|
|
return strncmp(name, "user.", 5) == 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// Name is a null pointer
|
|
|
|
|
|
|
|
return -1; // Not matched
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If this function is not specified in the call to attr_copy_file then the
|
|
|
|
// 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):
|
|
|
|
// default behavior is to use the following heuristic instead (see above):
|
|
|
|