static int handleRemovalConflict(rpmfiles fi, int fx, rpmfiles ofi, int ofx) { int rConflicts = 0; /* Removed files don't conflict, normally */ rpmFileTypes ft = rpmfiWhatis(rpmfilesFMode(fi, fx)); rpmFileTypes oft = rpmfiWhatis(rpmfilesFMode(ofi, ofx)); struct stat sb; char *fn = NULL; if (oft == XDIR) { /* We can't handle directory changing to anything else */ if (ft != XDIR) rConflicts = 1; } else if (oft == LINK) { /* We can't correctly handle directory symlink changing to directory */ if (ft == XDIR) { fn = rpmfilesFN(fi, fx); if (stat(fn, &sb) == 0 && S_ISDIR(sb.st_mode)) rConflicts = 1; } } /* * ...but if the conflicting item is either not on disk, or has * already been changed to the new type, we should be ok afterall. */ if (rConflicts) { if (fn == NULL) fn = rpmfilesFN(fi, fx); if (lstat(fn, &sb) || rpmfiWhatis(sb.st_mode) == ft) rConflicts = 0; } free(fn); return rConflicts; }
/** \ingroup payload * Create directory name iterator. * @param fi file info set * @param fs file state set * @param reverse traverse directory names in reverse order? * @return directory name iterator */ static DNLI_t dnlInitIterator(rpmfiles fi, rpmfs fs, int reverse) { DNLI_t dnli; int i, j; int dc; if (fi == NULL) return NULL; dc = rpmfilesDC(fi); dnli = xcalloc(1, sizeof(*dnli)); dnli->fi = fi; dnli->reverse = reverse; dnli->i = (reverse ? dc : 0); if (dc) { dnli->active = xcalloc(dc, sizeof(*dnli->active)); int fc = rpmfilesFC(fi); /* Identify parent directories not skipped. */ for (i = 0; i < fc; i++) if (!XFA_SKIPPING(rpmfsGetAction(fs, i))) dnli->active[rpmfilesDI(fi, i)] = 1; /* Exclude parent directories that are explicitly included. */ for (i = 0; i < fc; i++) { int dil; size_t dnlen, bnlen; if (!S_ISDIR(rpmfilesFMode(fi, i))) continue; dil = rpmfilesDI(fi, i); dnlen = strlen(rpmfilesDN(fi, dil)); bnlen = strlen(rpmfilesBN(fi, i)); for (j = 0; j < dc; j++) { const char * dnl; size_t jlen; if (!dnli->active[j] || j == dil) continue; dnl = rpmfilesDN(fi, j); jlen = strlen(dnl); if (jlen != (dnlen+bnlen+1)) continue; if (!rstreqn(dnl, rpmfilesDN(fi, dil), dnlen)) continue; if (!rstreqn(dnl+dnlen, rpmfilesBN(fi, i), bnlen)) continue; if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0') continue; /* This directory is included in the package. */ dnli->active[j] = 0; break; } } /* Print only once per package. */ if (!reverse) { j = 0; for (i = 0; i < dc; i++) { if (!dnli->active[i]) continue; if (j == 0) { j = 1; rpmlog(RPMLOG_DEBUG, "========== Directories not explicitly included in package:\n"); } rpmlog(RPMLOG_DEBUG, "%10d %s\n", i, rpmfilesDN(fi, i)); } if (j) rpmlog(RPMLOG_DEBUG, "==========\n"); } } return dnli; }