[pacman-dev] CVS update of pacman-lib/lib/libalpm (alpm.h error.c remove.c)

Aaron Griffin aaron at archlinux.org
Thu Feb 8 03:09:35 EST 2007


    Date: Thursday, February 8, 2007 @ 03:09:35
  Author: aaron
    Path: /home/cvs-pacman/pacman-lib/lib/libalpm

Modified: alpm.h (1.71 -> 1.72) error.c (1.16 -> 1.17)
          remove.c (1.60 -> 1.61)

Attempt to NOT remove packages on filesystem errors (like a read-only
filesystem). See FS#5887


----------+
 alpm.h   |    1 
 error.c  |    2 +
 remove.c |   95 +++++++++++++++++++++++++++++++++++++++++++------------------
 3 files changed, 71 insertions(+), 27 deletions(-)


Index: pacman-lib/lib/libalpm/alpm.h
diff -u pacman-lib/lib/libalpm/alpm.h:1.71 pacman-lib/lib/libalpm/alpm.h:1.72
--- pacman-lib/lib/libalpm/alpm.h:1.71	Sun Feb  4 03:26:52 2007
+++ pacman-lib/lib/libalpm/alpm.h	Thu Feb  8 03:09:34 2007
@@ -450,6 +450,7 @@
 	PM_ERR_PKG_LOAD,
 	PM_ERR_PKG_INSTALLED,
 	PM_ERR_PKG_CANT_FRESH,
+	PM_ERR_PKG_CANT_REMOVE,
 	PM_ERR_PKG_INVALID_NAME,
 	PM_ERR_PKG_CORRUPTED,
 	PM_ERR_PKG_REPO_NOT_FOUND,
Index: pacman-lib/lib/libalpm/error.c
diff -u pacman-lib/lib/libalpm/error.c:1.16 pacman-lib/lib/libalpm/error.c:1.17
--- pacman-lib/lib/libalpm/error.c:1.16	Tue Jan 30 02:47:20 2007
+++ pacman-lib/lib/libalpm/error.c	Thu Feb  8 03:09:35 2007
@@ -97,6 +97,8 @@
 			return _("package already installed");
 		case PM_ERR_PKG_CANT_FRESH:
 			return _("package not installed or lesser version");
+		case PM_ERR_PKG_CANT_REMOVE:
+			return _("cannot remove all files for package");
 		case PM_ERR_PKG_INVALID_NAME:
 			return _("package name is not valid");
 		case PM_ERR_PKG_CORRUPTED:
Index: pacman-lib/lib/libalpm/remove.c
diff -u pacman-lib/lib/libalpm/remove.c:1.60 pacman-lib/lib/libalpm/remove.c:1.61
--- pacman-lib/lib/libalpm/remove.c:1.60	Wed Jan 31 01:10:21 2007
+++ pacman-lib/lib/libalpm/remove.c	Thu Feb  8 03:09:35 2007
@@ -162,8 +162,40 @@
 	return(strcmp(s1, s2));
 }
 
+
+static int can_remove_file(const char *path)
+{
+	alpm_list_t *i;
+	char file[PATH_MAX+1];
+
+	snprintf(file, PATH_MAX, "%s%s", handle->root, path);
+
+	for(i = handle->trans->skiplist; i; i = i->next) {
+		if(strcmp(file, i->data) == 0) {
+			/* skipping this file, return success because "removing" this
+			 * file does nothing */
+			return(1);
+		}
+	}
+	/* If we fail write permissions due to a read-only filesystem, abort.
+	 * Assume all other possible failures are covered somewhere else */
+	if(access(file, W_OK) == -1) {
+		if(access(file, F_OK) == 0) {
+			/* only return failure if the file ACTUALLY exists and we don't have
+			 * permissions */
+			_alpm_log(PM_LOG_WARNING, _("cannot remove file '%s': %s"), file, strerror(errno));
+			return(0);
+		}
+	}
+
+	return(1);
+}
+
 /* Helper function for iterating through a package's file and deleting them
  * Used by _alpm_remove_commit
+ *
+ * TODO the parameters are a bit out of control here.  This function doesn't
+ * need to report PROGRESS, do it in the parent function.
 */
 static void unlink_file(pmpkg_t *info, alpm_list_t *lp, alpm_list_t *targ,
 												pmtrans_t *trans, int filenum, int *position)
@@ -171,34 +203,35 @@
 	struct stat buf;
 	int nb = 0;
 	double percent = 0.0;
-	char *file = lp->data;
-	char line[PATH_MAX+1];
+	char file[PATH_MAX+1];
 	char *checksum = _alpm_needbackup(lp->data, info->backup);
 
 	ALPM_LOG_FUNC;
 
