summaryrefslogtreecommitdiff
path: root/test/bbackupd
diff options
context:
space:
mode:
authorBen Summers <ben@fluffy.co.uk>2006-01-06 10:02:44 +0000
committerBen Summers <ben@fluffy.co.uk>2006-01-06 10:02:44 +0000
commitbe32ddee052ee73f74e744a2e907865667b042fa (patch)
tree55b5bd98cafc3554c58a76cbfda9084f725171c6 /test/bbackupd
parent143bb18701167817d218ea7027365a274f6433f4 (diff)
Simple test for xattr support in test/bbackupd, fix xattr support for Darwin, move xattr adjustments to BoxPlatform.h to use globally
Diffstat (limited to 'test/bbackupd')
-rw-r--r--test/bbackupd/testbbackupd.cpp224
1 files changed, 224 insertions, 0 deletions
diff --git a/test/bbackupd/testbbackupd.cpp b/test/bbackupd/testbbackupd.cpp
index 560cf16f..72917978 100644
--- a/test/bbackupd/testbbackupd.cpp
+++ b/test/bbackupd/testbbackupd.cpp
@@ -16,6 +16,11 @@
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
+#ifdef HAVE_SYS_XATTR_H
+#include <cerrno>
+#include <sys/xattr.h>
+#endif
+#include <map>
#include "Test.h"
#include "BackupClientFileAttributes.h"
@@ -57,12 +62,188 @@ void wait_for_backup_operation(int seconds = TIME_TO_WAIT_FOR_BACKUP_OPERATION)
int bbstored_pid = 0;
+#ifdef HAVE_SYS_XATTR_H
+bool readxattr_into_map(const char *filename, std::map<std::string,std::string> &rOutput)
+{
+ rOutput.clear();
+
+ ssize_t xattrNamesBufferSize = llistxattr(filename, NULL, 0);
+ if(xattrNamesBufferSize < 0)
+ {
+ return false;
+ }
+ else if(xattrNamesBufferSize > 0)
+ {
+ // There is some data there to look at
+ char *xattrNamesBuffer = (char*)malloc(xattrNamesBufferSize + 4);
+ if(xattrNamesBuffer == NULL) return false;
+ char *xattrDataBuffer = 0;
+ int xattrDataBufferSize = 0;
+ // note: will leak these buffers if a read error occurs. (test code, so doesn't matter)
+
+ ssize_t ns = llistxattr(filename, xattrNamesBuffer, xattrNamesBufferSize);
+ if(ns < 0)
+ {
+ return false;
+ }
+ else if(ns > 0)
+ {
+ // Read all the attribute values
+ const char *xattrName = xattrNamesBuffer;
+ while(xattrName < (xattrNamesBuffer + ns))
+ {
+ // Store size of name
+ int xattrNameSize = strlen(xattrName);
+
+ bool ok = true;
+
+ ssize_t dataSize = lgetxattr(filename, xattrName, NULL, 0);
+ if(dataSize < 0)
+ {
+ if(errno == ENOATTR)
+ {
+ // Deleted from under us
+ ok = false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if(dataSize == 0)
+ {
+ // something must have removed all the data from under us
+ ok = false;
+ }
+ else
+ {
+ // Make sure there's enough space in the buffer to get the attribute
+ if(xattrDataBuffer == 0)
+ {
+ xattrDataBuffer = (char*)malloc(dataSize + 4);
+ xattrDataBufferSize = dataSize + 4;
+ }
+ else if(xattrDataBufferSize < (dataSize + 4))
+ {
+ char *resized = (char*)realloc(xattrDataBuffer, dataSize + 4);
+ if(resized == NULL) return false;
+ xattrDataBuffer = resized;
+ xattrDataBufferSize = dataSize + 4;
+ }
+ }
+
+ // Read the data!
+ dataSize = 0;
+ if(ok)
+ {
+ dataSize = lgetxattr(filename, xattrName, xattrDataBuffer,
+ xattrDataBufferSize - 1 /*for terminator*/);
+ if(dataSize < 0)
+ {
+ if(errno == ENOATTR)
+ {
+ // Deleted from under us
+ ok = false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if(dataSize == 0)
+ {
+ // something must have deleted this from under us
+ ok = false;
+ }
+ else
+ {
+ // Terminate the data
+ xattrDataBuffer[dataSize] = '\0';
+ }
+ // Got the data in the buffer
+ }
+
+ // Store in map
+ if(ok)
+ {
+ rOutput[std::string(xattrName)] = std::string(xattrDataBuffer, dataSize);
+ }
+
+ // Next attribute
+ xattrName += xattrNameSize + 1;
+ }
+ }
+
+ if(xattrNamesBuffer != 0) ::free(xattrNamesBuffer);
+ if(xattrDataBuffer != 0) ::free(xattrDataBuffer);
+ }
+
+ return true;
+}
+
+static FILE *xattrTestDataHandle = 0;
+bool write_xattr_test(const char *filename, const char *attrName, unsigned int length, bool *pNotSupported = 0)
+{
+ if(xattrTestDataHandle == 0)
+ {
+ xattrTestDataHandle = ::fopen("testfiles/test3.tgz", "rb"); // largest test file
+ }
+ if(xattrTestDataHandle == 0)
+ {
+ return false;
+ }
+ else
+ {
+ char data[4096];
+ if(length > sizeof(data)) length = sizeof(data);
+
+ if(::fread(data, length, 1, xattrTestDataHandle) != 1)
+ {
+ return false;
+ }
+
+ if(::lsetxattr(filename, attrName, data, length, 0) != 0)
+ {
+ if(pNotSupported != 0)
+ {
+ *pNotSupported = (errno == ENOTSUP);
+ }
+ return false;
+ }
+ }
+
+ return true;
+}
+void finish_with_write_xattr_test()
+{
+ if(xattrTestDataHandle != 0)
+ {
+ ::fclose(xattrTestDataHandle);
+ }
+}
+#endif // HAVE_SYS_XATTR_H
+
bool attrmatch(const char *f1, const char *f2)
{
struct stat s1, s2;
TEST_THAT(::lstat(f1, &s1) == 0);
TEST_THAT(::lstat(f2, &s2) == 0);
+#ifdef HAVE_SYS_XATTR_H
+ {
+ std::map<std::string,std::string> xattr1, xattr2;
+ if(!readxattr_into_map(f1, xattr1)
+ || !readxattr_into_map(f2, xattr2))
+ {
+ return false;
+ }
+ if(!(xattr1 == xattr2))
+ {
+ return false;
+ }
+ }
+#endif // HAVE_SYS_XATTR_H
+
// if link, just make sure other file is a link too, and that the link to names match
if((s1.st_mode & S_IFMT) == S_IFLNK)
{
@@ -143,6 +324,49 @@ int test_basics()
TEST_THAT(t1_r == t1b);
TEST_THAT(t1b_r == t1);
+#ifdef HAVE_SYS_XATTR_H
+ // Write some attributes to the file, checking for ENOTSUP
+ bool xattrNotSupported = false;
+ if(!write_xattr_test("testfiles/test1", "attr_1", 1276, &xattrNotSupported) && xattrNotSupported)
+ {
+ ::printf("***********\nYour platform supports xattr, but your filesystem does not.\nSkipping tests.\n***********\n");
+ }
+ else
+ {
+ BackupClientFileAttributes x1, x2, x3, x4;
+
+ // Write more attributes
+ TEST_THAT(write_xattr_test("testfiles/test1", "attr_2", 3427));
+ TEST_THAT(write_xattr_test("testfiles/test1", "sadfohij39998.3hj", 123));
+
+ // Read file attributes
+ x1.ReadAttributes("testfiles/test1");
+
+ // Write file attributes
+ FILE *f = fopen("testfiles/test1_nx", "w");
+ fclose(f);
+ x1.WriteAttributes("testfiles/test1_nx");
+
+ // Compare to see if xattr copied
+ TEST_THAT(attrmatch("testfiles/test1", "testfiles/test1_nx"));
+
+ // Add more attributes to a file
+ x2.ReadAttributes("testfiles/test1");
+ TEST_THAT(write_xattr_test("testfiles/test1", "328989sj..sdf", 23));
+
+ // Read them again, and check that the Compare() function detects that they're different
+ x3.ReadAttributes("testfiles/test1");
+ TEST_THAT(x1.Compare(x2, true, true));
+ TEST_THAT(!x1.Compare(x3, true, true));
+
+ // Change the value of one of them, leaving the size the same.
+ TEST_THAT(write_xattr_test("testfiles/test1", "328989sj..sdf", 23));
+ x4.ReadAttributes("testfiles/test1");
+ TEST_THAT(!x1.Compare(x4, true, true));
+ }
+ finish_with_write_xattr_test();
+#endif // HAVE_SYS_XATTR_H
+
return 0;
}