Merging in recent fixes/additions from 2.9.7
This commit is contained in:
parent
79031ccd1a
commit
5ef51b3e26
23 changed files with 317 additions and 153 deletions
|
@ -191,6 +191,7 @@ error:
|
||||||
int add_prepare(pmtrans_t *trans, pmdb_t *db, PMList **data)
|
int add_prepare(pmtrans_t *trans, pmdb_t *db, PMList **data)
|
||||||
{
|
{
|
||||||
PMList *lp;
|
PMList *lp;
|
||||||
|
PMList *skiplist;
|
||||||
|
|
||||||
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
|
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
|
||||||
ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
|
ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
|
||||||
|
@ -269,12 +270,17 @@ int add_prepare(pmtrans_t *trans, pmdb_t *db, PMList **data)
|
||||||
EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL);
|
EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL);
|
||||||
|
|
||||||
_alpm_log(PM_LOG_FLOW1, "looking for file conflicts");
|
_alpm_log(PM_LOG_FLOW1, "looking for file conflicts");
|
||||||
lp = db_find_conflicts(db, trans->packages, handle->root);
|
lp = db_find_conflicts(db, trans->packages, handle->root, &skiplist);
|
||||||
if(lp != NULL) {
|
if(lp != NULL) {
|
||||||
*data = lp;
|
*data = lp;
|
||||||
RET_ERR(PM_ERR_FILE_CONFLICTS, -1);
|
RET_ERR(PM_ERR_FILE_CONFLICTS, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* copy the file skiplist into the transaction */
|
||||||
|
for(lp = skiplist; lp; lp = lp->next) {
|
||||||
|
trans->skiplist = pm_list_add(trans->skiplist, lp->data);
|
||||||
|
}
|
||||||
|
|
||||||
EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL);
|
EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,6 +360,10 @@ int add_commit(pmtrans_t *trans, pmdb_t *db)
|
||||||
FREETRANS(tr);
|
FREETRANS(tr);
|
||||||
RET_ERR(PM_ERR_TRANS_ABORT, -1);
|
RET_ERR(PM_ERR_TRANS_ABORT, -1);
|
||||||
}
|
}
|
||||||
|
/* copy the skiplist over */
|
||||||
|
for(lp = trans->skiplist; lp; lp = lp->next) {
|
||||||
|
pm_list_add(tr->skiplist, lp->data);
|
||||||
|
}
|
||||||
if(remove_commit(tr, db) == -1) {
|
if(remove_commit(tr, db) == -1) {
|
||||||
FREETRANS(tr);
|
FREETRANS(tr);
|
||||||
RET_ERR(PM_ERR_TRANS_ABORT, -1);
|
RET_ERR(PM_ERR_TRANS_ABORT, -1);
|
||||||
|
@ -361,9 +371,8 @@ int add_commit(pmtrans_t *trans, pmdb_t *db)
|
||||||
FREETRANS(tr);
|
FREETRANS(tr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* no previous package version is installed, so this is actually just an
|
/* no previous package version is installed, so this is actually
|
||||||
* install
|
* just an install. */
|
||||||
*/
|
|
||||||
pmo_upgrade = 0;
|
pmo_upgrade = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,6 +418,17 @@ int add_commit(pmtrans_t *trans, pmdb_t *db)
|
||||||
snprintf(expath, PATH_MAX, "%s%s", handle->root, pathname);
|
snprintf(expath, PATH_MAX, "%s%s", handle->root, pathname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if a file is in NoExtract then we never extract it.
|
||||||
|
*
|
||||||
|
* eg, /home/httpd/html/index.html may be removed so index.php
|
||||||
|
* could be used.
|
||||||
|
*/
|
||||||
|
if(pm_list_is_strin(pathname, handle->noextract)) {
|
||||||
|
alpm_logaction("notice: %s is in NoExtract -- skipping extraction", pathname);
|
||||||
|
tar_skip_regfile(tar);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(!stat(expath, &buf) && !S_ISDIR(buf.st_mode)) {
|
if(!stat(expath, &buf) && !S_ISDIR(buf.st_mode)) {
|
||||||
/* file already exists */
|
/* file already exists */
|
||||||
if(pm_list_is_strin(pathname, handle->noupgrade)) {
|
if(pm_list_is_strin(pathname, handle->noupgrade)) {
|
||||||
|
@ -589,7 +609,7 @@ int add_commit(pmtrans_t *trans, pmdb_t *db)
|
||||||
/* Add the package to the database */
|
/* Add the package to the database */
|
||||||
t = time(NULL);
|
t = time(NULL);
|
||||||
|
|
||||||
/* Update the requiredby field by scaning the whole database
|
/* Update the requiredby field by scanning the whole database
|
||||||
* looking for packages depending on the package to add */
|
* looking for packages depending on the package to add */
|
||||||
for(lp = db_get_pkgcache(db); lp; lp = lp->next) {
|
for(lp = db_get_pkgcache(db); lp; lp = lp->next) {
|
||||||
pmpkg_t *tmpp = lp->data;
|
pmpkg_t *tmpp = lp->data;
|
||||||
|
|
|
@ -84,6 +84,7 @@ enum {
|
||||||
PM_OPT_LOCALDB,
|
PM_OPT_LOCALDB,
|
||||||
PM_OPT_SYNCDB,
|
PM_OPT_SYNCDB,
|
||||||
PM_OPT_NOUPGRADE,
|
PM_OPT_NOUPGRADE,
|
||||||
|
PM_OPT_NOEXTRACT,
|
||||||
PM_OPT_IGNOREPKG,
|
PM_OPT_IGNOREPKG,
|
||||||
PM_OPT_HOLDPKG
|
PM_OPT_HOLDPKG
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "conflict.h"
|
#include "conflict.h"
|
||||||
|
|
||||||
PMList *db_find_conflicts(pmdb_t *db, PMList *targets, char *root)
|
PMList *db_find_conflicts(pmdb_t *db, PMList *targets, char *root, PMList **skip_list)
|
||||||
{
|
{
|
||||||
PMList *i, *j, *k;
|
PMList *i, *j, *k;
|
||||||
char *filestr = NULL;
|
char *filestr = NULL;
|
||||||
|
@ -44,41 +44,7 @@ PMList *db_find_conflicts(pmdb_t *db, PMList *targets, char *root)
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CHECK 1: check every db package against every target package */
|
/* CHECK 1: check every target against every target */
|
||||||
/* XXX: I've disabled the database-against-targets check for now, as the
|
|
||||||
* many many strcmp() calls slow it down heavily and most of the
|
|
||||||
* checking is redundant to the targets-against-filesystem check.
|
|
||||||
* This will be re-enabled if I can improve performance significantly.
|
|
||||||
*
|
|
||||||
pmpkg_t *info = NULL;
|
|
||||||
char *dbstr = NULL;
|
|
||||||
db_rewind(db);
|
|
||||||
while((info = db_scan(db, NULL, INFRQ_DESC | INFRQ_FILES)) != NULL) {
|
|
||||||
for(i = info->files; i; i = i->next) {
|
|
||||||
if(i->data == NULL) continue;
|
|
||||||
dbstr = (char*)i->data;
|
|
||||||
for(j = targets; j; j = j->next) {
|
|
||||||
pmpkg_t *targ = (pmpkg_t*)j->data;
|
|
||||||
if(strcmp(info->name, targ->name)) {
|
|
||||||
for(k = targ->files; k; k = k->next) {
|
|
||||||
filestr = (char*)k->data;
|
|
||||||
if(!strcmp(dbstr, filestr)) {
|
|
||||||
if(rindex(k->data, '/') == filestr+strlen(filestr)-1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
MALLOC(str, 512);
|
|
||||||
snprintf(str, 512, "%s: exists in \"%s\" (target) and \"%s\" (installed)", dbstr,
|
|
||||||
targ->name, info->name);
|
|
||||||
conflicts = pm_list_add(conflicts, str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FREEPKG(info);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/* CHECK 2: check every target against every target */
|
|
||||||
for(i = targets; i; i = i->next) {
|
for(i = targets; i; i = i->next) {
|
||||||
pmpkg_t *p1 = (pmpkg_t*)i->data;
|
pmpkg_t *p1 = (pmpkg_t*)i->data;
|
||||||
for(j = i; j; j = j->next) {
|
for(j = i; j; j = j->next) {
|
||||||
|
@ -104,52 +70,90 @@ PMList *db_find_conflicts(pmdb_t *db, PMList *targets, char *root)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CHECK 3: check every target against the filesystem */
|
/* CHECK 2: check every target against the filesystem */
|
||||||
for(i = targets; i; i = i->next) {
|
for(i = targets; i; i = i->next) {
|
||||||
pmpkg_t *p = (pmpkg_t*)i->data;
|
pmpkg_t *p = (pmpkg_t*)i->data;
|
||||||
pmpkg_t *dbpkg = NULL;
|
pmpkg_t *dbpkg = NULL;
|
||||||
for(j = p->files; j; j = j->next) {
|
for(j = p->files; j; j = j->next) {
|
||||||
|
int isdir = 0;
|
||||||
filestr = (char*)j->data;
|
filestr = (char*)j->data;
|
||||||
snprintf(path, PATH_MAX, "%s%s", root, filestr);
|
snprintf(path, PATH_MAX, "%s%s", root, filestr);
|
||||||
if(!stat(path, &buf) && !S_ISDIR(buf.st_mode)) {
|
/* is this target a file or directory? */
|
||||||
|
if(path[strlen(path)-1] == '/') {
|
||||||
|
isdir = 1;
|
||||||
|
path[strlen(path)-1] = '\0';
|
||||||
|
}
|
||||||
|
if(!lstat(path, &buf)) {
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
if(dbpkg == NULL) {
|
if(!S_ISLNK(buf.st_mode) && ((isdir && !S_ISDIR(buf.st_mode)) || (!isdir && S_ISDIR(buf.st_mode)))) {
|
||||||
dbpkg = db_scan(db, p->name, INFRQ_DESC | INFRQ_FILES);
|
/* if the package target is a directory, and the filesystem target
|
||||||
|
* is not (or vice versa) then it's a conflict
|
||||||
|
*/
|
||||||
|
ok = 0;
|
||||||
|
goto donecheck;
|
||||||
}
|
}
|
||||||
if(dbpkg && pm_list_is_strin(j->data, dbpkg->files)) {
|
/* re-fetch with stat() instead of lstat() */
|
||||||
|
stat(path, &buf);
|
||||||
|
if(S_ISDIR(buf.st_mode)) {
|
||||||
|
/* if it's a directory, then we have no conflict */
|
||||||
ok = 1;
|
ok = 1;
|
||||||
}
|
} else {
|
||||||
/* Make sure that the supposedly-conflicting file is not actually just
|
if(dbpkg == NULL) {
|
||||||
* a symlink that points to a path that used to exist in the package.
|
dbpkg = db_scan(db, p->name, INFRQ_DESC | INFRQ_FILES);
|
||||||
*/
|
|
||||||
/* Check if any part of the conflicting file's path is a symlink */
|
|
||||||
if(dbpkg && !ok) {
|
|
||||||
char str[PATH_MAX];
|
|
||||||
for(k = dbpkg->files; k; k = k->next) {
|
|
||||||
snprintf(str, PATH_MAX, "%s%s", root, (char*)k->data);
|
|
||||||
stat(str, &buf2);
|
|
||||||
if(buf.st_ino == buf2.st_ino) {
|
|
||||||
ok = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
if(dbpkg && pm_list_is_strin(j->data, dbpkg->files)) {
|
||||||
/* Check if the conflicting file has been moved to another package/target */
|
ok = 1;
|
||||||
if(!ok) {
|
}
|
||||||
/* Look at all the targets */
|
/* Make sure that the supposedly-conflicting file is not actually just
|
||||||
for(k = targets; k && !ok; k = k->next) {
|
* a symlink that points to a path that used to exist in the package.
|
||||||
pmpkg_t *p1 = (pmpkg_t *)k->data;
|
*/
|
||||||
/* As long as they're not the current package */
|
/* Check if any part of the conflicting file's path is a symlink */
|
||||||
if(strcmp(p1->name, p->name)) {
|
if(dbpkg && !ok) {
|
||||||
pmpkg_t *dbpkg2 = NULL;
|
char str[PATH_MAX];
|
||||||
dbpkg2 = db_scan(db, p1->name, INFRQ_DESC | INFRQ_FILES);
|
for(k = dbpkg->files; k; k = k->next) {
|
||||||
/* If it used to exist in there, but doesn't anymore */
|
snprintf(str, PATH_MAX, "%s%s", root, (char*)k->data);
|
||||||
if(dbpkg2 && !pm_list_is_strin(filestr, p1->files) && pm_list_is_strin(filestr, dbpkg2->files)) {
|
stat(str, &buf2);
|
||||||
|
if(buf.st_ino == buf2.st_ino) {
|
||||||
ok = 1;
|
ok = 1;
|
||||||
}
|
}
|
||||||
FREEPKG(dbpkg2);
|
}
|
||||||
|
}
|
||||||
|
/* Check if the conflicting file has been moved to another package/target */
|
||||||
|
if(!ok) {
|
||||||
|
/* Look at all the targets */
|
||||||
|
for(k = targets; k && !ok; k = k->next) {
|
||||||
|
pmpkg_t *p1 = (pmpkg_t *)k->data;
|
||||||
|
/* As long as they're not the current package */
|
||||||
|
if(strcmp(p1->name, p->name)) {
|
||||||
|
pmpkg_t *dbpkg2 = NULL;
|
||||||
|
dbpkg2 = db_scan(db, p1->name, INFRQ_DESC | INFRQ_FILES);
|
||||||
|
/* If it used to exist in there, but doesn't anymore */
|
||||||
|
if(dbpkg2 && !pm_list_is_strin(filestr, p1->files) && pm_list_is_strin(filestr, dbpkg2->files)) {
|
||||||
|
ok = 1;
|
||||||
|
/* Add to the "skip list" of files that we shouldn't remove during an upgrade.
|
||||||
|
*
|
||||||
|
* This is a workaround for the following scenario:
|
||||||
|
*
|
||||||
|
* - the old package A provides file X
|
||||||
|
* - the new package A does not
|
||||||
|
* - the new package B provides file X
|
||||||
|
* - package A depends on B, so B is upgraded first
|
||||||
|
*
|
||||||
|
* Package B is upgraded, so file X is installed. Then package A
|
||||||
|
* is upgraded, and it *removes* file X, since it no longer exists
|
||||||
|
* in package A.
|
||||||
|
*
|
||||||
|
* Our workaround is to scan through all "old" packages and all "new"
|
||||||
|
* ones, looking for files that jump to different packages.
|
||||||
|
*/
|
||||||
|
*skip_list = pm_list_add(*skip_list, filestr);
|
||||||
|
}
|
||||||
|
FREEPKG(dbpkg2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
donecheck:
|
||||||
if(!ok) {
|
if(!ok) {
|
||||||
MALLOC(str, 512);
|
MALLOC(str, 512);
|
||||||
snprintf(str, 512, "%s: %s: exists in filesystem", p->name, path);
|
snprintf(str, 512, "%s: %s: exists in filesystem", p->name, path);
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
|
|
||||||
PMList *db_find_conflicts(pmdb_t *db, PMList *targets, char *root);
|
PMList *db_find_conflicts(pmdb_t *db, PMList *targets, char *root, PMList **skip_list);
|
||||||
|
|
||||||
#endif /* _ALPM_CONFLICT_H */
|
#endif /* _ALPM_CONFLICT_H */
|
||||||
|
|
||||||
|
|
|
@ -139,6 +139,15 @@ int handle_set_option(pmhandle_t *handle, unsigned char val, unsigned long data)
|
||||||
_alpm_log(PM_LOG_FLOW2, "PM_OPT_NOUPGRADE flushed");
|
_alpm_log(PM_LOG_FLOW2, "PM_OPT_NOUPGRADE flushed");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PM_OPT_NOEXTRACT:
|
||||||
|
if((char *)data && strlen((char *)data) != 0) {
|
||||||
|
handle->noextract = pm_list_add(handle->noextract, strdup((char *)data));
|
||||||
|
_alpm_log(PM_LOG_FLOW2, "'%s' added to PM_OPT_NOEXTRACT", (char *)data);
|
||||||
|
} else {
|
||||||
|
FREELIST(handle->noextract);
|
||||||
|
_alpm_log(PM_LOG_FLOW2, "PM_OPT_NOEXTRACT flushed");
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PM_OPT_IGNOREPKG:
|
case PM_OPT_IGNOREPKG:
|
||||||
if((char *)data && strlen((char *)data) != 0) {
|
if((char *)data && strlen((char *)data) != 0) {
|
||||||
handle->ignorepkg = pm_list_add(handle->ignorepkg, strdup((char *)data));
|
handle->ignorepkg = pm_list_add(handle->ignorepkg, strdup((char *)data));
|
||||||
|
@ -189,6 +198,7 @@ int handle_get_option(pmhandle_t *handle, unsigned char val, long *data)
|
||||||
case PM_OPT_SYNCDB: *data = (long)handle->dbs_sync; break;
|
case PM_OPT_SYNCDB: *data = (long)handle->dbs_sync; break;
|
||||||
case PM_OPT_LOGFILE: *data = (long)handle->logfile; break;
|
case PM_OPT_LOGFILE: *data = (long)handle->logfile; break;
|
||||||
case PM_OPT_NOUPGRADE: *data = (long)handle->noupgrade; break;
|
case PM_OPT_NOUPGRADE: *data = (long)handle->noupgrade; break;
|
||||||
|
case PM_OPT_NOEXTRACT: *data = (long)handle->noextract; break;
|
||||||
case PM_OPT_IGNOREPKG: *data = (long)handle->ignorepkg; break;
|
case PM_OPT_IGNOREPKG: *data = (long)handle->ignorepkg; break;
|
||||||
case PM_OPT_USESYSLOG: *data = handle->usesyslog; break;
|
case PM_OPT_USESYSLOG: *data = handle->usesyslog; break;
|
||||||
case PM_OPT_LOGCB: *data = (long)pm_logcb; break;
|
case PM_OPT_LOGCB: *data = (long)pm_logcb; break;
|
||||||
|
|
|
@ -44,6 +44,7 @@ typedef struct __pmhandle_t {
|
||||||
char *dbpath;
|
char *dbpath;
|
||||||
char *logfile;
|
char *logfile;
|
||||||
PMList *noupgrade; /* List of strings */
|
PMList *noupgrade; /* List of strings */
|
||||||
|
PMList *noextract; /* List of strings */
|
||||||
PMList *ignorepkg; /* List of strings */
|
PMList *ignorepkg; /* List of strings */
|
||||||
unsigned char usesyslog;
|
unsigned char usesyslog;
|
||||||
} pmhandle_t;
|
} pmhandle_t;
|
||||||
|
|
|
@ -256,6 +256,24 @@ PMList* pm_list_last(PMList *list)
|
||||||
return(list->last);
|
return(list->last);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Filter out any duplicate strings in a list.
|
||||||
|
*
|
||||||
|
* Not the most efficient way, but simple to implement -- we assemble
|
||||||
|
* a new list, using is_in() to check for dupes at each iteration.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
PMList *_alpm_list_remove_dupes(PMList *list)
|
||||||
|
{
|
||||||
|
PMList *i, *newlist = NULL;
|
||||||
|
|
||||||
|
for(i = list; i; i = i->next) {
|
||||||
|
if(!pm_list_is_strin(i->data, newlist)) {
|
||||||
|
newlist = pm_list_add(newlist, strdup(i->data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newlist;
|
||||||
|
}
|
||||||
|
|
||||||
/* Reverse the order of a list
|
/* Reverse the order of a list
|
||||||
*
|
*
|
||||||
* The caller is responsible for freeing the old list
|
* The caller is responsible for freeing the old list
|
||||||
|
|
|
@ -55,6 +55,7 @@ int pm_list_count(PMList *list);
|
||||||
int pm_list_is_in(void *needle, PMList *haystack);
|
int pm_list_is_in(void *needle, PMList *haystack);
|
||||||
PMList *pm_list_is_strin(char *needle, PMList *haystack);
|
PMList *pm_list_is_strin(char *needle, PMList *haystack);
|
||||||
PMList *pm_list_last(PMList *list);
|
PMList *pm_list_last(PMList *list);
|
||||||
|
PMList *_alpm_list_remove_dupes(PMList *list);
|
||||||
PMList *_alpm_list_reverse(PMList *list);
|
PMList *_alpm_list_reverse(PMList *list);
|
||||||
PMList *_alpm_list_strdup(PMList *list);
|
PMList *_alpm_list_strdup(PMList *list);
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ typedef unsigned char *POINTER;
|
||||||
typedef unsigned short int UINT2;
|
typedef unsigned short int UINT2;
|
||||||
|
|
||||||
/* UINT4 defines a four byte word */
|
/* UINT4 defines a four byte word */
|
||||||
typedef unsigned long int UINT4;
|
typedef unsigned int UINT4;
|
||||||
|
|
||||||
|
|
||||||
/* MD5 context. */
|
/* MD5 context. */
|
||||||
|
|
|
@ -191,28 +191,42 @@ int remove_commit(pmtrans_t *trans, pmdb_t *db)
|
||||||
_alpm_log(PM_LOG_FLOW2, "removing directory %s", file);
|
_alpm_log(PM_LOG_FLOW2, "removing directory %s", file);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* if the file is flagged, back it up to .pacsave */
|
/* check the "skip list" before removing the file.
|
||||||
if(nb) {
|
* see the big comment block in db_find_conflicts() for an
|
||||||
if(trans->type == PM_TRANS_TYPE_UPGRADE) {
|
* explanation. */
|
||||||
/* we're upgrading so just leave the file as is. pacman_add() will handle it */
|
int skipit = 0;
|
||||||
} else {
|
PMList *j;
|
||||||
if(!(trans->flags & PM_TRANS_FLAG_NOSAVE)) {
|
for(j = trans->skiplist; j; j = j->next) {
|
||||||
char newpath[PATH_MAX];
|
if(!strcmp(file, (char*)j->data)) {
|
||||||
snprintf(newpath, PATH_MAX, "%s.pacsave", line);
|
skipit = 1;
|
||||||
rename(line, newpath);
|
}
|
||||||
_alpm_log(PM_LOG_WARNING, "%s saved as %s", file, newpath);
|
}
|
||||||
alpm_logaction("%s saved as %s", line, newpath);
|
if(skipit) {
|
||||||
|
_alpm_log(PM_LOG_FLOW2, "skipping removal of %s as it has moved to another package\n", file);
|
||||||
|
} else {
|
||||||
|
/* if the file is flagged, back it up to .pacsave */
|
||||||
|
if(nb) {
|
||||||
|
if(trans->type == PM_TRANS_TYPE_UPGRADE) {
|
||||||
|
/* we're upgrading so just leave the file as is. pacman_add() will handle it */
|
||||||
} else {
|
} else {
|
||||||
_alpm_log(PM_LOG_FLOW2, "unlinking %s", file);
|
if(!(trans->flags & PM_TRANS_FLAG_NOSAVE)) {
|
||||||
if(unlink(line)) {
|
char newpath[PATH_MAX];
|
||||||
_alpm_log(PM_LOG_ERROR, "cannot remove file %s", file);
|
snprintf(newpath, PATH_MAX, "%s.pacsave", line);
|
||||||
|
rename(line, newpath);
|
||||||
|
_alpm_log(PM_LOG_WARNING, "%s saved as %s", file, newpath);
|
||||||
|
alpm_logaction("%s saved as %s", line, newpath);
|
||||||
|
} else {
|
||||||
|
_alpm_log(PM_LOG_FLOW2, "unlinking %s", file);
|
||||||
|
if(unlink(line)) {
|
||||||
|
_alpm_log(PM_LOG_ERROR, "cannot remove file %s", file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
_alpm_log(PM_LOG_FLOW2, "unlinking %s", file);
|
||||||
_alpm_log(PM_LOG_FLOW2, "unlinking %s", file);
|
if(unlink(line)) {
|
||||||
if(unlink(line)) {
|
_alpm_log(PM_LOG_ERROR, "cannot remove file %s", file);
|
||||||
_alpm_log(PM_LOG_ERROR, "cannot remove file %s", file);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ pmtrans_t *trans_new()
|
||||||
|
|
||||||
trans->targets = NULL;
|
trans->targets = NULL;
|
||||||
trans->packages = NULL;
|
trans->packages = NULL;
|
||||||
|
trans->skiplist = NULL;
|
||||||
trans->type = 0;
|
trans->type = 0;
|
||||||
trans->flags = 0;
|
trans->flags = 0;
|
||||||
trans->cb_event = NULL;
|
trans->cb_event = NULL;
|
||||||
|
@ -68,6 +69,7 @@ void trans_free(pmtrans_t *trans)
|
||||||
i->data = NULL;
|
i->data = NULL;
|
||||||
}
|
}
|
||||||
FREELIST(trans->packages);
|
FREELIST(trans->packages);
|
||||||
|
FREELIST(trans->skiplist);
|
||||||
} else {
|
} else {
|
||||||
FREELISTPKGS(trans->packages);
|
FREELISTPKGS(trans->packages);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ typedef struct __pmtrans_t {
|
||||||
unsigned char state;
|
unsigned char state;
|
||||||
PMList *targets; /* PMList of (char *) */
|
PMList *targets; /* PMList of (char *) */
|
||||||
PMList *packages; /* PMList of (pmpkg_t *) or (pmsyncpkg_t *) */
|
PMList *packages; /* PMList of (pmpkg_t *) or (pmsyncpkg_t *) */
|
||||||
|
PMList *skiplist; /* PMList of (char *) */
|
||||||
alpm_trans_cb_event cb_event;
|
alpm_trans_cb_event cb_event;
|
||||||
} pmtrans_t;
|
} pmtrans_t;
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "alpm.h"
|
#include "alpm.h"
|
||||||
|
|
||||||
|
static char *chrootbin = NULL;
|
||||||
|
|
||||||
/* borrowed and modified from Per Liden's pkgutils (http://crux.nu) */
|
/* borrowed and modified from Per Liden's pkgutils (http://crux.nu) */
|
||||||
long _alpm_gzopen_frontend(char *pathname, int oflags, int mode)
|
long _alpm_gzopen_frontend(char *pathname, int oflags, int mode)
|
||||||
{
|
{
|
||||||
|
@ -366,6 +368,23 @@ int _alpm_runscriptlet(char *root, char *installfn, char *script, char *ver, cha
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(chrootbin == NULL) {
|
||||||
|
char *dirs[] = {"/usr/sbin","/usr/bin","/sbin","/bin"};
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < 4 && !chrootbin; i++) {
|
||||||
|
char cpath[PATH_MAX];
|
||||||
|
snprintf(cpath, PATH_MAX, "%s/chroot", dirs[i]);
|
||||||
|
if(!stat(cpath, &buf)) {
|
||||||
|
chrootbin = strdup(cpath);
|
||||||
|
_alpm_log(PM_LOG_DEBUG, "found chroot binary: %s", chrootbin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(chrootbin == NULL) {
|
||||||
|
_alpm_log(PM_LOG_ERROR, "cannot find chroot binary - unable to run scriptlet");
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!strcmp(script, "pre_upgrade") || !strcmp(script, "pre_install")) {
|
if(!strcmp(script, "pre_upgrade") || !strcmp(script, "pre_install")) {
|
||||||
snprintf(tmpdir, PATH_MAX, "%stmp/", root);
|
snprintf(tmpdir, PATH_MAX, "%stmp/", root);
|
||||||
if(stat(tmpdir, &buf)) {
|
if(stat(tmpdir, &buf)) {
|
||||||
|
|
|
@ -10,15 +10,16 @@ DEFINES = -DFTPLIB_DEFMODE=FTPLIB_PORT
|
||||||
SONAME = 3
|
SONAME = 3
|
||||||
SOVERSION = $(SONAME).1
|
SOVERSION = $(SONAME).1
|
||||||
|
|
||||||
TARGETS = qftp libftp.a libftp.so
|
TARGETS = libftp.a libftp.so
|
||||||
OBJECTS = qftp.o ftplib.o
|
OBJECTS = ftplib.o
|
||||||
SOURCES = qftp.c ftplib.c
|
SOURCES = ftplib.c
|
||||||
|
|
||||||
CFLAGS = -Wall $(DEBUG) -I. $(INCLUDES) $(DEFINES)
|
CFLAGS = -Wall $(DEBUG) -I. $(INCLUDES) $(DEFINES)
|
||||||
LDFLAGS = -L.
|
LDFLAGS = -L.
|
||||||
DEPFLAGS =
|
DEPFLAGS =
|
||||||
|
|
||||||
all : $(TARGETS)
|
#all : $(TARGETS)
|
||||||
|
all : libftp.a
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
rm -f $(OBJECTS) core *.bak
|
rm -f $(OBJECTS) core *.bak
|
||||||
|
@ -29,15 +30,11 @@ clobber : clean
|
||||||
rm -f libftp.so.*
|
rm -f libftp.so.*
|
||||||
|
|
||||||
install : all
|
install : all
|
||||||
install qftp /usr/local/bin
|
|
||||||
install -m 644 libftp.so.$(SOVERSION) /usr/local/lib
|
install -m 644 libftp.so.$(SOVERSION) /usr/local/lib
|
||||||
install -m 644 ftplib.h /usr/local/include
|
install -m 644 ftplib.h /usr/local/include
|
||||||
(cd /usr/local/lib && \
|
(cd /usr/local/lib && \
|
||||||
ln -sf libftp.so.$(SOVERSION) libftp.so.$(SONAME) && \
|
ln -sf libftp.so.$(SOVERSION) libftp.so.$(SONAME) && \
|
||||||
ln -sf libftp.so.$(SONAME) libftp.so)
|
ln -sf libftp.so.$(SONAME) libftp.so)
|
||||||
-(cd /usr/local/bin && \
|
|
||||||
for f in ftpdir ftpget ftplist ftprm ftpsend; \
|
|
||||||
do ln -s qftp $$f; done)
|
|
||||||
|
|
||||||
depend :
|
depend :
|
||||||
$(CC) $(CFLAGS) -M $(SOURCES) > .depend
|
$(CC) $(CFLAGS) -M $(SOURCES) > .depend
|
||||||
|
@ -60,9 +57,6 @@ libftp.so: libftp.so.$(SOVERSION)
|
||||||
ln -sf $< libftp.so.$(SONAME)
|
ln -sf $< libftp.so.$(SONAME)
|
||||||
ln -sf $< $@
|
ln -sf $< $@
|
||||||
|
|
||||||
qftp : qftp.o libftp.so ftplib.h
|
|
||||||
$(CC) $(LDFLAGS) -o $@ $< -lftp
|
|
||||||
|
|
||||||
ifeq (.depend,$(wildcard .depend))
|
ifeq (.depend,$(wildcard .depend))
|
||||||
include .depend
|
include .depend
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -25,7 +25,7 @@ all: pacman
|
||||||
%.o: %.c %.h
|
%.o: %.c %.h
|
||||||
$(CC) -c $(CFLAGS) -o $@ $<
|
$(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
pacman: $(OBJECTS) ../../lib/libalpm/libalpm.a
|
pacman: $(OBJECTS) ../../lib/libalpm/libalpm.a ../../lib/libftp/libftp.a
|
||||||
$(CC) $(OBJECTS) -o $@ $(CFLAGS) $(LDFLAGS)
|
$(CC) $(OBJECTS) -o $@ $(CFLAGS) $(LDFLAGS)
|
||||||
# $(CC) $(OBJECTS) -o $@.static $(CFLAGS) $(LDFLAGS)
|
# $(CC) $(OBJECTS) -o $@.static $(CFLAGS) $(LDFLAGS)
|
||||||
|
|
||||||
|
|
|
@ -159,6 +159,24 @@ int parseconfig(char *file)
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
vprint("config: noupgrade: %s\n", p);
|
vprint("config: noupgrade: %s\n", p);
|
||||||
|
} else if(!strcmp(key, "NOEXTRACT")) {
|
||||||
|
char *p = ptr;
|
||||||
|
char *q;
|
||||||
|
while((q = strchr(p, ' '))) {
|
||||||
|
*q = '\0';
|
||||||
|
if(alpm_set_option(PM_OPT_NOEXTRACT, (long)p) == -1) {
|
||||||
|
ERR(NL, "failed to set option NOEXTRACT (%s)\n", alpm_strerror(pm_errno));
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
vprint("config: noextract: %s\n", p);
|
||||||
|
p = q;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
if(alpm_set_option(PM_OPT_NOEXTRACT, (long)p) == -1) {
|
||||||
|
ERR(NL, "failed to set option NOEXTRACT (%s)\n", alpm_strerror(pm_errno));
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
vprint("config: noextract: %s\n", p);
|
||||||
} else if(!strcmp(key, "IGNOREPKG")) {
|
} else if(!strcmp(key, "IGNOREPKG")) {
|
||||||
char *p = ptr;
|
char *p = ptr;
|
||||||
char *q;
|
char *q;
|
||||||
|
|
105
src/pacman/db.c
105
src/pacman/db.c
|
@ -34,64 +34,87 @@
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
|
|
||||||
int db_search(PM_DB *db, char *treename, char *needle)
|
int db_search(PM_DB *db, const char *treename, list_t *needles)
|
||||||
{
|
{
|
||||||
PM_LIST *lp;
|
list_t *i;
|
||||||
char *targ;
|
|
||||||
|
|
||||||
targ = strdup(needle);
|
if(needles == NULL || needles->data == NULL) {
|
||||||
strtoupper(targ);
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = needles; i; i = i->next) {
|
||||||
|
PM_LIST *j;
|
||||||
|
char *targ;
|
||||||
|
int ret;
|
||||||
|
|
||||||
for(lp = alpm_db_getpkgcache(db); lp; lp = alpm_list_next(lp)) {
|
if(i->data == NULL) {
|
||||||
PM_PKG *pkg = alpm_list_getdata(lp);
|
continue;
|
||||||
char *haystack;
|
|
||||||
char *pkgname, *pkgdesc;
|
|
||||||
int match = 0;
|
|
||||||
|
|
||||||
pkgname = alpm_pkg_getinfo(pkg, PM_PKG_NAME);
|
|
||||||
pkgdesc = alpm_pkg_getinfo(pkg, PM_PKG_DESC);
|
|
||||||
|
|
||||||
/* check name */
|
|
||||||
haystack = strdup(pkgname);
|
|
||||||
strtoupper(haystack);
|
|
||||||
if(strstr(haystack, targ)) {
|
|
||||||
match = 1;
|
|
||||||
}
|
}
|
||||||
FREE(haystack);
|
targ = strdup(i->data);
|
||||||
|
|
||||||
/* check description */
|
for(j = alpm_db_getpkgcache(db); j; j = alpm_list_next(j)) {
|
||||||
if(!match) {
|
PM_PKG *pkg = alpm_list_getdata(j);
|
||||||
haystack = strdup(pkgdesc);
|
char *haystack;
|
||||||
strtoupper(haystack);
|
char *pkgname, *pkgdesc;
|
||||||
if(strstr(haystack, targ)) {
|
int match = 0;
|
||||||
|
|
||||||
|
pkgname = alpm_pkg_getinfo(pkg, PM_PKG_NAME);
|
||||||
|
pkgdesc = alpm_pkg_getinfo(pkg, PM_PKG_DESC);
|
||||||
|
|
||||||
|
/* check name */
|
||||||
|
haystack = strdup(pkgname);
|
||||||
|
ret = reg_match(haystack, targ);
|
||||||
|
if(ret < 0) {
|
||||||
|
/* bad regexp */
|
||||||
|
FREE(haystack);
|
||||||
|
return(1);
|
||||||
|
} else if(ret) {
|
||||||
match = 1;
|
match = 1;
|
||||||
}
|
}
|
||||||
FREE(haystack);
|
FREE(haystack);
|
||||||
}
|
|
||||||
|
|
||||||
/* check provides */
|
/* check description */
|
||||||
if(!match) {
|
if(!match) {
|
||||||
PM_LIST *m;
|
haystack = strdup(pkgdesc);
|
||||||
|
ret = reg_match(haystack, targ);
|
||||||
for(m = alpm_pkg_getinfo(pkg, PM_PKG_PROVIDES); m; m = alpm_list_next(m)) {
|
if(ret < 0) {
|
||||||
haystack = strdup(alpm_list_getdata(m));
|
/* bad regexp */
|
||||||
strtoupper(haystack);
|
FREE(haystack);
|
||||||
if(strstr(haystack, targ)) {
|
return(1);
|
||||||
|
} else if(ret) {
|
||||||
match = 1;
|
match = 1;
|
||||||
}
|
}
|
||||||
FREE(haystack);
|
FREE(haystack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check provides */
|
||||||
|
if(!match) {
|
||||||
|
PM_LIST *m;
|
||||||
|
|
||||||
|
for(m = alpm_pkg_getinfo(pkg, PM_PKG_PROVIDES); m; m = alpm_list_next(m)) {
|
||||||
|
haystack = strdup(alpm_list_getdata(m));
|
||||||
|
ret = reg_match(haystack, targ);
|
||||||
|
if(ret < 0) {
|
||||||
|
/* bad regexp */
|
||||||
|
FREE(haystack);
|
||||||
|
return(1);
|
||||||
|
} else if(ret) {
|
||||||
|
match = 1;
|
||||||
|
}
|
||||||
|
FREE(haystack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(match) {
|
||||||
|
printf("%s/%s %s\n ", treename, pkgname, (char *)alpm_pkg_getinfo(pkg, PM_PKG_VERSION));
|
||||||
|
indentprint(pkgdesc, 4);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(match) {
|
FREE(targ);
|
||||||
printf("%s/%s %s\n ", treename, pkgname, (char *)alpm_pkg_getinfo(pkg, PM_PKG_VERSION));
|
|
||||||
indentprint(pkgdesc, 4);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FREE(targ);
|
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#ifndef _PM_DB_H
|
#ifndef _PM_DB_H
|
||||||
#define _PM_DB_H
|
#define _PM_DB_H
|
||||||
|
|
||||||
int db_search(PM_DB *db, char *treename, char *needle);
|
int db_search(PM_DB *db, const char *treename, list_t *needles);
|
||||||
|
|
||||||
#endif /* _PM_DB_H */
|
#endif /* _PM_DB_H */
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
#ifndef CYGWIN
|
#ifndef CYGWIN
|
||||||
#include <mcheck.h> /* debug */
|
#include <mcheck.h> /* debug */
|
||||||
#else
|
#else
|
||||||
|
@ -96,6 +97,7 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char *cenv = NULL;
|
char *cenv = NULL;
|
||||||
|
uid_t myuid;
|
||||||
|
|
||||||
#ifndef CYGWIN
|
#ifndef CYGWIN
|
||||||
/* debug */
|
/* debug */
|
||||||
|
@ -122,6 +124,27 @@ int main(int argc, char *argv[])
|
||||||
exit(ret);
|
exit(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* see if we're root or not */
|
||||||
|
myuid = geteuid();
|
||||||
|
if(!myuid && getenv("FAKEROOTKEY")) {
|
||||||
|
/* fakeroot doesn't count, we're non-root */
|
||||||
|
myuid = 99;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if we have sufficient permission for the requested operation */
|
||||||
|
if(myuid > 0) {
|
||||||
|
if(pmo_op != PM_OP_MAIN && pmo_op != PM_OP_QUERY && pmo_op != PM_OP_DEPTEST) {
|
||||||
|
if((pmo_op == PM_OP_SYNC && !pmo_s_sync &&
|
||||||
|
(pmo_s_search || pmo_s_printuris || pmo_group || pmo_q_list ||
|
||||||
|
pmo_q_info)) || (pmo_op == PM_OP_DEPTEST && !pmo_d_resolve)) {
|
||||||
|
/* special case: PM_OP_SYNC can be used w/ pmo_s_search by any user */
|
||||||
|
} else {
|
||||||
|
ERR(NL, "you cannot perform this operation unless you are root.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(pmo_root == NULL) {
|
if(pmo_root == NULL) {
|
||||||
pmo_root = strdup("/");
|
pmo_root = strdup("/");
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,8 +106,8 @@ int pacman_query(list_t *targets)
|
||||||
int done = 0;
|
int done = 0;
|
||||||
|
|
||||||
if(pmo_q_search) {
|
if(pmo_q_search) {
|
||||||
for(targ = targets; targ; targ = targ->next) {
|
if(db_search(db_local, "local", targets)) {
|
||||||
db_search(db_local, "local", targ->data);
|
return(1);
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,10 +219,8 @@ static int sync_search(list_t *syncs, list_t *targets)
|
||||||
for(i = syncs; i; i = i->next) {
|
for(i = syncs; i; i = i->next) {
|
||||||
sync_t *sync = i->data;
|
sync_t *sync = i->data;
|
||||||
if(targets) {
|
if(targets) {
|
||||||
list_t *j;
|
if(db_search(sync->db, sync->treename, targets)) {
|
||||||
|
return(1);
|
||||||
for(j = targets; j; j = j->next) {
|
|
||||||
db_search(sync->db, sync->treename, j->data);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PM_LIST *lp;
|
PM_LIST *lp;
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <regex.h>
|
||||||
#ifdef CYGWIN
|
#ifdef CYGWIN
|
||||||
#include <limits.h> /* PATH_MAX */
|
#include <limits.h> /* PATH_MAX */
|
||||||
#endif
|
#endif
|
||||||
|
@ -224,4 +225,19 @@ int yesno(char *fmt, ...)
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* match a string against a regular expression */
|
||||||
|
int reg_match(char *string, char *pattern)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
regex_t reg;
|
||||||
|
|
||||||
|
if(regcomp(®, pattern, REG_EXTENDED | REG_NOSUB | REG_ICASE) != 0) {
|
||||||
|
fprintf(stderr, "error: %s is not a valid regular expression.\n", pattern);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
result = regexec(®, string, 0, 0, 0);
|
||||||
|
regfree(®);
|
||||||
|
return(!(result));
|
||||||
|
}
|
||||||
|
|
||||||
/* vim: set ts=2 sw=2 noet: */
|
/* vim: set ts=2 sw=2 noet: */
|
||||||
|
|
|
@ -34,6 +34,7 @@ void indentprint(char *str, int indent);
|
||||||
char *strtrim(char *str);
|
char *strtrim(char *str);
|
||||||
char *strtoupper(char *str);
|
char *strtoupper(char *str);
|
||||||
int yesno(char *fmt, ...);
|
int yesno(char *fmt, ...);
|
||||||
|
int reg_match(char *string, char *pattern);
|
||||||
|
|
||||||
#endif /* _PM_UTIL_H */
|
#endif /* _PM_UTIL_H */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue