specdFlags specdFlags; /* which attributes have been explicitly specified. */
rpmVerifyFlags verifyFlags;
char *langs; /* XXX locales separated with | */
+ char *caps;
} * FileListRec;
/**
rpmVerifyFlags defVerifyFlags;
int nLangs;
char ** currentLangs;
+ int haveCaps;
+ char *currentCaps;
ARGV_t docDirs;
FileListRec fileList;
}
/**
+ * Parse %caps from file manifest.
+ * @param buf current spec file line
+ * @param fl package file tree walk data
+ * @return RPMRC_OK on success
+ */
+static rpmRC parseForCaps(const char * buf, FileList fl)
+{
+ char *p, *pe, *q = NULL;
+ const char *name;
+ rpmRC rc = RPMRC_FAIL;
+
+ if ((p = strstr(buf, (name = "%caps"))) == NULL)
+ return RPMRC_OK;
+
+ /* Erase "%caps" token. */
+ for (pe = p; (pe-p) < strlen(name); pe++)
+ *pe = ' ';
+ SKIPSPACE(pe);
+ if (*pe != '(')
+ return RPMRC_OK;
+
+ /* Bracket %caps args */
+ *pe++ = ' ';
+ for (p = pe; *pe && *pe != ')'; pe++)
+ {};
+
+ if (*pe == '\0') {
+ rpmlog(RPMLOG_ERR, _("Missing ')' in %s(%s\n"), name, p);
+ goto exit;
+ }
+
+ /* Localize. Erase parsed string. */
+ q = xmalloc((pe-p) + 1);
+ rstrlcpy(q, p, (pe-p) + 1);
+ while (p <= pe)
+ *p++ = ' ';
+
+#if WITH_CAP
+ {
+ char *captxt = NULL;
+ cap_t fcaps = cap_from_text(q);
+ if (fcaps == NULL) {
+ rpmlog(RPMLOG_ERR, _("Invalid capability: %s\n"), q);
+ goto exit;
+ }
+ /* run our string through cap_to_text() to get libcap presentation */
+ captxt = cap_to_text(fcaps, NULL);
+ fl->currentCaps = xstrdup(captxt);
+ fl->haveCaps = 1;
+ cap_free(captxt);
+ cap_free(fcaps);
+ }
+#else
+ rpmlog(RPMLOG_ERR, _("File capability support not built in\n"));
+ goto exit;
+#endif
+
+ rc = RPMRC_OK;
+
+exit:
+ free(q);
+ if (rc != RPMRC_OK) {
+ fl->processingFailed = 1;
+ }
+
+ return rc;
+}
+/**
*/
static VFA_t virtualFileAttributes[] = {
{ "%dir", 0, 0 }, /* XXX why not RPMFILE_DIR? */
}
headerPutString(h, RPMTAG_FILELANGS, flp->langs);
+
+ if (fl->haveCaps) {
+ headerPutString(h, RPMTAG_FILECAPS, flp->caps);
+ }
buf[0] = '\0';
if (S_ISREG(flp->fl_mode))
rpmlibNeedsFeature(h, "FileDigests", "4.4.90-1");
}
+ if (fl->haveCaps) {
+ rpmlibNeedsFeature(h, "FileCaps", "4.6.1-1");
+ }
+
if (_addDotSlash)
(void) rpmlibNeedsFeature(h, "PayloadFilesHavePrefix", "4.0-1");
fileList[count].diskPath = _free(fileList[count].diskPath);
fileList[count].cpioPath = _free(fileList[count].cpioPath);
fileList[count].langs = _free(fileList[count].langs);
+ fileList[count].caps = _free(fileList[count].caps);
}
fileList = _free(fileList);
return NULL;
flp->langs = xstrdup("");
}
+ if (fl->currentCaps) {
+ flp->caps = fl->currentCaps;
+ } else {
+ flp->caps = xstrdup("");
+ }
+
flp->flags = fl->currentFlags;
flp->specdFlags = fl->currentSpecdFlags;
flp->verifyFlags = fl->currentVerifyFlags;
fl.defVerifyFlags = RPMVERIFY_ALL;
fl.nLangs = 0;
fl.currentLangs = NULL;
+ fl.haveCaps = 0;
+ fl.currentCaps = NULL;
fl.currentSpecdFlags = 0;
fl.defSpecdFlags = 0;
fl.currentLangs = _free(fl.currentLangs);
}
fl.nLangs = 0;
+ fl.currentCaps = NULL;
dupAttrRec(&fl.def_ar, &fl.cur_ar);
continue;
if (parseForLang(buf, &fl))
continue;
+ if (parseForCaps(buf, &fl))
+ continue;
if (parseForSimple(spec, pkg, buf, &fl, &fileName))
continue;
if (fileName == NULL)