--- a/src/utils/pxattr.cpp
+++ b/src/utils/pxattr.cpp
@@ -23,9 +23,14 @@
OTHER DEALINGS IN THE SOFTWARE.
*/
+/** \file pxattr.cpp
+ \brief This is a comment for file pxattr.cpp
+ */
+
// We want this to compile even to empty on non-supported systems. makes
// things easier for autoconf
-#if defined(__FreeBSD__) || defined(__gnu_linux__) || defined(__APPLE__)
+#if defined(__FreeBSD__) || defined(__gnu_linux__) || defined(__APPLE__) || \
+ defined(__CYGWIN32__)
#ifndef TEST_PXATTR
@@ -38,6 +43,8 @@
#include <sys/extattr.h>
#include <sys/uio.h>
#elif defined(__gnu_linux__)
+#include <sys/xattr.h>
+#elif defined(__CYGWIN32__)
#include <sys/xattr.h>
#elif defined(__APPLE__)
#include <sys/xattr.h>
@@ -489,128 +496,7 @@
#include "pxattr.h"
-static void dotests()
-{
- static const char *tfn = "pxattr_testtmp.xyz";
- static const char *NAMES[] = {"ORG.PXATTR.NAME1", "ORG.PXATTR.N2",
- "ORG.PXATTR.LONGGGGGGGGisSSSHHHHHHHHHNAME3"};
- static const char *VALUES[] = {"VALUE1", "VALUE2", "VALUE3"};
- static bool verbose = true;
-
- /* Create test file if it doesn't exist, remove all attributes */
- int fd = open(tfn, O_RDWR|O_CREAT, 0755);
- if (fd < 0) {
- perror("open/create");
- exit(1);
- }
-
-
- if (verbose)
- fprintf(stdout, "Cleanup old attrs\n");
- vector<string> names;
- if (!pxattr::list(tfn, &names)) {
- perror("pxattr::list");
- exit(1);
- }
- for (vector<string>::const_iterator it = names.begin();
- it != names.end(); it++) {
- string value;
- if (!pxattr::del(fd, *it)) {
- perror("pxattr::del");
- exit(1);
- }
- }
- /* Check that there are no attributes left */
- names.clear();
- if (!pxattr::list(tfn, &names)) {
- perror("pxattr::list");
- exit(1);
- }
- if (names.size() != 0) {
- fprintf(stderr, "Attributes remain after initial cleanup !\n");
- for (vector<string>::const_iterator it = names.begin();
- it != names.end(); it++) {
- fprintf(stderr, "%s\n", (*it).c_str());
- }
- exit(1);
- }
-
- /* Create attributes, check existence and value */
- if (verbose)
- fprintf(stdout, "Creating extended attributes\n");
- for (int i = 0; i < 3; i++) {
- if (!pxattr::set(fd, NAMES[i], VALUES[i])) {
- perror("pxattr::set");
- exit(1);
- }
- }
- if (verbose)
- fprintf(stdout, "Checking creation\n");
- for (int i = 0; i < 3; i++) {
- string value;
- if (!pxattr::get(tfn, NAMES[i], &value)) {
- perror("pxattr::get");
- exit(1);
- }
- if (value.compare(VALUES[i])) {
- fprintf(stderr, "Wrong value after create !\n");
- exit(1);
- }
- }
-
- /* Delete one, check list */
- if (verbose)
- fprintf(stdout, "Delete one\n");
- if (!pxattr::del(tfn, NAMES[1])) {
- perror("pxattr::del one name");
- exit(1);
- }
- if (verbose)
- fprintf(stdout, "Check list\n");
- for (int i = 0; i < 3; i++) {
- string value;
- if (!pxattr::get(fd, NAMES[i], &value)) {
- if (i == 1)
- continue;
- perror("pxattr::get");
- exit(1);
- } else if (i == 1) {
- fprintf(stderr, "Name at index 1 still exists after deletion\n");
- exit(1);
- }
- if (value.compare(VALUES[i])) {
- fprintf(stderr, "Wrong value after delete 1 !\n");
- exit(1);
- }
- }
-
- /* Test the CREATE/REPLACE flags */
- // Set existing with flag CREATE should fail
- if (verbose)
- fprintf(stdout, "Testing CREATE/REPLACE flags use\n");
- if (pxattr::set(tfn, NAMES[0], VALUES[0], pxattr::PXATTR_CREATE)) {
- fprintf(stderr, "Create existing with flag CREATE succeeded !\n");
- exit(1);
- }
- // Set new with flag REPLACE should fail
- if (pxattr::set(tfn, NAMES[1], VALUES[1], pxattr::PXATTR_REPLACE)) {
- fprintf(stderr, "Create new with flag REPLACE succeeded !\n");
- exit(1);
- }
- // Set new with flag CREATE should succeed
- if (!pxattr::set(fd, NAMES[1], VALUES[1], pxattr::PXATTR_CREATE)) {
- fprintf(stderr, "Create new with flag CREATE failed !\n");
- exit(1);
- }
- // Set existing with flag REPLACE should succeed
- if (!pxattr::set(fd, NAMES[0], VALUES[0], pxattr::PXATTR_REPLACE)) {
- fprintf(stderr, "Create existing with flag REPLACE failed !\n");
- exit(1);
- }
- close(fd);
- unlink(tfn);
- exit(0);
-}
+static void dotests();
// \-quote character c in input \ -> \\, nl -> \n cr -> \rc -> \c
static void quote(const string& in, string& out, int c)
@@ -938,7 +824,227 @@
exit(0);
}
-
+static void fatal(const string& s)
+{
+ perror(s.c_str());
+ exit(1);
+}
+
+static bool testbackups()
+{
+ static const char *top = "ttop";
+ static const char *d1 = "d1";
+ static const char *d2 = "d2";
+ static const char *tfn1 = "tpxattr1.txt";
+ static const char *tfn2 = "tpxattr2.txt";
+ static const char *dump = "attrdump.txt";
+ static const char *NAMES[] = {"ORG.PXATTR.NAME1",
+ "ORG=PXATTR\"=\\=\n",
+ "=", "Name4"};
+ static const char *VALUES[] =
+ {"VALUE1", "VALUE2", "VALUE3=VALUE3equal",
+ "VALUE4\n is more like"
+ " normal text\n with new lines and \"\\\" \\\" backslashes"};
+
+ static const int nattrs = sizeof(NAMES) / sizeof(char *);
+
+ if (mkdir(top, 0777))
+ fatal("Cant mkdir ttop");
+ if (chdir(top))
+ fatal("cant chdir ttop");
+ if (mkdir(d1, 0777) || mkdir(d2, 0777))
+ fatal("Can't mkdir ttdop/dx\n");
+ if (chdir(d1))
+ fatal("chdir d1");
+
+ int fd;
+ if ((fd = open(tfn1, O_RDWR|O_CREAT, 0755)) < 0)
+ fatal("create d1/tpxattr1.txt");
+ /* Set attrs */
+ for (int i = 0; i < nattrs; i++) {
+ if (!pxattr::set(fd, NAMES[i], VALUES[i]))
+ fatal("pxattr::set");
+ }
+ close(fd);
+ if ((fd = open(tfn2, O_RDWR|O_CREAT, 0755)) < 0)
+ fatal("create d1/tpxattr2.txt");
+ /* Set attrs */
+ for (int i = 0; i < nattrs; i++) {
+ if (!pxattr::set(fd, NAMES[i], VALUES[i]))
+ fatal("pxattr::set");
+ }
+ close(fd);
+
+ /* Create dump */
+ string cmd;
+ cmd = string("pxattr -lR . > " ) + dump;
+ if (system(cmd.c_str()))
+ fatal(cmd + " in d1");
+ if (chdir("../d2"))
+ fatal("chdir ../d2");
+ if (close(open(tfn1, O_RDWR|O_CREAT, 0755)))
+ fatal("create d2/tpxattr.txt");
+ if (close(open(tfn2, O_RDWR|O_CREAT, 0755)))
+ fatal("create d2/tpxattr.txt");
+ cmd = string("pxattr -S ../d1/" ) + dump;
+ if (system(cmd.c_str()))
+ fatal(cmd);
+ cmd = string("pxattr -lR . > " ) + dump;
+ if (system(cmd.c_str()))
+ fatal(cmd + " in d2");
+ cmd = string("diff ../d1/") + dump + " " + dump;
+ if (system(cmd.c_str()))
+ fatal(cmd);
+ cmd = string("cat ") + dump;
+ system(cmd.c_str());
+
+ if (1) {
+ unlink(dump);
+ unlink(tfn1);
+ unlink(tfn2);
+ if (chdir("../d1"))
+ fatal("chdir ../d1");
+ unlink(dump);
+ unlink(tfn1);
+ unlink(tfn2);
+ if (chdir("../"))
+ fatal("chdir .. 1");
+ if (rmdir(d1))
+ fatal("rmdir d1");
+ if (rmdir(d2))
+ fatal("rmdir d2");
+ if (chdir("../"))
+ fatal("chdir .. 2");
+ if (rmdir(top))
+ fatal("rmdir ttop");
+ }
+ return true;
+}
+
+static void dotests()
+{
+ static const char *tfn = "pxattr_testtmp.xyz";
+ static const char *NAMES[] = {"ORG.PXATTR.NAME1", "ORG.PXATTR.N2",
+ "ORG.PXATTR.LONGGGGGGGGisSSSHHHHHHHHHNAME3"};
+ static const char *VALUES[] = {"VALUE1", "VALUE2", "VALUE3"};
+ static bool verbose = true;
+
+ /* Create test file if it doesn't exist, remove all attributes */
+ int fd = open(tfn, O_RDWR|O_CREAT, 0755);
+ if (fd < 0) {
+ perror("open/create");
+ exit(1);
+ }
+
+ if (verbose)
+ fprintf(stdout, "Cleanup old attrs\n");
+ vector<string> names;
+ if (!pxattr::list(tfn, &names)) {
+ perror("pxattr::list");
+ exit(1);
+ }
+ for (vector<string>::const_iterator it = names.begin();
+ it != names.end(); it++) {
+ string value;
+ if (!pxattr::del(fd, *it)) {
+ perror("pxattr::del");
+ exit(1);
+ }
+ }
+ /* Check that there are no attributes left */
+ names.clear();
+ if (!pxattr::list(tfn, &names)) {
+ perror("pxattr::list");
+ exit(1);
+ }
+ if (names.size() != 0) {
+ fprintf(stderr, "Attributes remain after initial cleanup !\n");
+ for (vector<string>::const_iterator it = names.begin();
+ it != names.end(); it++) {
+ fprintf(stderr, "%s\n", (*it).c_str());
+ }
+ exit(1);
+ }
+
+ /* Create attributes, check existence and value */
+ if (verbose)
+ fprintf(stdout, "Creating extended attributes\n");
+ for (int i = 0; i < 3; i++) {
+ if (!pxattr::set(fd, NAMES[i], VALUES[i])) {
+ perror("pxattr::set");
+ exit(1);
+ }
+ }
+ if (verbose)
+ fprintf(stdout, "Checking creation\n");
+ for (int i = 0; i < 3; i++) {
+ string value;
+ if (!pxattr::get(tfn, NAMES[i], &value)) {
+ perror("pxattr::get");
+ exit(1);
+ }
+ if (value.compare(VALUES[i])) {
+ fprintf(stderr, "Wrong value after create !\n");
+ exit(1);
+ }
+ }
+
+ /* Delete one, check list */
+ if (verbose)
+ fprintf(stdout, "Delete one\n");
+ if (!pxattr::del(tfn, NAMES[1])) {
+ perror("pxattr::del one name");
+ exit(1);
+ }
+ if (verbose)
+ fprintf(stdout, "Check list\n");
+ for (int i = 0; i < 3; i++) {
+ string value;
+ if (!pxattr::get(fd, NAMES[i], &value)) {
+ if (i == 1)
+ continue;
+ perror("pxattr::get");
+ exit(1);
+ } else if (i == 1) {
+ fprintf(stderr, "Name at index 1 still exists after deletion\n");
+ exit(1);
+ }
+ if (value.compare(VALUES[i])) {
+ fprintf(stderr, "Wrong value after delete 1 !\n");
+ exit(1);
+ }
+ }
+
+ /* Test the CREATE/REPLACE flags */
+ // Set existing with flag CREATE should fail
+ if (verbose)
+ fprintf(stdout, "Testing CREATE/REPLACE flags use\n");
+ if (pxattr::set(tfn, NAMES[0], VALUES[0], pxattr::PXATTR_CREATE)) {
+ fprintf(stderr, "Create existing with flag CREATE succeeded !\n");
+ exit(1);
+ }
+ // Set new with flag REPLACE should fail
+ if (pxattr::set(tfn, NAMES[1], VALUES[1], pxattr::PXATTR_REPLACE)) {
+ fprintf(stderr, "Create new with flag REPLACE succeeded !\n");
+ exit(1);
+ }
+ // Set new with flag CREATE should succeed
+ if (!pxattr::set(fd, NAMES[1], VALUES[1], pxattr::PXATTR_CREATE)) {
+ fprintf(stderr, "Create new with flag CREATE failed !\n");
+ exit(1);
+ }
+ // Set existing with flag REPLACE should succeed
+ if (!pxattr::set(fd, NAMES[0], VALUES[0], pxattr::PXATTR_REPLACE)) {
+ fprintf(stderr, "Create existing with flag REPLACE failed !\n");
+ exit(1);
+ }
+ close(fd);
+ unlink(tfn);
+
+ if (testbackups())
+ exit(0);
+ exit(1);
+}
#endif // Testing pxattr
#endif // Supported systems.