mirror of
https://github.com/SELinuxProject/selinux
synced 2024-12-25 23:42:05 +00:00
308 lines
6.0 KiB
C
308 lines
6.0 KiB
C
/* Copyright (C) 2005 Red Hat, Inc. */
|
|
|
|
#include <stdio.h>
|
|
#include <stdio_ext.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <semanage/handle.h>
|
|
#include "parse_utils.h"
|
|
#include "debug.h"
|
|
|
|
int parse_init(semanage_handle_t * handle,
|
|
const char *filename, void *parse_arg, parse_info_t ** info)
|
|
{
|
|
|
|
parse_info_t *tmp_info = (parse_info_t *) malloc(sizeof(parse_info_t));
|
|
|
|
if (!tmp_info) {
|
|
ERR(handle,
|
|
"out of memory, could not allocate parse structure");
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
tmp_info->filename = filename;
|
|
tmp_info->file_stream = NULL;
|
|
tmp_info->working_copy = NULL;
|
|
tmp_info->orig_line = NULL;
|
|
tmp_info->ptr = NULL;
|
|
tmp_info->lineno = 0;
|
|
tmp_info->parse_arg = parse_arg;
|
|
|
|
*info = tmp_info;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
void parse_release(parse_info_t * info)
|
|
{
|
|
|
|
parse_close(info);
|
|
parse_dispose_line(info);
|
|
free(info);
|
|
}
|
|
|
|
int parse_open(semanage_handle_t * handle, parse_info_t * info)
|
|
{
|
|
|
|
info->file_stream = fopen(info->filename, "r");
|
|
if (!info->file_stream && (errno != ENOENT)) {
|
|
ERR(handle, "could not open file %s: %s",
|
|
info->filename, strerror(errno));
|
|
return STATUS_ERR;
|
|
}
|
|
if (info->file_stream)
|
|
__fsetlocking(info->file_stream, FSETLOCKING_BYCALLER);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
void parse_close(parse_info_t * info)
|
|
{
|
|
|
|
if (info->file_stream)
|
|
fclose(info->file_stream);
|
|
info->file_stream = NULL;
|
|
}
|
|
|
|
void parse_dispose_line(parse_info_t * info)
|
|
{
|
|
if (info->orig_line) {
|
|
free(info->orig_line);
|
|
info->orig_line = NULL;
|
|
}
|
|
|
|
if (info->working_copy) {
|
|
free(info->working_copy);
|
|
info->working_copy = NULL;
|
|
}
|
|
|
|
info->ptr = NULL;
|
|
}
|
|
|
|
int parse_skip_space(semanage_handle_t * handle, parse_info_t * info)
|
|
{
|
|
|
|
size_t buf_len = 0;
|
|
ssize_t len;
|
|
int lineno = info->lineno;
|
|
char *buffer = NULL;
|
|
char *ptr;
|
|
|
|
if (info->ptr) {
|
|
while (*(info->ptr) && isspace(*(info->ptr)))
|
|
info->ptr++;
|
|
|
|
if (*(info->ptr))
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
parse_dispose_line(info);
|
|
|
|
while (info->file_stream &&
|
|
((len = getline(&buffer, &buf_len, info->file_stream)) > 0)) {
|
|
|
|
lineno++;
|
|
|
|
/* Eat newline, preceding whitespace */
|
|
if (buffer[len - 1] == '\n')
|
|
buffer[len - 1] = '\0';
|
|
|
|
ptr = buffer;
|
|
while (*ptr && isspace(*ptr))
|
|
ptr++;
|
|
|
|
/* Skip comments and blank lines */
|
|
if ((*ptr) && *ptr != '#') {
|
|
char *tmp = strdup(buffer);
|
|
if (!tmp)
|
|
goto omem;
|
|
|
|
info->lineno = lineno;
|
|
info->working_copy = buffer;
|
|
info->orig_line = tmp;
|
|
info->ptr = ptr;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
free(buffer);
|
|
buffer = NULL;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
omem:
|
|
ERR(handle, "out of memory, could not allocate buffer");
|
|
free(buffer);
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
int parse_assert_noeof(semanage_handle_t * handle, parse_info_t * info)
|
|
{
|
|
|
|
if (!info->ptr) {
|
|
ERR(handle, "unexpected end of file (%s: %u)",
|
|
info->filename, info->lineno);
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
int parse_assert_space(semanage_handle_t * handle, parse_info_t * info)
|
|
{
|
|
|
|
if (parse_assert_noeof(handle, info) < 0)
|
|
return STATUS_ERR;
|
|
|
|
if (*(info->ptr) && !isspace(*(info->ptr))) {
|
|
ERR(handle, "missing whitespace (%s: %u):\n%s",
|
|
info->filename, info->lineno, info->orig_line);
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
if (parse_skip_space(handle, info) < 0)
|
|
return STATUS_ERR;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
int parse_assert_ch(semanage_handle_t * handle,
|
|
parse_info_t * info, const char ch)
|
|
{
|
|
|
|
if (parse_assert_noeof(handle, info) < 0)
|
|
return STATUS_ERR;
|
|
|
|
if (*(info->ptr) != ch) {
|
|
ERR(handle, "expected character \'%c\', but found \'%c\' "
|
|
"(%s: %u):\n%s", ch, *(info->ptr), info->filename,
|
|
info->lineno, info->orig_line);
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
info->ptr++;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
int parse_assert_str(semanage_handle_t * handle,
|
|
parse_info_t * info, const char *assert_str)
|
|
{
|
|
|
|
size_t len = strlen(assert_str);
|
|
|
|
if (parse_assert_noeof(handle, info) < 0)
|
|
return STATUS_ERR;
|
|
|
|
if (strncmp(info->ptr, assert_str, len)) {
|
|
ERR(handle, "experted string \"%s\", but found \"%s\" "
|
|
"(%s: %u):\n%s", assert_str, info->ptr,
|
|
info->filename, info->lineno, info->orig_line);
|
|
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
info->ptr += len;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
int parse_optional_ch(parse_info_t * info, const char ch)
|
|
{
|
|
|
|
if (!info->ptr)
|
|
return STATUS_NODATA;
|
|
if (*(info->ptr) != ch)
|
|
return STATUS_NODATA;
|
|
|
|
info->ptr++;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
int parse_optional_str(parse_info_t * info, const char *str)
|
|
{
|
|
size_t len = strlen(str);
|
|
|
|
if (strncmp(info->ptr, str, len))
|
|
return STATUS_NODATA;
|
|
|
|
info->ptr += len;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
int parse_fetch_int(semanage_handle_t * handle,
|
|
parse_info_t * info, int *num, char delim)
|
|
{
|
|
|
|
char *str = NULL;
|
|
char *test = NULL;
|
|
int value = 0;
|
|
|
|
if (parse_fetch_string(handle, info, &str, delim) < 0)
|
|
goto err;
|
|
|
|
if (!isdigit((int)*str)) {
|
|
ERR(handle, "expected a numeric value: (%s: %u)\n%s",
|
|
info->filename, info->lineno, info->orig_line);
|
|
goto err;
|
|
}
|
|
|
|
value = strtol(str, &test, 10);
|
|
if (*test != '\0') {
|
|
ERR(handle, "could not parse numeric value \"%s\": "
|
|
"(%s: %u)\n%s", str, info->filename,
|
|
info->lineno, info->orig_line);
|
|
goto err;
|
|
}
|
|
|
|
*num = value;
|
|
free(str);
|
|
return STATUS_SUCCESS;
|
|
|
|
err:
|
|
ERR(handle, "could not fetch numeric value");
|
|
free(str);
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
int parse_fetch_string(semanage_handle_t * handle,
|
|
parse_info_t * info, char **str, char delim)
|
|
{
|
|
|
|
char *start = info->ptr;
|
|
int len = 0;
|
|
char *tmp_str = NULL;
|
|
|
|
if (parse_assert_noeof(handle, info) < 0)
|
|
goto err;
|
|
|
|
while (*(info->ptr) && !isspace(*(info->ptr)) &&
|
|
(*(info->ptr) != delim)) {
|
|
info->ptr++;
|
|
len++;
|
|
}
|
|
|
|
if (len == 0) {
|
|
ERR(handle, "expected non-empty string, but did not "
|
|
"find one (%s: %u):\n%s", info->filename, info->lineno,
|
|
info->orig_line);
|
|
goto err;
|
|
}
|
|
|
|
tmp_str = (char *)malloc(len + 1);
|
|
if (!tmp_str) {
|
|
ERR(handle, "out of memory");
|
|
goto err;
|
|
}
|
|
|
|
strncpy(tmp_str, start, len);
|
|
*(tmp_str + len) = '\0';
|
|
*str = tmp_str;
|
|
return STATUS_SUCCESS;
|
|
|
|
err:
|
|
ERR(handle, "could not fetch string value");
|
|
return STATUS_ERR;
|
|
}
|