mirror of
https://github.com/SELinuxProject/selinux
synced 2025-01-15 01:40:53 +00:00
244 lines
5.4 KiB
C
244 lines
5.4 KiB
C
/* Copyright (C) 2005 Red Hat, Inc. */
|
|
|
|
/* Object: dbase_file_t (File)
|
|
* Extends: dbase_llist_t (Linked List)
|
|
* Implements: dbase_t (Database)
|
|
*/
|
|
|
|
struct dbase_file;
|
|
typedef struct dbase_file dbase_t;
|
|
#define DBASE_DEFINED
|
|
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdio_ext.h>
|
|
#include "debug.h"
|
|
#include "handle.h"
|
|
#include "parse_utils.h"
|
|
#include "database_file.h"
|
|
#include "database_llist.h"
|
|
#include "semanage_store.h"
|
|
|
|
/* FILE dbase */
|
|
struct dbase_file {
|
|
|
|
/* Parent object - must always be
|
|
* the first field - here we are using
|
|
* a linked list to store the records */
|
|
dbase_llist_t llist;
|
|
|
|
/* Backing file suffix */
|
|
const char *suffix;
|
|
|
|
/* FILE extension */
|
|
record_file_table_t *rftable;
|
|
};
|
|
|
|
static int construct_filename(semanage_handle_t * handle,
|
|
dbase_file_t * dbase, char **filename)
|
|
{
|
|
|
|
const char *path = (handle->is_in_transaction) ?
|
|
semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL) :
|
|
semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
|
|
|
|
size_t fname_length = strlen(path) + strlen(dbase->suffix) + 2;
|
|
|
|
char *fname = malloc(fname_length);
|
|
if (!fname) {
|
|
ERR(handle, "out of memory, could not construct filename");
|
|
return STATUS_ERR;
|
|
}
|
|
snprintf(fname, fname_length, "%s/%s", path, dbase->suffix);
|
|
|
|
*filename = fname;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static int dbase_file_cache(semanage_handle_t * handle, dbase_file_t * dbase)
|
|
{
|
|
|
|
record_table_t *rtable = dbase_llist_get_rtable(&dbase->llist);
|
|
record_file_table_t *rftable = dbase->rftable;
|
|
|
|
record_t *process_record = NULL;
|
|
int pstatus = STATUS_SUCCESS;
|
|
|
|
parse_info_t *parse_info = NULL;
|
|
char *fname = NULL;
|
|
|
|
/* Already cached */
|
|
if (!dbase_llist_needs_resync(handle, &dbase->llist))
|
|
return STATUS_SUCCESS;
|
|
|
|
/* Update cache serial */
|
|
dbase_llist_cache_init(&dbase->llist);
|
|
if (dbase_llist_set_serial(handle, &dbase->llist) < 0)
|
|
goto err;
|
|
|
|
if (construct_filename(handle, dbase, &fname) < 0)
|
|
goto err;
|
|
|
|
if (parse_init(handle, fname, NULL, &parse_info) < 0)
|
|
goto err;
|
|
|
|
if (parse_open(handle, parse_info) < 0)
|
|
goto err;
|
|
|
|
/* Main processing loop */
|
|
do {
|
|
|
|
/* Create record */
|
|
if (rtable->create(handle, &process_record) < 0)
|
|
goto err;
|
|
|
|
/* Parse record */
|
|
pstatus = rftable->parse(handle, parse_info, process_record);
|
|
|
|
/* Parse error */
|
|
if (pstatus < 0)
|
|
goto err;
|
|
|
|
/* End of file */
|
|
else if (pstatus == STATUS_NODATA)
|
|
break;
|
|
|
|
/* Prepend to cache */
|
|
if (dbase_llist_cache_prepend(handle, &dbase->llist,
|
|
process_record) < 0)
|
|
goto err;
|
|
|
|
rtable->free(process_record);
|
|
process_record = NULL;
|
|
|
|
} while (pstatus != STATUS_NODATA);
|
|
|
|
rtable->free(process_record);
|
|
parse_close(parse_info);
|
|
parse_release(parse_info);
|
|
free(fname);
|
|
return STATUS_SUCCESS;
|
|
|
|
err:
|
|
ERR(handle, "could not cache file database");
|
|
rtable->free(process_record);
|
|
if (parse_info) {
|
|
parse_close(parse_info);
|
|
parse_release(parse_info);
|
|
}
|
|
dbase_llist_drop_cache(&dbase->llist);
|
|
free(fname);
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
/* Flush database to file */
|
|
static int dbase_file_flush(semanage_handle_t * handle, dbase_file_t * dbase)
|
|
{
|
|
|
|
record_file_table_t *rftable = dbase->rftable;
|
|
|
|
cache_entry_t *ptr;
|
|
char *fname = NULL;
|
|
FILE *str = NULL;
|
|
|
|
if (!dbase_llist_is_modified(&dbase->llist))
|
|
return STATUS_SUCCESS;
|
|
|
|
if (construct_filename(handle, dbase, &fname) < 0)
|
|
goto err;
|
|
|
|
str = fopen(fname, "w");
|
|
if (!str) {
|
|
ERR(handle, "could not open %s for writing: %s",
|
|
fname, strerror(errno));
|
|
goto err;
|
|
}
|
|
__fsetlocking(str, FSETLOCKING_BYCALLER);
|
|
|
|
if (fprintf(str, "# This file is auto-generated by libsemanage\n"
|
|
"# Do not edit directly.\n\n") < 0) {
|
|
|
|
ERR(handle, "could not write file header for %s", fname);
|
|
goto err;
|
|
}
|
|
|
|
for (ptr = dbase->llist.cache_tail; ptr != NULL; ptr = ptr->prev) {
|
|
if (rftable->print(handle, ptr->data, str) < 0)
|
|
goto err;
|
|
}
|
|
|
|
dbase_llist_set_modified(&dbase->llist, 0);
|
|
fclose(str);
|
|
free(fname);
|
|
return STATUS_SUCCESS;
|
|
|
|
err:
|
|
if (str != NULL)
|
|
fclose(str);
|
|
|
|
ERR(handle, "could not flush database to file");
|
|
free(fname);
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
int dbase_file_init(semanage_handle_t * handle,
|
|
const char *suffix,
|
|
record_table_t * rtable,
|
|
record_file_table_t * rftable, dbase_file_t ** dbase)
|
|
{
|
|
|
|
dbase_file_t *tmp_dbase = (dbase_file_t *) malloc(sizeof(dbase_file_t));
|
|
|
|
if (!tmp_dbase)
|
|
goto omem;
|
|
|
|
tmp_dbase->suffix = suffix;
|
|
tmp_dbase->rftable = rftable;
|
|
dbase_llist_init(&tmp_dbase->llist, rtable, &SEMANAGE_FILE_DTABLE);
|
|
|
|
*dbase = tmp_dbase;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
omem:
|
|
ERR(handle, "out of memory, could not initialize file database");
|
|
free(tmp_dbase);
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
/* Release dbase resources */
|
|
void dbase_file_release(dbase_file_t * dbase)
|
|
{
|
|
|
|
dbase_llist_drop_cache(&dbase->llist);
|
|
free(dbase);
|
|
}
|
|
|
|
/* FILE dbase - method table implementation */
|
|
dbase_table_t SEMANAGE_FILE_DTABLE = {
|
|
|
|
/* Cache/Transactions */
|
|
.cache = dbase_file_cache,
|
|
.drop_cache = (void *)dbase_llist_drop_cache,
|
|
.flush = dbase_file_flush,
|
|
.is_modified = (void *)dbase_llist_is_modified,
|
|
|
|
/* Database API */
|
|
.iterate = (void *)dbase_llist_iterate,
|
|
.exists = (void *)dbase_llist_exists,
|
|
.list = (void *)dbase_llist_list,
|
|
.add = (void *)dbase_llist_add,
|
|
.set = (void *)dbase_llist_set,
|
|
.del = (void *)dbase_llist_del,
|
|
.clear = (void *)dbase_llist_clear,
|
|
.modify = (void *)dbase_llist_modify,
|
|
.query = (void *)dbase_llist_query,
|
|
.count = (void *)dbase_llist_count,
|
|
|
|
/* Polymorphism */
|
|
.get_rtable = (void *)dbase_llist_get_rtable
|
|
};
|