static int process_file(const char *path, const char *file, void *arg) { struct pfdata *pfd = (struct pfdata *) arg; int ret = 0, path_len, file_len, cur_inst = 0, fd = -1, substr_cnt, buf_size = 0, buf_used = 0, ofs = 0, buf_inc = 4096; char *whole_path = NULL, *buf = NULL; SEXP_t *next_inst = NULL; struct stat st; if (file == NULL) goto cleanup; path_len = strlen(path); file_len = strlen(file); whole_path = oscap_alloc(path_len + file_len + 2); memcpy(whole_path, path, path_len); if (whole_path[path_len - 1] != FILE_SEPARATOR) { whole_path[path_len] = FILE_SEPARATOR; ++path_len; } memcpy(whole_path + path_len, file, file_len + 1); /* * If stat() fails, don't report an error and just skip the file. * This is an expected situation, because the fts_*() functions * are called with the 'FTS_PHYSICAL' option. Normally, stumbling * upon a symlink without a target would cause fts_read() to return * the 'FTS_SLNONE' flag, but the 'FTS_PHYSICAL' option causes it * to return 'FTS_SL' and the presence of a valid target has to * be determined with stat(). */ if (stat(whole_path, &st) == -1) goto cleanup; if (!S_ISREG(st.st_mode)) goto cleanup; fd = open(whole_path, O_RDONLY); if (fd == -1) { SEXP_t *msg; msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, "open(): '%s' %s.", whole_path, strerror(errno)); probe_cobj_add_msg(probe_ctx_getresult(pfd->ctx), msg); SEXP_free(msg); probe_cobj_set_flag(probe_ctx_getresult(pfd->ctx), SYSCHAR_FLAG_ERROR); ret = -1; goto cleanup; } do { buf_size += buf_inc; buf = oscap_realloc(buf, buf_size); ret = read(fd, buf + buf_used, buf_inc); if (ret == -1) { SEXP_t *msg; msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, "read(): '%s' %s.", whole_path, strerror(errno)); probe_cobj_add_msg(probe_ctx_getresult(pfd->ctx), msg); SEXP_free(msg); probe_cobj_set_flag(probe_ctx_getresult(pfd->ctx), SYSCHAR_FLAG_ERROR); ret = -2; goto cleanup; } buf_used += ret; } while (ret == buf_inc); if (buf_used == buf_size) buf = realloc(buf, ++buf_size); buf[buf_used++] = '\0'; do { char **substrs; int want_instance; next_inst = SEXP_number_newi_32(cur_inst + 1); if (probe_entobj_cmp(pfd->instance_ent, next_inst) == OVAL_RESULT_TRUE) want_instance = 1; else want_instance = 0; SEXP_free(next_inst); substr_cnt = get_substrings(buf, &ofs, pfd->compiled_regex, want_instance, &substrs); if (substr_cnt > 0) { ++cur_inst; if (want_instance) { int k; SEXP_t *item; item = create_item(path, file, pfd->pattern, cur_inst, substrs, substr_cnt); probe_item_collect(pfd->ctx, item); for (k = 0; k < substr_cnt; ++k) oscap_free(substrs[k]); oscap_free(substrs); } } } while (substr_cnt > 0 && ofs < buf_used); cleanup: if (fd != -1) close(fd); oscap_free(buf); if (whole_path != NULL) oscap_free(whole_path); return ret; }
static int process_file(const char *prefix, const char *path, const char *filename, void *arg, oval_schema_version_t over) { struct pfdata *pfd = (struct pfdata *) arg; int ret = 0, path_len, filename_len; char *whole_path = NULL, *whole_path_with_prefix = NULL; FILE *fp = NULL; struct stat st; // todo: move to probe_main()? int erroffset = -1; pcre *re = NULL; const char *error; re = pcre_compile(pfd->pattern, PCRE_UTF8, &error, &erroffset, NULL); if (re == NULL) { return -1; } if (filename == NULL) goto cleanup; path_len = strlen(path); filename_len = strlen(filename); whole_path = malloc(path_len + filename_len + 2); memcpy(whole_path, path, path_len); if (whole_path[path_len - 1] != FILE_SEPARATOR) { whole_path[path_len] = FILE_SEPARATOR; ++path_len; } memcpy(whole_path + path_len, filename, filename_len + 1); /* * If stat() fails, don't report an error and just skip the file. * This is an expected situation, because the fts_*() functions * are called with the 'FTS_PHYSICAL' option. Normally, stumbling * upon a symlink without a target would cause fts_read() to return * the 'FTS_SLNONE' flag, but the 'FTS_PHYSICAL' option causes it * to return 'FTS_SL' and the presence of a valid target has to * be determined with stat(). */ whole_path_with_prefix = oscap_path_join(prefix, whole_path); if (stat(whole_path_with_prefix, &st) == -1) goto cleanup; if (!S_ISREG(st.st_mode)) goto cleanup; fp = fopen(whole_path_with_prefix, "rb"); if (fp == NULL) { ret = -2; goto cleanup; } int cur_inst = 0; char line[4096]; while (fgets(line, sizeof(line), fp) != NULL) { char **substrs; int substr_cnt; substr_cnt = get_substrings(line, re, 1, &substrs); if (substr_cnt > 0) { int k; SEXP_t *item; ++cur_inst; item = create_item(path, filename, pfd->pattern, cur_inst, substrs, substr_cnt, over); probe_item_collect(pfd->ctx, item); for (k = 0; k < substr_cnt; ++k) free(substrs[k]); free(substrs); } } cleanup: if (fp != NULL) fclose(fp); if (whole_path != NULL) free(whole_path); if (re != NULL) pcre_free(re); free(whole_path_with_prefix); return ret; }