* apt-pkg/contrib/fileutl.cc:
authorJulian Andres Klode <jak@debian.org>
Tue, 29 Jun 2010 15:23:24 +0000 (17:23 +0200)
committerJulian Andres Klode <jak@debian.org>
Tue, 29 Jun 2010 15:23:24 +0000 (17:23 +0200)
  - Make FileFd replace files atomically in WriteTemp mode (for cache, etc).

apt-pkg/contrib/fileutl.cc
apt-pkg/contrib/fileutl.h
debian/changelog

index 16f7ce9..0b0739c 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <cstdlib>
 #include <cstring>
+#include <cstdio>
 
 #include <iostream>
 #include <unistd.h>
@@ -654,10 +655,11 @@ bool FileFd::Open(string FileName,OpenMode Mode, unsigned long Perms)
       
       case WriteEmpty:
       {
-        struct stat Buf;
-        if (lstat(FileName.c_str(),&Buf) == 0 && S_ISLNK(Buf.st_mode))
-           unlink(FileName.c_str());
-        iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_TRUNC,Perms);
+        Flags |= Replace;
+        char *name = strdup((FileName + ".XXXXXX").c_str());
+        TemporaryFileName = string(mktemp(name));
+        iFd = open(TemporaryFileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms);
+        free(name);
         break;
       }
       
@@ -839,11 +841,19 @@ bool FileFd::Close()
       if (iFd >= 0 && close(iFd) != 0)
         Res &= _error->Errno("close",_("Problem closing the file"));
    iFd = -1;
-   
+
+   if ((Flags & Replace) == Replace) {
+      FileName = TemporaryFileName; // for the unlink() below.
+      if (rename(TemporaryFileName.c_str(), FileName.c_str()) != 0)
+        Res &= _error->Errno("rename",_("Problem renaming the file"));
+   }
+           
    if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail &&
        FileName.empty() == false)
       if (unlink(FileName.c_str()) != 0)
         Res &= _error->WarningE("unlnk",_("Problem unlinking the file"));
+
+
    return Res;
 }
                                                                        /*}}}*/
index 003bd9b..528725f 100644 (file)
@@ -34,9 +34,10 @@ class FileFd
    int iFd;
  
    enum LocalFlags {AutoClose = (1<<0),Fail = (1<<1),DelOnFail = (1<<2),
-                    HitEof = (1<<3)};
+                    HitEof = (1<<3), Replace = (1<<4) };
    unsigned long Flags;
    string FileName;
+   string TemporaryFileName;
    
    public:
    enum OpenMode {ReadOnly,WriteEmpty,WriteExists,WriteAny,WriteTemp};
index 3a0fcd8..1bf6815 100644 (file)
@@ -8,6 +8,8 @@ apt (0.7.26~exp8) experimental; urgency=low
     - Support matching pins by regular expressions or glob() like patterns,
       regular expressions have to be put between to slashes; for example,
       /.*/.
+  * apt-pkg/contrib/fileutl.cc:
+    - Make FileFd replace files atomically in WriteTemp mode (for cache, etc).
   * debian/control:
     - Set Standards-Version to 3.9.0