static void assert_version_support(const char *const *argv, struct versionrevision *version, const char *feature_name) { struct pkginfo *pkg; if (*argv) badusage(_("--%s takes no arguments"), cipaction->olong); modstatdb_init(admindir,msdbrw_readonly|msdbrw_noavail); pkg = pkg_db_find("dpkg"); switch (pkg->status) { case stat_installed: case stat_triggerspending: break; case stat_unpacked: case stat_halfconfigured: case stat_halfinstalled: case stat_triggersawaited: if (versionsatisfied3(&pkg->configversion, version, dvr_laterequal)) break; printf(_("Version of dpkg with working %s support not yet configured.\n" " Please use 'dpkg --configure dpkg', and then try again.\n"), feature_name); exit(1); default: printf(_("dpkg not recorded as installed, cannot check for %s support!\n"), feature_name); exit(1); } }
static int assert_version_support(const char *const *argv, struct versionrevision *version, const char *feature_name) { struct pkginfo *pkg; enum modstatdb_rw msdb_status; if (*argv) badusage(_("--%s takes no arguments"), cipaction->olong); msdb_status = modstatdb_open(msdbrw_readonly); pkg_infodb_init(msdb_status); pkg = pkg_db_find_pkg("dpkg", NULL); switch (pkg->status) { case stat_installed: case stat_triggerspending: return 0; case stat_unpacked: case stat_halfconfigured: case stat_halfinstalled: case stat_triggersawaited: if (versionsatisfied3(&pkg->configversion, version, dvr_laterequal)) return 0; printf(_("Version of dpkg with working %s support not yet configured.\n" " Please use 'dpkg --configure dpkg', and then try again.\n"), feature_name); return 1; default: printf(_("dpkg not recorded as installed, cannot check for %s support!\n"), feature_name); return 1; } }
int main(int argc, char *argv[]) { const char *err; struct versionrevision ver, ref; if (argc < 4) { fprintf(stderr, "usage: %s: version op refversion\n", argv[0]); return 2; } err = parseversion(&ver, argv[1]); if (err) { fprintf(stderr, "Invalid version `%s': %s\n", argv[1], err); return 2; } err = parseversion(&ref, argv[3]); if (err) { fprintf(stderr, "Invalid version `%s': %s\n", argv[3], err); return 2; } return ! versionsatisfied3(&ver, &ref, argv[2]); }
int main(int argc, char *argv[]) { const char *err; struct versionrevision ver, ref; if (argc < 4) { fprintf(stderr, "usage: %s version1 lt|gt|le|ge|eq version2\n return value 0 if true, else 1\n", argv[0]); return 2; } err = parseversion(&ver, argv[1]); if (err) { fprintf(stderr, "Invalid version `%s': %s\n", argv[1], err); return 2; } err = parseversion(&ref, argv[3]); if (err) { fprintf(stderr, "Invalid version `%s': %s\n", argv[3], err); return 2; } return ! versionsatisfied3(&ver, &ref, argv[2]); }
/* * *whynot must already have been initialized; it need not be * empty though - it will be reset before use. * * If depisok returns false for ‘not OK’ it will contain a description, * newline-terminated BUT NOT NUL-TERMINATED, of the reason. * * If depisok returns true it will contain garbage. * allowunconfigd should be non-zero during the ‘Pre-Depends’ checking * before a package is unpacked, when it is sufficient for the package * to be unpacked provided that both the unpacked and previously-configured * versions are acceptable. * * On false return (‘not OK’), *canfixbyremove refers to a package which * if removed (dep_conflicts) or deconfigured (dep_breaks) will fix * the problem. Caller may pass NULL for canfixbyremove and need not * initialize *canfixbyremove. */ bool depisok(struct dependency *dep, struct varbuf *whynot, struct pkginfo **canfixbyremove, bool allowunconfigd) { struct deppossi *possi; struct deppossi *provider; int nconflicts; /* Use this buffer so that when internationalisation comes along we * don't have to rewrite the code completely, only redo the sprintf strings * (assuming we have the fancy argument-number-specifiers). * Allow 250x3 for package names, versions, &c, + 250 for ourselves. */ char linebuf[1024]; assert(dep->type == dep_depends || dep->type == dep_predepends || dep->type == dep_breaks || dep->type == dep_conflicts || dep->type == dep_recommends || dep->type == dep_suggests || dep->type == dep_enhances); if (canfixbyremove) *canfixbyremove = NULL; /* The dependency is always OK if we're trying to remove the depend*ing* * package. */ switch (dep->up->clientdata->istobe) { case itb_remove: case itb_deconfigure: return true; case itb_normal: /* Only installed packages can be make dependency problems. */ switch (dep->up->status) { case stat_installed: case stat_triggerspending: case stat_triggersawaited: break; case stat_notinstalled: case stat_configfiles: case stat_halfinstalled: case stat_halfconfigured: case stat_unpacked: return true; default: internerr("unknown status depending '%d'", dep->up->status); } break; case itb_installnew: case itb_preinstall: break; default: internerr("unknown istobe depending '%d'", dep->up->clientdata->istobe); } /* Describe the dependency, in case we have to moan about it. */ varbufreset(whynot); varbufaddc(whynot, ' '); describedepcon(whynot, dep); varbufaddc(whynot,'\n'); /* TODO: Check dep_enhances as well. */ if (dep->type == dep_depends || dep->type == dep_predepends || dep->type == dep_recommends || dep->type == dep_suggests ) { /* Go through the alternatives. As soon as we find one that * we like, we return ‘true’ straight away. Otherwise, when we get to * the end we'll have accumulated all the reasons in whynot and * can return ‘false’. */ for (possi= dep->list; possi; possi= possi->next) { switch (possi->ed->clientdata->istobe) { case itb_remove: sprintf(linebuf,_(" %.250s is to be removed.\n"),possi->ed->name); break; case itb_deconfigure: sprintf(linebuf,_(" %.250s is to be deconfigured.\n"),possi->ed->name); break; case itb_installnew: if (versionsatisfied(&possi->ed->available, possi)) return true; sprintf(linebuf,_(" %.250s is to be installed, but is version %.250s.\n"), possi->ed->name, versiondescribe(&possi->ed->available.version,vdew_nonambig)); break; case itb_normal: case itb_preinstall: switch (possi->ed->status) { case stat_installed: case stat_triggerspending: if (versionsatisfied(&possi->ed->installed, possi)) return true; sprintf(linebuf,_(" %.250s is installed, but is version %.250s.\n"), possi->ed->name, versiondescribe(&possi->ed->installed.version,vdew_nonambig)); break; case stat_notinstalled: /* Don't say anything about this yet - it might be a virtual package. * Later on, if nothing has put anything in linebuf, we know that it * isn't and issue a diagnostic then. */ *linebuf = '\0'; break; case stat_unpacked: case stat_halfconfigured: case stat_triggersawaited: if (allowunconfigd) { if (!informativeversion(&possi->ed->configversion)) { sprintf(linebuf, _(" %.250s is unpacked, but has never been configured.\n"), possi->ed->name); break; } else if (!versionsatisfied(&possi->ed->installed, possi)) { sprintf(linebuf, _(" %.250s is unpacked, but is version %.250s.\n"), possi->ed->name, versiondescribe(&possi->ed->available.version,vdew_nonambig)); break; } else if (!versionsatisfied3(&possi->ed->configversion, &possi->version,possi->verrel)) { sprintf(linebuf, _(" %.250s latest configured version is %.250s.\n"), possi->ed->name, versiondescribe(&possi->ed->configversion,vdew_nonambig)); break; } else { return true; } } /* Fall through. */ default: sprintf(linebuf, _(" %.250s is %s.\n"), possi->ed->name, gettext(statusstrings[possi->ed->status])); break; } break; default: internerr("unknown istobe depended '%d'", possi->ed->clientdata->istobe); } varbufaddstr(whynot, linebuf); /* If there was no version specified we try looking for Providers. */ if (possi->verrel == dvr_none) { /* See if the package we're about to install Provides it. */ for (provider= possi->ed->available.depended; provider; provider = provider->rev_next) { if (provider->up->type != dep_provides) continue; if (provider->up->up->clientdata->istobe == itb_installnew) return true; } /* Now look at the packages already on the system. */ for (provider= possi->ed->installed.depended; provider; provider = provider->rev_next) { if (provider->up->type != dep_provides) continue; switch (provider->up->up->clientdata->istobe) { case itb_installnew: /* Don't pay any attention to the Provides field of the * currently-installed version of the package we're trying * to install. We dealt with that by using the available * information above. */ continue; case itb_remove: sprintf(linebuf, _(" %.250s provides %.250s but is to be removed.\n"), provider->up->up->name, possi->ed->name); break; case itb_deconfigure: sprintf(linebuf, _(" %.250s provides %.250s but is to be deconfigured.\n"), provider->up->up->name, possi->ed->name); break; case itb_normal: case itb_preinstall: if (provider->up->up->status == stat_installed) return true; sprintf(linebuf, _(" %.250s provides %.250s but is %s.\n"), provider->up->up->name, possi->ed->name, gettext(statusstrings[provider->up->up->status])); break; default: internerr("unknown istobe provider '%d'", provider->up->up->clientdata->istobe); } varbufaddstr(whynot, linebuf); } if (!*linebuf) { /* If the package wasn't installed at all, and we haven't said * yet why this isn't satisfied, we should say so now. */ sprintf(linebuf, _(" %.250s is not installed.\n"), possi->ed->name); varbufaddstr(whynot, linebuf); } } } return false; } else { /* It's conflicts or breaks. There's only one main alternative, * but we also have to consider Providers. We return ‘false’ as soon * as we find something that matches the conflict, and only describe * it then. If we get to the end without finding anything we return * ‘true’. */ possi= dep->list; nconflicts= 0; if (possi->ed != possi->up->up) { /* If the package conflicts with or breaks itself it must mean * other packages which provide the same virtual name. We * therefore don't look at the real package and go on to the * virtual ones. */ switch (possi->ed->clientdata->istobe) { case itb_remove: break; case itb_installnew: if (!versionsatisfied(&possi->ed->available, possi)) break; sprintf(linebuf, _(" %.250s (version %.250s) is to be installed.\n"), possi->ed->name, versiondescribe(&possi->ed->available.version,vdew_nonambig)); varbufaddstr(whynot, linebuf); if (!canfixbyremove) return false; nconflicts++; *canfixbyremove= possi->ed; break; case itb_deconfigure: if (dep->type == dep_breaks) break; /* Already deconfiguring this. */ /* Fall through. */ case itb_normal: case itb_preinstall: switch (possi->ed->status) { case stat_notinstalled: case stat_configfiles: break; case stat_halfinstalled: case stat_unpacked: case stat_halfconfigured: if (dep->type == dep_breaks) break; /* No problem. */ case stat_installed: case stat_triggerspending: case stat_triggersawaited: if (!versionsatisfied(&possi->ed->installed, possi)) break; sprintf(linebuf, _(" %.250s (version %.250s) is present and %s.\n"), possi->ed->name, versiondescribe(&possi->ed->installed.version,vdew_nonambig), gettext(statusstrings[possi->ed->status])); varbufaddstr(whynot, linebuf); if (!canfixbyremove) return false; nconflicts++; *canfixbyremove= possi->ed; } break; default: internerr("unknown istobe conflict '%d'", possi->ed->clientdata->istobe); } } /* If there was no version specified we try looking for Providers. */ if (possi->verrel == dvr_none) { /* See if the package we're about to install Provides it. */ for (provider= possi->ed->available.depended; provider; provider = provider->rev_next) { if (provider->up->type != dep_provides) continue; if (provider->up->up->clientdata->istobe != itb_installnew) continue; if (provider->up->up == dep->up) continue; /* Conflicts and provides the same. */ sprintf(linebuf, _(" %.250s provides %.250s and is to be installed.\n"), provider->up->up->name, possi->ed->name); varbufaddstr(whynot, linebuf); /* We can't remove the one we're about to install: */ if (canfixbyremove) *canfixbyremove = NULL; return false; } /* Now look at the packages already on the system. */ for (provider= possi->ed->installed.depended; provider; provider = provider->rev_next) { if (provider->up->type != dep_provides) continue; if (provider->up->up == dep->up) continue; /* Conflicts and provides the same. */ switch (provider->up->up->clientdata->istobe) { case itb_installnew: /* Don't pay any attention to the Provides field of the * currently-installed version of the package we're trying * to install. We dealt with that package by using the * available information above. */ continue; case itb_remove: continue; case itb_deconfigure: if (dep->type == dep_breaks) continue; /* Already deconfiguring. */ case itb_normal: case itb_preinstall: switch (provider->up->up->status) { case stat_notinstalled: case stat_configfiles: continue; case stat_halfinstalled: case stat_unpacked: case stat_halfconfigured: if (dep->type == dep_breaks) break; /* No problem. */ case stat_installed: case stat_triggerspending: case stat_triggersawaited: sprintf(linebuf, _(" %.250s provides %.250s and is present and %s.\n"), provider->up->up->name, possi->ed->name, gettext(statusstrings[provider->up->up->status])); varbufaddstr(whynot, linebuf); if (!canfixbyremove) return false; nconflicts++; *canfixbyremove= provider->up->up; break; } break; default: internerr("unknown istobe conflict provider '%d'", provider->up->up->clientdata->istobe); } } } if (!nconflicts) return true; if (nconflicts > 1) *canfixbyremove = NULL; return false; } /* if (dependency) {...} else {...} */ }
int versionsatisfied(struct pkginfoperfile *it, struct deppossi *against) { return versionsatisfied3(&it->version,&against->version,against->verrel); }