Remove package name dependency from libalpm

Previously, package names must match a specified scheme or they will cause
pacman add operations to fail. This is not a very intelligent or necessary
way to act, so remove the dependency on the name of the package to be
installed and read all relevant information from the metadata instead.

This does have one causality to be addressed later- pacman cache cleaning
functionality, which has never been phenomenal, just lost most capability.

Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
Dan McGee 2007-06-17 23:25:07 -04:00
parent 0758012b66
commit f7bbfe4052
7 changed files with 61 additions and 271 deletions

View File

@ -53,11 +53,9 @@
int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
{
pmpkg_t *info = NULL;
pmpkg_t *dummy;
char pkgname[PKG_NAME_LEN], pkgver[PKG_VERSION_LEN];
pmpkg_t *pkg = NULL;
const char *pkgname, *pkgver;
alpm_list_t *i;
struct stat buf;
ALPM_LOG_FUNC;
@ -67,24 +65,11 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
_alpm_log(PM_LOG_DEBUG, "loading target '%s'\n", name);
/* TODO FS#5120 we need a better way to check if a package is a valid package,
* and read the metadata instead of relying on the filename for package name
* and version */
if(stat(name, &buf)) {
pm_errno = PM_ERR_NOT_A_FILE;
goto error;
}
if(_alpm_pkg_splitname(name, pkgname, pkgver, 1) == -1) {
pm_errno = PM_ERR_PKG_INVALID_NAME;
goto error;
}
/* no additional hyphens in version strings */
if(strchr(pkgver, '-') != strrchr(pkgver, '-')) {
pm_errno = PM_ERR_PKG_INVALID_NAME;
if(alpm_pkg_load(name, &pkg) != 0) {
goto error;
}
pkgname = alpm_pkg_get_name(pkg);
pkgver = alpm_pkg_get_version(pkg);
if(trans->type != PM_TRANS_TYPE_UPGRADE) {
/* only install this package if it is not already installed */
@ -95,7 +80,7 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
} else {
if(trans->flags & PM_TRANS_FLAG_FRESHEN) {
/* only upgrade/install this package if it is already installed and at a lesser version */
dummy = _alpm_db_get_pkgfromcache(db, pkgname);
pmpkg_t *dummy = _alpm_db_get_pkgfromcache(db, pkgname);
if(dummy == NULL || _alpm_versioncmp(dummy->version, pkgver) >= 0) {
pm_errno = PM_ERR_PKG_CANT_FRESH;
goto error;
@ -126,29 +111,17 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
}
}
_alpm_log(PM_LOG_DEBUG, "reading '%s' metadata\n", pkgname);
info = _alpm_pkg_load(name);
if(info == NULL) {
/* pm_errno is already set by pkg_load() */
goto error;
}
/* check to verify we're not getting fooled by a corrupted package */
if(strcmp(pkgname, info->name) != 0 || strcmp(pkgver, info->version) != 0) {
pm_errno = PM_ERR_PKG_INVALID;
goto error;
}
if(trans->flags & PM_TRANS_FLAG_ALLDEPS) {
info->reason = PM_PKG_REASON_DEPEND;
pkg->reason = PM_PKG_REASON_DEPEND;
}
/* add the package to the transaction */
trans->packages = alpm_list_add(trans->packages, info);
trans->packages = alpm_list_add(trans->packages, pkg);
return(0);
error:
_alpm_pkg_free(info);
_alpm_pkg_free(pkg);
return(-1);
}

View File

@ -180,20 +180,11 @@ typedef enum _pmpkgreason_t {
PM_PKG_REASON_DEPEND = 1 /* installed as a dependency for another package */
} pmpkgreason_t;
/* package name formats */
/*
typedef enum _pmpkghasarch_t {
PM_PKG_WITHOUT_ARCH = 0, / pkgname-pkgver-pkgrel, used under PM_DBPATH /
PM_PKG_WITH_ARCH = 1 / pkgname-pkgver-pkgrel-arch, used under PM_CACHEDIR /
} pmpkghasarch_t;
*/
int alpm_pkg_load(const char *filename, pmpkg_t **pkg);
int alpm_pkg_free(pmpkg_t *pkg);
int alpm_pkg_checkmd5sum(pmpkg_t *pkg);
char *alpm_fetch_pkgurl(const char *url);
int alpm_pkg_vercmp(const char *ver1, const char *ver2);
char *alpm_pkg_name_hasarch(const char *pkgname);
alpm_list_t *alpm_pkg_compute_requiredby(pmpkg_t *pkg);
const char *alpm_pkg_get_filename(pmpkg_t *pkg);

View File

@ -104,6 +104,43 @@ void _alpm_db_rewind(pmdb_t *db)
rewinddir(db->handle);
}
static int _alpm_db_splitname(const char *target, char *name, char *version)
{
/* the format of a db entry is as follows:
* package-version-rel/
* package name can contain hyphens, so parse from the back- go back
* two hyphens and we have split the version from the name.
*/
char *tmp, *p, *q;
if(target == NULL) {
return(-1);
}
tmp = strdup(target);
p = tmp + strlen(tmp);
/* do the magic parsing- find the beginning of the version string
* by doing two iterations of same loop to lop off two hyphens */
for(q = --p; *q && *q != '-'; q--);
for(p = --q; *p && *p != '-'; p--);
if(*p != '-' || p == tmp) {
return(-1);
}
/* copy into fields and return */
if(version) {
strncpy(version, p+1, PKG_VERSION_LEN);
}
/* insert a terminator at the end of the name (on hyphen)- then copy it */
*p = '\0';
if(name) {
strncpy(name, tmp, PKG_NAME_LEN);
}
free(tmp);
return(0);
}
pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)
{
struct dirent *ent = NULL;
@ -177,8 +214,10 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)
_alpm_log(PM_LOG_DEBUG, "db scan could not find package: %s\n", target);
return(NULL);
}
if(_alpm_pkg_splitname(ent->d_name, pkg->name, pkg->version, 0) == -1) {
_alpm_log(PM_LOG_ERROR, _("invalid name for database entry '%s'\n"), ent->d_name);
/* split the db entry name */
if(_alpm_db_splitname(ent->d_name, pkg->name, pkg->version) != 0) {
_alpm_log(PM_LOG_ERROR, _("invalid name for database entry '%s'\n"),
ent->d_name);
alpm_pkg_free(pkg);
pkg = NULL;
continue;

View File

@ -65,7 +65,8 @@ int SYMEXPORT alpm_pkg_load(const char *filename, pmpkg_t **pkg)
_alpm_log(PM_LOG_FUNCTION, "enter alpm_pkg_load\n");
/* Sanity checks */
ASSERT(filename != NULL && strlen(filename) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1));
ASSERT(filename != NULL && strlen(filename) != 0,
RET_ERR(PM_ERR_WRONG_ARGS, -1));
ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
*pkg = _alpm_pkg_load(filename);
@ -151,51 +152,6 @@ int SYMEXPORT alpm_pkg_vercmp(const char *ver1, const char *ver2)
return(_alpm_versioncmp(ver1, ver2));
}
/* internal */
static char *_supported_archs[] = {
"i586",
"i686",
"ppc",
"x86_64",
};
/**
* @brief Determine if a package name has -ARCH tacked on.
* @param pkgname name of the package to parse
* @return pointer to start of -ARCH text if it exists, else NULL
*/
char SYMEXPORT *alpm_pkg_name_hasarch(const char *pkgname)
{
/* TODO remove this when we transfer everything over to -ARCH
*
* this parsing sucks... it's done to support
* two package formats for the time being:
* package-name-foo-1.0.0-1-i686
* and
* package-name-bar-1.2.3-1
*/
size_t i = 0;
char *arch, *cmp, *p;
ALPM_LOG_FUNC;
if((p = strrchr(pkgname, '-'))) {
for(i=0; i < sizeof(_supported_archs)/sizeof(char*); ++i) {
cmp = p+1;
arch = _supported_archs[i];
/* whee, case insensitive compare */
while(*arch && *cmp && tolower(*arch++) == tolower(*cmp++)) ;
if(*arch || *cmp) {
continue;
}
return(p);
}
}
return(NULL);
}
const char SYMEXPORT *alpm_pkg_get_filename(pmpkg_t *pkg)
{
ALPM_LOG_FUNC;
@ -1113,59 +1069,6 @@ pmpkg_t *_alpm_pkg_find(const char *needle, alpm_list_t *haystack)
return(NULL);
}
int _alpm_pkg_splitname(const char *target, char *name, char *version, int witharch)
{
char tmp[PKG_FULLNAME_LEN+7];
const char *t;
char *p, *q;
ALPM_LOG_FUNC;
if(target == NULL) {
return(-1);
}
/* trim path name (if any) */
if((t = strrchr(target, '/')) == NULL) {
t = target;
} else {
t++;
}
strncpy(tmp, t, PKG_FULLNAME_LEN+7);
/* trim file extension (if any) */
if((p = strstr(tmp, PKGEXT))) {
*p = '\0';
}
if(witharch) {
/* trim architecture */
if((p = alpm_pkg_name_hasarch(tmp))) {
*p = '\0';
}
}
p = tmp + strlen(tmp);
for(q = --p; *q && *q != '-'; q--);
if(*q != '-' || q == tmp) {
return(-1);
}
for(p = --q; *p && *p != '-'; p--);
if(*p != '-' || p == tmp) {
return(-1);
}
if(version) {
strncpy(version, p+1, PKG_VERSION_LEN);
}
*p = '\0';
if(name) {
strncpy(name, tmp, PKG_NAME_LEN);
}
return(0);
}
/* fill in requiredby field of package,
* used when we want to install or add a package */
void _alpm_pkg_update_requiredby(pmpkg_t *pkg)

