123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- /*
- * libdpkg - Debian packaging suite library routines
- * dump.c - code to write in-core database to a file
- *
- * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
- * Copyright © 2001 Wichert Akkerman
- *
- * 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 this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /* FIXME: don't write uninteresting packages */
- #include <config.h>
- #include <compat.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <assert.h>
- #include <errno.h>
- #include <ctype.h>
- #include <string.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <dpkg/i18n.h>
- #include <dpkg/dpkg.h>
- #include <dpkg/dpkg-db.h>
- #include <dpkg/parsedump.h>
- void w_name(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip) {
- assert(pigp->name);
- if (flags&fw_printheader)
- varbufaddstr(vb,"Package: ");
- varbufaddstr(vb, pigp->name);
- if (flags&fw_printheader)
- varbufaddc(vb,'\n');
- }
- void w_version(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip) {
- /* Epoch and revision information is printed in version field too. */
- if (!informativeversion(&pifp->version)) return;
- if (flags&fw_printheader)
- varbufaddstr(vb,"Version: ");
- varbufversion(vb,&pifp->version,vdew_nonambig);
- if (flags&fw_printheader)
- varbufaddc(vb,'\n');
- }
- void w_configversion(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip) {
- if (pifp != &pigp->installed) return;
- if (!informativeversion(&pigp->configversion)) return;
- if (pigp->status == stat_installed ||
- pigp->status == stat_notinstalled ||
- pigp->status == stat_triggerspending ||
- pigp->status == stat_triggersawaited)
- return;
- if (flags&fw_printheader)
- varbufaddstr(vb,"Config-Version: ");
- varbufversion(vb,&pigp->configversion,vdew_nonambig);
- if (flags&fw_printheader)
- varbufaddc(vb,'\n');
- }
- void w_null(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip) {
- }
- void w_section(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip) {
- const char *value= pigp->section;
- if (!value || !*value) return;
- if (flags&fw_printheader)
- varbufaddstr(vb,"Section: ");
- varbufaddstr(vb,value);
- if (flags&fw_printheader)
- varbufaddc(vb,'\n');
- }
- void w_charfield(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip) {
- const char *value= pifp->valid ? PKGPFIELD(pifp,fip->integer,const char*) : NULL;
- if (!value || !*value) return;
- if (flags&fw_printheader) {
- varbufaddstr(vb,fip->name);
- varbufaddstr(vb, ": ");
- }
- varbufaddstr(vb,value);
- if (flags&fw_printheader)
- varbufaddc(vb,'\n');
- }
- void w_filecharf(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip) {
- struct filedetails *fdp;
-
- if (pifp != &pigp->available) return;
- fdp= pigp->files;
- if (!fdp || !FILEFFIELD(fdp,fip->integer,const char*)) return;
- if (flags&fw_printheader) {
- varbufaddstr(vb,fip->name);
- varbufaddc(vb,':');
- }
- while (fdp) {
- varbufaddc(vb,' ');
- varbufaddstr(vb,FILEFFIELD(fdp,fip->integer,const char*));
- fdp= fdp->next;
- }
- if (flags&fw_printheader)
- varbufaddc(vb,'\n');
- }
- void w_booleandefno(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip) {
- int value= pifp->valid ? PKGPFIELD(pifp,fip->integer,int) : -1;
- if (!(flags&fw_printheader)) {
- varbufaddstr(vb, (value==1) ? "yes" : "no");
- return;
- }
- if (!value) return;
- assert(value==1);
- varbufaddstr(vb,fip->name); varbufaddstr(vb, ": yes\n");
- }
- void w_priority(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip) {
- if (pigp->priority == pri_unknown) return;
- assert(pigp->priority <= pri_unknown);
- if (flags&fw_printheader)
- varbufaddstr(vb,"Priority: ");
- varbufaddstr(vb,
- pigp->priority == pri_other
- ? pigp->otherpriority
- : priorityinfos[pigp->priority].name);
- if (flags&fw_printheader)
- varbufaddc(vb,'\n');
- }
- void w_status(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip) {
- if (pifp != &pigp->installed) return;
- assert(pigp->want <= want_purge);
- assert(pigp->eflag <= eflag_reinstreq);
- #define PEND pigp->trigpend_head
- #define AW pigp->trigaw.head
- switch (pigp->status) {
- case stat_notinstalled:
- case stat_configfiles:
- assert(!PEND);
- assert(!AW);
- break;
- case stat_halfinstalled:
- case stat_unpacked:
- case stat_halfconfigured:
- assert(!PEND);
- break;
- case stat_triggersawaited:
- assert(AW);
- break;
- case stat_triggerspending:
- assert(PEND);
- assert(!AW);
- break;
- case stat_installed:
- assert(!PEND);
- assert(!AW);
- break;
- default:
- internerr("unknown package status '%d'", pigp->status);
- }
- #undef PEND
- #undef AW
- if (flags&fw_printheader)
- 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);
- if (flags&fw_printheader)
- 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 '%d'", dop->verrel);
- }
- varbufaddc(vb,' ');
- varbufversion(vb,&dop->version,vdew_nonambig);
- varbufaddc(vb,')');
- }
- }
- }
- void w_dependency(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip) {
- char fnbuf[50];
- const char *depdel;
- struct dependency *dyp;
- if (!pifp->valid) return;
- if (flags&fw_printheader)
- sprintf(fnbuf,"%s: ",fip->name);
- else
- fnbuf[0] = '\0';
- 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 ((flags&fw_printheader) && (depdel!=fnbuf))
- varbufaddc(vb,'\n');
- }
- void w_conffiles(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip) {
- struct conffile *i;
- if (!pifp->valid || !pifp->conffiles || pifp == &pigp->available) return;
- if (flags&fw_printheader)
- varbufaddstr(vb,"Conffiles:\n");
- for (i=pifp->conffiles; i; i= i->next) {
- if (i!=pifp->conffiles) varbufaddc(vb,'\n');
- varbufaddc(vb,' '); varbufaddstr(vb,i->name); varbufaddc(vb,' ');
- varbufaddstr(vb,i->hash);
- if (i->obsolete) varbufaddstr(vb," obsolete");
- }
- if (flags&fw_printheader)
- varbufaddc(vb,'\n');
- }
- void
- w_trigpend(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip)
- {
- struct trigpend *tp;
- if (!pifp->valid || pifp == &pigp->available || !pigp->trigpend_head)
- return;
- assert(pigp->status >= stat_triggersawaited &&
- pigp->status <= stat_triggerspending);
- if (flags & fw_printheader)
- varbufaddstr(vb, "Triggers-Pending:");
- for (tp = pigp->trigpend_head; tp; tp = tp->next) {
- varbufaddc(vb, ' ');
- varbufaddstr(vb, tp->name);
- }
- if (flags & fw_printheader)
- varbufaddc(vb, '\n');
- }
- void
- w_trigaw(struct varbuf *vb,
- const struct pkginfo *pigp, const struct pkginfoperfile *pifp,
- enum fwriteflags flags, const struct fieldinfo *fip)
- {
- struct trigaw *ta;
- if (!pifp->valid || pifp == &pigp->available || !pigp->trigaw.head)
- return;
- assert(pigp->status > stat_configfiles &&
- pigp->status <= stat_triggersawaited);
- if (flags & fw_printheader)
- varbufaddstr(vb, "Triggers-Awaited:");
- for (ta = pigp->trigaw.head; ta; ta = ta->sameaw.next) {
- varbufaddc(vb, ' ');
- varbufaddstr(vb, ta->pend->name);
- }
- if (flags & fw_printheader)
- 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,fw_printheader,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 = VARBUF_INIT;
- varbufrecord(&vb,pigp,pifp);
- varbufaddc(&vb,'\0');
- if (fputs(vb.buf,file) < 0)
- ohshite(_("failed to write details of `%.50s' to `%.250s'"), pigp->name,
- filename);
- varbuffree(&vb);
- }
- void writedb(const char *filename, int available, int mustsync) {
- static char writebuf[8192];
-
- struct pkgiterator *it;
- struct pkginfo *pigp;
- struct pkginfoperfile *pifp;
- char *oldfn, *newfn;
- const char *which;
- FILE *file;
- struct varbuf vb = VARBUF_INIT;
- int old_umask;
- 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);
- old_umask = umask(022);
- file= fopen(newfn,"w");
- umask(old_umask);
- 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)) != NULL) {
- pifp= available ? &pigp->available : &pigp->installed;
- /* Don't dump records which have no useful content. */
- if (!informative(pigp,pifp)) continue;
- if (!pifp->valid) blankpackageperfile(pifp);
- varbufrecord(&vb,pigp,pifp);
- varbufaddc(&vb,'\n'); varbufaddc(&vb,0);
- if (fputs(vb.buf,file) < 0)
- ohshite(_("failed to write %s record about `%.50s' to `%.250s'"),
- which, pigp->name, filename);
- varbufreset(&vb);
- }
- iterpkgend(it);
- 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);
- free(newfn);
- free(oldfn);
- }
|