00001
00004 #include "system.h"
00005
00006 #include <rpmiotypes.h>
00007 #include <rpmio.h>
00008 #include <rpmmacro.h>
00009 #include <yarn.h>
00010
00011 #include <rpmtypes.h>
00012
00013 #define _RPMSX_INTERNAL
00014 #include "rpmsx.h"
00015
00016 #include "debug.h"
00017
00018
00019
00020
00021 int _rpmsx_debug = 0;
00022
00027 static void rpmsxSort(rpmsx sx)
00028
00029 {
00030 rpmsxp sxp;
00031 int i, j;
00032
00033
00034 sxp = xmalloc(sizeof(*sxp) * sx->Count);
00035
00036
00037 j = 0;
00038 for (i = 0; i < sx->Count; i++) {
00039 if (!sx->sxp[i].hasMetaChars)
00040 continue;
00041 memcpy(sxp + j, sx->sxp + i, sizeof(*sxp));
00042 j++;
00043 }
00044
00045
00046 for (i = 0; i < sx->Count; i++) {
00047 if (sx->sxp[i].hasMetaChars)
00048 continue;
00049 memcpy(sxp + j, sx->sxp + i, sizeof(*sxp));
00050 j++;
00051 }
00052
00053 sx->sxp = _free(sx->sxp);
00054 sx->sxp = sxp;
00055
00056 return;
00057
00058 }
00059
00060
00061 static void rpmsxpHasMetaChars(rpmsxp sxp)
00062
00063 {
00064 const char * s = sxp->pattern;
00065 size_t ns = strlen(s);
00066 const char * se = s + ns;
00067
00068 sxp->hasMetaChars = 0;
00069
00070
00071
00072 while (s != se) {
00073 switch(*s) {
00074 case '.':
00075 case '^':
00076 case '$':
00077 case '?':
00078 case '*':
00079 case '+':
00080 case '|':
00081 case '[':
00082 case '(':
00083 case '{':
00084 sxp->hasMetaChars = 1;
00085 return;
00086 break;
00087 case '\\':
00088 s++;
00089 break;
00090 default:
00091 break;
00092
00093 }
00094 s++;
00095 }
00096 return;
00097 }
00098
00103 static size_t rpmsxsPStem(const char * const buf)
00104
00105 {
00106
00107 static const char * const regex_chars = ".^$?*+|[({";
00108 const char * tmp = strchr(buf, '/');
00109 const char * ind;
00110
00111 if (!tmp)
00112 return 0;
00113
00114 for (ind = buf; ind < tmp; ind++) {
00115 if (strchr(regex_chars, (int)*ind))
00116 return 0;
00117 }
00118 return tmp - buf;
00119 }
00120
00125 static size_t rpmsxsFStem(const char * const buf)
00126
00127 {
00128 const char * tmp = strchr(buf + 1, '/');
00129
00130 if (!tmp)
00131 return 0;
00132 return tmp - buf;
00133 }
00134
00142 static int rpmsxAdd(rpmsx sx, const char ** bpp)
00143
00144 {
00145 size_t stem_len = rpmsxsPStem(*bpp);
00146 rpmsxs sxs;
00147 int i;
00148
00149 if (!stem_len)
00150 return -1;
00151 for (i = 0; i < sx->nsxs; i++) {
00152 sxs = sx->sxs + i;
00153 if (stem_len != sxs->len)
00154 continue;
00155 if (strncmp(*bpp, sxs->stem, stem_len))
00156 continue;
00157 *bpp += stem_len;
00158 return i;
00159 }
00160
00161 if (sx->nsxs == sx->maxsxs) {
00162 sx->maxsxs = sx->maxsxs * 2 + 16;
00163 sx->sxs = xrealloc(sx->sxs, sizeof(*sx->sxs) * sx->maxsxs);
00164 }
00165 sxs = sx->sxs + sx->nsxs;
00166 sxs->len = stem_len;
00167 #ifdef HAVE_STRNDUP
00168 sxs->stem = strndup(*bpp, stem_len);
00169 #else
00170 sxs->stem = xmalloc(stem_len+1);
00171 strncpy((char *)sxs->stem, *bpp, stem_len);
00172 #endif
00173 sx->nsxs++;
00174 *bpp += stem_len;
00175 return sx->nsxs - 1;
00176 }
00177
00186 static int rpmsxFind( const rpmsx sx, const char ** bpp)
00187
00188 {
00189 size_t stem_len = rpmsxsFStem(*bpp);
00190 rpmsxs sxs;
00191 int i;
00192
00193 if (sx != NULL && stem_len > 0)
00194 for (i = 0; i < sx->nsxs; i++) {
00195 sxs = sx->sxs + i;
00196 if (stem_len != sxs->len)
00197 continue;
00198 if (strncmp(*bpp, sxs->stem, stem_len))
00199 continue;
00200 *bpp += stem_len;
00201 return i;
00202 }
00203 return -1;
00204 }
00205
00206
00207 static void rpmsxFini(void * _sx)
00208
00209 {
00210 rpmsx sx = _sx;
00211 int i;
00212
00213 if (sx->Count > 0)
00214 for (i = 0; i < sx->Count; i++) {
00215 rpmsxp sxp = sx->sxp + i;
00216 sxp->pattern = _free(sxp->pattern);
00217 sxp->type = _free(sxp->type);
00218 sxp->context = _free(sxp->context);
00219 regfree(sxp->preg);
00220 sxp->preg = _free(sxp->preg);
00221 }
00222 sx->sxp = _free(sx->sxp);
00223
00224 if (sx->nsxs > 0)
00225 for (i = 0; i < sx->nsxs; i++) {
00226 rpmsxs sxs = sx->sxs + i;
00227 sxs->stem = _free(sxs->stem);
00228 }
00229 sx->sxs = _free(sx->sxs);
00230 }
00231
00232
00233
00234 rpmioPool _rpmsxPool;
00235
00236 static rpmsx rpmsxGetPool( rpmioPool pool)
00237
00238
00239 {
00240 rpmsx sx;
00241
00242 if (_rpmsxPool == NULL) {
00243 _rpmsxPool = rpmioNewPool("sx", sizeof(*sx), -1, _rpmsx_debug,
00244 NULL, NULL, rpmsxFini);
00245 pool = _rpmsxPool;
00246 }
00247 return (rpmsx) rpmioGetPool(pool, sizeof(*sx));
00248 }
00249
00259 static int rpmsxpCheckNoDupes(const rpmsx sx)
00260
00261 {
00262 int i, j;
00263 int rc = 0;
00264
00265 for (i = 0; i < sx->Count; i++) {
00266 rpmsxp sxpi = sx->sxp + i;
00267 for (j = i + 1; j < sx->Count; j++) {
00268 rpmsxp sxpj = sx->sxp + j;
00269
00270
00271 if (strcmp(sxpj->pattern, sxpi->pattern))
00272 continue;
00273 if (sxpj->fmode && sxpi->fmode && sxpj->fmode != sxpi->fmode)
00274 continue;
00275
00276
00277 if (strcmp(sxpj->context, sxpi->context)) {
00278
00279
00280 fprintf(stderr,
00281 "ERROR: Multiple different specifications for %s (%s and %s).\n",
00282 sxpi->pattern, sxpj->context, sxpi->context);
00283
00284 rc = -1;
00285 } else {
00286
00287
00288 fprintf(stderr,
00289 "WARNING: Multiple same specifications for %s.\n",
00290 sxpi->pattern);
00291
00292 }
00293 }
00294 }
00295 return rc;
00296 }
00297
00298 int rpmsxParse(rpmsx sx, const char * fn)
00299 {
00300 FILE * fp;
00301 char buf[BUFSIZ + 1];
00302 char * bp;
00303 char * regex;
00304 char * type;
00305 char * context;
00306 char * anchored_regex;
00307 int items;
00308 size_t len;
00309 int lineno;
00310 int pass;
00311 int regerr;
00312 int nerr = 0;
00313
00314 #define inc_err() nerr++
00315
00316 if (fn == NULL)
00317 fn = "%{?__file_context_path}";
00318
00319 { const char * myfn = rpmGetPath(fn, NULL);
00320
00321 if (myfn == NULL || *myfn == '\0'
00322 || (fp = fopen(myfn, "r")) == NULL)
00323 {
00324 myfn = _free(myfn);
00325 return -1;
00326 }
00327 myfn = _free(myfn);
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 for (pass = 0; pass < 2; pass++) {
00339 rpmsxp sxp;
00340
00341 lineno = 0;
00342 sx->Count = 0;
00343 sxp = sx->sxp;
00344 while (fgets(buf, sizeof(buf)-1, fp)) {
00345 buf[sizeof(buf)-1] = '\0';
00346 lineno++;
00347 len = strlen(buf);
00348 if (buf[len - 1] != '\n') {
00349 fprintf(stderr,
00350 _("%s: no newline on line number %d (only read %s)\n"),
00351 fn, lineno, buf);
00352 inc_err();
00353 continue;
00354 }
00355 buf[len - 1] = 0;
00356 bp = buf;
00357 while (isspace(*bp))
00358 bp++;
00359
00360 if (*bp == '#' || *bp == 0)
00361 continue;
00362
00363 #if defined(__GLIBC__)
00364 items = sscanf(buf, "%as %as %as", ®ex, &type, &context);
00365 #else
00366 regex = malloc(len+1);
00367 type = malloc(len+1);
00368 context = malloc(len+1);
00369 items = sscanf(buf, "%s %s %s", regex, type, context);
00370 #endif
00371
00372 if (items < 2) {
00373 fprintf(stderr,
00374 _("%s: line number %d is missing fields (only read %s)\n"),
00375 fn, lineno, buf);
00376 inc_err();
00377 if (items == 1)
00378 free(regex);
00379 continue;
00380 } else if (items == 2) {
00381
00382 free(context);
00383 context = type;
00384 type = 0;
00385 }
00386
00387
00388 if (pass == 1) {
00389 const char * reg_buf = regex;
00390 sxp->fstem = rpmsxAdd(sx, ®_buf);
00391 sxp->pattern = regex;
00392
00393
00394 len = strlen(reg_buf);
00395 anchored_regex = xmalloc(len + 3);
00396 sprintf(anchored_regex, "^%s$", reg_buf);
00397
00398
00399 sxp->preg = xcalloc(1, sizeof(*sxp->preg));
00400 regerr = regcomp(sxp->preg, anchored_regex,
00401 REG_EXTENDED | REG_NOSUB);
00402 if (regerr < 0) {
00403 char errbuf[BUFSIZ + 1];
00404 (void) regerror(regerr, sxp->preg, errbuf, sizeof(errbuf)-1);
00405 errbuf[sizeof(errbuf)-1] = '\0';
00406 fprintf(stderr,
00407 _("%s: unable to compile regular expression %s on line number %d: %s\n"),
00408 fn, regex, lineno,
00409 errbuf);
00410 inc_err();
00411 }
00412 free(anchored_regex);
00413
00414
00415 sxp->type = type;
00416 sxp->fmode = 0;
00417 if (!type)
00418 goto skip_type;
00419 len = strlen(type);
00420 if (type[0] != '-' || len != 2) {
00421 fprintf(stderr,
00422 _("%s: invalid type specifier %s on line number %d\n"),
00423 fn, type, lineno);
00424 inc_err();
00425 goto skip_type;
00426 }
00427 switch (type[1]) {
00428 case 'b': sxp->fmode = S_IFBLK; break;
00429 case 'c': sxp->fmode = S_IFCHR; break;
00430 case 'd': sxp->fmode = S_IFDIR; break;
00431 case 'p': sxp->fmode = S_IFIFO; break;
00432 case 'l': sxp->fmode = S_IFLNK; break;
00433 case 's': sxp->fmode = S_IFSOCK; break;
00434 case '-': sxp->fmode = S_IFREG; break;
00435 default:
00436 fprintf(stderr,
00437 _("%s: invalid type specifier %s on line number %d\n"),
00438 fn, type, lineno);
00439 inc_err();
00440 break;
00441 }
00442
00443 skip_type:
00444
00445 sxp->context = context;
00446
00447 if (strcmp(context, "<<none>>")) {
00448 if (security_check_context(context) < 0 && errno != ENOENT) {
00449 fprintf(stderr,
00450 _("%s: invalid context %s on line number %d\n"),
00451 fn, context, lineno);
00452 inc_err();
00453 }
00454 }
00455
00456
00457
00458 rpmsxpHasMetaChars(sxp);
00459 sxp++;
00460 }
00461
00462 sx->Count++;
00463 if (pass == 0) {
00464
00465 free(regex);
00466 if (type)
00467 free(type);
00468 free(context);
00469
00470 }
00471 }
00472
00473 if (nerr) {
00474 (void) fclose(fp);
00475 return -1;
00476 }
00477
00478 if (pass == 0) {
00479 if (sx->Count == 0) {
00480 (void) fclose(fp);
00481 return 0;
00482 }
00483 sx->sxp = xcalloc(sx->Count, sizeof(*sx->sxp));
00484 rewind(fp);
00485 }
00486 }
00487 (void) fclose(fp);
00488
00489
00490 rpmsxSort(sx);
00491
00492
00493 if (rpmsxpCheckNoDupes(sx) != 0)
00494 return -1;
00495
00496 return 0;
00497
00498 }
00499
00500 rpmsx rpmsxNew(const char * fn)
00501 {
00502 rpmsx sx = rpmsxGetPool(_rpmsxPool);
00503
00504 sx->sxp = NULL;
00505 sx->Count = 0;
00506 sx->i = -1;
00507 sx->sxs = NULL;
00508 sx->nsxs = 0;
00509 sx->maxsxs = 0;
00510 sx->reverse = 0;
00511
00512 (void) rpmsxLink(sx, "rpmsxNew");
00513
00514 if (rpmsxParse(sx, fn) != 0)
00515 return rpmsxFree(sx);
00516
00517 return sx;
00518 }
00519
00520 int rpmsxCount(const rpmsx sx)
00521 {
00522 return (sx != NULL ? sx->Count : 0);
00523 }
00524
00525 int rpmsxIx(const rpmsx sx)
00526 {
00527 return (sx != NULL ? sx->i : -1);
00528 }
00529
00530 int rpmsxSetIx(rpmsx sx, int ix)
00531 {
00532 int i = -1;
00533
00534 if (sx != NULL) {
00535 i = sx->i;
00536 sx->i = ix;
00537 }
00538 return i;
00539 }
00540
00541 const char * rpmsxPattern(const rpmsx sx)
00542 {
00543 const char * pattern = NULL;
00544
00545 if (sx != NULL && sx->i >= 0 && sx->i < sx->Count)
00546 pattern = (sx->sxp + sx->i)->pattern;
00547 return pattern;
00548 }
00549
00550 const char * rpmsxType(const rpmsx sx)
00551 {
00552 const char * type = NULL;
00553
00554 if (sx != NULL && sx->i >= 0 && sx->i < sx->Count)
00555 type = (sx->sxp + sx->i)->type;
00556 return type;
00557 }
00558
00559 const char * rpmsxContext(const rpmsx sx)
00560 {
00561 const char * context = NULL;
00562
00563 if (sx != NULL && sx->i >= 0 && sx->i < sx->Count)
00564 context = (sx->sxp + sx->i)->context;
00565 return context;
00566 }
00567
00568 regex_t * rpmsxRE(const rpmsx sx)
00569 {
00570 regex_t * preg = NULL;
00571
00572 if (sx != NULL && sx->i >= 0 && sx->i < sx->Count)
00573 preg = (sx->sxp + sx->i)->preg;
00574 return preg;
00575 }
00576
00577 mode_t rpmsxFMode(const rpmsx sx)
00578 {
00579 mode_t fmode = 0;
00580
00581 if (sx != NULL && sx->i >= 0 && sx->i < sx->Count)
00582 fmode = (sx->sxp + sx->i)->fmode;
00583 return fmode;
00584 }
00585
00586 int rpmsxFStem(const rpmsx sx)
00587 {
00588 int fstem = -1;
00589
00590 if (sx != NULL && sx->i >= 0 && sx->i < sx->Count)
00591 fstem = (sx->sxp + sx->i)->fstem;
00592 return fstem;
00593 }
00594
00595 int rpmsxNext( rpmsx sx)
00596
00597 {
00598 int i = -1;
00599
00600 if (sx != NULL) {
00601 if (sx->reverse != 0) {
00602 i = --sx->i;
00603 if (sx->i < 0) {
00604 sx->i = sx->Count;
00605 i = -1;
00606 }
00607 } else {
00608 i = ++sx->i;
00609 if (sx->i >= sx->Count) {
00610 sx->i = -1;
00611 i = -1;
00612 }
00613 }
00614
00615
00616 if (_rpmsx_debug < 0 && i != -1) {
00617 rpmsxp sxp = sx->sxp + i;
00618 fprintf(stderr, "*** sx %p\t%s[%d]\t%s\t%s\n", sx, "rpmsxNext", i, sxp->pattern, sxp->context);
00619
00620 }
00621
00622 }
00623
00624 return i;
00625 }
00626
00627 rpmsx rpmsxInit( rpmsx sx, int reverse)
00628
00629 {
00630 if (sx != NULL) {
00631 sx->reverse = reverse;
00632 sx->i = (sx->reverse ? sx->Count : -1);
00633 }
00634
00635 return sx;
00636
00637 }
00638
00639 const char * rpmsxFContext(rpmsx sx, const char * fn, mode_t fmode)
00640 {
00641 const char * fcontext = NULL;
00642 const char * myfn = fn;
00643
00644 int fstem = rpmsxFind(sx, &myfn);
00645
00646 int i;
00647
00648 sx = rpmsxInit(sx, 1);
00649 if (sx != NULL)
00650 while ((i = rpmsxNext(sx)) >= 0) {
00651 regex_t * preg;
00652 mode_t sxfmode;
00653 int sxfstem;
00654 int ret;
00655
00656 sxfstem = rpmsxFStem(sx);
00657 if (sxfstem != -1 && sxfstem != fstem)
00658 continue;
00659
00660 sxfmode = rpmsxFMode(sx);
00661 if (sxfmode && (fmode & S_IFMT) != sxfmode)
00662 continue;
00663
00664 preg = rpmsxRE(sx);
00665 if (preg == NULL)
00666 continue;
00667
00668 ret = regexec(preg, (sxfstem == -1 ? fn : myfn), 0, NULL, 0);
00669 switch (ret) {
00670 case REG_NOMATCH:
00671 continue;
00672 break;
00673 case 0:
00674 fcontext = rpmsxContext(sx);
00675 break;
00676 default:
00677 { static char errbuf[BUFSIZ + 1];
00678 (void) regerror(ret, preg, errbuf, sizeof(errbuf)-1);
00679
00680 errbuf[sizeof(errbuf)-1] = '\0';
00681 fprintf(stderr, "unable to match %s against %s: %s\n",
00682 fn, rpmsxPattern(sx), errbuf);
00683
00684 } break;
00685 }
00686 break;
00687 }
00688
00689 return fcontext;
00690 }