]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- simplify XA comparison (use only syscalls prefixed with 'l' to deal with links)
authorOndrej Kozina <okozina@redhat.com>
Mon, 18 Feb 2013 12:29:04 +0000 (13:29 +0100)
committerOndrej Kozina <okozina@redhat.com>
Wed, 27 Feb 2013 16:30:10 +0000 (17:30 +0100)
client/snapper.cc
snapper/Compare.cc
snapper/Compare.h
snapper/File.cc
snapper/XAttributes.cc
snapper/XAttributes.h

index 8cf627bdd94d2050eb29d64cccca15dd025df0a7..f55eb00ea569c2022034f3a925dd26419bfa19d9 100644 (file)
@@ -1125,19 +1125,8 @@ help_xa_diff()
 void
 print_xa_diff(const string loc_pre, const string loc_post)
 {
-    int src_fd = open(loc_pre.c_str(), O_RDONLY | O_NOATIME | O_NOFOLLOW);
-    if (src_fd < 0)
-        cerr << "Can't open " << loc_pre << stringerror(errno) << endl;
-
-    int dest_fd = open(loc_post.c_str(), O_RDONLY | O_NOATIME | O_NOFOLLOW);
-    if (dest_fd < 0)
-    {
-        close(src_fd);
-        cerr << "Can't open " << loc_post << stringerror(errno) << endl;
-    }
-
     try {
-        XAModification xa_mod = XAModification(XAttributes(src_fd), XAttributes(dest_fd));
+        XAModification xa_mod = XAModification(XAttributes(loc_pre), XAttributes(loc_post));
         if (xa_mod.isEmpty())
             y2deb("XA Modification object is empty!");
         cout << "extended attributes diff:" << endl << "--- " << loc_pre << endl << "+++ " << loc_post << endl << xa_mod;
index 0f405491403e86b356109bc4e0ba16f7f8015dda..8c48ead49208737a394ccfa228f454be7e547224 100644 (file)
@@ -202,6 +202,20 @@ namespace snapper
        {
            if (!cmpFilesContent(file1, stat1, file2, stat2))
                status |= CONTENT;
+
+#ifdef ENABLE_XATTRS
+            /* TODO: think about this. Do you want to report
+             * XA modification in case the compared files differ
+             * in their types file A: link, file B: directory
+             */
+            if (file1.xaSupported() && file2.xaSupported())
+            {
+                if (!cmpFilesXattrs(file1, stat1, file2, stat2))
+                {
+                    status |= XATTRS;
+                }
+            }
+#endif
        }
 
        if ((stat1.st_mode ^ stat2.st_mode) & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID |
@@ -220,18 +234,6 @@ namespace snapper
            status |= GROUP;
        }
 
-#ifdef ENABLE_XATTRS
-        if (file1.xaSupported() && file2.xaSupported())
-        {
-            // TODO: think about how XATTRS are related to
-            // to other status changes...
-            if (!cmpFilesXattrs(file1, file2))
-            {
-                status |= XATTRS;
-            }
-        }
-#endif
-
         return status;
     }
 
@@ -471,19 +473,41 @@ namespace snapper
 
 #ifdef ENABLE_XATTRS
     bool
-    cmpFilesXattrs(const SFile& file1, const SFile& file2)
+    cmpFilesXattrs(const SFile& file1, const struct stat& stat1, const SFile& file2, const struct stat& stat2)
+    {
+        if ((stat1.st_mode & S_IFMT) != (stat2.st_mode & S_IFMT))
+            throw LogicErrorException();
+
+        bool retval;
+
+        try
+        {
+            XAttributes xa(file1.fullname(true)), xb(file2.fullname(true));
+            retval = (xa == xb);
+        }
+        catch (XAttributesException xae)
+        {
+            y2err("extended attributes compare failed");
+            retval = false;
+        }
+
+        return retval;
+    }
+
+/*
+    bool cmpFilesXattrsLnk(const SFile& file1, const SFile& file2)
     {
-        int fd1 = file1.open(O_RDONLY | O_NOFOLLOW | O_NOATIME | O_CLOEXEC);
+        int fd1 = file1.open(O_RDONLY | O_NOATIME | O_CLOEXEC);
         if (fd1 < 0)
         {
-            y2err("open failed path:" << file1.fullname() << " errno:" << errno);
+            y2err("Can't open link: " << file1.fullname() << " w/ error: " << stringerror(errno));
             throw IOErrorException();
         }
 
-        int fd2 = file2.open(O_RDONLY | O_NOFOLLOW | O_NOATIME | O_CLOEXEC);
+        int fd2 = file2.open(O_RDONLY | O_NOATIME | O_CLOEXEC);
         if (fd2 < 0)
         {
-            y2err("open failed path:" << file2.fullname() << " errno:" << errno);
+            y2err("Can't open link:" << file2.fullname() << " w/ error: " << stringerror(errno));
             close(fd1);
             throw IOErrorException();
         }
@@ -497,6 +521,7 @@ namespace snapper
         }
         catch (XAttributesException xae)
         {
+            y2err("extended attributes compare failed");
             retval = false;
         }
         close(fd1);
@@ -504,5 +529,6 @@ namespace snapper
 
         return retval;
     }
+*/
 #endif
 }
