Browse Source

libdpkg: Add varbuf_snapshot() and varbuf_rollback() support

This adds a proper interface to snapshot a varbuf state and it rollback
so that a common stem can be reused on multiple instances.
Guillem Jover 9 years ago
parent
commit
da97e399c2
9 changed files with 83 additions and 28 deletions
  1. 33 1
      lib/dpkg/t/t-varbuf.c
  2. 13 1
      lib/dpkg/varbuf.c
  3. 7 0
      lib/dpkg/varbuf.h
  4. 6 5
      src/archives.c
  5. 1 1
      src/archives.h
  6. 3 3
      src/infodb-access.c
  7. 4 4
      src/infodb-upgrade.c
  8. 14 11
      src/remove.c
  9. 2 2
      src/unpack.c

+ 33 - 1
lib/dpkg/t/t-varbuf.c

@@ -268,6 +268,37 @@ test_varbuf_reset(void)
 	varbuf_destroy(&vb);
 }
 
+static void
+test_varbuf_snapshot(void)
+{
+	struct varbuf vb;
+	struct varbuf_state vbs;
+
+	varbuf_init(&vb, 0);
+
+	test_pass(vb.used == 0);
+	varbuf_snapshot(&vb, &vbs);
+	test_pass(vb.used == 0);
+	test_pass(vb.used == vbs.used);
+
+	varbuf_add_buf(&vb, "1234567890", 10);
+	test_pass(vb.used == 10);
+	varbuf_rollback(&vb, &vbs);
+	test_pass(vb.used == 0);
+
+	varbuf_add_buf(&vb, "1234567890", 10);
+	test_pass(vb.used == 10);
+	varbuf_snapshot(&vb, &vbs);
+	test_pass(vb.used == 10);
+
+	varbuf_add_buf(&vb, "1234567890", 10);
+	test_pass(vb.used == 20);
+	varbuf_rollback(&vb, &vbs);
+	test_pass(vb.used == 10);
+
+	varbuf_destroy(&vb);
+}
+
 static void
 test_varbuf_detach(void)
 {
@@ -291,7 +322,7 @@ test_varbuf_detach(void)
 static void
 test(void)
 {
-	test_plan(99);
+	test_plan(108);
 
 	test_varbuf_init();
 	test_varbuf_prealloc();
@@ -304,6 +335,7 @@ test(void)
 	test_varbuf_end_str();
 	test_varbuf_printf();
 	test_varbuf_reset();
+	test_varbuf_snapshot();
 	test_varbuf_detach();
 
 	/* FIXME: Complete. */

+ 13 - 1
lib/dpkg/varbuf.c

@@ -3,7 +3,7 @@
  * varbuf.c - variable length expandable buffer handling
  *
  * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
- * Copyright © 2008-2011 Guillem Jover <guillem@debian.org>
+ * Copyright © 2008-2014 Guillem Jover <guillem@debian.org>
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -149,6 +149,18 @@ varbuf_trunc(struct varbuf *v, size_t used_size)
   v->used = used_size;
 }
 
+void
+varbuf_snapshot(struct varbuf *v, struct varbuf_state *vs)
+{
+  vs->used = v->used;
+}
+
+void
+varbuf_rollback(struct varbuf *v, struct varbuf_state *vs)
+{
+  varbuf_trunc(v, vs->used);
+}
+
 char *
 varbuf_detach(struct varbuf *v)
 {

+ 7 - 0
lib/dpkg/varbuf.h

@@ -89,6 +89,13 @@ int varbuf_printf(struct varbuf *v, const char *fmt, ...) DPKG_ATTR_PRINTF(2);
 int varbuf_vprintf(struct varbuf *v, const char *fmt, va_list va)
 	DPKG_ATTR_VPRINTF(2);
 
+struct varbuf_state {
+	size_t used;
+};
+
+void varbuf_snapshot(struct varbuf *v, struct varbuf_state *vs);
+void varbuf_rollback(struct varbuf *v, struct varbuf_state *vs);
+
 /** @} */
 
 DPKG_END_DECLS

+ 6 - 5
src/archives.c

@@ -268,7 +268,7 @@ tarobject_skip_entry(struct tarcontext *tc, struct tar_entry *ti)
   }
 }
 