-	if ( *position != 0 ) {
+	if(*position != 0) {
 		percent = (double)*position / filenum;
-	} if ( checksum ) {
+	}
+	if(checksum) {
 		nb = 1;
 		FREE(checksum);
-	} if ( !nb && trans->type == PM_TRANS_TYPE_UPGRADE ) {
+	}
+	if(!nb && trans->type == PM_TRANS_TYPE_UPGRADE) {
 		/* check noupgrade */
-		if ( alpm_list_find_str(handle->noupgrade, file) ) {
+		if(alpm_list_find_str(handle->noupgrade, lp->data)) {
 			nb = 1;
 		}
 	}
-	snprintf(line, PATH_MAX, "%s%s", handle->root, file);
-	if ( lstat(line, &buf) ) {
-		_alpm_log(PM_LOG_DEBUG, _("file %s does not exist"), line);
+	snprintf(file, PATH_MAX, "%s%s", handle->root, (char *)lp->data);
+	if(lstat(file, &buf)) {
+		_alpm_log(PM_LOG_DEBUG, _("file %s does not exist"), file);
 		return;
 	}
-	if ( S_ISDIR(buf.st_mode) ) {
-		if ( rmdir(line) ) {
+	if(S_ISDIR(buf.st_mode)) {
+		if(rmdir(file)) {
 			/* this is okay, other pakcages are probably using it (like /usr) */
-			_alpm_log(PM_LOG_DEBUG, _("keeping directory %s"), line);
+			_alpm_log(PM_LOG_DEBUG, _("keeping directory %s"), file);
 		} else {
-			_alpm_log(PM_LOG_DEBUG, _("removing directory %s"), line);
+			_alpm_log(PM_LOG_DEBUG, _("removing directory %s"), file);
 		}
 	} else {
 		/* check the "skip list" before removing the file.
@@ -206,35 +239,36 @@
 		 * explanation. */
 		int skipit = 0;
 		alpm_list_t *j;
-		for ( j = trans->skiplist; j; j = j->next ) {
-			if ( !strcmp(file, (char*)j->data) ) {
+		for(j = trans->skiplist; j; j = j->next) {
+			if(!strcmp(lp->data, (char*)j->data)) {
 				skipit = 1;
 			}
 		}
-		if ( skipit ) {
-			_alpm_log(PM_LOG_DEBUG, _("skipping removal of %s as it has moved to another package"),
-								line);
+		if(skipit) {
+			_alpm_log(PM_LOG_WARNING, _("skipping removal of %s as it has moved to another package"),
+								file);
 		} else {
 			/* if the file is flagged, back it up to .pacsave */
-			if ( nb ) {
-				if ( !(trans->type == PM_TRANS_TYPE_UPGRADE) ) {
+			if(nb) {
+				if(!(trans->type == PM_TRANS_TYPE_UPGRADE)) {
 					/* if it was an upgrade, the file would be left alone because
 					 * pacman_add() would handle it */
-					if ( !(trans->type & PM_TRANS_FLAG_NOSAVE) ) {
+					if(!(trans->type & PM_TRANS_FLAG_NOSAVE)) {
 						char newpath[PATH_MAX];
-						snprintf(newpath, PATH_MAX, "%s.pacsave", line);
-						rename(line, newpath);
-						_alpm_log(PM_LOG_WARNING, _("%s saved as %s"), line, newpath);
+						snprintf(newpath, PATH_MAX, "%s.pacsave", file);
+						rename(file, newpath);
+						_alpm_log(PM_LOG_WARNING, _("%s saved as %s"), file, newpath);
 					}
 				}
 			} else {
-				_alpm_log(PM_LOG_DEBUG, _("unlinking %s"), line);
+				_alpm_log(PM_LOG_DEBUG, _("unlinking %s"), file);
 				int list_count = alpm_list_count(trans->packages); /* this way we don't have to call alpm_list_count twice during PROGRESS */
+
 				PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, info->name, (double)(percent * 100), list_count, (list_count - alpm_list_count(targ) + 1));
 				++(*position);
 
-				if (unlink(line) == -1) {
-					_alpm_log(PM_LOG_ERROR, _("cannot remove file %s: %s"), file, strerror(errno));
+				if(unlink(file) == -1) {
+					_alpm_log(PM_LOG_ERROR, _("cannot remove file %s: %s"), lp->data, strerror(errno));
 				}
 			}
 		}
@@ -272,6 +306,13 @@
 		}
 
 		if(!(trans->flags & PM_TRANS_FLAG_DBONLY)) {
+			for(lp = info->files; lp; lp = lp->next) {
+				if(!can_remove_file(lp->data)) {
+					_alpm_log(PM_LOG_DEBUG, _("not removing package '%s', can't remove all files"), info->name);
+					RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1);
+				}
+			}
+
 			int filenum = alpm_list_count(info->files);
 			_alpm_log(PM_LOG_DEBUG, _("removing files"));
 




More information about the pacman-dev mailing list