1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-02-09 13:57:55 +03:00

Refactoring.

This commit is contained in:
Alasdair Kergon 2002-11-18 14:01:16 +00:00
parent 74b27447c1
commit d1d9800ef1
61 changed files with 1776 additions and 1074 deletions

View File

@ -4,27 +4,48 @@
* This file is released under the LGPL.
*/
#include "lib.h"
#include "metadata.h"
#include "activate.h"
#include "display.h"
#include "log.h"
#include "fs.h"
#include "lvm-string.h"
#include "pool.h"
#include "toolcontext.h"
#include "dev_manager.h"
/* FIXME Temporary */
#include "vgcache.h"
#include <limits.h>
#include <linux/kdev_t.h>
#include <fcntl.h>
#define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
static int _activation = 1;
void set_activation(int activation)
{
if (activation == _activation)
return;
_activation = activation;
if (_activation)
log_verbose("Activation enabled. Device-mapper kernel "
"driver will be used.");
else
log_verbose("Activation disabled. No device-mapper "
"interaction will be attempted.");
}
int activation()
{
return _activation;
}
int library_version(char *version, size_t size)
{
if (!activation())
return 0;
if (!dm_get_library_version(version, size))
return 0;
return 1;
@ -35,6 +56,9 @@ int driver_version(char *version, size_t size)
int r = 0;
struct dm_task *dmt;
if (!activation())
return 0;
log_very_verbose("Getting driver version");
if (!(dmt = dm_task_create(DM_DEVICE_VERSION))) {
stack;
@ -63,6 +87,9 @@ int lv_info(struct logical_volume *lv, struct dm_info *info)
int r;
struct dev_manager *dm;
if (!activation())
return 0;
if (!(dm = dev_manager_create(lv->vg->name))) {
stack;
return 0;
@ -83,6 +110,9 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
int r;
struct dev_manager *dm;
if (!activation())
return 0;
if (!(dm = dev_manager_create(lv->vg->name))) {
stack;
return 0;
@ -182,6 +212,9 @@ int lvs_in_vg_activated(struct volume_group *vg)
struct logical_volume *lv;
int count = 0;
if (!activation())
return 0;
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
count += (_lv_active(lv) == 1);
@ -196,6 +229,9 @@ int lvs_in_vg_opened(struct volume_group *vg)
struct logical_volume *lv;
int count = 0;
if (!activation())
return 0;
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
count += (_lv_open_count(lv) == 1);
@ -204,44 +240,21 @@ int lvs_in_vg_opened(struct volume_group *vg)
return count;
}
static struct logical_volume *_lv_from_lvid(struct cmd_context *cmd,
const char *lvid_s)
{
struct lv_list *lvl;
struct volume_group *vg;
union lvid *lvid;
lvid = (union lvid *) lvid_s;
log_very_verbose("Finding volume group for uuid %s", lvid_s);
if (!(vg = vg_read_by_vgid(cmd, lvid->id[0].uuid))) {
log_error("Volume group for uuid not found: %s", lvid_s);
return NULL;
}
log_verbose("Found volume group \"%s\"", vg->name);
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg->name);
return NULL;
}
if (!(lvl = find_lv_in_vg_by_lvid(vg, lvid))) {
log_very_verbose("Can't find logical volume id %s", lvid_s);
return NULL;
}
return lvl->lv;
}
/* These return success if the device is not active */
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
{
struct logical_volume *lv;
struct dm_info info;
if (!(lv = _lv_from_lvid(cmd, lvid_s)))
if (!activation())
return 1;
if (!(lv = lv_from_lvid(cmd, lvid_s)))
return 0;
if (!activation())
return 1;
if (test_mode()) {
_skip("Suspending '%s'.", lv->name);
return 0;
@ -263,7 +276,10 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
struct logical_volume *lv;
struct dm_info info;
if (!(lv = _lv_from_lvid(cmd, lvid_s)))
if (!activation())
return 1;
if (!(lv = lv_from_lvid(cmd, lvid_s)))
return 0;
if (test_mode()) {
@ -287,7 +303,10 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
struct logical_volume *lv;
struct dm_info info;
if (!(lv = _lv_from_lvid(cmd, lvid_s)))
if (!activation())
return 1;
if (!(lv = lv_from_lvid(cmd, lvid_s)))
return 0;
if (test_mode()) {
@ -311,7 +330,10 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
struct logical_volume *lv;
struct dm_info info;
if (!(lv = _lv_from_lvid(cmd, lvid_s)))
if (!activation())
return 1;
if (!(lv = lv_from_lvid(cmd, lvid_s)))
return 0;
if (test_mode()) {

View File

@ -7,8 +7,12 @@
#ifndef LVM_ACTIVATE_H
#define LVM_ACTIVATE_H
#include "metadata.h"
#include <libdevmapper.h>
void set_activation(int activation);
int activation();
int driver_version(char *version, size_t size);
int library_version(char *version, size_t size);

View File

@ -4,10 +4,10 @@
* This file is released under the LGPL.
*/
#include "lib.h"
#include "dev_manager.h"
#include "pool.h"
#include "hash.h"
#include "log.h"
#include "lvm-string.h"
#include "fs.h"
@ -162,7 +162,7 @@ static int _pre_list_add(struct pool *mem, struct list *pl, char *str)
* another hyphen. The top layer of any device has no layer
* name. eg, vg0-lvol0.
*/
static void _count_hyphens(const char *str, size_t * len, int *hyphens)
static void _count_hyphens(const char *str, size_t *len, int *hyphens)
{
const char *ptr;
@ -577,7 +577,7 @@ static int _resume(struct dev_layer *dl)
* Emit a target for a given segment.
* FIXME: tidy this function.
*/
static int _emit_target(struct dm_task *dmt, struct stripe_segment *seg)
static int _emit_target(struct dm_task *dmt, struct lv_segment *seg)
{
char params[1024];
uint64_t esize = seg->lv->vg->extent_size;
@ -638,11 +638,11 @@ static int _populate_vanilla(struct dev_manager *dm,
struct dm_task *dmt, struct dev_layer *dl)
{
struct list *segh;
struct stripe_segment *seg;
struct lv_segment *seg;
struct logical_volume *lv = dl->lv;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct stripe_segment);
seg = list_item(segh, struct lv_segment);
if (!_emit_target(dmt, seg)) {
log_error("Unable to build table for '%s'", lv->name);
return 0;

View File

@ -4,20 +4,16 @@
* This file is released under the LGPL.
*/
#include "lib.h"
#include "fs.h"
#include "log.h"
#include "toolcontext.h"
#include "lvm-string.h"
#include "lvm-file.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <libdevmapper.h>
static int _mk_dir(struct volume_group *vg)

475
lib/commands/toolcontext.c Normal file
View File

@ -0,0 +1,475 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*
*/
#include "lib.h"
#include "toolcontext.h"
#include "pool.h"
#include "metadata.h"
#include "defaults.h"
#include "lvm-string.h"
#include "activate.h"
#include "filter.h"
#include "filter-composite.h"
#include "filter-persistent.h"
#include "filter-regex.h"
#include "label.h"
#include "lvm-file.h"
#include "format-text.h"
#include "sharedlib.h"
#ifdef LVM1_INTERNAL
#include "format1.h"
#endif
#include <locale.h>
#include <sys/stat.h>
#include <syslog.h>
#include <dlfcn.h>
#include <time.h>
static FILE *_log;
static int _get_env_vars(struct cmd_context *cmd)
{
const char *e;
/* Set to "" to avoid using any system directory */
if ((e = getenv("LVM_SYSTEM_DIR"))) {
if (lvm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir),
"%s", e) < 0) {
log_error("LVM_SYSTEM_DIR environment variable "
"is too long.");
return 0;
}
}
return 1;
}
static void _init_logging(struct cmd_context *cmd)
{
char *open_mode = "a";
time_t t;
const char *log_file;
/* Syslog */
cmd->default_settings.syslog =
find_config_int(cmd->cf->root, "log/syslog", '/', DEFAULT_SYSLOG);
if (cmd->default_settings.syslog != 1)
fin_syslog();
if (cmd->default_settings.syslog > 1)
init_syslog(cmd->default_settings.syslog);
/* Debug level for log file output */
cmd->default_settings.debug =
find_config_int(cmd->cf->root, "log/level", '/', DEFAULT_LOGLEVEL);
init_debug(cmd->default_settings.debug);
/* Verbose level for tty output */
cmd->default_settings.verbose =
find_config_int(cmd->cf->root, "log/verbose", '/', DEFAULT_VERBOSE);
init_verbose(cmd->default_settings.verbose);
/* Log message formatting */
init_indent(find_config_int(cmd->cf->root, "log/indent", '/',
DEFAULT_INDENT));
cmd->default_settings.msg_prefix = find_config_str(cmd->cf->root,
"log/prefix", '/',
DEFAULT_MSG_PREFIX);
init_msg_prefix(cmd->default_settings.msg_prefix);
cmd->default_settings.cmd_name = find_config_int(cmd->cf->root,
"log/command_names",
'/', DEFAULT_CMD_NAME);
init_cmd_name(cmd->default_settings.cmd_name);
/* Test mode */
cmd->default_settings.test =
find_config_int(cmd->cf->root, "global/test", '/', 0);
/* Settings for logging to file */
if (find_config_int(cmd->cf->root, "log/overwrite", '/',
DEFAULT_OVERWRITE))
open_mode = "w";
log_file = find_config_str(cmd->cf->root, "log/file", '/', 0);
if (log_file) {
/* set up the logging */
if (!(_log = fopen(log_file, open_mode)))
log_error("Couldn't open log file %s", log_file);
else
init_log(_log);
}
t = time(NULL);
log_verbose("Logging initialised at %s", ctime(&t));
/* Tell device-mapper about our logging */
dm_log_init(print_log);
}
static int _process_config(struct cmd_context *cmd)
{
mode_t old_umask;
/* umask */
cmd->default_settings.umask = find_config_int(cmd->cf->root,
"global/umask", '/',
DEFAULT_UMASK);
if ((old_umask = umask((mode_t) cmd->default_settings.umask)) !=
(mode_t) cmd->default_settings.umask)
log_verbose("Set umask to %04o", cmd->default_settings.umask);
/* dev dir */
if (lvm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
find_config_str(cmd->cf->root, "devices/dir",
'/', DEFAULT_DEV_DIR)) < 0) {
log_error("Device directory given in config file too long");
return 0;
}
dm_set_dev_dir(cmd->dev_dir);
/* proc dir */
if (lvm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
find_config_str(cmd->cf->root, "global/proc",
'/', DEFAULT_PROC_DIR)) < 0) {
log_error("Device directory given in config file too long");
return 0;
}
/* activation? */
cmd->default_settings.activation = find_config_int(cmd->cf->root,
"global/activation",
'/',
DEFAULT_ACTIVATION);
set_activation(cmd->default_settings.activation);
return 1;
}
/* Find and read config file */
static int _init_config(struct cmd_context *cmd)
{
struct stat info;
char config_file[PATH_MAX] = "";
if (!(cmd->cf = create_config_tree())) {
stack;
return 0;
}
/* No config file if LVM_SYSTEM_DIR is empty */
if (!*cmd->sys_dir)
return 1;
if (lvm_snprintf(config_file, sizeof(config_file),
"%s/lvm.conf", cmd->sys_dir) < 0) {
log_error("LVM_SYSTEM_DIR was too long");
destroy_config_tree(cmd->cf);
return 0;
}
/* Is there a config file? */
if (stat(config_file, &info) == -1) {
if (errno == ENOENT)
return 1;
log_sys_error("stat", config_file);
destroy_config_tree(cmd->cf);
return 0;
}
if (!read_config_file(cmd->cf, config_file)) {
log_error("Failed to load config file %s", config_file);
destroy_config_tree(cmd->cf);
return 0;
}
return 1;
}
static int _init_dev_cache(struct cmd_context *cmd)
{
struct config_node *cn;
struct config_value *cv;
if (!dev_cache_init()) {
stack;
return 0;
}
if (!(cn = find_config_node(cmd->cf->root, "devices/scan", '/'))) {
if (!dev_cache_add_dir("/dev")) {
log_error("Failed to add /dev to internal "
"device cache");
return 0;
}
log_verbose("device/scan not in config file: "
"Defaulting to /dev");
return 1;
}
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != CFG_STRING) {
log_error("Invalid string in config file: "
"devices/scan");
return 0;
}
if (!dev_cache_add_dir(cv->v.str)) {
log_error("Failed to add %s to internal device cache",
cv->v.str);
return 0;
}
}
return 1;
}
static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
{
struct config_node *cn;
struct dev_filter *f1, *f2, *f3;
if (!(f2 = lvm_type_filter_create(cmd->proc_dir)))
return NULL;
if (!(cn = find_config_node(cmd->cf->root, "devices/filter", '/'))) {
log_debug("devices/filter not found in config file: no regex "
"filter installed");
return f2;
}
if (!(f1 = regex_filter_create(cn->v))) {
log_error("Failed to create regex device filter");
return f2;
}
if (!(f3 = composite_filter_create(2, f1, f2))) {
log_error("Failed to create composite device filter");
return f2;
}
return f3;
}
static int _init_filters(struct cmd_context *cmd)
{
const char *lvm_cache;
struct dev_filter *f3, *f4;
struct stat st;
char cache_file[PATH_MAX];
cmd->dump_filter = 0;
if (!(f3 = _init_filter_components(cmd)))
return 0;
if (lvm_snprintf(cache_file, sizeof(cache_file),
"%s/.cache", cmd->sys_dir) < 0) {
log_error("Persistent cache filename too long ('%s/.cache').",
cmd->sys_dir);
return 0;
}
lvm_cache =
find_config_str(cmd->cf->root, "devices/cache", '/', cache_file);
if (!(f4 = persistent_filter_create(f3, lvm_cache))) {
log_error("Failed to create persistent device filter");
return 0;
}
/* Should we ever dump persistent filter state? */
if (find_config_int(cmd->cf->root, "devices/write_cache_state", '/', 1))
cmd->dump_filter = 1;
if (!*cmd->sys_dir)
cmd->dump_filter = 0;
if (!stat(lvm_cache, &st) && !persistent_filter_load(f4))
log_verbose("Failed to load existing device cache from %s",
lvm_cache);
cmd->filter = f4;
return 1;
}
static int _init_formats(struct cmd_context *cmd)
{
const char *format;
struct format_type *fmt;
struct list *fmth;
struct config_node *cn;
struct config_value *cv;
struct format_type *(*init_format_fn) (struct cmd_context * cmd);
void *lib;
label_init();
#ifdef LVM1_INTERNAL
if (!(fmt = init_lvm1_format(cmd)))
return 0;
fmt->library = NULL;
list_add(&cmd->formats, &fmt->list);
#endif
/* Load any formats in shared libs */
if ((cn = find_config_node(cmd->cf->root, "global/format_libraries",
'/'))) {
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != CFG_STRING) {
log_error("Invalid string in config file: "
"global/format_libraries");
return 0;
}
if (!(lib = load_shared_library(cmd->cf, cv->v.str,
"format"))) {
stack;
return 0;
}
if (!(init_format_fn = dlsym(lib, "init_format"))) {
log_error("Shared library %s does not contain "
"format functions", cv->v.str);
dlclose(lib);
return 0;
}
if (!(fmt = init_format_fn(cmd)))
return 0;
fmt->library = lib;
list_add(&cmd->formats, &fmt->list);
}
}
if (!(fmt = create_text_format(cmd)))
return 0;
fmt->library = NULL;
list_add(&cmd->formats, &fmt->list);
cmd->fmt_backup = fmt;
format = find_config_str(cmd->cf->root, "global/format", '/',
DEFAULT_FORMAT);
list_iterate(fmth, &cmd->formats) {
fmt = list_item(fmth, struct format_type);
if (!strcasecmp(fmt->name, format) ||
(fmt->alias && !strcasecmp(fmt->alias, format))) {
cmd->default_settings.fmt = fmt;
return 1;
}
}
log_error("_init_formats: Default format (%s) not found", format);
return 0;
}
/* Entry point */
struct cmd_context *create_toolcontext(struct arg *the_args)
{
struct cmd_context *cmd;
if (!setlocale(LC_ALL, ""))
log_error("setlocale failed");
init_syslog(DEFAULT_LOG_FACILITY);
if (!(cmd = dbg_malloc(sizeof(*cmd)))) {
log_error("Failed to allocate command context");
return NULL;
}
memset(cmd, 0, sizeof(*cmd));
cmd->args = the_args;
list_init(&cmd->formats);
strcpy(cmd->sys_dir, DEFAULT_SYS_DIR);
if (!_get_env_vars(cmd))
goto error;
/* Create system directory if it doesn't already exist */
if (*cmd->sys_dir && !create_dir(cmd->sys_dir))
goto error;
if (!_init_config(cmd))
goto error;
_init_logging(cmd);
if (!_process_config(cmd))
goto error;
if (!_init_dev_cache(cmd))
goto error;
if (!_init_filters(cmd))
goto error;
if (!(cmd->mem = pool_create(4 * 1024))) {
log_error("Command memory pool creation failed");
return 0;
}
if (!_init_formats(cmd))
goto error;
cmd->current_settings = cmd->default_settings;
return cmd;
error:
dbg_free(cmd);
return NULL;
}
void destroy_formats(struct list *formats)
{
struct list *fmtl, *tmp;
struct format_type *fmt;
void *lib;
list_iterate_safe(fmtl, tmp, formats) {
fmt = list_item(fmtl, struct format_type);
list_del(&fmt->list);
lib = fmt->library;
fmt->ops->destroy(fmt);
if (lib)
dlclose(lib);
}
}
void destroy_toolcontext(struct cmd_context *cmd)
{
if (cmd->dump_filter)
persistent_filter_dump(cmd->filter);
cache_destroy();
label_exit();
destroy_formats(&cmd->formats);
cmd->filter->destroy(cmd->filter);
pool_destroy(cmd->mem);
dev_cache_exit();
destroy_config_tree(cmd->cf);
dbg_free(cmd);
dump_memory();
fin_log();
fin_syslog();
if (_log)
fclose(_log);
}

View File

@ -13,25 +13,57 @@
#include "pool.h"
#include "metadata.h"
#include <stdio.h>
#include <limits.h>
/*
* Config options that can be changed while commands are processed
*/
struct config_info {
int debug;
int verbose;
int test;
int syslog;
int activation;
const char *msg_prefix;
int cmd_name; /* Show command name? */
int archive; /* should we archive ? */
int backup; /* should we backup ? */
struct format_type *fmt;
mode_t umask;
};
/* FIXME Split into tool & library contexts */
/* command-instance-related variables needed by library */
struct cmd_context {
/* format handler allocates all objects from here */
struct pool *mem;
struct format_type *fmt; /* Current format to use by default */
struct format_type *fmt_backup; /* Format to use for backups */
/* FIXME Move into dynamic list */
struct format_type *fmt1; /* Format1 */
struct format_type *fmtt; /* Format_text */
struct list formats; /* Available formats */
char *cmd_line;
char *dev_dir;
struct dev_filter *filter;
struct config_file *cf;
struct command *command;
struct uuid_map *um;
struct arg *args;
struct dev_filter *filter;
int dump_filter; /* Dump filter when exiting? */
struct config_tree *cf;
struct config_info default_settings;
struct config_info current_settings;
char sys_dir[PATH_MAX];
char dev_dir[PATH_MAX];
char proc_dir[PATH_MAX];
};
struct cmd_context *create_toolcontext(struct arg *the_args);
void destroy_toolcontext(struct cmd_context *cmd);
#endif

View File

@ -4,18 +4,18 @@
* This file is released under the LGPL.
*/
#include <sys/types.h>
#include "lib.h"
#include "config.h"
#include "crc.h"
#include "pool.h"
#include "device.h"
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "pool.h"
#include "log.h"
#include <asm/page.h>
enum {
TOK_INT,
@ -32,10 +32,10 @@ enum {
};
struct parser {
const char *fb, *fe; /* file limits */
char *fb, *fe; /* file limits */
int t; /* token limits and type */
const char *tb, *te;
char *tb, *te;
int fd; /* descriptor for file being parsed */
int line; /* line number we are on */
@ -44,8 +44,10 @@ struct parser {
};
struct cs {
struct config_file cf;
struct config_tree cf;
struct pool *mem;
time_t timestamp;
char *filename;
};
static void _get_token(struct parser *p);
@ -81,7 +83,7 @@ static int _tok_match(const char *str, const char *b, const char *e)
/*
* public interface
*/
struct config_file *create_config_file(void)
struct config_tree *create_config_tree(void)
{
struct cs *c;
struct pool *mem = pool_create(10 * 1024);
@ -99,20 +101,24 @@ struct config_file *create_config_file(void)
c->mem = mem;
c->cf.root = (struct config_node *) NULL;
c->timestamp = 0;
c->filename = NULL;
return &c->cf;
}
void destroy_config_file(struct config_file *cf)
void destroy_config_tree(struct config_tree *cf)
{
pool_destroy(((struct cs *) cf)->mem);
}
int read_config(struct config_file *cf, const char *file)
int read_config_fd(struct config_tree *cf, int fd, const char *file,
off_t offset, uint32_t size, off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn, uint32_t checksum)
{
struct cs *c = (struct cs *) cf;
struct parser *p;
struct stat info;
int r = 1, fd;
off_t mmap_offset;
int r = 0;
if (!(p = pool_alloc(c->mem, sizeof(*p)))) {
stack;
@ -120,12 +126,93 @@ int read_config(struct config_file *cf, const char *file)
}
p->mem = c->mem;
/* memory map the file */
if (stat(file, &info) || S_ISDIR(info.st_mode)) {
if (size2) {
/* FIXME Attempt adjacent mmaps MAP_FIXED into malloced space
* one PAGE_SIZE larger than required...
*/
if (!(p->fb = dbg_malloc(size + size2))) {
stack;
return 0;
}
if (lseek(fd, offset, SEEK_SET) < 0) {
log_sys_error("lseek", file);
goto out;
}
if (raw_read(fd, p->fb, size) != size) {
log_error("Circular read from %s failed", file);
goto out;
}
if (lseek(fd, offset2, SEEK_SET) < 0) {
log_sys_error("lseek", file);
goto out;
}
if (raw_read(fd, p->fb + size, size2) != size2) {
log_error("Circular read from %s failed", file);
goto out;
}
} else {
mmap_offset = offset % PAGE_SIZE;
/* memory map the file */
p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
MAP_PRIVATE, fd, offset - mmap_offset);
if (p->fb == (caddr_t) (-1)) {
log_sys_error("mmap", file);
goto out;
}
p->fb = p->fb + mmap_offset;
}
if (checksum_fn && checksum !=
(checksum_fn(checksum_fn(INITIAL_CRC, p->fb, size),
p->fb + size, size2))) {
log_error("%s: Checksum error", file);
goto out;
}
p->fe = p->fb + size + size2;
/* parse */
p->tb = p->te = p->fb;
p->line = 1;
_get_token(p);
if (!(cf->root = _file(p))) {
stack;
goto out;
}
r = 1;
out:
if (size2)
dbg_free(p->fb);
else {
/* unmap the file */
if (munmap((char *) (p->fb - mmap_offset), size)) {
log_sys_error("munmap", file);
r = 0;
}
}
return r;
}
int read_config_file(struct config_tree *cf, const char *file)
{
struct cs *c = (struct cs *) cf;
struct stat info;
int r = 1, fd;
if (stat(file, &info)) {
log_sys_error("stat", file);
return 0;
}
if (!S_ISREG(info.st_mode)) {
log_error("%s is not a regular file", file);
return 0;
}
if (info.st_size == 0) {
log_verbose("%s is empty", file);
return 1;
@ -136,34 +223,79 @@ int read_config(struct config_file *cf, const char *file)
return 0;
}
p->fb = mmap((caddr_t) 0, info.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (p->fb == (caddr_t) (-1)) {
log_sys_error("mmap", file);
close(fd);
return 0;
}
p->fe = p->fb + info.st_size;
/* parse */
p->tb = p->te = p->fb;
p->line = 1;
_get_token(p);
if (!(cf->root = _file(p))) {
stack;
r = 0;
}
/* unmap the file */
if (munmap((char *) p->fb, info.st_size)) {
log_sys_error("munmap", file);
r = 0;
}
r = read_config_fd(cf, fd, file, 0, info.st_size, 0, 0,
(checksum_fn_t) NULL, 0);
close(fd);
c->timestamp = info.st_mtime;
c->filename = pool_strdup(c->mem, file);
return r;
}
static void _write_value(FILE * fp, struct config_value *v)
/*
* Returns 1 if config file reloaded
*/
int reload_config_file(struct config_tree **cf)
{
struct config_tree *new_cf;
struct cs *c = (struct cs *) *cf;
struct cs *new_cs;
struct stat info;
int r, fd;
if (stat(c->filename, &info) == -1) {
if (errno == ENOENT)
return 1;
log_sys_error("stat", c->filename);
log_error("Failed to reload configuration file");
return 0;
}
if (!S_ISREG(info.st_mode)) {
log_error("Configuration file %s is not a regular file",
c->filename);
return 0;
}
/* Unchanged? */
if (c->timestamp == info.st_mtime)
return 0;
log_verbose("Detected config file change: Reloading %s", c->filename);
if (info.st_size == 0) {
log_verbose("Config file reload: %s is empty", c->filename);
return 0;
}
if ((fd = open(c->filename, O_RDONLY)) < 0) {
log_sys_error("open", c->filename);
return 0;
}
if (!(new_cf = create_config_tree())) {
log_error("Allocation of new config_tree failed");
return 0;
}
r = read_config_fd(new_cf, fd, c->filename, 0, info.st_size, 0, 0,
(checksum_fn_t) NULL, 0);
close(fd);
if (r) {
new_cs = (struct cs *) new_cf;
new_cs->filename = pool_strdup(new_cs->mem, c->filename);
new_cs->timestamp = info.st_mtime;
destroy_config_tree(*cf);
*cf = new_cf;
}
return r;
}
static void _write_value(FILE *fp, struct config_value *v)
{
switch (v->type) {
case CFG_STRING:
@ -183,11 +315,12 @@ static void _write_value(FILE * fp, struct config_value *v)
break;
default:
log_err("Unknown value type");
log_error("_write_value: Unknown value type: %d", v->type);
}
}
static int _write_config(struct config_node *n, FILE * fp, int level)
static int _write_config(struct config_node *n, FILE *fp, int level)
{
char space[MAX_INDENT + 1];
int l = (level < MAX_INDENT) ? level : MAX_INDENT;
@ -230,7 +363,7 @@ static int _write_config(struct config_node *n, FILE * fp, int level)
return 1;
}
int write_config(struct config_file *cf, const char *file)
int write_config_file(struct config_tree *cf, const char *file)
{
int r = 1;
FILE *fp = fopen(file, "w");
@ -332,9 +465,8 @@ static struct config_value *_value(struct parser *p)
match(TOK_COMMA);
}
match(TOK_ARRAY_E);
/*
* Special case an empty array.
* Special case for an empty array.
*/
if (!h) {
if (!(h = _create_value(p)))
@ -342,6 +474,7 @@ static struct config_value *_value(struct parser *p)
h->type = CFG_EMPTY_ARRAY;
}
} else
h = _type(p);
@ -352,6 +485,7 @@ static struct config_value *_type(struct parser *p)
{
/* [0-9]+ | [0-9]*\.[0-9]* | ".*" */
struct config_value *v = _create_value(p);
if (!v)
return NULL;
@ -403,7 +537,7 @@ static void _get_token(struct parser *p)
{
p->tb = p->te;
_eat_space(p);
if (p->tb == p->fe) {
if (p->tb == p->fe || !*p->tb) {
p->t = TOK_EOF;
return;
}
@ -444,13 +578,14 @@ static void _get_token(struct parser *p)
case '"':
p->t = TOK_STRING;
p->te++;
while ((p->te != p->fe) && (*p->te != '"')) {
if ((*p->te == '\\') && (p->te + 1 != p->fe))
while ((p->te != p->fe) && (*p->te) && (*p->te != '"')) {
if ((*p->te == '\\') && (p->te + 1 != p->fe) &&
*(p->te + 1))
p->te++;
p->te++;
}
if (p->te != p->fe)
if ((p->te != p->fe) && (*p->te))
p->te++;
break;
@ -467,7 +602,7 @@ static void _get_token(struct parser *p)
case '8':
case '9':
p->te++;
while (p->te != p->fe) {
while ((p->te != p->fe) && (*p->te)) {
if (*p->te == '.') {
if (p->t == TOK_FLOAT)
break;
@ -480,7 +615,7 @@ static void _get_token(struct parser *p)
default:
p->t = TOK_IDENTIFIER;
while ((p->te != p->fe) && !isspace(*p->te) &&
while ((p->te != p->fe) && (*p->te) && !isspace(*p->te) &&
(*p->te != '#') && (*p->te != '='))
p->te++;
break;
@ -489,15 +624,15 @@ static void _get_token(struct parser *p)
static void _eat_space(struct parser *p)
{
while (p->tb != p->fe) {
while ((p->tb != p->fe) && (*p->tb)) {
if (*p->te == '#') {
while ((p->te != p->fe) && (*p->te != '\n'))
while ((p->te != p->fe) && (*p->te) && (*p->te != '\n'))
p->te++;
p->line++;
}
else if (isspace(*p->te)) {
while ((p->te != p->fe) && isspace(*p->te)) {
while ((p->te != p->fe) && (*p->te) && isspace(*p->te)) {
if (*p->te == '\n')
p->line++;
p->te++;
@ -674,7 +809,7 @@ int find_config_bool(struct config_node *cn, const char *path,
}
int get_config_uint32(struct config_node *cn, const char *path,
char sep, uint32_t * result)
char sep, uint32_t *result)
{
struct config_node *n;
@ -688,7 +823,7 @@ int get_config_uint32(struct config_node *cn, const char *path,
}
int get_config_uint64(struct config_node *cn, const char *path,
char sep, uint64_t * result)
char sep, uint64_t *result)
{
struct config_node *n;
@ -715,4 +850,3 @@ int get_config_str(struct config_node *cn, const char *path,
*result = n->v->v.str;
return 1;
}

View File

@ -8,39 +8,47 @@
#define _LVM_CONFIG_H
#include <inttypes.h>
#include <sys/types.h>
enum {
CFG_STRING,
CFG_FLOAT,
CFG_INT,
CFG_STRING,
CFG_FLOAT,
CFG_INT,
CFG_EMPTY_ARRAY
};
struct config_value {
int type;
union {
int i;
float r;
char *str;
} v;
struct config_value *next; /* for arrays */
int type;
union {
int i;
float r;
char *str;
} v;
struct config_value *next; /* for arrays */
};
struct config_node {
char *key;
struct config_node *sib, *child;
struct config_value *v;
char *key;
struct config_node *sib, *child;
struct config_value *v;
};
struct config_file {
struct config_node *root;
struct config_tree {
struct config_node *root;
};
struct config_file *create_config_file(void);
void destroy_config_file(struct config_file *cf);
struct config_tree *create_config_tree(void);
void destroy_config_tree(struct config_tree *cf);
int read_config(struct config_file *cf, const char *file);
int write_config(struct config_file *cf, const char *file);
typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size);
int read_config_fd(struct config_tree *cf, int fd, const char *file,
off_t offset, uint32_t size, off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn, uint32_t checksum);
int read_config_file(struct config_tree *cf, const char *file);
int write_config_file(struct config_tree *cf, const char *file);
int reload_config_file(struct config_tree **cf);
struct config_node *find_config_node(struct config_node *cn,
const char *path, char seperator);
@ -59,9 +67,7 @@ float find_config_float(struct config_node *cn, const char *path,
* off), (true, false).
*/
int find_config_bool(struct config_node *cn, const char *path,
char sep, int fail);
char sep, int fail);
int get_config_uint32(struct config_node *cn, const char *path,
char sep, uint32_t *result);
@ -73,4 +79,3 @@ int get_config_str(struct config_node *cn, const char *path,
char sep, char **result);
#endif

View File

@ -7,9 +7,6 @@
#ifndef _LVM_DEFAULTS_H
#define _LVM_DEFAULTS_H
#define DEFAULT_SYS_DIR "/etc/lvm"
#define DEFAULT_ARCHIVE_ENABLED 1
#define DEFAULT_BACKUP_ENABLED 1
@ -19,22 +16,42 @@
#define DEFAULT_ARCHIVE_DAYS 30
#define DEFAULT_ARCHIVE_NUMBER 10
#define DEFAULT_SYS_DIR "/etc/lvm"
#define DEFAULT_DEV_DIR "/dev"
#define DEFAULT_PROC_DIR "/proc"
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
#define DEFAULT_LOCKING_LIB "lvm2_locking.so"
#define DEFAULT_UMASK 0077
#define DEFAULT_FORMAT "lvm1"
#ifdef LVM1_SUPPORT
#define DEFAULT_FORMAT "lvm1"
#else
#define DEFAULT_FORMAT "lvm2"
#endif
#define DEFAULT_PVMETADATASIZE 255
#define DEFAULT_PVMETADATACOPIES 1
#define DEFAULT_LABELSECTOR 1
#define DEFAULT_MSG_PREFIX " "
#define DEFAULT_CMD_NAME 0
#define DEFAULT_OVERWRITE 0
#ifndef DEFAULT_LOG_FACILITY
#define DEFAULT_LOG_FACILITY LOG_USER
#endif
#define DEFAULT_SYSLOG 1
#define DEFAULT_VERBOSE 0
#define DEFAULT_LOGLEVEL 0
#define DEFAULT_INDENT 1
#define DEFAULT_ACTIVATION 1
#ifdef READLINE_SUPPORT
#define DEFAULT_MAX_HISTORY 100
#endif
#endif /* _LVM_DEFAULTS_H */
#endif /* _LVM_DEFAULTS_H */

View File

@ -4,15 +4,13 @@