View File

@ -96,7 +96,6 @@ int _alpm_pkg_cmp(const void *p1, const void *p2);
int alpm_pkg_compare_versions(pmpkg_t *local_pkg, pmpkg_t *pkg);
pmpkg_t *_alpm_pkg_load(const char *pkgfile);
pmpkg_t *_alpm_pkg_find(const char *needle, alpm_list_t *haystack);
int _alpm_pkg_splitname(const char *target, char *name, char *version, int witharch);
int _alpm_pkg_istoonew(pmpkg_t *pkg);
void _alpm_pkg_update_requiredby(pmpkg_t *pkg);

View File

@ -187,22 +187,15 @@ int _alpm_downloadfiles_forreal(alpm_list_t *servers, const char *localpath,
char output[PATH_MAX];
char *fn = (char *)lp->data;
char pkgname[PKG_NAME_LEN];
char *p;
fileurl = url_for_file(server, fn);
if(!fileurl) {
return(-1);
}
/* Try to get JUST the name of the package from the filename */
memset(pkgname, 0, PKG_NAME_LEN);
if((p = strstr(fn, PKGEXT))) {
_alpm_pkg_splitname(fn, pkgname, NULL, 1);
}
if(!strlen(pkgname)) {
/* just use the raw filename if we can't find crap */
strncpy(pkgname, fn, PKG_NAME_LEN);
}
/* use the raw filename for download progress */
/* TODO maybe strip the normal pkg.tar.gz extension? */
strncpy(pkgname, fn, PKG_NAME_LEN);
_alpm_log(PM_LOG_DEBUG, "using '%s' for download progress\n", pkgname);
snprintf(realfile, PATH_MAX, "%s%s", localpath, fn);

View File

@ -42,50 +42,6 @@
extern config_t *config;
/* splits package name into its respective parts */
static int split_pkgname(char *target, char *name, char *version)
{
char tmp[512];
char *p, *q;
if(target == NULL) {
return(-1);
}
/* trim path name (if any) */
if((p = strrchr(target, '/')) == NULL) {
p = target;
} else {
p++;
}
strncpy(tmp, p, 512);
/* trim file extension (if any) */
if((p = strstr(tmp, PKGEXT))) {
*p = '\0';
}
/* trim architecture */
if((p = alpm_pkg_name_hasarch(tmp))) {
*p = '\0';
}
p = tmp + strlen(tmp);
for(q = --p; *q && *q != '-'; q--);
if(*q != '-' || q == tmp) {
return(-1);
}
for(p = --q; *p && *p != '-'; p--);
if(*p != '-' || p == tmp) {
return(-1);
}
strncpy(version, p+1, 64);
*p = '\0';
strncpy(name, tmp, 256);
return(0);
}
static int sync_cleancache(int level)
{
/* TODO for now, just mess with the first cache directory */
@ -93,75 +49,11 @@ static int sync_cleancache(int level)
const char *cachedir = alpm_list_getdata(cachedirs);
if(level == 1) {
/* incomplete cleanup: we keep latest packages and partial downloads */
DIR *dir;
struct dirent *ent;
alpm_list_t *cache = NULL, *clean = NULL, *i, *j;
if(!yesno(_("Do you want to remove old packages from cache? [Y/n] ")))
return(0);
printf(_("removing old packages from cache... "));
dir = opendir(cachedir);
if(dir == NULL) {
fprintf(stderr, _("error: could not access cache directory\n"));
return(1);
}
rewinddir(dir);
while((ent = readdir(dir)) != NULL) {
if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
continue;
}
cache = alpm_list_add(cache, strdup(ent->d_name));
}
closedir(dir);
for(i = cache; i; i = alpm_list_next(i)) {
char *str = alpm_list_getdata(i);
char name[256], version[64];
if(strstr(str, PKGEXT) == NULL) {
clean = alpm_list_add(clean, strdup(str));
continue;
}
/* we keep partially downloaded files */
if(strstr(str, PKGEXT ".part")) {
continue;
}
if(split_pkgname(str, name, version) != 0) {
clean = alpm_list_add(clean, strdup(str));
continue;
}
for(j = alpm_list_next(i); j; j = alpm_list_next(j)) {
char *s = alpm_list_getdata(j);
char n[256], v[64];
if(strstr(s, PKGEXT) == NULL) {
continue;
}
if(strstr(s, PKGEXT ".part")) {
continue;
}
if(split_pkgname(s, n, v) != 0) {
continue;
}
/* TODO Do not remove the currently installed version EITHER */
if(!strcmp(name, n)) {
char *ptr = (alpm_pkg_vercmp(version, v) < 0) ? str : s;
if(!alpm_list_find_str(clean, ptr)) {
clean = alpm_list_add(clean, strdup(ptr));
}
}
}
}
FREELIST(cache);
for(i = clean; i; i = alpm_list_next(i)) {
char path[PATH_MAX];
snprintf(path, PATH_MAX, "%s/%s", cachedir, (char *)alpm_list_getdata(i));
unlink(path);
}
FREELIST(clean);
/* incomplete cleanup */
printf(_("Partial cache cleaning functionality in pacman needs a lot of work.\n"
"For now it is recommended to use one of the many external tools, such\n"
"as a python script, to do so.\n"));
return(1);
} else {
/* full cleanup */
if(!yesno(_("Do you want to remove all packages from cache? [Y/n] ")))
@ -177,9 +69,9 @@ static int sync_cleancache(int level)
fprintf(stderr, _("error: could not create new cache directory\n"));
return(1);
}
printf(_("done.\n"));
}
printf(_("done.\n"));
return(0);
}