The following commit has been merged in the master branch:
commit e5954543cbe61a8b9e3af09b4feffec20590ead0
Author: Guillem Jover <[email protected]>
Date: Tue Nov 22 22:44:07 2011 +0100
libdpkg: New atomic file module
diff --git a/lib/dpkg/Makefile.am b/lib/dpkg/Makefile.am
index c3b3cd0..e2c8aae 100644
--- a/lib/dpkg/Makefile.am
+++ b/lib/dpkg/Makefile.am
@@ -26,6 +26,7 @@ libdpkg_a_SOURCES = \
dlist.h \
ar.c \
arch.c \
+ atomic-file.c \
buffer.c \
cleanup.c \
command.c \
@@ -77,6 +78,7 @@ libdpkg_a_SOURCES = \
pkginclude_HEADERS = \
ar.h \
arch.h \
+ atomic-file.h \
buffer.h \
command.h \
compress.h \
diff --git a/lib/dpkg/atomic-file.c b/lib/dpkg/atomic-file.c
new file mode 100644
index 0000000..bb5e2ab
--- /dev/null
+++ b/lib/dpkg/atomic-file.c
@@ -0,0 +1,124 @@
+/*
+ * libdpkg - Debian packaging suite library routines
+ * atomic-file.c - atomic file helper functions
+ *
+ * Copyright © 2011 Guillem Jover <[email protected]>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <compat.h>
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <dpkg/i18n.h>
+#include <dpkg/dpkg.h>
+#include <dpkg/atomic-file.h>
+
+#define ATOMIC_FILE_NEW_EXT "-new"
+#define ATOMIC_FILE_OLD_EXT "-old"
+
+struct atomic_file *
+atomic_file_new(const char *filename, enum atomic_file_flags flags)
+{
+ struct atomic_file *file;
+
+ file = m_malloc(sizeof(*file));
+ file->flags = flags;
+ file->fp = NULL;
+ file->name = m_strdup(filename);
+ m_asprintf(&file->name_new, "%s%s", filename, ATOMIC_FILE_NEW_EXT);
+
+ return file;
+}
+
+void
+atomic_file_open(struct atomic_file *file)
+{
+ file->fp = fopen(file->name_new, "w");
+ if (file->fp == NULL)
+ ohshite(_("unable to create new file '%.250s'"),
+ file->name_new);
+ fchmod(fileno(file->fp), 0644);
+
+ push_cleanup(cu_closestream, ~ehflag_normaltidy, NULL, 0, 1, file->fp);
+}
+
+void
+atomic_file_sync(struct atomic_file *file)
+{
+ if (ferror(file->fp))
+ ohshite(_("unable to write new file '%.250s'"), file->name_new);
+ if (fflush(file->fp))
+ ohshite(_("unable to flush new file '%.250s'"), file->name_new);
+ if (fsync(fileno(file->fp)))
+ ohshite(_("unable to sync new file '%.250s'"), file->name_new);
+}
+
+void
+atomic_file_close(struct atomic_file *file)
+{
+ pop_cleanup(ehflag_normaltidy); /* fopen */
+
+ if (fclose(file->fp))
+ ohshite(_("unable to close new file `%.250s'"), file->name_new);
+}
+
+static void
+atomic_file_backup(struct atomic_file *file)
+{
+ char *name_old;
+
+ m_asprintf(&name_old, "%s%s", file->name, ATOMIC_FILE_OLD_EXT);
+
+ if (unlink(name_old) && errno != ENOENT)
+ ohshite(_("error removing old backup file '%s'"), name_old);
+ if (link(file->name, name_old) && errno != ENOENT)
+ ohshite(_("error creating new backup file '%s'"), name_old);
+
+ free(name_old);
+}
+
+void
+atomic_file_remove(struct atomic_file *file)
+{
+ if (unlink(file->name_new))
+ ohshite(_("cannot remove `%.250s'"), file->name_new);
+ if (unlink(file->name) && errno != ENOENT)
+ ohshite(_("cannot remove `%.250s'"), file->name);
+}
+
+void
+atomic_file_commit(struct atomic_file *file)
+{
+ if (file->flags & aff_backup)
+ atomic_file_backup(file);
+
+ if (rename(file->name_new, file->name))
+ ohshite(_("error installing new file '%s'"), file->name);
+}
+
+void
+atomic_file_free(struct atomic_file *file)
+{
+ free(file->name_new);
+ free(file->name);
+ free(file);
+}
diff --git a/lib/dpkg/error.h b/lib/dpkg/atomic-file.h
similarity index 54%
copy from lib/dpkg/error.h
copy to lib/dpkg/atomic-file.h
index 2f285df..f000f53 100644
--- a/lib/dpkg/error.h
+++ b/lib/dpkg/atomic-file.h
@@ -1,6 +1,6 @@
/*
* libdpkg - Debian packaging suite library routines
- * error.h - error message reporting
+ * atomic-file.h - atomic file helper functions
*
* Copyright © 2011 Guillem Jover <[email protected]>
*
@@ -18,32 +18,35 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef LIBDPKG_ERROR_H
-#define LIBDPKG_ERROR_H
+#ifndef LIBDPKG_ATOMIC_FILE_H
+#define LIBDPKG_ATOMIC_FILE_H
+
+#include <stdio.h>
#include <dpkg/macros.h>
DPKG_BEGIN_DECLS
-struct dpkg_error {
- enum dpkg_msg_type {
- DPKG_MSG_NONE,
- DPKG_MSG_WARN,
- DPKG_MSG_ERROR,
- } type;
-
- char *str;
+enum atomic_file_flags {
+ aff_backup = 01,
};
-int dpkg_put_warn(struct dpkg_error *err, const char *fmt, ...)
- DPKG_ATTR_PRINTF(2);
-int dpkg_put_error(struct dpkg_error *err, const char *fmt, ...)
- DPKG_ATTR_PRINTF(2);
-int dpkg_put_errno(struct dpkg_error *err, const char *fmt, ...)
- DPKG_ATTR_PRINTF(2);
+struct atomic_file {
+ enum atomic_file_flags flags;
+ char *name;
+ char *name_new;
+ FILE *fp;
+};
-void dpkg_error_destroy(struct dpkg_error *err);
+struct atomic_file *
+atomic_file_new(const char *filename, enum atomic_file_flags flags);
+void atomic_file_open(struct atomic_file *file);
+void atomic_file_sync(struct atomic_file *file);
+void atomic_file_close(struct atomic_file *file);
+void atomic_file_commit(struct atomic_file *file);
+void atomic_file_remove(struct atomic_file *file);
+void atomic_file_free(struct atomic_file *file);
DPKG_END_DECLS
-#endif /* LIBDPKG_ERROR_H */
+#endif /* LIBDPKG_ATOMIC_FILE_H */
diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h
index a2d1b89..ba8fbd9 100644
--- a/lib/dpkg/dpkg-db.h
+++ b/lib/dpkg/dpkg-db.h
@@ -231,6 +231,8 @@ const char *dpkg_db_set_dir(const char *dir);
const char *dpkg_db_get_dir(void);
char *dpkg_db_get_path(const char *pathpart);
+#include <dpkg/atomic-file.h>
+
/*** from dbmodify.c ***/
enum modstatdb_rw {
diff --git a/lib/dpkg/libdpkg.map b/lib/dpkg/libdpkg.map
index f0476cf..41d3ad5 100644
--- a/lib/dpkg/libdpkg.map
+++ b/lib/dpkg/libdpkg.map
@@ -91,6 +91,14 @@ LIBDPKG_PRIVATE {
file_copy_perms;
+ atomic_file_new;
+ atomic_file_open;
+ atomic_file_sync;
+ atomic_file_close;
+ atomic_file_commit;
+ atomic_file_remove;
+ atomic_file_free;
+
glob_list_prepend;
glob_list_free;
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1d40109..5d59646 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -2,6 +2,7 @@
lib/dpkg/ar.c
lib/dpkg/arch.c
+lib/dpkg/atomic-file.c
lib/dpkg/buffer.c
lib/dpkg/cleanup.c
lib/dpkg/command.c
--
dpkg's main repository
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]