summaryrefslogtreecommitdiff
path: root/lib/dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dump.c')
-rw-r--r--lib/dump.c289
1 files changed, 289 insertions, 0 deletions
diff --git a/lib/dump.c b/lib/dump.c
new file mode 100644
index 000000000..97d5c4304
--- /dev/null
+++ b/lib/dump.c
@@ -0,0 +1,289 @@
+/*
+ * libdpkg - Debian packaging suite library routines
+ * dump.c - code to write in-core database to a file
+ *
+ * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
+ *
+ * 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,
+ * 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 dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* fixme: don't write uninteresting packages */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "config.h"
+#include "dpkg.h"
+#include "dpkg-db.h"
+#include "parsedump.h"
+
+void w_name(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
+ const struct fieldinfo *fip) {
+ assert(pigp->name);
+ varbufaddstr(vb,"Package: "); varbufaddstr(vb, pigp->name);
+ varbufaddc(vb,'\n');
+}
+
+void w_version(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
+ const struct fieldinfo *fip) {
+ /* Revision information is printed in version field too. */
+ if ((!pifp->version || !*pifp->version) &&
+ (!pifp->revision || !*pifp->revision)) return;
+ varbufaddstr(vb,"Version: ");
+ varbufaddstr(vb,pifp->version ? pifp->version : "");
+ if (pifp->revision && *pifp->revision) {
+ varbufaddc(vb,'-');
+ varbufaddstr(vb,pifp->revision);
+ }
+ varbufaddc(vb,'\n');
+}
+
+void w_configversion(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
+ const struct fieldinfo *fip) {
+ if ((!pigp->configversion || !*pigp->configversion) &&
+ (!pigp->configrevision || !*pigp->configrevision)) return;
+ if (pifp != &pigp->installed) return;
+ if (pigp->status == stat_installed || pigp->status == stat_notinstalled) return;
+ varbufaddstr(vb,"Config-Version: ");
+ varbufaddstr(vb,pigp->configversion ? pigp->configversion : "");
+ if (pigp->configrevision && *pigp->configrevision) {
+ varbufaddc(vb,'-');
+ varbufaddstr(vb,pigp->configrevision);
+ }
+ varbufaddc(vb,'\n');
+}
+
+void w_null(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
+ const struct fieldinfo *fip) {
+}
+
+void w_section(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
+ const struct fieldinfo *fip) {
+ const char *value= pigp->section;
+ if (!value || !*value) return;
+ varbufaddstr(vb,"Section: ");
+ varbufaddstr(vb,value);
+ varbufaddc(vb,'\n');
+}
+
+void w_charfield(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
+ const struct fieldinfo *fip) {
+ const char *value= pifp->valid ? PKGPFIELD(pifp,fip->integer,char*) : 0;
+ if (!value || !*value) return;
+ varbufaddstr(vb,fip->name); varbufaddstr(vb, ": "); varbufaddstr(vb,value);
+ varbufaddc(vb,'\n');
+}
+
+void w_filecharf(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
+ const struct fieldinfo *fip) {
+ struct filedetails *fdp;
+
+ if (pifp != &pigp->available) return;
+ fdp= pigp->files;
+ if (!fdp || !FILEFFIELD(fdp,fip->integer,char*)) return;
+ varbufaddstr(vb,fip->name); varbufaddc(vb,':');
+ while (fdp) {
+ varbufaddc(vb,' ');
+ varbufaddstr(vb,FILEFFIELD(fdp,fip->integer,char*));
+ fdp= fdp->next;
+ }
+ varbufaddc(vb,'\n');
+}
+
+void w_booleandefno(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
+ const struct fieldinfo *fip) {
+ int value= pifp->valid ? PKGPFIELD(pifp,fip->integer,int) : 0;
+ if (!value) return;
+ assert(value==1);
+ varbufaddstr(vb,"Essential: yes\n");
+}
+
+void w_priority(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
+ const struct fieldinfo *fip) {
+ if (pigp->priority == pri_unknown) return;
+ assert(pigp->priority <= pri_unknown);
+ varbufaddstr(vb,"Priority: ");
+ varbufaddstr(vb,
+ pigp->priority == pri_other
+ ? pigp->otherpriority
+ : priorityinfos[pigp->priority].name);
+ varbufaddc(vb,'\n');
+}
+
+void w_status(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
+ const struct fieldinfo *fip) {
+ if (pifp != &pigp->installed) return;
+ assert(pigp->want <= want_purge &&
+ pigp->eflag <= eflagv_both &&
+ pigp->status <= stat_configfiles);
+ varbufaddstr(vb,"Status: ");
+ varbufaddstr(vb,wantinfos[pigp->want].name); varbufaddc(vb,' ');
+ varbufaddstr(vb,eflaginfos[pigp->eflag].name); varbufaddc(vb,' ');
+ varbufaddstr(vb,statusinfos[pigp->status].name); varbufaddc(vb,'\n');
+}
+
+void varbufdependency(struct varbuf *vb, struct dependency *dep) {
+ struct deppossi *dop;
+ const char *possdel;
+
+ possdel= "";
+ for (dop= dep->list; dop; dop= dop->next) {
+ assert(dop->up == dep);
+ varbufaddstr(vb,possdel); possdel= " | ";
+ varbufaddstr(vb,dop->ed->name);
+ if (dop->verrel != dvr_none) {
+ varbufaddstr(vb," (");
+ switch (dop->verrel) {
+ case dvr_exact: varbufaddc(vb,'='); break;
+ case dvr_laterequal: varbufaddstr(vb,">="); break;
+ case dvr_earlierequal: varbufaddstr(vb,"<="); break;
+ case dvr_laterstrict: varbufaddstr(vb,">>"); break;
+ case dvr_earlierstrict: varbufaddstr(vb,"<<"); break;
+ default: internerr("unknown verrel");
+ }
+ if (!isalnum(dop->version[0])) varbufaddc(vb,' ');
+ varbufaddstr(vb,dop->version);
+ if (dop->revision) { varbufaddc(vb,'-'); varbufaddstr(vb,dop->revision); }
+ varbufaddc(vb,')');
+ }
+ }
+}
+
+void w_dependency(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
+ const struct fieldinfo *fip) {
+ char fnbuf[50];
+ const char *depdel;
+ struct dependency *dyp;
+
+ if (!pifp->valid) return;
+ sprintf(fnbuf,"%s: ",fip->name); depdel= fnbuf;
+ for (dyp= pifp->depends; dyp; dyp= dyp->next) {
+ if (dyp->type != fip->integer) continue;
+ assert(dyp->up == pigp);
+ varbufaddstr(vb,depdel); depdel= ", ";
+ varbufdependency(vb,dyp);
+ }
+ if (depdel != fnbuf) varbufaddc(vb,'\n');
+}
+
+void w_conffiles(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
+ const struct fieldinfo *fip) {
+ struct conffile *i;
+
+ if (!pifp->valid || !pifp->conffiles || pifp == &pigp->available) return;
+ varbufaddstr(vb,"Conffiles:\n");
+ for (i=pifp->conffiles; i; i= i->next) {
+ varbufaddc(vb,' '); varbufaddstr(vb,i->name); varbufaddc(vb,' ');
+ varbufaddstr(vb,i->hash); varbufaddc(vb,'\n');
+ }
+}
+
+void varbufrecord(struct varbuf *vb,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp) {
+ const struct fieldinfo *fip;
+ const struct arbitraryfield *afp;
+
+ for (fip= fieldinfos; fip->name; fip++) {
+ fip->wcall(vb,pigp,pifp,fip);
+ }
+ if (pifp->valid) {
+ for (afp= pifp->arbs; afp; afp= afp->next) {
+ varbufaddstr(vb,afp->name); varbufaddstr(vb,": ");
+ varbufaddstr(vb,afp->value); varbufaddc(vb,'\n');
+ }
+ }
+}
+
+void writerecord(FILE *file, const char *filename,
+ const struct pkginfo *pigp, const struct pkginfoperfile *pifp) {
+ struct varbuf vb;
+
+ varbufinit(&vb);
+ varbufrecord(&vb,pigp,pifp);
+ varbufaddc(&vb,'\0');
+ if (!fputs(vb.buf,file))
+ ohshite("failed to write details of `%.50s' to `%.250s'", pigp->name, filename);
+}
+
+void writedb(const char *filename, int available, int mustsync) {
+ static char writebuf[8192];
+
+ struct pkgiterator *it;
+ struct pkginfo *pigp;
+ char *oldfn, *newfn;
+ const char *which;
+ FILE *file;
+ struct varbuf vb;
+
+ which= available ? "available" : "status";
+ oldfn= m_malloc(strlen(filename)+sizeof(OLDDBEXT));
+ strcpy(oldfn,filename); strcat(oldfn,OLDDBEXT);
+ newfn= m_malloc(strlen(filename)+sizeof(NEWDBEXT));
+ strcpy(newfn,filename); strcat(newfn,NEWDBEXT);
+ varbufinit(&vb);
+
+ file= fopen(newfn,"w");
+ if (!file) ohshite("failed to open `%s' for writing %s information",filename,which);
+
+ if (setvbuf(file,writebuf,_IOFBF,sizeof(writebuf)))
+ ohshite("unable to set buffering on status file");
+
+ it= iterpkgstart();
+ while ((pigp= iterpkgnext(it)) != 0) {
+ if (!(informative(pigp) ||
+ informativeperfile(&pigp->available) ||
+ informativeperfile(&pigp->installed)))
+ /* Don't dump records which have no useful content. */
+ continue;
+ varbufrecord(&vb, pigp, available ? &pigp->available : &pigp->installed);
+ varbufaddc(&vb,'\n'); varbufaddc(&vb,0);
+ if (!fputs(vb.buf,file))
+ ohshite("failed to write %s record about `%.50s' to `%.250s'",
+ which, pigp->name, filename);
+ varbufreset(&vb);
+ }
+ varbuffree(&vb);
+ if (mustsync) {
+ if (fflush(file))
+ ohshite("failed to flush %s information to `%.250s'", which, filename);
+ if (fsync(fileno(file)))
+ ohshite("failed to fsync %s information to `%.250s'", which, filename);
+ }
+ if (fclose(file)) ohshite("failed to close `%.250s' after writing %s information",
+ filename, which);
+ unlink(oldfn);
+ if (link(filename,oldfn) && errno != ENOENT)
+ ohshite("failed to link `%.250s' to `%.250s' for backup of %s info",
+ filename, oldfn, which);
+ if (rename(newfn,filename))
+ ohshite("failed to install `%.250s' as `%.250s' containing %s info",
+ newfn, filename, which);
+}