The following commit has been merged in the master branch:
commit 62668eb422853854976560949f95a5afcc6a8677
Author: Guillem Jover <[email protected]>
Date: Sat Feb 27 19:55:25 2010 +0100
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
<[email protected]>
diff --git a/debian/changelog b/debian/changelog
index f4a58f0..aa19047 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 <[email protected]>. 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 <[email protected]>.
+ 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 d14f796..3dd2c97 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 6b200d8..97b6cd6 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 ed114e6..dae30c4 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 118994b..c7c6924 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 69110c1..ab10d19 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 9f5e473..cd66604 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 7a7fda4..a30d84c 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) {
--
dpkg's main repository
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]