bool find_command(const char *prog) { struct varbuf filename = VARBUF_INIT; struct stat stab; const char *path_list; const char *path, *path_end; size_t path_len; path_list = getenv("PATH"); if (!path_list) ohshit(_("PATH is not set")); for (path = path_list; path; path = path_end ? path_end + 1 : NULL) { path_end = strchr(path, ':'); path_len = path_end ? (size_t)(path_end - path) : strlen(path); varbuf_reset(&filename); varbuf_add_buf(&filename, path, path_len); if (path_len) varbuf_add_char(&filename, '/'); varbuf_add_str(&filename, prog); varbuf_end_str(&filename); if (stat(filename.buf, &stab) == 0 && (stab.st_mode & 0111)) { varbuf_destroy(&filename); return true; } } varbuf_destroy(&filename); return false; }
void check_breaks(struct dependency *dep, struct pkginfo *pkg, const char *pfilename) { struct pkginfo *fixbydeconf; struct varbuf why = VARBUF_INIT; int ok; fixbydeconf = NULL; if (depisok(dep, &why, &fixbydeconf, false)) { varbuf_destroy(&why); return; } varbufaddc(&why, 0); if (fixbydeconf && f_autodeconf) { char action[512]; ensure_package_clientdata(fixbydeconf); assert(fixbydeconf->clientdata->istobe == itb_normal); sprintf(action, _("installation of %.250s"), pkg->name); fprintf(stderr, _("dpkg: considering deconfiguration of %s," " which would be broken by %s ...\n"), fixbydeconf->name, action); ok= try_deconfigure_can(force_breaks, fixbydeconf, dep->list, action, NULL, why.buf); if (ok == 1) { fprintf(stderr, _("dpkg: yes, will deconfigure %s (broken by %s).\n"), fixbydeconf->name, pkg->name); } } else { fprintf(stderr, _("dpkg: regarding %s containing %s:\n%s"), pfilename, pkg->name, why.buf); ok= 0; } varbuf_destroy(&why); if (ok > 0) return; if (force_breaks(dep->list)) { warning(_("ignoring breakage, may proceed anyway!")); return; } if (fixbydeconf && !f_autodeconf) { ohshit(_("installing %.250s would break %.250s, and\n" " deconfiguration is not permitted (--auto-deconfigure might help)"), pkg->name, fixbydeconf->name); } else { ohshit(_("installing %.250s would break existing software"), pkg->name); } }
static void test_varbuf_grow(void) { struct varbuf vb; size_t old_size; int i; varbuf_init(&vb, 10); /* Test that we grow when needed. */ varbuf_grow(&vb, 100); test_pass(vb.used == 0); test_pass(vb.size >= 100); old_size = vb.size; /* Test that we are not leaking. */ for (i = 0; i < 10; i++) { varbuf_grow(&vb, 100); test_pass(vb.used == 0); test_pass(vb.size >= 100); test_pass(vb.size == old_size); } /* Test that we grow when needed, with used space. */ vb.used = 10; varbuf_grow(&vb, 100); test_pass(vb.used == 10); test_pass(vb.size >= 110); varbuf_destroy(&vb); }
void extractDebPackageInfo(const struct pkginfo *pkg, QueryData &results) { Row r; struct varbuf vb; varbuf_init(&vb, 20); // Iterate over the desired fieldinfos, calling their fwritefunctions // to extract the package's information. const struct fieldinfo *fip = nullptr; for (fip = fieldinfos; fip->name; fip++) { fip->wcall(&vb, pkg, &pkg->installed, fw_printheader, fip); std::string line = vb.string(); if (!line.empty()) { size_t separator_position = line.find(':'); std::string key = line.substr(0, separator_position); std::string value = line.substr(separator_position + 1, line.length()); auto it = kFieldMappings.find(key); if (it != kFieldMappings.end()) { boost::algorithm::trim(value); r[it->second] = std::move(value); } } varbuf_reset(&vb); } varbuf_destroy(&vb); results.push_back(r); }
static void test_varbuf_addc(void) { struct varbuf vb; varbuf_init(&vb, 1); varbuf_add_char(&vb, 'a'); test_pass(vb.used == 1); test_pass(vb.size >= vb.used); test_pass(vb.buf[0] == 'a'); varbuf_add_char(&vb, 'b'); test_pass(vb.used == 2); test_pass(vb.size >= vb.used); test_mem(vb.buf, ==, "ab", 2); varbuf_add_char(&vb, 'c'); test_pass(vb.used == 3); test_pass(vb.size >= vb.used); test_mem(vb.buf, ==, "abc", 3); varbuf_add_char(&vb, 'd'); test_pass(vb.used == 4); test_pass(vb.size >= vb.used); test_mem(vb.buf, ==, "abcd", 4); varbuf_destroy(&vb); }
static void info_spew(const char *debar, const char *dir, const char *const *argv) { struct dpkg_error err; const char *component; struct varbuf controlfile = VARBUF_INIT; int fd; int re= 0; while ((component = *argv++) != NULL) { varbuf_reset(&controlfile); varbuf_printf(&controlfile, "%s/%s", dir, component); fd = open(controlfile.buf, O_RDONLY); if (fd >= 0) { if (fd_fd_copy(fd, 1, -1, &err) < 0) ohshit(_("cannot extract control file '%s' from '%s': %s"), controlfile.buf, debar, err.str); close(fd); } else if (errno == ENOENT) { notice(_("'%.255s' contains no control component '%.255s'"), debar, component); re++; } else { ohshite(_("open component `%.255s' (in %.255s) failed in an unexpected way"), component, dir); } } varbuf_destroy(&controlfile); if (re > 0) ohshit(P_("%d requested control component is missing", "%d requested control components are missing", re), re); }
static void info_spew(const char *debar, const char *directory, const char *const *argv) { const char *component; struct varbuf controlfile = VARBUF_INIT; int fd; int re= 0; while ((component = *argv++) != NULL) { varbufreset(&controlfile); varbufaddstr(&controlfile, directory); varbufaddc(&controlfile, '/'); varbufaddstr(&controlfile, component); varbufaddc(&controlfile, '\0'); fd = open(controlfile.buf, O_RDONLY); if (fd >= 0) { fd_fd_copy(fd, 1, -1, _("control file '%s'"), controlfile.buf); close(fd); } else if (errno == ENOENT) { fprintf(stderr, _("dpkg-deb: `%.255s' contains no control component `%.255s'\n"), debar, component); re++; } else { ohshite(_("open component `%.255s' (in %.255s) failed in an unexpected way"), component, directory); } } varbuf_destroy(&controlfile); if (re > 0) ohshit(P_("%d requested control component is missing", "%d requested control components are missing", re), re); }
/** * Returns the path to the script inside the chroot. */ static const char * preexecscript(struct command *cmd) { const char *admindir = dpkg_db_get_dir(); size_t instdirl = strlen(instdir); if (*instdir) { if (strncmp(admindir, instdir, instdirl) != 0) ohshit(_("admindir must be inside instdir for dpkg to work properly")); if (setenv("DPKG_ADMINDIR", admindir + instdirl, 1) < 0) ohshite(_("unable to setenv for subprocesses")); if (chroot(instdir)) ohshite(_("failed to chroot to `%.250s'"),instdir); if (chdir("/")) ohshite(_("failed to chdir to `%.255s'"), "/"); } if (debug_has_flag(dbg_scripts)) { struct varbuf args = VARBUF_INIT; const char **argv = cmd->argv; while (*++argv) { varbuf_add_char(&args, ' '); varbuf_add_str(&args, *argv); } varbuf_end_str(&args); debug(dbg_scripts, "fork/exec %s (%s )", cmd->filename, args.buf); varbuf_destroy(&args); } if (!instdirl) return cmd->filename; assert(strlen(cmd->filename) >= instdirl); return cmd->filename + instdirl; }
/** * Verify that some programs can be found in the PATH. */ void checkpath(void) { static const char *const prog_list[] = { DEFAULTSHELL, RM, TAR, FIND, BACKEND, "ldconfig", #if WITH_START_STOP_DAEMON "start-stop-daemon", #endif NULL }; const char *const *prog; const char *path_list; struct varbuf filename = VARBUF_INIT; int warned= 0; path_list = getenv("PATH"); if (!path_list) ohshit(_("PATH is not set.")); for (prog = prog_list; *prog; prog++) { struct stat stab; const char *path, *path_end; size_t path_len; for (path = path_list; path; path = path_end ? path_end + 1 : NULL) { path_end = strchr(path, ':'); path_len = path_end ? (size_t)(path_end - path) : strlen(path); varbuf_reset(&filename); varbuf_add_buf(&filename, path, path_len); if (path_len) varbuf_add_char(&filename, '/'); varbuf_add_str(&filename, *prog); varbuf_end_str(&filename); if (stat(filename.buf, &stab) == 0 && (stab.st_mode & 0111)) break; } if (!path) { warning(_("'%s' not found in PATH or not executable."), *prog); warned++; } } varbuf_destroy(&filename); if (warned) forcibleerr(fc_badpath, P_("%d expected program not found in PATH or not executable.\n%s", "%d expected programs not found in PATH or not executable.\n%s", warned), warned, _("Note: root's PATH should usually contain " "/usr/local/sbin, /usr/sbin and /sbin.")); }
/** * Cycle breaking works recursively down the package dependency tree. * * ‘sofar’ is the list of packages we've descended down already - if we * encounter any of its packages again in a dependency we have found a cycle. */ static bool findbreakcyclerecursive(struct pkginfo *pkg, struct cyclesofarlink *sofar) { struct cyclesofarlink thislink, *sol; struct dependency *dep; struct deppossi *possi, *providelink; struct pkginfo *provider; if (pkg->clientdata->color == black) return false; pkg->clientdata->color = gray; if (f_debug & dbg_depcondetail) { struct varbuf str_pkgs = VARBUF_INIT; for (sol = sofar; sol; sol = sol->prev) { varbufaddstr(&str_pkgs, " <- "); varbufaddstr(&str_pkgs, sol->pkg->name); } varbufaddc(&str_pkgs, '\0'); debug(dbg_depcondetail, "findbreakcyclerecursive %s %s", pkg->name, str_pkgs.buf); varbuf_destroy(&str_pkgs); } thislink.pkg= pkg; thislink.prev = sofar; thislink.possi = NULL; for (dep= pkg->installed.depends; dep; dep= dep->next) { if (dep->type != dep_depends && dep->type != dep_predepends) continue; for (possi= dep->list; possi; possi= possi->next) { /* Don't find the same cycles again. */ if (possi->cyclebreak) continue; thislink.possi= possi; if (foundcyclebroken(&thislink, sofar, possi->ed,possi)) return true; /* Right, now we try all the providers ... */ for (providelink= possi->ed->installed.depended; providelink; providelink = providelink->rev_next) { if (providelink->up->type != dep_provides) continue; provider= providelink->up->up; if (provider->clientdata->istobe == itb_normal) continue; /* We don't break things at ‘provides’ links, so ‘possi’ is * still the one we use. */ if (foundcyclebroken(&thislink, sofar, provider, possi)) return true; } } } /* Nope, we didn't find a cycle to break. */ pkg->clientdata->color = black; return false; }
static void breaks_check_one(struct varbuf *aemsgs, enum dep_check *ok, struct deppossi *breaks, struct pkginfo *broken, struct pkginfo *breaker, struct deppossi *virtbroken) { struct varbuf depmsg = VARBUF_INIT; debug(dbg_depcondetail, " checking breaker %s virtbroken %s", pkg_name(breaker, pnaw_always), virtbroken ? virtbroken->ed->name : "<none>"); if (breaker->status == PKG_STAT_NOTINSTALLED || breaker->status == PKG_STAT_CONFIGFILES) return; if (broken == breaker) return; if (!versionsatisfied(&broken->installed, breaks)) return; /* The test below can only trigger if dep_breaks start having * arch qualifiers different from “any”. */ if (!archsatisfied(&broken->installed, breaks)) return; if (ignore_depends(breaker)) return; if (virtbroken && ignore_depends(&virtbroken->ed->pkg)) return; if (virtbroken && !pkg_virtual_deppossi_satisfied(breaks, virtbroken)) return; varbufdependency(&depmsg, breaks->up); varbuf_end_str(&depmsg); varbuf_printf(aemsgs, _(" %s (%s) breaks %s and is %s.\n"), pkg_name(breaker, pnaw_nonambig), versiondescribe(&breaker->installed.version, vdew_nonambig), depmsg.buf, gettext(statusstrings[breaker->status])); varbuf_destroy(&depmsg); if (virtbroken) { varbuf_printf(aemsgs, _(" %s (%s) provides %s.\n"), pkg_name(broken, pnaw_nonambig), versiondescribe(&broken->installed.version, vdew_nonambig), virtbroken->ed->name); } else if (breaks->verrel != DPKG_RELATION_NONE) { varbuf_printf(aemsgs, _(" Version of %s to be configured is %s.\n"), pkg_name(broken, pnaw_nonambig), versiondescribe(&broken->installed.version, vdew_nonambig)); if (in_force(FORCE_DEPENDS_VERSION)) return; } if (force_breaks(breaks)) return; *ok = DEP_CHECK_HALT; }
static void test_varbuf_prealloc(void) { struct varbuf vb; varbuf_init(&vb, 10); test_pass(vb.used == 0); test_pass(vb.size >= 10); test_pass(vb.buf != NULL); varbuf_destroy(&vb); test_pass(vb.used == 0); test_pass(vb.size == 0); test_pass(vb.buf == NULL); }
static void test_varbuf_init(void) { struct varbuf vb; varbuf_init(&vb, 0); test_pass(vb.used == 0); test_pass(vb.size == 0); test_pass(vb.buf == NULL); varbuf_destroy(&vb); test_pass(vb.used == 0); test_pass(vb.size == 0); test_pass(vb.buf == NULL); }
void decompress_filter(enum compressor_type type, int fd_in, int fd_out, const char *desc_fmt, ...) { va_list args; struct varbuf desc = VARBUF_INIT; va_start(args, desc_fmt); varbuf_vprintf(&desc, desc_fmt, args); va_end(args); compressor(type)->decompress(fd_in, fd_out, desc.buf); varbuf_destroy(&desc); }
void compress_filter(struct compress_params *params, int fd_in, int fd_out, const char *desc_fmt, ...) { va_list args; struct varbuf desc = VARBUF_INIT; va_start(args, desc_fmt); varbuf_vprintf(&desc, desc_fmt, args); va_end(args); compressor(params->type)->compress(fd_in, fd_out, params, desc.buf); varbuf_destroy(&desc); }
static void test_varbuf_map_char(void) { struct varbuf vb; varbuf_init(&vb, 5); varbuf_add_buf(&vb, "1234a5678a9012a", 15); varbuf_map_char(&vb, 'a', 'z'); test_pass(vb.used == 15); test_pass(vb.size >= vb.used); test_mem(vb.buf, ==, "1234z5678z9012z", 15); varbuf_destroy(&vb); }
static void breaks_check_one(struct varbuf *aemsgs, enum dep_check *ok, struct deppossi *breaks, struct pkginfo *broken, struct pkginfo *breaker, struct pkgset *virtbroken) { struct varbuf depmsg = VARBUF_INIT; debug(dbg_depcondetail, " checking breaker %s virtbroken %s", pkg_name(breaker, pnaw_always), virtbroken ? virtbroken->name : "<none>"); if (breaker->status == stat_notinstalled || breaker->status == stat_configfiles) return; if (broken == breaker) return; if (!versionsatisfied(&broken->installed, breaks)) return; /* The test below can only trigger if dep_breaks start having * arch qualifiers different from “any”. */ if (!archsatisfied(&broken->installed, breaks)) return; if (ignore_depends(breaker)) return; if (virtbroken && ignore_depends(&virtbroken->pkg)) return; varbufdependency(&depmsg, breaks->up); varbuf_end_str(&depmsg); varbuf_printf(aemsgs, _(" %s (%s) breaks %s and is %s.\n"), pkg_name(breaker, pnaw_nonambig), versiondescribe(&breaker->installed.version, vdew_nonambig), depmsg.buf, gettext(statusstrings[breaker->status])); varbuf_destroy(&depmsg); if (virtbroken) { varbuf_printf(aemsgs, _(" %s (%s) provides %s.\n"), pkg_name(broken, pnaw_nonambig), versiondescribe(&broken->installed.version, vdew_nonambig), virtbroken->name); } else if (breaks->verrel != dpkg_relation_none) { varbuf_printf(aemsgs, _(" Version of %s to be configured is %s.\n"), pkg_name(broken, pnaw_nonambig), versiondescribe(&broken->installed.version, vdew_nonambig)); if (fc_dependsversion) return; } if (force_breaks(breaks)) return; *ok = dep_check_halt; }
/* FIXME: Ideally we'd use openat() here, to avoid the path mangling, but * it's not widely available yet, so this will do for now. */ static void dir_file_sync(const char *dir, const char *filename) { struct varbuf path = VARBUF_INIT; int fd; varbufprintf(&path, "%s/%s", dir, filename); fd = open(path.buf, O_WRONLY); if (fd < 0) ohshite(_("unable to open file '%s'"), path.buf); if (fsync(fd)) ohshite(_("unable to sync file '%s'"), path.buf); if (close(fd)) ohshite(_("unable to close file '%s'"), path.buf); varbuf_destroy(&path); }
static void verify_package(struct pkginfo *pkg) { struct fsys_namenode_list *file; struct varbuf filename = VARBUF_INIT; ensure_packagefiles_available(pkg); parse_filehash(pkg, &pkg->installed); pkg_conffiles_mark_old(pkg); for (file = pkg->files; file; file = file->next) { struct verify_checks checks; struct fsys_namenode *fnn; char hash[MD5HASHLEN + 1]; int failures = 0; fnn = namenodetouse(file->namenode, pkg, &pkg->installed); if (strcmp(fnn->newhash, EMPTYHASHFLAG) == 0) { if (fnn->oldhash == NULL) continue; else fnn->newhash = fnn->oldhash; } varbuf_reset(&filename); varbuf_add_str(&filename, instdir); varbuf_add_str(&filename, fnn->name); varbuf_end_str(&filename); memset(&checks, 0, sizeof(checks)); md5hash(pkg, hash, filename.buf); if (strcmp(hash, fnn->newhash) != 0) { checks.md5sum = VERIFY_FAIL; failures++; } if (failures) verify_output(fnn, &checks); } varbuf_destroy(&filename); }
static void test_varbuf_addbuf(void) { struct varbuf vb; varbuf_init(&vb, 5); varbuf_add_buf(&vb, "1234567890", 10); test_pass(vb.used == 10); test_pass(vb.size >= vb.used); test_mem(vb.buf, ==, "1234567890", 10); varbuf_add_buf(&vb, "abcde", 5); test_pass(vb.used == 15); test_pass(vb.size >= vb.used); test_mem(vb.buf, ==, "1234567890abcde", 15); varbuf_destroy(&vb); }
static void test_varbuf_dup_char(void) { struct varbuf vb; varbuf_init(&vb, 5); varbuf_dup_char(&vb, 'z', 10); test_pass(vb.used == 10); test_pass(vb.size >= vb.used); test_mem(vb.buf, ==, "zzzzzzzzzz", 10); varbuf_dup_char(&vb, 'y', 5); test_pass(vb.used == 15); test_pass(vb.size >= vb.used); test_mem(vb.buf, ==, "zzzzzzzzzzyyyyy", 15); varbuf_destroy(&vb); }
static void test_varbuf_trunc(void) { struct varbuf vb; varbuf_init(&vb, 50); /* Test that we truncate (grow). */ varbuf_trunc(&vb, 20); test_pass(vb.used == 20); test_pass(vb.size >= 50); /* Test that we truncate (shrink). */ varbuf_trunc(&vb, 10); test_pass(vb.used == 10); test_pass(vb.size >= 50); varbuf_destroy(&vb); }
void modstatdb_shutdown(void) { if (cflags >= msdbrw_available_write) writedb(availablefile, wdb_dump_available); switch (cstatus) { case msdbrw_write: modstatdb_checkpoint(); /* Tidy up a bit, but don't worry too much about failure. */ fclose(importanttmp); unlink(importanttmpfile); varbuf_destroy(&uvb); /* Fall through. */ case msdbrw_needsuperuserlockonly: modstatdb_unlock(); default: break; } modstatdb_done(); }
static void test_varbuf_reset(void) { struct varbuf vb; varbuf_init(&vb, 10); varbuf_add_buf(&vb, "1234567890", 10); varbuf_reset(&vb); test_pass(vb.used == 0); test_pass(vb.size >= vb.used); varbuf_add_buf(&vb, "abcdefghijklmno", 15); test_pass(vb.used == 15); test_pass(vb.size >= vb.used); test_mem(vb.buf, ==, "abcdefghijklmno", 15); varbuf_destroy(&vb); }
/** * Return a string representation of the package name. * * The returned string must not be freed, and it's permanently allocated so * can be used as long as the non-freeing memory pool has not been freed. * * The pnaw parameter should be one of pnaw_never (never print arch), * pnaw_foreign (print arch for foreign packages only), pnaw_nonambig (print * arch for non ambiguous cases) or pnaw_always (always print arch), * * @param pkg The package to consider. * @param pkgbin The binary package instance to consider. * @param pnaw When to display the architecture qualifier. * * @return The string representation. */ const char * pkgbin_name(struct pkginfo *pkg, struct pkgbin *pkgbin, enum pkg_name_arch_when pnaw) { if (!pkgbin_name_needs_arch(pkgbin, pnaw)) return pkg->set->name; /* Cache the package name representation, for later reuse. */ if (pkgbin->pkgname_archqual == NULL) { struct varbuf vb = VARBUF_INIT; varbuf_add_str(&vb, pkg->set->name); varbuf_add_archqual(&vb, pkgbin->arch); varbuf_end_str(&vb); pkgbin->pkgname_archqual = nfstrsave(vb.buf); varbuf_destroy(&vb); } return pkgbin->pkgname_archqual; }
static void test_varbuf_end_str(void) { struct varbuf vb; varbuf_init(&vb, 10); varbuf_add_buf(&vb, "1234567890X", 11); test_pass(vb.used == 11); test_pass(vb.size >= vb.used); test_mem(vb.buf, ==, "1234567890X", 11); varbuf_trunc(&vb, 10); varbuf_end_str(&vb); test_pass(vb.used == 10); test_pass(vb.size >= vb.used + 1); test_pass(vb.buf[10] == '\0'); test_str(vb.buf, ==, "1234567890"); varbuf_destroy(&vb); }
/** * Check control directory and file permissions. */ static void check_file_perms(const char *ctrldir) { struct varbuf path = VARBUF_INIT; const char *const *mscriptp; struct stat mscriptstab; varbuf_printf(&path, "%s/", ctrldir); if (lstat(path.buf, &mscriptstab)) ohshite(_("unable to stat control directory")); if (!S_ISDIR(mscriptstab.st_mode)) ohshit(_("control directory is not a directory")); if ((mscriptstab.st_mode & 07757) != 0755) ohshit(_("control directory has bad permissions %03lo " "(must be >=0755 and <=0775)"), (unsigned long)(mscriptstab.st_mode & 07777)); for (mscriptp = maintainerscripts; *mscriptp; mscriptp++) { varbuf_reset(&path); varbuf_printf(&path, "%s/%s", ctrldir, *mscriptp); if (!lstat(path.buf, &mscriptstab)) { if (S_ISLNK(mscriptstab.st_mode)) continue; if (!S_ISREG(mscriptstab.st_mode)) ohshit(_("maintainer script '%.50s' is not a plain file or symlink"), *mscriptp); if ((mscriptstab.st_mode & 07557) != 0555) ohshit(_("maintainer script '%.50s' has bad permissions %03lo " "(must be >=0555 and <=0775)"), *mscriptp, (unsigned long)(mscriptstab.st_mode & 07777)); } else if (errno != ENOENT) { ohshite(_("maintainer script '%.50s' is not stattable"), *mscriptp); } } varbuf_destroy(&path); }
void describedepcon(struct varbuf *addto, struct dependency *dep) { const char *fmt; struct varbuf depstr = VARBUF_INIT; switch (dep->type) { case dep_depends: fmt = _("%s depends on %s"); break; case dep_predepends: fmt = _("%s pre-depends on %s"); break; case dep_recommends: fmt = _("%s recommends %s"); break; case dep_suggests: fmt = _("%s suggests %s"); break; case dep_breaks: fmt = _("%s breaks %s"); break; case dep_conflicts: fmt = _("%s conflicts with %s"); break; case dep_enhances: fmt = _("%s enhances %s"); break; default: internerr("unknown deptype '%d'", dep->type); } varbufdependency(&depstr, dep); varbufaddc(&depstr, 0); varbufprintf(addto, fmt, dep->up->name, depstr.buf); varbuf_destroy(&depstr); }
static void test_varbuf_printf(void) { struct varbuf vb; varbuf_init(&vb, 5); /* Test normal format printing. */ varbuf_printf(&vb, "format %s number %d", "string", 10); test_pass(vb.used == strlen("format string number 10")); test_pass(vb.size >= vb.used); test_str(vb.buf, ==, "format string number 10"); varbuf_reset(&vb); /* Test concatenated format printing. */ varbuf_printf(&vb, "format %s number %d", "string", 10); varbuf_printf(&vb, " extra %s", "string"); test_pass(vb.used == strlen("format string number 10 extra string")); test_pass(vb.size >= vb.used); test_str(vb.buf, ==, "format string number 10 extra string"); varbuf_destroy(&vb); }
/** * Cycle breaking works recursively down the package dependency tree. * * ‘sofar’ is the list of packages we've descended down already - if we * encounter any of its packages again in a dependency we have found a cycle. */ static bool findbreakcyclerecursive(struct pkginfo *pkg, struct cyclesofarlink *sofar) { struct cyclesofarlink thislink, *sol; struct dependency *dep; struct deppossi *possi, *providelink; struct pkginfo *provider, *pkg_pos; if (pkg->clientdata->color == PKG_CYCLE_BLACK) return false; pkg->clientdata->color = PKG_CYCLE_GRAY; if (debug_has_flag(dbg_depcondetail)) { struct varbuf str_pkgs = VARBUF_INIT; for (sol = sofar; sol; sol = sol->prev) { varbuf_add_str(&str_pkgs, " <- "); varbuf_add_pkgbin_name(&str_pkgs, sol->pkg, &sol->pkg->installed, pnaw_nonambig); } varbuf_end_str(&str_pkgs); debug(dbg_depcondetail, "findbreakcyclerecursive %s %s", pkg_name(pkg, pnaw_always), str_pkgs.buf); varbuf_destroy(&str_pkgs); } thislink.pkg= pkg; thislink.prev = sofar; thislink.possi = NULL; for (dep= pkg->installed.depends; dep; dep= dep->next) { if (dep->type != dep_depends && dep->type != dep_predepends) continue; for (possi= dep->list; possi; possi= possi->next) { struct deppossi_pkg_iterator *possi_iter; /* Don't find the same cycles again. */ if (possi->cyclebreak) continue; thislink.possi= possi; possi_iter = deppossi_pkg_iter_new(possi, wpb_installed); while ((pkg_pos = deppossi_pkg_iter_next(possi_iter))) if (foundcyclebroken(&thislink, sofar, pkg_pos, possi)) { deppossi_pkg_iter_free(possi_iter); return true; } deppossi_pkg_iter_free(possi_iter); /* Right, now we try all the providers ... */ for (providelink = possi->ed->depended.installed; providelink; providelink = providelink->rev_next) { if (providelink->up->type != dep_provides) continue; provider= providelink->up->up; if (provider->clientdata->istobe == PKG_ISTOBE_NORMAL) continue; /* We don't break things at ‘provides’ links, so ‘possi’ is * still the one we use. */ if (foundcyclebroken(&thislink, sofar, provider, possi)) return true; } } } /* Nope, we didn't find a cycle to break. */ pkg->clientdata->color = PKG_CYCLE_BLACK; return false; }