Exemplo n.º 1
0
int dpkg_psys_unregister(const char *vendor, const char *name, psys_err_t *err)
{
	int ret;
	jmp_buf buf;
	char *dpkgname;
	struct pkginfo *dpkg;

	init_error_handler(err, buf, out);
	modstatdb_init(ADMINDIR, msdbrw_needsuperuser);

	dpkgname = dpkg_name(vendor, name);
	dpkg = findpackage(dpkgname);
	if (ensure_installed(dpkg, err)) {
		ret = -1;
		goto out;
	}

	remove_info_files(dpkg);
	dpkg->want = want_purge;
	dpkg->status = stat_notinstalled;
	blankpackageperfile(&dpkg->installed);
	modstatdb_note(dpkg);

	ret = 0;
out:
	modstatdb_shutdown();
	cleanup();
	return ret;	
}
Exemplo n.º 2
0
int ensure_dependencies_met(psys_pkg_t pkg, psys_err_t *err)
{
	struct pkginfo *lsb_dpkg;

	lsb_dpkg = findpackage("lsb");
	if (lsb_dpkg->status != stat_installed) {
		psys_err_set(err, PSYS_ELSBVER,
			     "The system is currently not Linux Standard "
			     "Base (LSB) compliant: Package `lsb' is not "
			     "installed");
		return -1;
	}

	if (psys_pkg_lsbvercmp(pkg, lsb_dpkg->installed.version.version) < 0) {
		psys_err_set(err, PSYS_ELSBVER,
			     "The system's Linux Standard Base (LSB) "
			     "compliance is not sufficient: version %s is "
			     "required, but package `lsb' is at version %s",
			     psys_pkg_lsbversion(pkg),
			     lsb_dpkg->installed.version);
		return -1;
	}

	return 0;
}
Exemplo n.º 3
0
Arquivo: main.c Projeto: jtniehof/dpkg
static void ignoredepends(const struct cmdinfo *cip, const char *value) {
  char *copy, *p;
  const char *pnerr;

  copy= m_malloc(strlen(value)+2);
  strcpy(copy,value);
  copy[strlen(value) + 1] = '\0';
  for (p=copy; *p; p++) {
    if (*p != ',') continue;
    *p++ = '\0';
    if (!*p || *p==',' || p==copy+1)
      badusage(_("null package name in --ignore-depends comma-separated list `%.250s'"),
               value);
  }
  p= copy;
  while (*p) {
    pnerr = illegal_packagename(p, NULL);
    if (pnerr) ohshite(_("--ignore-depends requires a legal package name. "
                       "`%.250s' is not; %s"), p, pnerr);

    pkg_list_prepend(&ignoredependss, findpackage(p));

    p+= strlen(p)+1;
  }

  free(copy);
}
Exemplo n.º 4
0
int dpkg_psys_announce(psys_pkg_t pkg, psys_err_t *err)
{
	int ret;
	jmp_buf buf;
	char *dpkgname = NULL;
	struct pkginfo *dpkg;

	pkg = psys_pkg_copy(pkg);
	if (!pkg) {
		psys_err_set_nomem(err);
		return -1;
	}
	psys_pkg_assert_valid(pkg);

	init_error_handler(err, buf, out);
	modstatdb_init(ADMINDIR, msdbrw_needsuperuser);

	dpkgname = dpkg_name(psys_pkg_vendor(pkg), psys_pkg_name(pkg));
	dpkg = findpackage(dpkgname);
	if (ensure_not_installed(dpkg, err)) {
		ret = -1;
		goto out;
	}

	if (ensure_dependencies_met(pkg, err)) {
		ret = -1;
		goto out;
	}

	if (ensure_no_conflicting_extras(pkg, err)) {
		ret = -1;
		goto out;
	}

	ret = 0;
out:
	modstatdb_shutdown();
	cleanup();
	psys_pkg_free(pkg);
	return ret;
}
Exemplo n.º 5
0
void add_dependencies(struct pkginfo *dpkg, psys_pkg_t pkg)
{
	struct dependency *dep;
	struct deppossi *depp;

	dep = nfmalloc(sizeof(*dep));
	dep->up = dpkg;
	dep->next = NULL;
	dep->type = dep_depends;

	depp = nfmalloc(sizeof(*depp));
	depp->up = dep;
	depp->next = NULL;
	depp->nextrev = NULL;
	depp->backrev = NULL;
	depp->ed = findpackage("lsb");
	depp->verrel = dvr_laterequal;
	parseversion(&depp->version, psys_pkg_lsbversion(pkg));

	dep->list = depp;
	dpkg->installed.depends = dep;
}
Exemplo n.º 6
0
int dpkg_psys_unannounce(const char *vendor, const char *name, psys_err_t *err)
{
	int ret;
	jmp_buf buf;
	char *dpkgname;
	struct pkginfo *dpkg;

	init_error_handler(err, buf, out);
	modstatdb_init(ADMINDIR, msdbrw_needsuperuser);

	dpkgname = dpkg_name(vendor, name);
	dpkg = findpackage(dpkgname);
	if (ensure_installed(dpkg, err)) {
		ret = -1;
		goto out;
	}

	ret = 0;
out:
	modstatdb_shutdown();
	cleanup();
	return ret;
}
Exemplo n.º 7
0
int dpkg_psys_register_update(psys_pkg_t pkg, psys_err_t *err)
{
	int ret;
	jmp_buf buf;
	char *dpkgname;
	struct pkginfo *dpkg;

	pkg = psys_pkg_copy(pkg);
	if (!pkg) {
		psys_err_set_nomem(err);
		return -1;
	}
	psys_pkg_assert_valid(pkg);

	init_error_handler(err, buf, out);
	modstatdb_init(ADMINDIR, msdbrw_needsuperuser);

	dpkgname = dpkg_name(psys_pkg_vendor(pkg), psys_pkg_name(pkg));
	dpkg = findpackage(dpkgname);
	if (ensure_installed(dpkg, err)) {
		ret = -1;
		goto out;
	}

	if (ensure_version_newer(pkg, dpkg, err)) {
		ret = -1;
		goto out;
	}

	dpkg->status = stat_notinstalled;
	ret = do_register(pkg, err, &buf);
out:
	modstatdb_shutdown();
	cleanup();
	psys_pkg_free(pkg);
	return ret;
}
Exemplo n.º 8
0
static int do_register(psys_pkg_t pkg, psys_err_t *err, jmp_buf *buf)
{
	int ret;
	char *dpkgname = NULL;
	const char *dpkgarch;
	struct pkginfo *dpkg;
	psys_flist_t flist = NULL;
	char *filelist_path = NULL;
	char *md5list_path = NULL;

	set_error_handler(err, *buf, out);

	dpkgname = dpkg_name(psys_pkg_vendor(pkg), psys_pkg_name(pkg));
	dpkg = findpackage(dpkgname);
	if (ensure_not_installed(dpkg, err)) {
		ret = -1;
		goto out;
	}

	if (ensure_dependencies_met(pkg, err)) {
		ret = -1;
		goto out;
	}

	blankpackage(dpkg);
	blankpackageperfile(&dpkg->installed);

	/* Name, Version */
	dpkg->name = dpkgname;
	parseversion(&dpkg->installed.version, psys_pkg_version(pkg));

	/* Architecture */
	dpkgarch = dpkg_arch(psys_pkg_arch(pkg), err);
	if (!dpkgarch) {
		ret = -1;
		goto out;
	}
	dpkg->installed.architecture = dpkgarch;

	/* Description */
	set_description(dpkg, pkg);

	/* 
	 * Maintainer
	 *
	 * FIXME: Our Maintainer value does not conform to the format
	 * mandated by the Debian Policy Manual (which is "Name <E-Mail>"),
	 * but this is better than not specifying a Maintainer at all
	 * (which is a mandatory field)
	 */
	dpkg->installed.maintainer = nfstrsave(psys_pkg_vendor(pkg));

	/* Priority */
	dpkg->priority = pri_optional;

	/* Dependencies */
	add_dependencies(dpkg, pkg);

	flist = psys_pkg_flist(pkg, err);
	if (!flist) {
		ret = -1;
		goto out;
	}

	/* Installed Size */
	set_installed_size(dpkg, flist);

	/* File List */
	filelist_path = create_file_list(dpkg, flist, err);
	if (!filelist_path) {
		ret = -1;
		goto out;
	}

	/* MD5SUMS List */
	md5list_path = create_md5sums_list(dpkg, flist, err);
	if (!md5list_path) {
		ret = -1;
		goto out;
	}

	dpkg->want = want_install;
	dpkg->status = stat_installed;
	modstatdb_note(dpkg);

	ret = 0;
out:
	if (md5list_path) {
		if (ret == -1)
			remove(md5list_path);
		free(md5list_path);
	}
	if (filelist_path) {
		if (ret == -1)
			remove(filelist_path);
		free(filelist_path);
	}
	if (flist)
		psys_flist_free(flist);
	return ret;
}
Exemplo n.º 9
0
int parsedb(const char *filename, enum parsedbflags flags,
            struct pkginfo **donep, FILE *warnto, int *warncount) {
  /* warnto, warncount and donep may be null.
   * If donep is not null only one package's information is expected.
   */
  
  static int fd;
  struct pkginfo newpig, *pigp;
  struct pkginfoperfile *newpifp, *pifp;
  struct arbitraryfield *arp, **larpp;
  struct trigaw *ta;
  int pdone;
  int fieldencountered[array_count(fieldinfos)];
  const struct fieldinfo *fip;
  const struct nickname *nick;
  char *data, *dataptr, *endptr;
  const char *fieldstart, *valuestart;
  char *value= NULL;
  int fieldlen= 0, valuelen= 0;
  int *ip, c;
  struct stat st;
  struct parsedb_state ps;

  ps.filename = filename;
  ps.flags = flags;
  ps.lno = 0;
  ps.warnto = warnto;
  ps.warncount = 0;

  newpifp= (flags & pdb_recordavailable) ? &newpig.available : &newpig.installed;
  fd= open(filename, O_RDONLY);
  if (fd == -1) ohshite(_("failed to open package info file `%.255s' for reading"),filename);

  push_cleanup(cu_closefd, ~ehflag_normaltidy, NULL, 0, 1, &fd);

  if (fstat(fd, &st) == -1)
    ohshite(_("can't stat package info file `%.255s'"),filename);

  if (st.st_size > 0) {
#ifdef USE_MMAP
    dataptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
    if (dataptr == MAP_FAILED)
      ohshite(_("can't mmap package info file `%.255s'"),filename);
#else
    dataptr = m_malloc(st.st_size);

    fd_buf_copy(fd, dataptr, st.st_size, _("copy info file `%.255s'"), filename);
#endif
    data= dataptr;
    endptr = dataptr + st.st_size;
  } else {
    data= dataptr= endptr= NULL;
  }

  pdone= 0;
#define EOF_mmap(dataptr, endptr)	(dataptr >= endptr)
#define getc_mmap(dataptr)		*dataptr++;
#define ungetc_mmap(c, dataptr, data)	dataptr--;

  for (;;) { /* loop per package */
    memset(fieldencountered, 0, sizeof(fieldencountered));
    blankpackage(&newpig);

/* Skip adjacent new lines */
    while(!EOF_mmap(dataptr, endptr)) {
      c= getc_mmap(dataptr); if (c!='\n' && c!=MSDOS_EOF_CHAR ) break;
      ps.lno++;
    }
    if (EOF_mmap(dataptr, endptr)) break;
    for (;;) { /* loop per field */
      fieldstart= dataptr - 1;
      while (!EOF_mmap(dataptr, endptr) && !isspace(c) && c!=':' && c!=MSDOS_EOF_CHAR)
        c= getc_mmap(dataptr);
      fieldlen= dataptr - fieldstart - 1;
      while (!EOF_mmap(dataptr, endptr) && c != '\n' && isspace(c)) c= getc_mmap(dataptr);
      if (EOF_mmap(dataptr, endptr))
        parse_error(&ps, &newpig,
                    _("EOF after field name `%.*s'"), fieldlen, fieldstart);
      if (c == '\n')
        parse_error(&ps, &newpig,
                    _("newline in field name `%.*s'"), fieldlen, fieldstart);
      if (c == MSDOS_EOF_CHAR)
        parse_error(&ps, &newpig,
                    _("MSDOS EOF (^Z) in field name `%.*s'"),
                    fieldlen, fieldstart);
      if (c != ':')
        parse_error(&ps, &newpig,
                    _("field name `%.*s' must be followed by colon"),
                    fieldlen, fieldstart);
/* Skip space after ':' but before value and eol */
      while(!EOF_mmap(dataptr, endptr)) {
        c= getc_mmap(dataptr);
        if (c == '\n' || !isspace(c)) break;
      }
      if (EOF_mmap(dataptr, endptr))
        parse_error(&ps, &newpig,
                    _("EOF before value of field `%.*s' (missing final newline)"),
                 fieldlen,fieldstart);
      if (c == MSDOS_EOF_CHAR)
        parse_error(&ps, &newpig,
                    _("MSDOS EOF char in value of field `%.*s' (missing newline?)"),
                    fieldlen,fieldstart);
      valuestart= dataptr - 1;
      for (;;) {
        if (c == '\n' || c == MSDOS_EOF_CHAR) {
          ps.lno++;
	  if (EOF_mmap(dataptr, endptr)) break;
          c= getc_mmap(dataptr);
/* Found double eol, or start of new field */
          if (EOF_mmap(dataptr, endptr) || c == '\n' || !isspace(c)) break;
          ungetc_mmap(c,dataptr, data);
          c= '\n';
        } else if (EOF_mmap(dataptr, endptr)) {
          parse_error(&ps, &newpig,
                      _("EOF during value of field `%.*s' (missing final newline)"),
                      fieldlen,fieldstart);
        }
        c= getc_mmap(dataptr);
      }
      valuelen= dataptr - valuestart - 1;
/* trim ending space on value */
      while (valuelen && isspace(*(valuestart+valuelen-1)))
 valuelen--;
      for (nick = nicknames;
           nick->nick && (strncasecmp(nick->nick, fieldstart, fieldlen) ||
                          nick->nick[fieldlen] != '\0'); nick++) ;
      if (nick->nick) {
	fieldstart= nick->canon;
	fieldlen= strlen(fieldstart);
      }
      for (fip= fieldinfos, ip= fieldencountered;
           fip->name && strncasecmp(fieldstart,fip->name, fieldlen);
           fip++, ip++);
      if (fip->name) {
        value = m_realloc(value, valuelen + 1);
	memcpy(value,valuestart,valuelen);
        *(value + valuelen) = '\0';
        if ((*ip)++)
          parse_error(&ps, &newpig,
                      _("duplicate value for `%s' field"), fip->name);
        fip->rcall(&newpig, newpifp, &ps, value, fip);
      } else {
        if (fieldlen<2)
          parse_error(&ps, &newpig,
                      _("user-defined field name `%.*s' too short"),
                      fieldlen, fieldstart);
        larpp= &newpifp->arbs;
        while ((arp= *larpp) != NULL) {
          if (!strncasecmp(arp->name,fieldstart,fieldlen))
            parse_error(&ps, &newpig,
                       _("duplicate value for user-defined field `%.*s'"),
                       fieldlen, fieldstart);
          larpp= &arp->next;
        }
        arp= nfmalloc(sizeof(struct arbitraryfield));
        arp->name= nfstrnsave(fieldstart,fieldlen);
        arp->value= nfstrnsave(valuestart,valuelen);
        arp->next= NULL;
        *larpp= arp;
      }
      if (EOF_mmap(dataptr, endptr) || c == '\n' || c == MSDOS_EOF_CHAR) break;
    } /* loop per field */
    if (pdone && donep)
      parse_error(&ps, &newpig,
                  _("several package info entries found, only one allowed"));
    parse_must_have_field(&ps, &newpig, newpig.name, "package name");
    if ((flags & pdb_recordavailable) || newpig.status != stat_notinstalled) {
      parse_ensure_have_field(&ps, &newpig,
                              &newpifp->description, "description");
      parse_ensure_have_field(&ps, &newpig,
                              &newpifp->maintainer, "maintainer");
      if (newpig.status != stat_halfinstalled)
        parse_must_have_field(&ps, &newpig,
                              newpifp->version.version, "version");
    }
    if (flags & pdb_recordavailable)
      parse_ensure_have_field(&ps, &newpig,
                              &newpifp->architecture, "architecture");

    /* Check the Config-Version information:
     * If there is a Config-Version it is definitely to be used, but
     * there shouldn't be one if the package is `installed' (in which case
     * the Version and/or Revision will be copied) or if the package is
     * `not-installed' (in which case there is no Config-Version).
     */
    if (!(flags & pdb_recordavailable)) {
      if (newpig.configversion.version) {
        if (newpig.status == stat_installed || newpig.status == stat_notinstalled)
          parse_error(&ps, &newpig,
                      _("Configured-Version for package with inappropriate Status"));
      } else {
        if (newpig.status == stat_installed) newpig.configversion= newpifp->version;
      }
    }

    if (newpig.trigaw.head &&
        (newpig.status <= stat_configfiles ||
         newpig.status >= stat_triggerspending))
      parse_error(&ps, &newpig,
                  _("package has status %s but triggers are awaited"),
                  statusinfos[newpig.status].name);
    else if (newpig.status == stat_triggersawaited && !newpig.trigaw.head)
      parse_error(&ps, &newpig,
                  _("package has status triggers-awaited but no triggers "
                    "awaited"));

    if (!(newpig.status == stat_triggerspending ||
          newpig.status == stat_triggersawaited) &&
        newpig.trigpend_head)
      parse_error(&ps, &newpig,
                  _("package has status %s but triggers are pending"),
                  statusinfos[newpig.status].name);
    else if (newpig.status == stat_triggerspending && !newpig.trigpend_head)
      parse_error(&ps, &newpig,
                  _("package has status triggers-pending but no triggers "
                    "pending"));

    /* FIXME: There was a bug that could make a not-installed package have
     * conffiles, so we check for them here and remove them (rather than
     * calling it an error, which will do at some point).
     */
    if (!(flags & pdb_recordavailable) &&
        newpig.status == stat_notinstalled &&
        newpifp->conffiles) {
      parse_warn(&ps, &newpig,
                 _("Package which in state not-installed has conffiles, "
                   "forgetting them"));
      newpifp->conffiles= NULL;
    }

    /* XXX: Mark not-installed leftover packages for automatic removal on
     * next database dump. This code can be removed after dpkg 1.16.x, when
     * there's guarantee that no leftover is found on the status file on
     * major distributions. */
    if (!(flags & pdb_recordavailable) &&
        newpig.status == stat_notinstalled &&
        newpig.eflag == eflag_ok &&
        (newpig.want == want_purge ||
         newpig.want == want_deinstall ||
         newpig.want == want_hold)) {
      newpig.want = want_unknown;
    }

    pigp= findpackage(newpig.name);
    pifp= (flags & pdb_recordavailable) ? &pigp->available : &pigp->installed;

    if ((flags & pdb_ignoreolder) &&
	versioncompare(&newpifp->version, &pifp->version) < 0)
      continue;

    /* Copy the priority and section across, but don't overwrite existing
     * values if the pdb_weakclassification flag is set.
     */
    if (newpig.section && *newpig.section &&
        !((flags & pdb_weakclassification) && pigp->section && *pigp->section))
      pigp->section= newpig.section;
    if (newpig.priority != pri_unknown &&
        !((flags & pdb_weakclassification) && pigp->priority != pri_unknown)) {
      pigp->priority= newpig.priority;
      if (newpig.priority == pri_other) pigp->otherpriority= newpig.otherpriority;
    }

    /* Sort out the dependency mess. */
    copy_dependency_links(pigp,&pifp->depends,newpifp->depends,
                          (flags & pdb_recordavailable) ? 1 : 0);
    /* Leave the `depended' pointer alone, we've just gone to such
     * trouble to get it right :-).  The `depends' pointer in
     * pifp was indeed also updated by copy_dependency_links,
     * but since the value was that from newpifp anyway there's
     * no need to copy it back.
     */
    newpifp->depended= pifp->depended;

    /* Copy across data */
    memcpy(pifp,newpifp,sizeof(struct pkginfoperfile));
    if (!(flags & pdb_recordavailable)) {
      pigp->want= newpig.want;
      pigp->eflag= newpig.eflag;
      pigp->status= newpig.status;
      pigp->configversion= newpig.configversion;
      pigp->files= NULL;

      pigp->trigpend_head = newpig.trigpend_head;
      pigp->trigaw = newpig.trigaw;
      for (ta = pigp->trigaw.head; ta; ta = ta->sameaw.next) {
        assert(ta->aw == &newpig);
        ta->aw = pigp;
        /* ->othertrigaw_head is updated by trig_note_aw in *(findpackage())
         * rather than in newpig */
      }

    } else if (!(flags & pdb_ignorefiles)) {
      pigp->files= newpig.files;
    }

    if (donep) *donep= pigp;
    pdone++;
    if (EOF_mmap(dataptr, endptr)) break;
    if (c == '\n')
      ps.lno++;
  }
  if (data != NULL) {
#ifdef USE_MMAP
    munmap(data, st.st_size);
#else
    free(data);
#endif
  }
  free(value);
  pop_cleanup(ehflag_normaltidy);
  if (close(fd)) ohshite(_("failed to close after read: `%.255s'"),filename);
  if (donep && !pdone) ohshit(_("no package information in `%.255s'"),filename);

  if (warncount)
    *warncount = ps.warncount;

  return pdone;
}
Exemplo n.º 10
0
void
ensure_diversions(void)
{
	static struct varbuf vb;

	struct stat stab1, stab2;
	char linebuf[MAXDIVERTFILENAME];
	FILE *file;
	struct diversion *ov, *oicontest, *oialtname;
	int l;

	varbufreset(&vb);
	varbufaddstr(&vb, admindir);
	varbufaddstr(&vb, "/" DIVERSIONSFILE);
	varbufaddc(&vb, 0);

	onerr_abort++;

	file = fopen(vb.buf,"r");
	if (!file) {
		if (errno != ENOENT)
			ohshite(_("failed to open diversions file"));
		if (!diversionsfile) {
			onerr_abort--;
			return;
		}
	} else if (diversionsfile) {
		if (fstat(fileno(diversionsfile), &stab1))
			ohshite(_("failed to fstat previous diversions file"));
		if (fstat(fileno(file), &stab2))
			ohshite(_("failed to fstat diversions file"));
		if (stab1.st_dev == stab2.st_dev &&
		    stab1.st_ino == stab2.st_ino) {
			fclose(file);
			onerr_abort--;
			return;
		}
	}
	if (diversionsfile)
		fclose(diversionsfile);
	diversionsfile = file;
	setcloexec(fileno(diversionsfile), vb.buf);

	for (ov = diversions; ov; ov = ov->next) {
		ov->useinstead->divert->camefrom->divert = NULL;
		ov->useinstead->divert = NULL;
	}
	diversions = NULL;
	if (!file) {
		onerr_abort--;
		return;
	}

	while ((l = fgets_checked(linebuf, sizeof(linebuf), file, vb.buf)) >= 0) {
		oicontest = nfmalloc(sizeof(struct diversion));
		oialtname = nfmalloc(sizeof(struct diversion));

		oialtname->camefrom = findnamenode(linebuf, 0);
		oialtname->useinstead = NULL;

		fgets_must(linebuf, sizeof(linebuf), file, vb.buf);
		oicontest->useinstead = findnamenode(linebuf, 0);
		oicontest->camefrom = NULL;

		fgets_must(linebuf, sizeof(linebuf), file, vb.buf);
		oicontest->pkg = oialtname->pkg = strcmp(linebuf, ":") ?
		                                  findpackage(linebuf) : NULL;

		if (oialtname->camefrom->divert ||
		    oicontest->useinstead->divert)
			ohshit(_("conflicting diversions involving `%.250s' or `%.250s'"),
			       oialtname->camefrom->name, oicontest->useinstead->name);

		oialtname->camefrom->divert = oicontest;
		oicontest->useinstead->divert = oialtname;

		oicontest->next = diversions;
		diversions = oicontest;
	}
	if (ferror(file))
		ohshite(_("read error in diversions [i]"));

	onerr_abort--;
}