diff options
author | Guillem Jover <guillem@debian.org> | 2010-02-27 19:55:25 +0100 |
---|---|---|
committer | Guillem Jover <guillem@debian.org> | 2010-03-06 10:41:40 +0100 |
commit | 62668eb422853854976560949f95a5afcc6a8677 (patch) | |
tree | 3865d678367a07dd7aec0ef6aee009801b402c9b | |
parent | 9d81bf92ef791ad4644f36d3b5f7361e883134d6 (diff) | |
download | dpkg-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/changelog | 4 | ||||
-rw-r--r-- | dpkg-deb/build.c | 4 | ||||
-rw-r--r-- | dpkg-split/join.c | 5 | ||||
-rw-r--r-- | dpkg-split/queue.c | 4 | ||||
-rw-r--r-- | lib/dpkg/triglib.c | 12 | ||||
-rw-r--r-- | src/archives.c | 2 | ||||
-rw-r--r-- | src/statcmd.c | 4 | ||||
-rw-r--r-- | utils/start-stop-daemon.c | 4 |
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) { |