index b88c430216b7ce385d2cbd568f2b4de3e77213b8..f831b219c80087398d40b22a54ed13eb9f5e0df5 100644 (file)
@@ -50,7 +50,7 @@ namespace snapper
 
 #ifdef ENABLE_XATTRS
     bool
-    cmpFilesXattrs(const SFile&, const SFile&);
+    cmpFilesXattrs(const SFile&, const struct stat&, const SFile&, const struct stat&);
 #endif
 }
 
index ff30d2fc26e7e0e433ed0d826250d36a8bd5491c..d5e916ae47532bf61520eb3a300f1fefd766bc0c 100644 (file)
@@ -526,18 +526,17 @@ namespace snapper
     }
 
 #ifdef ENABLE_XATTRS
-    bool
-    File::modifyXattributes() const
+/*  bool
+    File::modifyXattributesReg() const
     {
-
-        int src_fd = open(getAbsolutePath(LOC_PRE).c_str(), O_RDONLY | O_CLOEXEC);
+        int src_fd = open(getAbsolutePath(LOC_PRE).c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
         if (src_fd < 0)
         {
             y2err("open failed errno:" << errno << " (" << stringerror(errno) << ")");
             return false;
         }
 
-        int dest_fd = open(getAbsolutePath(LOC_SYSTEM).c_str(), O_RDWR | O_CLOEXEC);
+        int dest_fd = open(getAbsolutePath(LOC_SYSTEM).c_str(), O_RDWR | O_NOFOLLOW | O_CLOEXEC);
         if (dest_fd < 0)
         {
             y2err("open failed errno:" << errno << " (" << stringerror(errno) << ")");
@@ -557,7 +556,7 @@ namespace snapper
             XAModification xa_mod(xa_src, xa_dest);
             y2deb("xa_modmap(xa_dest) object: " << xa_mod);
 
-            ret_val = xa_mod.serializeTo(dest_fd);
+            ret_val = xa_mod.serializeToFd(dest_fd);
         }
         catch (XAttributesException xae) {
             ret_val = false;
@@ -568,6 +567,49 @@ namespace snapper
 
         return ret_val;
     }
+
+    bool
+    File::modifyXattributesLink() const
+    {
+        bool ret_val;
+
+        try {
+            XAttributes xa_src(getAbsolutePath(LOC_PRE)), xa_dest(getAbsolutePath(LOC_SYSTEM));
+            y2deb("xa_src object: " << xa_src << std::endl << "xa_dest object: " << xa_dest);
+
+            XAModification xa_mod(xa_src, xa_dest);
+            y2deb("xa_modmap(xa_dest) object: " << xa_mod);
+
+            ret_val = xa_mod.serializeToLink(getAbsolutePath(LOC_SYSTEM));
+        }
+        catch (XAttributesException xae) {
+            ret_val = false;
+        }
+
+        return ret_val;
+    }
+*/
+    bool
+    File::modifyXattributes() const
+    {
+        bool ret_val;
+
+        try {
+            XAttributes xa_src(getAbsolutePath(LOC_PRE)), xa_dest(getAbsolutePath(LOC_SYSTEM));
+            y2deb("xa_src object: " << xa_src << std::endl << "xa_dest object: " << xa_dest);
+
+            XAModification xa_mod(xa_src, xa_dest);
+            y2deb("xa_modmap(xa_dest) object: " << xa_mod);
+
+            ret_val = xa_mod.serializeTo(getAbsolutePath(LOC_SYSTEM));
+        }
+        catch (XAttributesException xae) {
+            ret_val = false;
+        }
+
+        return ret_val;
+    }
+
 #endif
 
     bool
