diff --git a/lib/fsm.c b/lib/fsm.c index 16658dc3e..de1712f6b 100644 --- a/lib/fsm.c +++ b/lib/fsm.c @@ -1801,71 +1801,6 @@ static int fsmStage(FSM_t fsm, fileStage stage) switch (stage) { case FSM_UNKNOWN: break; - case FSM_PKGERASE: - while (1) { - /* Clean fsm, free'ing memory. */ - rc = fsmInit(fsm); - - /* Exit on end-of-payload. */ - if (rc == CPIOERR_HDR_TRAILER) { - rc = 0; - break; - } - - /* Remove erased files. */ - if (!fsm->postpone && fsm->action == FA_ERASE) { - rpmte te = fsmGetTe(fsm); - if (S_ISDIR(st->st_mode)) { - rc = fsmRmdir(fsm->path); - if (!rc) break; - switch (rc) { - case CPIOERR_ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */ - case CPIOERR_ENOTEMPTY: - /* XXX make sure that build side permits %missingok on directories. */ - if (fsm->fflags & RPMFILE_MISSINGOK) - break; - - /* XXX common error message. */ - rpmlog( - (strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), - _("%s rmdir of %s failed: Directory not empty\n"), - rpmteTypeString(te), fsm->path); - break; - default: - rpmlog( - (strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), - _("%s rmdir of %s failed: %s\n"), - rpmteTypeString(te), fsm->path, strerror(errno)); - break; - } - } else { - rc = fsmUnlink(fsm->path, fsm->mapFlags); - if (!rc) break; - switch (rc) { - case CPIOERR_ENOENT: - if (fsm->fflags & RPMFILE_MISSINGOK) - break; - default: - rpmlog( - (strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), - _("%s unlink of %s failed: %s\n"), - rpmteTypeString(te), fsm->path, strerror(errno)); - break; - } - } - } - /* XXX Failure to remove is not (yet) cause for failure. */ - if (!strict_erasures) rc = 0; - - if (rc) break; - - /* Notify on success. */ - /* On erase we're iterating backwards, fixup for progress */ - rpm_loff_t amount = (fsm->ix >= 0) ? - rpmfiFC(fsmGetFi(fsm)) - fsm->ix : 0; - rpmpsmNotify(fsm->psm, RPMCALLBACK_UNINST_PROGRESS, amount); - } - break; case FSM_PKGBUILD: while (1) { @@ -2159,3 +2094,86 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfi fi, FD_t cfd, return (rc ? rc : ec); } + +int rpmPackageFilesRemove(rpmts ts, rpmte te, rpmfi fi, + rpmpsm psm, char ** failedFile) +{ + struct fsm_s fsm_; + FSM_t fsm = &fsm_; + int rc = 0; + int ec = 0; + + memset(fsm, 0, sizeof(*fsm)); + rc = fsmSetup(fsm, FSM_PKGERASE, ts, te, fi, NULL, psm, NULL, failedFile); + + while (!rc) { + /* Clean fsm, free'ing memory. */ + rc = fsmInit(fsm); + + /* Exit on end-of-payload. */ + if (rc == CPIOERR_HDR_TRAILER) { + rc = 0; + break; + } + + /* Remove erased files. */ + if (!fsm->postpone && fsm->action == FA_ERASE) { + rpmte te = fsmGetTe(fsm); + if (S_ISDIR(fsm->sb.st_mode)) { + rc = fsmRmdir(fsm->path); + if (!rc) break; + switch (rc) { + case CPIOERR_ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */ + case CPIOERR_ENOTEMPTY: + /* XXX make sure that build side permits %missingok on directories. */ + if (fsm->fflags & RPMFILE_MISSINGOK) + break; + + /* XXX common error message. */ + rpmlog( + (strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), + _("%s rmdir of %s failed: Directory not empty\n"), + rpmteTypeString(te), fsm->path); + break; + default: + rpmlog( + (strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), + _("%s rmdir of %s failed: %s\n"), + rpmteTypeString(te), fsm->path, strerror(errno)); + break; + } + } else { + rc = fsmUnlink(fsm->path, fsm->mapFlags); + if (!rc) break; + switch (rc) { + case CPIOERR_ENOENT: + if (fsm->fflags & RPMFILE_MISSINGOK) + break; + default: + rpmlog( + (strict_erasures ? RPMLOG_ERR : RPMLOG_DEBUG), + _("%s unlink of %s failed: %s\n"), + rpmteTypeString(te), fsm->path, strerror(errno)); + break; + } + } + } + /* XXX Failure to remove is not (yet) cause for failure. */ + if (!strict_erasures) rc = 0; + + if (rc) break; + + /* Notify on success. */ + /* On erase we're iterating backwards, fixup for progress */ + rpm_loff_t amount = (fsm->ix >= 0) ? + rpmfiFC(fsmGetFi(fsm)) - fsm->ix : 0; + rpmpsmNotify(fsm->psm, RPMCALLBACK_UNINST_PROGRESS, amount); + } + + ec = fsmTeardown(fsm); + + /* Return the relevant code: if setup failed, teardown doesn't matter */ + return (rc ? rc : ec); +} + + diff --git a/lib/fsm.h b/lib/fsm.h index 0156523db..756835f60 100644 --- a/lib/fsm.h +++ b/lib/fsm.h @@ -122,6 +122,9 @@ int rpmfsmRun(fileStage goal, rpmts ts, rpmte te, rpmfi fi, FD_t cfd, int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfi fi, FD_t cfd, rpmpsm psm, char ** failedFile); +int rpmPackageFilesRemove(rpmts ts, rpmte te, rpmfi fi, + rpmpsm psm, char ** failedFile); + RPM_GNUC_INTERNAL void rpmpsmNotify(rpmpsm psm, int what, rpm_loff_t amount); #ifdef __cplusplus diff --git a/lib/psm.c b/lib/psm.c index 161c77e13..8f5376d49 100644 --- a/lib/psm.c +++ b/lib/psm.c @@ -853,8 +853,8 @@ static rpmRC rpmpsmStage(rpmpsm psm, pkgStage stage) /* XXX should't we log errors from here? */ if (rpmfiFC(fi) > 0 && !(rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)) { - rc = rpmfsmRun(FSM_PKGERASE, psm->ts, psm->te, psm->fi, - NULL, psm, NULL, &psm->failedFile); + rc = rpmPackageFilesRemove(psm->ts, psm->te, psm->fi, + psm, &psm->failedFile); } /* XXX make sure progress reaches 100% */