-int fnameidlu;
+struct varbuf_state fname_state;
 struct varbuf fnamevb;
 struct varbuf fnametmpvb;
 struct varbuf fnamenewvb;
@@ -549,16 +549,16 @@ tarobject_matches(struct tarcontext *tc,
 }
 
 void setupfnamevbs(const char *filename) {
-  varbuf_trunc(&fnamevb, fnameidlu);
+  varbuf_rollback(&fnamevb, &fname_state);
   varbuf_add_str(&fnamevb, filename);
   varbuf_end_str(&fnamevb);
 
-  varbuf_trunc(&fnametmpvb, fnameidlu);
+  varbuf_rollback(&fnametmpvb, &fname_state);
   varbuf_add_str(&fnametmpvb, filename);
   varbuf_add_str(&fnametmpvb, DPKGTEMPEXT);
   varbuf_end_str(&fnametmpvb);
 
-  varbuf_trunc(&fnamenewvb, fnameidlu);
+  varbuf_rollback(&fnamenewvb, &fname_state);
   varbuf_add_str(&fnamenewvb, filename);
   varbuf_add_str(&fnamenewvb, DPKGNEWEXT);
   varbuf_end_str(&fnamenewvb);
@@ -1519,7 +1519,8 @@ archivefiles(const char *const *argv)
   varbuf_add_str(&fnamevb, instdir);
   varbuf_add_str(&fnametmpvb, instdir);
   varbuf_add_str(&fnamenewvb, instdir);
-  fnameidlu= fnamevb.used;
+
+  varbuf_snapshot(&fnamevb, &fname_state);
 
   ensure_diversions();
   ensure_statoverrides(STATDB_PARSE_NORMAL);

+ 1 - 1
src/archives.h

@@ -40,7 +40,7 @@ struct pkg_deconf_list {
   struct pkginfo *pkg_removal;
 };
 
-extern int fnameidlu;
+extern struct varbuf_state fname_state;
 extern struct varbuf fnamevb;
 extern struct varbuf fnametmpvb;
 extern struct varbuf fnamenewvb;

+ 3 - 3
src/infodb-access.c

@@ -59,9 +59,9 @@ pkg_infodb_foreach(struct pkginfo *pkg, struct pkgbin *pkgbin,
 {
 	DIR *db_dir;
 	struct dirent *db_de;
+	struct varbuf_state db_path_state;
 	struct varbuf db_path = VARBUF_INIT;
 	const char *pkgname;
-	size_t db_path_len;
 	enum pkg_infodb_format db_format;
 
 	/* Make sure to always read and verify the format version. */
@@ -76,7 +76,7 @@ pkg_infodb_foreach(struct pkginfo *pkg, struct pkgbin *pkgbin,
 	varbuf_add_str(&db_path, pkg_infodb_get_dir());
 	varbuf_add_char(&db_path, '/');
 	varbuf_end_str(&db_path);
-	db_path_len = db_path.used;
+	varbuf_snapshot(&db_path, &db_path_state);
 
 	db_dir = opendir(db_path.buf);
 	if (!db_dir)
@@ -108,7 +108,7 @@ pkg_infodb_foreach(struct pkginfo *pkg, struct pkgbin *pkgbin,
 		/* Skip past the full stop. */
 		filetype = dot + 1;
 
-		varbuf_trunc(&db_path, db_path_len);
+		varbuf_rollback(&db_path, &db_path_state);
 		varbuf_add_str(&db_path, db_de->d_name);
 		varbuf_end_str(&db_path);
 		filename = db_path.buf;

+ 4 - 4
src/infodb-upgrade.c

@@ -78,12 +78,12 @@ pkg_infodb_link_multiarch_files(void)
 	struct varbuf pkgname = VARBUF_INIT;
 	struct varbuf oldname = VARBUF_INIT;
 	struct varbuf newname = VARBUF_INIT;
-	size_t db_path_len;
+	struct varbuf_state db_path_state;
 
 	varbuf_add_str(&oldname, pkg_infodb_get_dir());
 	varbuf_add_char(&oldname, '/');
-	db_path_len = oldname.used;
 	varbuf_end_str(&oldname);
+	varbuf_snapshot(&oldname, &db_path_state);
 
 	varbuf_add_buf(&newname, oldname.buf, oldname.used);
 	varbuf_end_str(&newname);
@@ -132,11 +132,11 @@ pkg_infodb_link_multiarch_files(void)
 		/* Skip past the full stop. */
 		filetype = dot + 1;
 
-		varbuf_trunc(&oldname, db_path_len);
+		varbuf_rollback(&oldname, &db_path_state);
 		varbuf_add_str(&oldname, db_de->d_name);
 		varbuf_end_str(&oldname);
 
-		varbuf_trunc(&newname, db_path_len);
+		varbuf_rollback(&newname, &db_path_state);
 		varbuf_add_pkgbin_name(&newname, pkg, &pkg->installed, pnaw_always);
 		varbuf_add_char(&newname, '.');
 		varbuf_add_str(&newname, filetype);

+ 14 - 11
src/remove.c

@@ -57,7 +57,7 @@ static void checkforremoval(struct pkginfo *pkgtoremove,
   struct deppossi *possi;
   struct pkginfo *depender;
   enum dep_check ok;
-  int before;
+  struct varbuf_state raemsgs_state;
 
   for (possi = pkgdepcheck->depended.installed; possi; possi = possi->rev_next) {
     if (possi->up->type != dep_depends && possi->up->type != dep_predepends) continue;
@@ -72,14 +72,14 @@ static void checkforremoval(struct pkginfo *pkgtoremove,
       continue;
     }
     if (dependtry > 1) { if (findbreakcycle(pkgtoremove)) sincenothing= 0; }
-    before= raemsgs->used;
+    varbuf_snapshot(raemsgs, &raemsgs_state);
     ok= dependencies_ok(depender,pkgtoremove,raemsgs);
     if (ok == DEP_CHECK_HALT &&
         depender->clientdata->istobe == PKG_ISTOBE_REMOVE)
       ok = DEP_CHECK_DEFER;
     if (ok == DEP_CHECK_DEFER)
       /* Don't burble about reasons for deferral. */
-      varbuf_trunc(raemsgs, before);
+      varbuf_rollback(raemsgs, &raemsgs_state);
     if (ok < *rokp) *rokp= ok;
   }
 }
@@ -247,11 +247,11 @@ removal_bulk_file_is_shared(struct pkginfo *pkg, struct filenamenode *namenode)
 static void
 removal_bulk_remove_files(struct pkginfo *pkg)
 {
-  int before;
   struct reversefilelistiter rlistit;
   struct fileinlist *leftover;
   struct filenamenode *namenode;
   static struct varbuf fnvb;
+  struct varbuf_state fnvb_state;
   struct stat stab;
 
     pkg_set_status(pkg, PKG_STAT_HALFINSTALLED);
@@ -273,7 +273,7 @@ removal_bulk_remove_files(struct pkginfo *pkg)
       varbuf_add_str(&fnvb, instdir);
       varbuf_add_str(&fnvb, usenode->name);
       varbuf_end_str(&fnvb);
-      before= fnvb.used;
+      varbuf_snapshot(&fnvb, &fnvb_state);
 
       is_dir = stat(fnvb.buf, &stab) == 0 && S_ISDIR(stab.st_mode);
 
@@ -315,19 +315,19 @@ removal_bulk_remove_files(struct pkginfo *pkg)
 
       trig_path_activate(usenode, pkg);
 
-      varbuf_trunc(&fnvb, before);
+      varbuf_rollback(&fnvb, &fnvb_state);
       varbuf_add_str(&fnvb, DPKGTEMPEXT);
       varbuf_end_str(&fnvb);
       debug(dbg_eachfiledetail, "removal_bulk cleaning temp '%s'", fnvb.buf);
       path_remove_tree(fnvb.buf);
 
-      varbuf_trunc(&fnvb, before);
+      varbuf_rollback(&fnvb, &fnvb_state);
       varbuf_add_str(&fnvb, DPKGNEWEXT);
       varbuf_end_str(&fnvb);
       debug(dbg_eachfiledetail, "removal_bulk cleaning new '%s'", fnvb.buf);
       path_remove_tree(fnvb.buf);
 
-      varbuf_trunc(&fnvb, before);
+      varbuf_rollback(&fnvb, &fnvb_state);
       varbuf_end_str(&fnvb);
 
       debug(dbg_eachfiledetail, "removal_bulk removing '%s'", fnvb.buf);
@@ -462,7 +462,7 @@ static void removal_bulk_remove_leftover_dirs(struct pkginfo *pkg) {
 
 static void removal_bulk_remove_configfiles(struct pkginfo *pkg) {
   static const char *const removeconffexts[] = { REMOVECONFFEXTS, NULL };
-  int rc, removevbbase;
+  int rc;
   int conffnameused, conffbasenamelen;
   char *conffbasename;
   struct conffile *conff, **lconffp;
@@ -515,6 +515,8 @@ static void removal_bulk_remove_configfiles(struct pkginfo *pkg) {
 
     for (conff= pkg->installed.conffiles; conff; conff= conff->next) {
     static struct varbuf fnvb, removevb;
+      struct varbuf_state removevb_state;
+
       if (conff->obsolete) {
 	debug(dbg_conffdetail, "removal_bulk conffile obsolete %s",
 	      conff->name);
@@ -534,8 +536,9 @@ static void removal_bulk_remove_configfiles(struct pkginfo *pkg) {
       varbuf_reset(&removevb);
       varbuf_add_str(&removevb, fnvb.buf);
       varbuf_add_char(&removevb, '/');
-      removevbbase= removevb.used;
       varbuf_end_str(&removevb);
+      varbuf_snapshot(&removevb, &removevb_state);
+
       dsd= opendir(removevb.buf);
       if (!dsd) {
         int e=errno;
@@ -574,7 +577,7 @@ static void removal_bulk_remove_configfiles(struct pkginfo *pkg) {
         debug(dbg_stupidlyverbose, "removal_bulk conffile dsd entry not it");
         continue;
       yes_remove:
-        varbuf_trunc(&removevb, removevbbase);
+        varbuf_rollback(&removevb, &removevb_state);
         varbuf_add_str(&removevb, de->d_name);
         varbuf_end_str(&removevb);
         debug(dbg_conffdetail, "removal_bulk conffile dsd entry removing '%s'",

+ 2 - 2
src/unpack.c

@@ -1022,7 +1022,7 @@ void process_archive(const char *filename) {
 
     usenode = namenodetouse(namenode, pkg, &pkg->installed);
 
-    varbuf_trunc(&fnamevb, fnameidlu);
+    varbuf_rollback(&fnamevb, &fname_state);
     varbuf_add_str(&fnamevb, usenode->name);
     varbuf_end_str(&fnamevb);
 
@@ -1454,7 +1454,7 @@ void process_archive(const char *filename) {
     if (strcmp(usenode->name, "/.") == 0)
       continue;
 
-    varbuf_trunc(&fnametmpvb, fnameidlu);
+    varbuf_rollback(&fnametmpvb, &fname_state);
     varbuf_add_str(&fnametmpvb, usenode->name);
     varbuf_add_str(&fnametmpvb, DPKGTEMPEXT);
     varbuf_end_str(&fnametmpvb);