From 01b9b4048180ce28ccfceca91a7e5682e0611846 Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Thu, 16 Jun 2011 12:26:42 +0300 Subject: [PATCH] Try to generate fileclass in the tag ext at runtime if missing from header - For non-regular files we can easily generate this information based on file mode + in case of symlinks, the link target is available in the header elsewhere. This also means --fileclass will return at least partial data for packages built with the external depgen. - Clean up fileclassTag() a bit while at it, removing redundant fluff. - Arguably this "magic" should be done inside rpmfiFClass() instead, but that'd require changing the API to return malloced data. --- lib/tagexts.c | 76 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 21 deletions(-) diff --git a/lib/tagexts.c b/lib/tagexts.c index 62a4e10..4dc6e75 100644 --- a/lib/tagexts.c +++ b/lib/tagexts.c @@ -306,8 +306,48 @@ static int origfilenamesTag(Header h, rpmtd td, headerGetFlags hgflags) } return (td->data != NULL); } + +/* + * Attempt to generate libmagic-style file class if missing from header: + * we can easily generate this for symlinks and other special types. + * Always return malloced strings to simplify life in fileclassTag(). + */ +static char *makeFClass(rpmfi fi) +{ + char *fclass = NULL; + const char *hc = rpmfiFClass(fi); + + if (hc != NULL && hc[0] != '\0') { + fclass = xstrdup(hc); + } else { + switch (rpmfiFMode(fi) & S_IFMT) { + case S_IFBLK: + fclass = xstrdup("block special"); + break; + case S_IFCHR: + fclass = xstrdup("character special"); + break; + case S_IFDIR: + fclass = xstrdup("directory"); + break; + case S_IFIFO: + fclass = xstrdup("fifo (named pipe)"); + break; + case S_IFSOCK: + fclass = xstrdup("socket"); + break; + case S_IFLNK: + fclass = rstrscat(NULL, "symbolic link to `", + rpmfiFLink(fi), "'", NULL); + break; + } + } + + return (fclass != NULL) ? fclass : xstrdup(""); +} + /** - * Retrieve file classes. + * Retrieve/generate file classes. * @param h header * @retval td tag data container * @return 1 on success @@ -315,31 +355,25 @@ static int origfilenamesTag(Header h, rpmtd td, headerGetFlags hgflags) static int fileclassTag(Header h, rpmtd td, headerGetFlags hgflags) { rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, RPMFI_NOHEADER); - char **fclasses; - int ix, numfiles; - int rc = 0; + int numfiles = rpmfiFC(fi); - numfiles = rpmfiFC(fi); - if (numfiles <= 0) { - goto exit; - } + if (numfiles > 0) { + char **fclasses = xmalloc(numfiles * sizeof(*fclasses)); + int ix; - fclasses = xmalloc(numfiles * sizeof(*fclasses)); - rpmfiInit(fi, 0); - while ((ix = rpmfiNext(fi)) >= 0) { - const char *fclass = rpmfiFClass(fi); - fclasses[ix] = xstrdup(fclass ? fclass : ""); - } + rpmfiInit(fi, 0); + while ((ix = rpmfiNext(fi)) >= 0) { + fclasses[ix] = makeFClass(fi); + } - td->data = fclasses; - td->count = numfiles; - td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; - td->type = RPM_STRING_ARRAY_TYPE; - rc = 1; + td->data = fclasses; + td->count = numfiles; + td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; + td->type = RPM_STRING_ARRAY_TYPE; + } -exit: rpmfiFree(fi); - return rc; + return (numfiles > 0); } /** -- 2.7.4