summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillem Jover <guillem@debian.org>2010-02-27 19:55:25 +0100
committerGuillem Jover <guillem@debian.org>2010-03-06 10:41:40 +0100
commit62668eb422853854976560949f95a5afcc6a8677 (patch)
tree3865d678367a07dd7aec0ef6aee009801b402c9b
parent9d81bf92ef791ad4644f36d3b5f7361e883134d6 (diff)
downloaddpkg-62668eb422853854976560949f95a5afcc6a8677.tar.gz
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>
-rw-r--r--debian/changelog4
-rw-r--r--dpkg-deb/build.c4
-rw-r--r--dpkg-split/join.c5
-rw-r--r--dpkg-split/queue.c4
-rw-r--r--lib/dpkg/triglib.c12
-rw-r--r--src/archives.c2
-rw-r--r--src/statcmd.c4
-rw-r--r--utils/start-stop-daemon.c4
8 files changed, 39 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog
index f4a58f085..aa1904732 100644
--- a/debian/changelog
+++ b/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
diff --git a/dpkg-deb/build.c b/dpkg-deb/build.c
index d14f79686..3dd2c976e 100644
--- a/dpkg-deb/build.c
+++ b/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);
diff --git a/dpkg-split/join.c b/dpkg-split/join.c
index 6b200d846..97b6cd670 100644
--- a/dpkg-split/join.c
+++ b/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"));
}
diff --git a/dpkg-split/queue.c b/dpkg-split/queue.c
index ed114e61e..dae30c445 100644
--- a/dpkg-split/queue.c
+++ b/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);
diff --git a/lib/dpkg/triglib.c b/lib/dpkg/triglib.c
index 118994b01..c7c692455 100644
--- a/lib/dpkg/triglib.c
+++ b/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'"),
diff --git a/src/archives.c b/src/archives.c
index 69110c176..ab10d1954 100644
--- a/src/archives.c
+++ b/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);
diff --git a/src/statcmd.c b/src/statcmd.c
index 9f5e4732e..cd666049c 100644
--- a/src/statcmd.c
+++ b/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);
diff --git a/utils/start-stop-daemon.c b/utils/start-stop-daemon.c
index 7a7fda470..a30d84c75 100644
--- a/utils/start-stop-daemon.c
+++ b/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) {