소스 검색

Do an fsync on files written to disk

This guarantees the file contents will be there in case of abrupt
program termination (due to crashes for example, or user intervention).
This also guarantees the atomicity of rename(2) calls.

Closes: #430958

Based-on-patch-by: Jean-Baptiste Lallement <jeanbaptiste.lallement@gmail.com>
Guillem Jover 16 년 전
부모
커밋
62668eb422
8개의 변경된 파일39개의 추가작업 그리고 0개의 파일을 삭제
  1. 4 0
      debian/changelog
  2. 4 0
      dpkg-deb/build.c
  3. 5 0
      dpkg-split/join.c
  4. 4 0
      dpkg-split/queue.c
  5. 12 0
      lib/dpkg/triglib.c
  6. 2 0
      src/archives.c
  7. 4 0
      src/statcmd.c
  8. 4 0
      utils/start-stop-daemon.c

+ 4 - 0
debian/changelog

@@ -154,6 +154,10 @@ dpkg (1.15.6) UNRELEASED; urgency=low
   * When FIEMAP is not available use posix_fadvise() to start preloading the
     .list files before loading them. With a cold cache it improves up to 40%.
     Thanks to Stefan Fritsch <sf@sfritsch.de>. Closes: #557560
+  * Call fsync(2) after writting files on disk, to get the atomicity
+    guarantees when doing rename(2). Based on a patch by
+    Jean-Baptiste Lallement <jeanbaptiste.lallement@gmail.com>.
+    Closes: #430958
 
   [ Modestas Vainius ]
   * Implement symbol patterns (Closes: #563752). From now on, it is possible to

+ 4 - 0
dpkg-deb/build.c

@@ -552,6 +552,10 @@ void do_build(const char *const *argv) {
       if (putc('\n',ar) == EOF)
         werr(debar);
   }
+  if (fflush(ar))
+    ohshite(_("unable to flush file '%s'"), debar);
+  if (fsync(fileno(ar)))
+    ohshite(_("unable to sync file '%s'"), debar);
   if (fclose(ar)) werr(debar);
                              
   exit(0);

+ 5 - 0
dpkg-split/join.c

@@ -24,6 +24,7 @@
 #include <assert.h>
 #include <limits.h>
 #include <string.h>
+#include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
 
@@ -68,6 +69,10 @@ void reassemble(struct partinfo **partlist, const char *outputfile) {
     nr= fwrite(buffer,1,pi->thispartlen,output);
     if (nr != pi->thispartlen) werr(outputfile);
   }
+  if (fflush(output))
+    ohshite(_("unable to flush file '%s'"), outputfile);
+  if (fsync(fileno(output)))
+    ohshite(_("unable to sync file '%s'"), outputfile);
   if (fclose(output)) werr(outputfile);
   printf(_("done\n"));
 }

+ 4 - 0
dpkg-split/queue.c

@@ -166,6 +166,10 @@ void do_auto(const char *const *argv) {
     if (!part) ohshite(_("unable to open new depot file `%.250s'"),p);
     nr= fwrite(buffer,1,refi->filesize,part);
     if (nr != refi->filesize) werr(p);
+    if (fflush(part))
+      ohshite(_("unable to flush file '%s'"), p);
+    if (fsync(fileno(part)))
+      ohshite(_("unable to sync file '%s'"), p);
     if (fclose(part)) werr(p);
     if (rename(p,q)) ohshite(_("unable to rename new depot file `%.250s' to `%.250s'"),p,q);
 

+ 12 - 0
lib/dpkg/triglib.c

@@ -398,6 +398,12 @@ trk_explicit_interest_change(const char *trig,  struct pkginfo *pkg, int signum)
 	if (ferror(nf))
 		ohshite(_("unable to write new trigger interest file `%.250s'"),
 		        newfn.buf);
+	if (fflush(nf))
+		ohshite(_("unable to flush new trigger interest file '%.250s'"),
+		        newfn.buf);
+	if (fsync(fileno(nf)))
+		ohshite(_("unable to sync new trigger interest file '%.250s'"),
+		        newfn.buf);
 	pop_cleanup(ehflag_normaltidy);
 	if (fclose(nf))
 		ohshite(_("unable to close new trigger interest file `%.250s'"),
@@ -500,6 +506,12 @@ trig_file_interests_save(void)
 	if (ferror(nf))
 		ohshite(_("unable to write new file triggers file `%.250s'"),
 		        triggersnewfilefile);
+	if (fflush(nf))
+		ohshite(_("unable to flush new file triggers file '%.250s'"),
+		        triggersnewfilefile);
+	if (fsync(fileno(nf)))
+		ohshite(_("unable to sync new file triggers file '%.250s'"),
+		        triggersnewfilefile);
 	pop_cleanup(ehflag_normaltidy);
 	if (fclose(nf))
 		ohshite(_("unable to close new file triggers file `%.250s'"),

+ 2 - 0
src/archives.c

@@ -660,6 +660,8 @@ int tarobject(struct TarInfo *ti) {
     am=(nifd->namenode->statoverride ? nifd->namenode->statoverride->mode : ti->Mode) & ~S_IFMT;
     if (fchmod(fd,am))
       ohshite(_("error setting permissions of `%.255s'"),ti->Name);
+    if (fsync(fd))
+      ohshite(_("unable to sync file '%.255s'"), ti->Name);
     pop_cleanup(ehflag_normaltidy); /* fd= open(fnamenewvb.buf) */
     if (close(fd))
       ohshite(_("error closing/writing `%.255s'"),ti->Name);

+ 4 - 0
src/statcmd.c

@@ -229,6 +229,10 @@ statdb_write(void)
 		statdb_node_print(dbfile, file);
 	iterfileend(i);
 
+	if (fflush(dbfile))
+		ohshite(_("unable to flush file '%s'"), dbname_new.buf);
+	if (fsync(fileno(dbfile)))
+		ohshite(_("unable to sync file '%s'"), dbname_new.buf);
 	fclose(dbfile);
 
 	chmod(dbname_new.buf, 0644);

+ 4 - 0
utils/start-stop-daemon.c

@@ -1576,6 +1576,10 @@ main(int argc, char **argv)
 			fatal("Unable to open pidfile '%s' for writing: %s",
 			      pidfile, strerror(errno));
 		fprintf(pidf, "%d\n", pidt);
+		if (fflush(pidf))
+			fatal("unable to flush pidfile '%s'", pidfile);
+		if (fsync(fileno(pidf)))
+			fatal("unable to sync pidfile '%s'", pidfile);
 		fclose(pidf);
 	}
 	if (changeroot != NULL) {