static PromiseResult FindFilePromiserObjects(EvalContext *ctx, const Promise *pp) { char *val = PromiseGetConstraintAsRval(pp, "pathtype", RVAL_TYPE_SCALAR); int literal = (PromiseGetConstraintAsBoolean(ctx, "copy_from", pp)) || ((val != NULL) && (strcmp(val, "literal") == 0)); /* Check if we are searching over a regular expression */ PromiseResult result = PROMISE_RESULT_SKIPPED; if (literal) { // Prime the promiser temporarily, may override later result = PromiseResultUpdate(result, VerifyFilePromise(ctx, pp->promiser, pp)); } else // Default is to expand regex paths { result = PromiseResultUpdate(result, LocateFilePromiserGroup(ctx, pp->promiser, pp, VerifyFilePromise)); } return result; }
static PromiseResult FindFilePromiserObjects(EvalContext *ctx, Promise *pp) { char *val = ConstraintGetRvalValue(ctx, "pathtype", pp, RVAL_TYPE_SCALAR); int literal = (PromiseGetConstraintAsBoolean(ctx, "copy_from", pp)) || ((val != NULL) && (strcmp(val, "literal") == 0)); /* Check if we are searching over a regular expression */ PromiseResult result = PROMISE_RESULT_NOOP; if (literal) { // Prime the promiser temporarily, may override later EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", pp->promiser, DATA_TYPE_STRING); result = PromiseResultUpdate(result, VerifyFilePromise(ctx, pp->promiser, pp)); } else // Default is to expand regex paths { result = PromiseResultUpdate(result, LocateFilePromiserGroup(ctx, pp->promiser, pp, VerifyFilePromise)); } return result; }
void LocateFilePromiserGroup(EvalContext *ctx, char *wildpath, Promise *pp, void (*fnptr) (EvalContext *ctx, char *path, Promise *ptr)) { Item *path, *ip, *remainder = NULL; char pbuffer[CF_BUFSIZE]; struct stat statbuf; int count = 0, lastnode = false, expandregex = false; uid_t agentuid = getuid(); int create = PromiseGetConstraintAsBoolean(ctx, "create", pp); char *pathtype = ConstraintGetRvalValue(ctx, "pathtype", pp, RVAL_TYPE_SCALAR); /* Do a search for promiser objects matching wildpath */ if ((!IsPathRegex(wildpath)) || (pathtype && (strcmp(pathtype, "literal") == 0))) { Log(LOG_LEVEL_VERBOSE, "Using literal pathtype for '%s'", wildpath); (*fnptr) (ctx, wildpath, pp); return; } else { Log(LOG_LEVEL_VERBOSE, "Using regex pathtype for '%s' (see pathtype)", wildpath); } pbuffer[0] = '\0'; path = SplitString(wildpath, '/'); // require forward slash in regex on all platforms for (ip = path; ip != NULL; ip = ip->next) { if ((ip->name == NULL) || (strlen(ip->name) == 0)) { continue; } if (ip->next == NULL) { lastnode = true; } /* No need to chdir as in recursive descent, since we know about the path here */ if (IsRegex(ip->name)) { remainder = ip->next; expandregex = true; break; } else { expandregex = false; } if (!JoinPath(pbuffer, ip->name)) { Log(LOG_LEVEL_ERR, "Buffer has limited size in LocateFilePromiserGroup"); return; } if (stat(pbuffer, &statbuf) != -1) { if ((S_ISDIR(statbuf.st_mode)) && ((statbuf.st_uid) != agentuid) && ((statbuf.st_uid) != 0)) { Log(LOG_LEVEL_INFO, "Directory '%s' in search path '%s' is controlled by another user (uid %ju) - trusting its content is potentially risky (possible race condition)", pbuffer, wildpath, (uintmax_t)statbuf.st_uid); PromiseRef(LOG_LEVEL_INFO, pp); } } } if (expandregex) /* Expand one regex link and hand down */ { char nextbuffer[CF_BUFSIZE], nextbufferOrig[CF_BUFSIZE], regex[CF_BUFSIZE]; const struct dirent *dirp; Dir *dirh; memset(regex, 0, CF_BUFSIZE); strncpy(regex, ip->name, CF_BUFSIZE - 1); if ((dirh = DirOpen(pbuffer)) == NULL) { // Could be a dummy directory to be created so this is not an error. Log(LOG_LEVEL_VERBOSE, "Using best-effort expanded (but non-existent) file base path '%s'", wildpath); (*fnptr) (ctx, wildpath, pp); DeleteItemList(path); return; } else { count = 0; for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (!ConsiderLocalFile(dirp->d_name, pbuffer)) { continue; } if ((!lastnode) && (!S_ISDIR(statbuf.st_mode))) { Log(LOG_LEVEL_DEBUG, "Skipping non-directory '%s'", dirp->d_name); continue; } if (FullTextMatch(regex, dirp->d_name)) { Log(LOG_LEVEL_DEBUG, "Link '%s' matched regex '%s'", dirp->d_name, regex); } else { continue; } count++; strncpy(nextbuffer, pbuffer, CF_BUFSIZE - 1); AddSlash(nextbuffer); strcat(nextbuffer, dirp->d_name); for (ip = remainder; ip != NULL; ip = ip->next) { AddSlash(nextbuffer); strcat(nextbuffer, ip->name); } /* The next level might still contain regexs, so go again as long as expansion is not nullpotent */ if ((!lastnode) && (strcmp(nextbuffer, wildpath) != 0)) { LocateFilePromiserGroup(ctx, nextbuffer, pp, fnptr); } else { Promise *pcopy; Log(LOG_LEVEL_VERBOSE, "Using expanded file base path '%s'", nextbuffer); /* Now need to recompute any back references to get the complete path */ snprintf(nextbufferOrig, sizeof(nextbufferOrig), "%s", nextbuffer); MapNameForward(nextbuffer); if (!FullTextMatch(pp->promiser, nextbuffer)) { Log(LOG_LEVEL_DEBUG, "Error recomputing references for '%s' in '%s'", pp->promiser, nextbuffer); } /* If there were back references there could still be match.x vars to expand */ pcopy = ExpandDeRefPromise(ctx, ScopeGetCurrent()->scope, pp); (*fnptr) (ctx, nextbufferOrig, pcopy); PromiseDestroy(pcopy); } } DirClose(dirh); } } else { Log(LOG_LEVEL_VERBOSE, "Using file base path '%s'", pbuffer); (*fnptr) (ctx, pbuffer, pp); } if (count == 0) { Log(LOG_LEVEL_VERBOSE, "No promiser file objects matched as regular expression '%s'", wildpath); if (create) { (*fnptr)(ctx, pp->promiser, pp); } } DeleteItemList(path); }
static PromiseResult FindStoragePromiserObjects(EvalContext *ctx, Promise *pp) { /* Check if we are searching over a regular expression */ return LocateFilePromiserGroup(ctx, pp->promiser, pp, VerifyStoragePromise); }
static void FindStoragePromiserObjects(EvalContext *ctx, Promise *pp, const ReportContext *report_context) { /* Check if we are searching over a regular expression */ LocateFilePromiserGroup(ctx, pp->promiser, pp, VerifyStoragePromise, report_context); }
static void VerifyOccurrencePromises(Promise *pp) { Attributes a = { {0} }; char name[CF_BUFSIZE]; enum representations rep_type; Rlist *contexts, *rp; a = GetOccurrenceAttributes(pp); if (a.rep_type) { rep_type = String2Representation(a.rep_type); } else { rep_type = cfk_url; } if (a.represents == NULL) { if (rep_type == cfk_literal) { CfOut(cf_error, "", " ! Occurrence of text information \"%s\" does not promise any topics to represent", pp->promiser); } else { CfOut(cf_error, "", " ! Occurrence or reference to information \"%s\" does not promise any topics to represent", pp->promiser); } return; } contexts = SplitContextExpression(pp->classes, pp); for (rp = contexts; rp != NULL; rp = rp->next) { CfOut(cf_verbose, "", " -> New occurrence promise for \"%s\" about context \"%s\"", pp->promiser, ScalarValue(rp)); switch (rep_type) { case cfk_file: if (a.web_root == NULL || a.path_root == NULL) { CfOut(cf_error, "", " !! File pattern but no complete url mapping path_root -> web_root"); return; } strncpy(name, a.path_root, CF_BUFSIZE - 1); if (!JoinPath(name, pp->promiser)) { CfOut(cf_error, "", " !! Unable to form pathname in search for local files"); return; } // FIXME - this should pass rp->item instead of pp->classes if we want to keep this LocateFilePromiserGroup(name, pp, VerifyOccurrenceGroup); break; default: AddOccurrence(&OCCURRENCES, pp->promiser, a.represents, rep_type, rp->item); break; } } DeleteRlist(contexts); }