@@ -594,8 +636,12 @@ namespace snapper
        }
 
 #ifdef ENABLE_XATTRS
-       // NOTE: XATTR flasg must not be set w/ CREATED or DELETED flag
-        if (getPreToPostStatus() & XATTRS)
+        /*
+         * xattributes have to be transfered as well
+         * if we'are about to create new type during
+         * undo!
+         */
+        if (getPreToPostStatus() & (XATTRS | TYPE | DELETED))
         {
             if (!modifyXattributes())
                 error = true;
index 940cc270d281f87b62e60bb11e1da84dcc5722a7..211707dfa5d69f165000c90b205816f11f32966a 100644 (file)
@@ -36,6 +36,7 @@
 
 namespace snapper
 {
+    /* TODO: candidate for removal */
     XAttributes::XAttributes(int fd)
     {
         y2deb("entering Xattributes(int fd) constructor");
@@ -93,6 +94,63 @@ namespace snapper
         }
     }
 
+    XAttributes::XAttributes(const string &linkpath)
+    {
+        y2deb("entering Xattributes(string link) constructor");
+        ssize_t size = llistxattr(linkpath.c_str(), NULL, 0);
+        if (size < 0)
+        {
+            y2err("Couldn't get xattributes names-list size. link: " << linkpath << ", error: " << stringerror(errno));
+            throw XAttributesException();
+        }
+
+        // +1 to cover size == 0
+        boost::scoped_array<char> names(new char[size + 1]);
+        names[size] = '\0';
+
+        y2deb("XAttributes names-list size is: " << size);
+
+        size = llistxattr(linkpath.c_str(), names.get(), size);
+        if (size < 0)
+        {
+            y2err("Couldn't get xattributes names-list. link: " << linkpath << ", error: " << stringerror(errno));
+            throw XAttributesException();
+        }
+
+        int pos = 0;
+
+        while (pos < size)
+        {
+            string name = string(names.get() + pos);
+            // move beyond separating '\0' char
+            pos += name.length() + 1;
+
+            ssize_t v_size = lgetxattr(linkpath.c_str(), name.c_str(), NULL, 0);
+            if (v_size < 0)
+            {
+                y2err("Couldn't get a xattribute value size for the xattribute name '" << name << "': " << stringerror(errno));
+                throw XAttributesException();
+            }
+
+            y2deb("XAttribute value size for xattribute name: '" << name << "' is " << v_size);
+
+            boost::scoped_array<uint8_t> buffer(v_size ? new uint8_t[v_size] : NULL);
+
+            v_size = lgetxattr(linkpath.c_str(), name.c_str(), (void *)buffer.get(), v_size);
+            if (v_size < 0)
+            {
+                y2err("Coudln't get xattrbitue value for the xattrbite name '" << name << "': ");
+                throw XAttributesException();
+            }
+
+            if (!xamap.insert(xa_pair_t(name, xa_value_t(buffer.get(), buffer.get() + v_size))).second)
+            {
+                y2err("Duplicite extended attribute name in source file!");
+                throw XAttributesException();
+            }
+        }
+    }
+
     XAttributes::XAttributes(const XAttributes &xa)
     {
         y2deb("Starting copy constructor XAttribute(const XAttribute&)");
@@ -250,7 +308,7 @@ namespace snapper
     }
 
     bool
-    XAModification::serializeTo(int dest_fd) const
+    XAModification::serializeTo(const string &dest) const
     {
         if (this->isEmpty())
             return true;
@@ -263,7 +321,7 @@ namespace snapper
                 {
                     case XA_DELETE:
                         y2deb("delete xattribute: " << mod_cit->first);
-                        if (fremovexattr(dest_fd, mod_cit->first.c_str()))
+                        if (lremovexattr(dest.c_str(), mod_cit->first.c_str()))
                         {
                             y2err("Couldn't remove xattribute '" << mod_cit->first << "': " << stringerror(errno));
                             return false;
@@ -276,7 +334,7 @@ namespace snapper
                         if (mod_cit->second.empty())
                         {
                             y2deb("new value for xattribute '" << mod_cit->first << "' is empty!");
-                            if (fsetxattr(dest_fd, mod_cit->first.c_str(), NULL, 0, XATTR_REPLACE))
+                            if (lsetxattr(dest.c_str(), mod_cit->first.c_str(), NULL, 0, XATTR_REPLACE))
                             {
                                 y2err("Couldn't replace xattribute '" << mod_cit->first << "' by new (empty) value: " << stringerror(errno));
                                 return false;
@@ -285,7 +343,7 @@ namespace snapper
                         else
                         {
                             y2deb("new value for xattribute '" << mod_cit->first << "': " << mod_cit->second);
-                            if (fsetxattr(dest_fd, mod_cit->first.c_str(), &mod_cit->second.front(), mod_cit->second.size(), XATTR_REPLACE))
+                            if (lsetxattr(dest.c_str(), mod_cit->first.c_str(), &mod_cit->second.front(), mod_cit->second.size(), XATTR_REPLACE))
                             {
                                 y2err("Couldn't replace xattribute '" << mod_cit->first << "' by new (non-empty) value: " << stringerror(errno));
                                 y2deb("new XA value size: " << mod_cit->second.size() << ". The value: " << mod_cit->second);
@@ -299,7 +357,7 @@ namespace snapper
                         if (mod_cit->second.empty())
                         {
                             y2deb("new value for xattribute '" << mod_cit->first << "' is empty!");
-                            if (fsetxattr(dest_fd, mod_cit->first.c_str(), NULL, 0, XATTR_CREATE))
+                            if (lsetxattr(dest.c_str(), mod_cit->first.c_str(), NULL, 0, XATTR_CREATE))
                             {
                                 y2err("Couldn't create xattribute '" << mod_cit->first << "' with new (empty) value: " << stringerror(errno));
                                 return false;
@@ -308,7 +366,7 @@ namespace snapper
                         else
                         {
                             y2deb("new value for xattribute '" << mod_cit->first << "': " << mod_cit->second);
-                            if (fsetxattr(dest_fd, mod_cit->first.c_str(), &mod_cit->second.front(), mod_cit->second.size(), XATTR_CREATE))
+                            if (lsetxattr(dest.c_str(), mod_cit->first.c_str(), &mod_cit->second.front(), mod_cit->second.size(), XATTR_CREATE))
                             {
                                 y2err("Couldn't create xattribute '" << mod_cit->first << "' with new (non-empty) value: " << stringerror(errno));
                                 y2deb("new XA value size: " << mod_cit->second.size() << ". The value: " << mod_cit->second);
index ef2411a0f58c0325cccd2b07d9ad690362328f88..9319aeb44ebba17572d512bd33287175614357bb 100644 (file)
@@ -46,7 +46,7 @@ namespace snapper
 
         // this is ordered on purpose!
         // we can possibly avoid allocating new fs block if xattrs fits
-        // into 100 bytes (ext2,3,4)
+        // into 100 bytes (ext4)
         // so, first remove/change and create later
         enum XaCompareFlags {
             XA_DELETE = 0,
@@ -72,6 +72,7 @@ namespace snapper
             xa_map_t xamap;
         public:
             XAttributes(int);
+            XAttributes(const string&);
             XAttributes(const XAttributes&);
 
             xa_map_citer cbegin() const { return xamap.begin(); }
@@ -91,7 +92,7 @@ namespace snapper
             XAModification(const XAttributes&, const XAttributes&);
 
             bool isEmpty() const;
-            bool serializeTo(int) const;
+            bool serializeTo(const string&) const;
             xa_mod_citer cbegin() const { return xamodmap.begin(); };
             xa_mod_citer cend() const { return xamodmap.end(); };