Просмотр исходного кода

* apt-pkg/contrib/fileutl.cc:
- Make FileFd replace files atomically in WriteTemp mode (for cache, etc).

Julian Andres Klode лет назад: 16
Родитель
Сommit
3010fb0e06
3 измененных файлов с 19 добавлено и 6 удалено
  1. 15 5
      apt-pkg/contrib/fileutl.cc
  2. 2 1
      apt-pkg/contrib/fileutl.h
  3. 2 0
      debian/changelog

+ 15 - 5
apt-pkg/contrib/fileutl.cc

@@ -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;
 }
 									/*}}}*/

+ 2 - 1
apt-pkg/contrib/fileutl.h

@@ -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};

+ 2 - 0
debian/changelog

@@ -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