|
a/src/utils/pxattr.cpp |
|
b/src/utils/pxattr.cpp |
|
... |
|
... |
21 |
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21 |
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
22 |
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22 |
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
23 |
OTHER DEALINGS IN THE SOFTWARE.
|
23 |
OTHER DEALINGS IN THE SOFTWARE.
|
24 |
*/
|
24 |
*/
|
25 |
|
25 |
|
|
|
26 |
/** \file pxattr.cpp
|
|
|
27 |
\brief This is a comment for file pxattr.cpp
|
|
|
28 |
*/
|
|
|
29 |
|
26 |
// We want this to compile even to empty on non-supported systems. makes
|
30 |
// We want this to compile even to empty on non-supported systems. makes
|
27 |
// things easier for autoconf
|
31 |
// things easier for autoconf
|
28 |
#if defined(__FreeBSD__) || defined(__gnu_linux__) || defined(__APPLE__)
|
32 |
#if defined(__FreeBSD__) || defined(__gnu_linux__) || defined(__APPLE__) || \
|
|
|
33 |
defined(__CYGWIN32__)
|
29 |
|
34 |
|
30 |
#ifndef TEST_PXATTR
|
35 |
#ifndef TEST_PXATTR
|
31 |
|
36 |
|
32 |
#include <sys/types.h>
|
37 |
#include <sys/types.h>
|
33 |
#include <errno.h>
|
38 |
#include <errno.h>
|
|
... |
|
... |
36 |
|
41 |
|
37 |
#if defined(__FreeBSD__)
|
42 |
#if defined(__FreeBSD__)
|
38 |
#include <sys/extattr.h>
|
43 |
#include <sys/extattr.h>
|
39 |
#include <sys/uio.h>
|
44 |
#include <sys/uio.h>
|
40 |
#elif defined(__gnu_linux__)
|
45 |
#elif defined(__gnu_linux__)
|
|
|
46 |
#include <sys/xattr.h>
|
|
|
47 |
#elif defined(__CYGWIN32__)
|
41 |
#include <sys/xattr.h>
|
48 |
#include <sys/xattr.h>
|
42 |
#elif defined(__APPLE__)
|
49 |
#elif defined(__APPLE__)
|
43 |
#include <sys/xattr.h>
|
50 |
#include <sys/xattr.h>
|
44 |
#else
|
51 |
#else
|
45 |
#error "Unknown system can't compile"
|
52 |
#error "Unknown system can't compile"
|
|
... |
|
... |
487 |
#include <string>
|
494 |
#include <string>
|
488 |
using namespace std;
|
495 |
using namespace std;
|
489 |
|
496 |
|
490 |
#include "pxattr.h"
|
497 |
#include "pxattr.h"
|
491 |
|
498 |
|
492 |
static void dotests()
|
499 |
static void dotests();
|
493 |
{
|
|
|
494 |
static const char *tfn = "pxattr_testtmp.xyz";
|
|
|
495 |
static const char *NAMES[] = {"ORG.PXATTR.NAME1", "ORG.PXATTR.N2",
|
|
|
496 |
"ORG.PXATTR.LONGGGGGGGGisSSSHHHHHHHHHNAME3"};
|
|
|
497 |
static const char *VALUES[] = {"VALUE1", "VALUE2", "VALUE3"};
|
|
|
498 |
static bool verbose = true;
|
|
|
499 |
|
|
|
500 |
/* Create test file if it doesn't exist, remove all attributes */
|
|
|
501 |
int fd = open(tfn, O_RDWR|O_CREAT, 0755);
|
|
|
502 |
if (fd < 0) {
|
|
|
503 |
perror("open/create");
|
|
|
504 |
exit(1);
|
|
|
505 |
}
|
|
|
506 |
|
|
|
507 |
|
|
|
508 |
if (verbose)
|
|
|
509 |
fprintf(stdout, "Cleanup old attrs\n");
|
|
|
510 |
vector<string> names;
|
|
|
511 |
if (!pxattr::list(tfn, &names)) {
|
|
|
512 |
perror("pxattr::list");
|
|
|
513 |
exit(1);
|
|
|
514 |
}
|
|
|
515 |
for (vector<string>::const_iterator it = names.begin();
|
|
|
516 |
it != names.end(); it++) {
|
|
|
517 |
string value;
|
|
|
518 |
if (!pxattr::del(fd, *it)) {
|
|
|
519 |
perror("pxattr::del");
|
|
|
520 |
exit(1);
|
|
|
521 |
}
|
|
|
522 |
}
|
|
|
523 |
/* Check that there are no attributes left */
|
|
|
524 |
names.clear();
|
|
|
525 |
if (!pxattr::list(tfn, &names)) {
|
|
|
526 |
perror("pxattr::list");
|
|
|
527 |
exit(1);
|
|
|
528 |
}
|
|
|
529 |
if (names.size() != 0) {
|
|
|
530 |
fprintf(stderr, "Attributes remain after initial cleanup !\n");
|
|
|
531 |
for (vector<string>::const_iterator it = names.begin();
|
|
|
532 |
it != names.end(); it++) {
|
|
|
533 |
fprintf(stderr, "%s\n", (*it).c_str());
|
|
|
534 |
}
|
|
|
535 |
exit(1);
|
|
|
536 |
}
|
|
|
537 |
|
|
|
538 |
/* Create attributes, check existence and value */
|
|
|
539 |
if (verbose)
|
|
|
540 |
fprintf(stdout, "Creating extended attributes\n");
|
|
|
541 |
for (int i = 0; i < 3; i++) {
|
|
|
542 |
if (!pxattr::set(fd, NAMES[i], VALUES[i])) {
|
|
|
543 |
perror("pxattr::set");
|
|
|
544 |
exit(1);
|
|
|
545 |
}
|
|
|
546 |
}
|
|
|
547 |
if (verbose)
|
|
|
548 |
fprintf(stdout, "Checking creation\n");
|
|
|
549 |
for (int i = 0; i < 3; i++) {
|
|
|
550 |
string value;
|
|
|
551 |
if (!pxattr::get(tfn, NAMES[i], &value)) {
|
|
|
552 |
perror("pxattr::get");
|
|
|
553 |
exit(1);
|
|
|
554 |
}
|
|
|
555 |
if (value.compare(VALUES[i])) {
|
|
|
556 |
fprintf(stderr, "Wrong value after create !\n");
|
|
|
557 |
exit(1);
|
|
|
558 |
}
|
|
|
559 |
}
|
|
|
560 |
|
|
|
561 |
/* Delete one, check list */
|
|
|
562 |
if (verbose)
|
|
|
563 |
fprintf(stdout, "Delete one\n");
|
|
|
564 |
if (!pxattr::del(tfn, NAMES[1])) {
|
|
|
565 |
perror("pxattr::del one name");
|
|
|
566 |
exit(1);
|
|
|
567 |
}
|
|
|
568 |
if (verbose)
|
|
|
569 |
fprintf(stdout, "Check list\n");
|
|
|
570 |
for (int i = 0; i < 3; i++) {
|
|
|
571 |
string value;
|
|
|
572 |
if (!pxattr::get(fd, NAMES[i], &value)) {
|
|
|
573 |
if (i == 1)
|
|
|
574 |
continue;
|
|
|
575 |
perror("pxattr::get");
|
|
|
576 |
exit(1);
|
|
|
577 |
} else if (i == 1) {
|
|
|
578 |
fprintf(stderr, "Name at index 1 still exists after deletion\n");
|
|
|
579 |
exit(1);
|
|
|
580 |
}
|
|
|
581 |
if (value.compare(VALUES[i])) {
|
|
|
582 |
fprintf(stderr, "Wrong value after delete 1 !\n");
|
|
|
583 |
exit(1);
|
|
|
584 |
}
|
|
|
585 |
}
|
|
|
586 |
|
|
|
587 |
/* Test the CREATE/REPLACE flags */
|
|
|
588 |
// Set existing with flag CREATE should fail
|
|
|
589 |
if (verbose)
|
|
|
590 |
fprintf(stdout, "Testing CREATE/REPLACE flags use\n");
|
|
|
591 |
if (pxattr::set(tfn, NAMES[0], VALUES[0], pxattr::PXATTR_CREATE)) {
|
|
|
592 |
fprintf(stderr, "Create existing with flag CREATE succeeded !\n");
|
|
|
593 |
exit(1);
|
|
|
594 |
}
|
|
|
595 |
// Set new with flag REPLACE should fail
|
|
|
596 |
if (pxattr::set(tfn, NAMES[1], VALUES[1], pxattr::PXATTR_REPLACE)) {
|
|
|
597 |
fprintf(stderr, "Create new with flag REPLACE succeeded !\n");
|
|
|
598 |
exit(1);
|
|
|
599 |
}
|
|
|
600 |
// Set new with flag CREATE should succeed
|
|
|
601 |
if (!pxattr::set(fd, NAMES[1], VALUES[1], pxattr::PXATTR_CREATE)) {
|
|
|
602 |
fprintf(stderr, "Create new with flag CREATE failed !\n");
|
|
|
603 |
exit(1);
|
|
|
604 |
}
|
|
|
605 |
// Set existing with flag REPLACE should succeed
|
|
|
606 |
if (!pxattr::set(fd, NAMES[0], VALUES[0], pxattr::PXATTR_REPLACE)) {
|
|
|
607 |
fprintf(stderr, "Create existing with flag REPLACE failed !\n");
|
|
|
608 |
exit(1);
|
|
|
609 |
}
|
|
|
610 |
close(fd);
|
|
|
611 |
unlink(tfn);
|
|
|
612 |
exit(0);
|
|
|
613 |
}
|
|
|
614 |
|
500 |
|
615 |
// \-quote character c in input \ -> \\, nl -> \n cr -> \rc -> \c
|
501 |
// \-quote character c in input \ -> \\, nl -> \n cr -> \rc -> \c
|
616 |
static void quote(const string& in, string& out, int c)
|
502 |
static void quote(const string& in, string& out, int c)
|
617 |
{
|
503 |
{
|
618 |
out.clear();
|
504 |
out.clear();
|
|
... |
|
... |
936 |
}
|
822 |
}
|
937 |
|
823 |
|
938 |
exit(0);
|
824 |
exit(0);
|
939 |
}
|
825 |
}
|
940 |
|
826 |
|
|
|
827 |
static void fatal(const string& s)
|
|
|
828 |
{
|
|
|
829 |
perror(s.c_str());
|
|
|
830 |
exit(1);
|
|
|
831 |
}
|
941 |
|
832 |
|
|
|
833 |
static bool testbackups()
|
|
|
834 |
{
|
|
|
835 |
static const char *top = "ttop";
|
|
|
836 |
static const char *d1 = "d1";
|
|
|
837 |
static const char *d2 = "d2";
|
|
|
838 |
static const char *tfn1 = "tpxattr1.txt";
|
|
|
839 |
static const char *tfn2 = "tpxattr2.txt";
|
|
|
840 |
static const char *dump = "attrdump.txt";
|
|
|
841 |
static const char *NAMES[] = {"ORG.PXATTR.NAME1",
|
|
|
842 |
"ORG=PXATTR\"=\\=\n",
|
|
|
843 |
"=", "Name4"};
|
|
|
844 |
static const char *VALUES[] =
|
|
|
845 |
{"VALUE1", "VALUE2", "VALUE3=VALUE3equal",
|
|
|
846 |
"VALUE4\n is more like"
|
|
|
847 |
" normal text\n with new lines and \"\\\" \\\" backslashes"};
|
|
|
848 |
|
|
|
849 |
static const int nattrs = sizeof(NAMES) / sizeof(char *);
|
|
|
850 |
|
|
|
851 |
if (mkdir(top, 0777))
|
|
|
852 |
fatal("Cant mkdir ttop");
|
|
|
853 |
if (chdir(top))
|
|
|
854 |
fatal("cant chdir ttop");
|
|
|
855 |
if (mkdir(d1, 0777) || mkdir(d2, 0777))
|
|
|
856 |
fatal("Can't mkdir ttdop/dx\n");
|
|
|
857 |
if (chdir(d1))
|
|
|
858 |
fatal("chdir d1");
|
|
|
859 |
|
|
|
860 |
int fd;
|
|
|
861 |
if ((fd = open(tfn1, O_RDWR|O_CREAT, 0755)) < 0)
|
|
|
862 |
fatal("create d1/tpxattr1.txt");
|
|
|
863 |
/* Set attrs */
|
|
|
864 |
for (int i = 0; i < nattrs; i++) {
|
|
|
865 |
if (!pxattr::set(fd, NAMES[i], VALUES[i]))
|
|
|
866 |
fatal("pxattr::set");
|
|
|
867 |
}
|
|
|
868 |
close(fd);
|
|
|
869 |
if ((fd = open(tfn2, O_RDWR|O_CREAT, 0755)) < 0)
|
|
|
870 |
fatal("create d1/tpxattr2.txt");
|
|
|
871 |
/* Set attrs */
|
|
|
872 |
for (int i = 0; i < nattrs; i++) {
|
|
|
873 |
if (!pxattr::set(fd, NAMES[i], VALUES[i]))
|
|
|
874 |
fatal("pxattr::set");
|
|
|
875 |
}
|
|
|
876 |
close(fd);
|
|
|
877 |
|
|
|
878 |
/* Create dump */
|
|
|
879 |
string cmd;
|
|
|
880 |
cmd = string("pxattr -lR . > " ) + dump;
|
|
|
881 |
if (system(cmd.c_str()))
|
|
|
882 |
fatal(cmd + " in d1");
|
|
|
883 |
if (chdir("../d2"))
|
|
|
884 |
fatal("chdir ../d2");
|
|
|
885 |
if (close(open(tfn1, O_RDWR|O_CREAT, 0755)))
|
|
|
886 |
fatal("create d2/tpxattr.txt");
|
|
|
887 |
if (close(open(tfn2, O_RDWR|O_CREAT, 0755)))
|
|
|
888 |
fatal("create d2/tpxattr.txt");
|
|
|
889 |
cmd = string("pxattr -S ../d1/" ) + dump;
|
|
|
890 |
if (system(cmd.c_str()))
|
|
|
891 |
fatal(cmd);
|
|
|
892 |
cmd = string("pxattr -lR . > " ) + dump;
|
|
|
893 |
if (system(cmd.c_str()))
|
|
|
894 |
fatal(cmd + " in d2");
|
|
|
895 |
cmd = string("diff ../d1/") + dump + " " + dump;
|
|
|
896 |
if (system(cmd.c_str()))
|
|
|
897 |
fatal(cmd);
|
|
|
898 |
cmd = string("cat ") + dump;
|
|
|
899 |
system(cmd.c_str());
|
|
|
900 |
|
|
|
901 |
if (1) {
|
|
|
902 |
unlink(dump);
|
|
|
903 |
unlink(tfn1);
|
|
|
904 |
unlink(tfn2);
|
|
|
905 |
if (chdir("../d1"))
|
|
|
906 |
fatal("chdir ../d1");
|
|
|
907 |
unlink(dump);
|
|
|
908 |
unlink(tfn1);
|
|
|
909 |
unlink(tfn2);
|
|
|
910 |
if (chdir("../"))
|
|
|
911 |
fatal("chdir .. 1");
|
|
|
912 |
if (rmdir(d1))
|
|
|
913 |
fatal("rmdir d1");
|
|
|
914 |
if (rmdir(d2))
|
|
|
915 |
fatal("rmdir d2");
|
|
|
916 |
if (chdir("../"))
|
|
|
917 |
fatal("chdir .. 2");
|
|
|
918 |
if (rmdir(top))
|
|
|
919 |
fatal("rmdir ttop");
|
|
|
920 |
}
|
|
|
921 |
return true;
|
|
|
922 |
}
|
|
|
923 |
|
|
|
924 |
static void dotests()
|
|
|
925 |
{
|
|
|
926 |
static const char *tfn = "pxattr_testtmp.xyz";
|
|
|
927 |
static const char *NAMES[] = {"ORG.PXATTR.NAME1", "ORG.PXATTR.N2",
|
|
|
928 |
"ORG.PXATTR.LONGGGGGGGGisSSSHHHHHHHHHNAME3"};
|
|
|
929 |
static const char *VALUES[] = {"VALUE1", "VALUE2", "VALUE3"};
|
|
|
930 |
static bool verbose = true;
|
|
|
931 |
|
|
|
932 |
/* Create test file if it doesn't exist, remove all attributes */
|
|
|
933 |
int fd = open(tfn, O_RDWR|O_CREAT, 0755);
|
|
|
934 |
if (fd < 0) {
|
|
|
935 |
perror("open/create");
|
|
|
936 |
exit(1);
|
|
|
937 |
}
|
|
|
938 |
|
|
|
939 |
if (verbose)
|
|
|
940 |
fprintf(stdout, "Cleanup old attrs\n");
|
|
|
941 |
vector<string> names;
|
|
|
942 |
if (!pxattr::list(tfn, &names)) {
|
|
|
943 |
perror("pxattr::list");
|
|
|
944 |
exit(1);
|
|
|
945 |
}
|
|
|
946 |
for (vector<string>::const_iterator it = names.begin();
|
|
|
947 |
it != names.end(); it++) {
|
|
|
948 |
string value;
|
|
|
949 |
if (!pxattr::del(fd, *it)) {
|
|
|
950 |
perror("pxattr::del");
|
|
|
951 |
exit(1);
|
|
|
952 |
}
|
|
|
953 |
}
|
|
|
954 |
/* Check that there are no attributes left */
|
|
|
955 |
names.clear();
|
|
|
956 |
if (!pxattr::list(tfn, &names)) {
|
|
|
957 |
perror("pxattr::list");
|
|
|
958 |
exit(1);
|
|
|
959 |
}
|
|
|
960 |
if (names.size() != 0) {
|
|
|
961 |
fprintf(stderr, "Attributes remain after initial cleanup !\n");
|
|
|
962 |
for (vector<string>::const_iterator it = names.begin();
|
|
|
963 |
it != names.end(); it++) {
|
|
|
964 |
fprintf(stderr, "%s\n", (*it).c_str());
|
|
|
965 |
}
|
|
|
966 |
exit(1);
|
|
|
967 |
}
|
|
|
968 |
|
|
|
969 |
/* Create attributes, check existence and value */
|
|
|
970 |
if (verbose)
|
|
|
971 |
fprintf(stdout, "Creating extended attributes\n");
|
|
|
972 |
for (int i = 0; i < 3; i++) {
|
|
|
973 |
if (!pxattr::set(fd, NAMES[i], VALUES[i])) {
|
|
|
974 |
perror("pxattr::set");
|
|
|
975 |
exit(1);
|
|
|
976 |
}
|
|
|
977 |
}
|
|
|
978 |
if (verbose)
|
|
|
979 |
fprintf(stdout, "Checking creation\n");
|
|
|
980 |
for (int i = 0; i < 3; i++) {
|
|
|
981 |
string value;
|
|
|
982 |
if (!pxattr::get(tfn, NAMES[i], &value)) {
|
|
|
983 |
perror("pxattr::get");
|
|
|
984 |
exit(1);
|
|
|
985 |
}
|
|
|
986 |
if (value.compare(VALUES[i])) {
|
|
|
987 |
fprintf(stderr, "Wrong value after create !\n");
|
|
|
988 |
exit(1);
|
|
|
989 |
}
|
|
|
990 |
}
|
|
|
991 |
|
|
|
992 |
/* Delete one, check list */
|
|
|
993 |
if (verbose)
|
|
|
994 |
fprintf(stdout, "Delete one\n");
|
|
|
995 |
if (!pxattr::del(tfn, NAMES[1])) {
|
|
|
996 |
perror("pxattr::del one name");
|
|
|
997 |
exit(1);
|
|
|
998 |
}
|
|
|
999 |
if (verbose)
|
|
|
1000 |
fprintf(stdout, "Check list\n");
|
|
|
1001 |
for (int i = 0; i < 3; i++) {
|
|
|
1002 |
string value;
|
|
|
1003 |
if (!pxattr::get(fd, NAMES[i], &value)) {
|
|
|
1004 |
if (i == 1)
|
|
|
1005 |
continue;
|
|
|
1006 |
perror("pxattr::get");
|
|
|
1007 |
exit(1);
|
|
|
1008 |
} else if (i == 1) {
|
|
|
1009 |
fprintf(stderr, "Name at index 1 still exists after deletion\n");
|
|
|
1010 |
exit(1);
|
|
|
1011 |
}
|
|
|
1012 |
if (value.compare(VALUES[i])) {
|
|
|
1013 |
fprintf(stderr, "Wrong value after delete 1 !\n");
|
|
|
1014 |
exit(1);
|
|
|
1015 |
}
|
|
|
1016 |
}
|
|
|
1017 |
|
|
|
1018 |
/* Test the CREATE/REPLACE flags */
|
|
|
1019 |
// Set existing with flag CREATE should fail
|
|
|
1020 |
if (verbose)
|
|
|
1021 |
fprintf(stdout, "Testing CREATE/REPLACE flags use\n");
|
|
|
1022 |
if (pxattr::set(tfn, NAMES[0], VALUES[0], pxattr::PXATTR_CREATE)) {
|
|
|
1023 |
fprintf(stderr, "Create existing with flag CREATE succeeded !\n");
|
|
|
1024 |
exit(1);
|
|
|
1025 |
}
|
|
|
1026 |
// Set new with flag REPLACE should fail
|
|
|
1027 |
if (pxattr::set(tfn, NAMES[1], VALUES[1], pxattr::PXATTR_REPLACE)) {
|
|
|
1028 |
fprintf(stderr, "Create new with flag REPLACE succeeded !\n");
|
|
|
1029 |
exit(1);
|
|
|
1030 |
}
|
|
|
1031 |
// Set new with flag CREATE should succeed
|
|
|
1032 |
if (!pxattr::set(fd, NAMES[1], VALUES[1], pxattr::PXATTR_CREATE)) {
|
|
|
1033 |
fprintf(stderr, "Create new with flag CREATE failed !\n");
|
|
|
1034 |
exit(1);
|
|
|
1035 |
}
|
|
|
1036 |
// Set existing with flag REPLACE should succeed
|
|
|
1037 |
if (!pxattr::set(fd, NAMES[0], VALUES[0], pxattr::PXATTR_REPLACE)) {
|
|
|
1038 |
fprintf(stderr, "Create existing with flag REPLACE failed !\n");
|
|
|
1039 |
exit(1);
|
|
|
1040 |
}
|
|
|
1041 |
close(fd);
|
|
|
1042 |
unlink(tfn);
|
|
|
1043 |
|
|
|
1044 |
if (testbackups())
|
|
|
1045 |
exit(0);
|
|
|
1046 |
exit(1);
|
|
|
1047 |
}
|
942 |
#endif // Testing pxattr
|
1048 |
#endif // Testing pxattr
|
943 |
|
1049 |
|
944 |
#endif // Supported systems.
|
1050 |
#endif // Supported systems.
|