[Ocfs2-tools-devel] [PATCH 2/6] O2info: Build a main framework for o2info.
Sunil Mushran
sunil.mushran at oracle.com
Fri Apr 23 15:16:18 PDT 2010
sob
Tristan Ye wrote:
> This patch tries to build main framework with necessary *.h and *.c
> files being generated. it did the option parsing and initialization,
> and only works for --help and --version, more operations will be
> elaborated in later patches.
>
> To be more detail: all of o2info's operations will be linked to
> a task list, and executed one by one later.
>
> Workflow of adding a new operation task for o2info(such as --volinfo)
> will be like following:
>
> 1. Declare a new extern operation structure.
> extern struct o2info_operation volinfo_op;
>
> 2. Add a new option:
> static struct o2info_option volinfo_option = {
> .opt_option = {
> .name = "volinfo",
> .val = 'V',
> .has_arg = 0,
> .flag = NULL,
> },
> .opt_help =
> "-V|--volinfo",
> .opt_handler = NULL,
> .opt_op = &volinfo_op,
> .opt_private = NULL,
> };
>
> 3. Implement necessary utility func in utils.c.
>
> 4. Implement the real running codes for volinfo_op in operation.c.
>
> Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
> ---
> Makefile | 2 +-
> o2info/.gitignore | 6 +
> o2info/Makefile | 36 ++++
> o2info/o2info.c | 484 +++++++++++++++++++++++++++++++++++++++++++++++++++
> o2info/o2info.h | 82 +++++++++
> o2info/operations.c | 61 +++++++
> o2info/utils.c | 109 ++++++++++++
> o2info/utils.h | 30 ++++
> 8 files changed, 809 insertions(+), 1 deletions(-)
> create mode 100644 o2info/.gitignore
> create mode 100644 o2info/Makefile
> create mode 100644 o2info/o2info.c
> create mode 100644 o2info/o2info.h
> create mode 100644 o2info/operations.c
> create mode 100644 o2info/utils.c
> create mode 100644 o2info/utils.h
>
> diff --git a/Makefile b/Makefile
> index 88106fb..8b71e72 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -20,7 +20,7 @@ CHKCONFIG_DEP = chkconfig
> COMPILE_PY = 1
> endif
>
> -SUBDIRS = include libtools-internal libo2dlm libo2cb libocfs2 fsck.ocfs2 mkfs.ocfs2 mounted.ocfs2 tunefs.ocfs2 debugfs.ocfs2 o2cb_ctl ocfs2_hb_ctl mount.ocfs2 ocfs2_controld o2image listuuid sizetest extras fswreck patches
> +SUBDIRS = include libtools-internal libo2dlm libo2cb libocfs2 fsck.ocfs2 mkfs.ocfs2 mounted.ocfs2 tunefs.ocfs2 debugfs.ocfs2 o2cb_ctl ocfs2_hb_ctl mount.ocfs2 ocfs2_controld o2image o2info listuuid sizetest extras fswreck patches
>
> ifdef BUILD_OCFS2CONSOLE
> SUBDIRS += ocfs2console
> diff --git a/o2info/.gitignore b/o2info/.gitignore
> new file mode 100644
> index 0000000..46c8063
> --- /dev/null
> +++ b/o2info/.gitignore
> @@ -0,0 +1,6 @@
> +.*.sw?
> +*.d
> +.*.cmd
> +stamp-md5
> +cscope*
> +o2info
> diff --git a/o2info/Makefile b/o2info/Makefile
> new file mode 100644
> index 0000000..892d962
> --- /dev/null
> +++ b/o2info/Makefile
> @@ -0,0 +1,36 @@
> +TOPDIR = ..
> +
> +include $(TOPDIR)/Preamble.make
> +
> +WARNINGS = -Wall -Wstrict-prototypes -Wno-format -Wmissing-prototypes \
> + -Wmissing-declarations
> +
> +CFLAGS = $(OPTS) $(WARNINGS)
> +
> +LIBTOOLS_INTERNAL_LIBS = -L$(TOPDIR)/libtools-internal -ltools-internal
> +LIBTOOLS_INTERNAL_DEPS = $(TOPDIR)/libtools-internal/libtools-internal.a
> +
> +LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
> +LIBOCFS2_DEPS = $(TOPDIR)/libocfs2/libocfs2.a
> +
> +BIN_PROGRAMS = o2info
> +
> +INCLUDES = -I$(TOPDIR)/include -I.
> +DEFINES = -DVERSION=\"$(VERSION)\"
> +
> +HFILES = o2info.h \
> + utils.h
> +
> +CFILES = \
> + o2info.c \
> + operations.c \
> + utils.c
> +
> +OBJS = $(subst .c,.o,$(CFILES))
> +
> +DIST_FILES = $(CFILES) $(HFILES)
> +
> +o2info: $(OBJS) $(LIBOCFS2_DEPS)
> + $(LINK) $(LIBOCFS2_LIBS) $(LIBTOOLS_INTERNAL_LIBS) $(COM_ERR_LIBS)
> +
> +include $(TOPDIR)/Postamble.make
> diff --git a/o2info/o2info.c b/o2info/o2info.c
> new file mode 100644
> index 0000000..6aaeb46
> --- /dev/null
> +++ b/o2info/o2info.c
> @@ -0,0 +1,484 @@
> +/* -*- mode: c; c-basic-offset: 8; -*-
> + * vim: noexpandtab sw=8 ts=8 sts=0:
> + *
> + * o2info.c
> + *
> + * Ocfs2 utility to gather and report fs information
> + *
> + * Copyright (C) 2010 Oracle. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + */
> +
> +#define _XOPEN_SOURCE 600
> +#define _LARGEFILE64_SOURCE
> +#define _GNU_SOURCE /* Because libc really doesn't want us using O_DIRECT? */
> +
> +#include <unistd.h>
> +#include <errno.h>
> +#include <signal.h>
> +#include <getopt.h>
> +#include <assert.h>
> +
> +#include "ocfs2/ocfs2.h"
> +#include "ocfs2-kernel/ocfs2_ioctl.h"
> +#include "ocfs2-kernel/kernel-list.h"
> +#include "tools-internal/verbose.h"
> +
> +#include "utils.h"
> +
> +static LIST_HEAD(o2info_op_task_list);
> +static int o2info_op_task_count;
> +int cluster_coherent;
> +
> +void print_usage(int rc);
> +static int help_handler(struct o2info_option *opt, char *arg)
> +{
> + print_usage(0);
> + exit(0);
> +}
> +
> +static int version_handler(struct o2info_option *opt, char *arg)
> +{
> + tools_version();
> + exit(0);
> +}
> +
> +static struct o2info_option help_option = {
> + .opt_option = {
> + .name = "help",
> + .val = 'h',
> + .has_arg = 0,
> + .flag = NULL,
> + },
> + .opt_help = NULL,
> + .opt_handler = help_handler,
> + .opt_op = NULL,
> + .opt_private = NULL,
> +};
> +
> +static struct o2info_option version_option = {
> + .opt_option = {
> + .name = "version",
> + .val = 'V',
> + .has_arg = 0,
> + .flag = NULL,
> + },
> + .opt_help = NULL,
> + .opt_handler = version_handler,
> + .opt_op = NULL,
> + .opt_private = NULL,
> +};
> +
> +static struct o2info_option *options[] = {
> + &help_option,
> + &version_option,
> + NULL,
> +};
> +
> +void print_usage(int rc)
> +{
> + int i;
> + enum tools_verbosity_level level = VL_ERR;
> +
> + if (!rc)
> + level = VL_OUT;
> +
> + verbosef(level, "Usage: %s [options] <device or file>\n",
> + tools_progname());
> + verbosef(level, " %s -h|--help\n", tools_progname());
> + verbosef(level, " %s -V|--version\n", tools_progname());
> + verbosef(level, "[options] can be followings:\n");
> +
> + for (i = 0; options[i]; i++) {
> + if (options[i]->opt_help)
> + verbosef(level, "\t%s\n", options[i]->opt_help);
> + }
> +
> + exit(rc);
> +}
> +
> +static int build_options(char **optstring, struct option **longopts)
> +{
> + errcode_t err;
> + int i, num_opts, rc = 0;
> + int unprintable_counter;
> + size_t optstring_len;
> + char *p, *str = NULL;
> + struct option *lopts = NULL;
> + struct o2info_option *opt;
> +
> + unprintable_counter = 1; /* Start unique at CHAR_MAX + 1*/
> + optstring_len = 1; /* For the leading ':' */
> + for (i = 0; options[i]; i++) {
> + opt = options[i];
> +
> + /*
> + * Any option with a val of CHAR_MAX wants an unique but
> + * unreadable ->val. Only readable characters go into
> + * optstring.
> + */
> + if (opt->opt_option.val == CHAR_MAX) {
> + opt->opt_option.val =
> + CHAR_MAX + unprintable_counter;
> + unprintable_counter++;
> + continue;
> + }
> +
> + /*
> + * A given option has a single character in optstring.
> + * If it takes a mandatory argument, has_arg==1 and you add
> + * a ":" to optstring. If it takes an optional argument,
> + * has_arg==2 and you add "::" to optstring. Thus,
> + * 1 + has_arg is the total space needed in opstring.
> + */
> + optstring_len += 1 + opt->opt_option.has_arg;
> + }
> +
> + num_opts = i;
> +
> + err = ocfs2_malloc0(sizeof(char) * (optstring_len + 1), &str);
> + if (!err)
> + err = ocfs2_malloc(sizeof(struct option) * (num_opts + 1),
> + &lopts);
> + if (err) {
> + rc = -ENOMEM;
> + goto out;
> + }
> +
> + p = str;
> + *p++ = ':';
> + for (i = 0; options[i]; i++) {
> + assert(p < (str + optstring_len + 1));
> + opt = options[i];
> +
> + memcpy(&lopts[i], &opt->opt_option, sizeof(struct option));
> +
> + if (opt->opt_option.val >= CHAR_MAX)
> + continue;
> +
> + *p = opt->opt_option.val;
> + p++;
> + if (opt->opt_option.has_arg > 0) {
> + *p = ':';
> + p++;
> + }
> + if (opt->opt_option.has_arg > 1) {
> + *p = ':';
> + p++;
> + }
> + }
> +
> + /*
> + * Fill last entry of options with zeros.
> + */
> + memset(&lopts[i], 0, sizeof(struct option));
> +
> +out:
> + if (!rc) {
> + *optstring = str;
> + *longopts = lopts;
> + } else {
> + if (str)
> + free(str);
> + if (lopts)
> + free(lopts);
> + }
> +
> + return rc;
> +}
> +
> +static struct o2info_option *find_option_by_val(int val)
> +{
> + int i;
> + struct o2info_option *opt = NULL;
> +
> + for (i = 0; options[i]; i++) {
> + if (options[i]->opt_option.val == val) {
> + opt = options[i];
> + break;
> + }
> + }
> +
> + return opt;
> +}
> +
> +static errcode_t o2info_append_task(struct o2info_operation *o2p)
> +{
> + errcode_t err;
> + struct o2info_op_task *task;
> +
> + err = ocfs2_malloc0(sizeof(struct o2info_op_task), &task);
> + if (!err) {
> + task->o2p_task = o2p;
> + list_add_tail(&task->o2p_list, &o2info_op_task_list);
> + o2info_op_task_count++;
> + } else
> + ocfs2_free(&task);
> +
> + return err;
> +}
> +
> +static void o2info_free_op_task_list(void)
> +{
> + struct o2info_op_task *task;
> + struct list_head *pos, *next;
> +
> + if (list_empty(&o2info_op_task_list))
> + return;
> +
> + list_for_each_safe(pos, next, &o2info_op_task_list) {
> + task = list_entry(pos, struct o2info_op_task, o2p_list);
> + list_del(pos);
> + ocfs2_free(&task);
> + }
> +}
> +
> +extern int optind, opterr, optopt;
> +extern char *optarg;
> +static errcode_t parse_options(int argc, char *argv[], char **device_or_file)
> +{
> + int c, lopt_idx = 0;
> + errcode_t err;
> + struct option *long_options = NULL;
> + char error[PATH_MAX];
> + char *optstring = NULL;
> + struct o2info_option *opt;
> +
> + err = build_options(&optstring, &long_options);
> + if (err)
> + goto out;
> +
> + opterr = 0;
> + error[0] = '\0';
> + while ((c = getopt_long(argc, argv, optstring,
> + long_options, &lopt_idx)) != EOF) {
> + opt = NULL;
> + switch (c) {
> + case '?':
> + if (optopt)
> + errorf("Invalid option: '-%c'\n", optopt);
> + else
> + errorf("Invalid option: '%s'\n",
> + argv[optind - 1]);
> + print_usage(1);
> + break;
> +
> + case ':':
> + if (optopt < CHAR_MAX)
> + errorf("Option '-%c' requires an argument\n",
> + optopt);
> + else
> + errorf("Option '%s' requires an argument\n",
> + argv[optind - 1]);
> + print_usage(1);
> + break;
> +
> + default:
> + opt = find_option_by_val(c);
> + if (!opt) {
> + errorf("Shouldn't have gotten here: "
> + "option '-%c'\n", c);
> + print_usage(1);
> + }
> +
> + if (optarg)
> + opt->opt_private = (void *)optarg;
> +
> + break;
> + }
> +
> + if (opt->opt_set) {
> + errorf("Option '-%c' specified more than once\n",
> + c);
> + print_usage(1);
> + }
> +
> + opt->opt_set = 1;
> + /*
> + * Handlers for simple options such as showing version,
> + * printing the usage, or specify the coherency etc.
> + */
> + if (opt->opt_handler) {
> + if (opt->opt_handler(opt, optarg))
> + print_usage(1);
> + }
> +
> + /*
> + * Real operation will be added to a list to run later.
> + */
> + if (opt->opt_op) {
> + opt->opt_op->to_private = opt->opt_private;
> + err = o2info_append_task(opt->opt_op);
> + if (err)
> + goto out;
> + }
> + }
> +
> + if (optind == 1)
> + print_usage(1);
> +
> + if (optind >= argc) {
> + errorf("No device or file specified\n");
> + print_usage(1);
> + }
> +
> + *device_or_file = strdup(argv[optind]);
> + if (!*device_or_file) {
> + errorf("No memory for allocation\n");
> + goto out;
> + }
> +
> + optind++;
> +
> + if (optind < argc) {
> + errorf("Too many arguments\n");
> + print_usage(1);
> + }
> +
> +out:
> + if (optstring)
> + ocfs2_free(&optstring);
> +
> + if (long_options)
> + ocfs2_free(&long_options);
> +
> + return err;
> +}
> +
> +static errcode_t o2info_run_task(struct o2info_method *om)
> +{
> + struct list_head *p, *n;
> + struct o2info_op_task *task;
> +
> + list_for_each_safe(p, n, &o2info_op_task_list) {
> + task = list_entry(p, struct o2info_op_task, o2p_list);
> + task->o2p_task->to_run(task->o2p_task, om,
> + task->o2p_task->to_private);
> + }
> +
> + return 0;
> +}
> +
> +static void handle_signal(int caught_sig)
> +{
> + int exitp = 0, abortp = 0;
> + static int segv_already;
> +
> + switch (caught_sig) {
> + case SIGQUIT:
> + abortp = 1;
> + /* FALL THROUGH */
> +
> + case SIGTERM:
> + case SIGINT:
> + case SIGHUP:
> + errorf("Caught signal %d, exiting\n", caught_sig);
> + exitp = 1;
> + break;
> +
> + case SIGSEGV:
> + errorf("Segmentation fault, exiting\n");
> + exitp = 1;
> + if (segv_already) {
> + errorf("Segmentation fault loop detected\n");
> + abortp = 1;
> + } else
> + segv_already = 1;
> + break;
> +
> + default:
> + errorf("Caught signal %d, ignoring\n", caught_sig);
> + break;
> + }
> +
> + if (!exitp)
> + return;
> +
> + if (abortp)
> + abort();
> +
> + exit(1);
> +}
> +
> +static int setup_signals(void)
> +{
> + int rc = 0;
> + struct sigaction act;
> +
> + act.sa_sigaction = NULL;
> + sigemptyset(&act.sa_mask);
> + act.sa_handler = handle_signal;
> +#ifdef SA_INTERRUPT
> + act.sa_flags = SA_INTERRUPT;
> +#endif
> + rc += sigaction(SIGTERM, &act, NULL);
> + rc += sigaction(SIGINT, &act, NULL);
> + rc += sigaction(SIGHUP, &act, NULL);
> + rc += sigaction(SIGQUIT, &act, NULL);
> + rc += sigaction(SIGSEGV, &act, NULL);
> + act.sa_handler = SIG_IGN;
> + rc += sigaction(SIGPIPE, &act, NULL); /* Get EPIPE instead */
> +
> + return rc;
> +}
> +
> +static void o2info_init(const char *argv0)
> +{
> + initialize_ocfs_error_table();
> +
> + tools_setup_argv0(argv0);
> +
> + setbuf(stdout, NULL);
> + setbuf(stderr, NULL);
> +
> + if (setup_signals()) {
> + errorf("Unable to setup signal handling \n");
> + exit(1);
> + }
> +
> + cluster_coherent = OCFS2_INFO_FL_NON_COHERENT;
> +}
> +
> +int main(int argc, char *argv[])
> +{
> + int rc = 0;
> +
> + char *device_or_file = NULL;
> + static struct o2info_method om;
> +
> + o2info_init(argv[0]);
> + parse_options(argc, argv, &device_or_file);
> +
> + rc = o2info_method(device_or_file);
> + if (rc < 0)
> + goto out;
> + else
> + om.om_method = rc;
> +
> + strncpy(om.om_path, device_or_file, PATH_MAX);
> +
> + rc = o2info_open(&om, 0);
> + if (rc)
> + goto out;
> +
> + rc = o2info_run_task(&om);
> + if (rc)
> + goto out;
> +
> + o2info_free_op_task_list();
> +
> + rc = o2info_close(&om);
> +out:
> + if (device_or_file)
> + ocfs2_free(&device_or_file);
> +
> + return rc;
> +}
> diff --git a/o2info/o2info.h b/o2info/o2info.h
> new file mode 100644
> index 0000000..9290f81
> --- /dev/null
> +++ b/o2info/o2info.h
> @@ -0,0 +1,82 @@
> +/* -*- mode: c; c-basic-offset: 8; -*-
> + * vim: noexpandtab sw=8 ts=8 sts=0:
> + *
> + * o2info.h
> + *
> + * o2info operation prototypes.
> + *
> + * Copyright (C) 2010 Oracle. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + */
> +
> +#ifndef __O2INFO_H__
> +#define __O2INFO_H__
> +
> +#include <getopt.h>
> +
> +#include "ocfs2/ocfs2.h"
> +#include "ocfs2-kernel/kernel-list.h"
> +
> +enum o2info_method_type {
> + O2INFO_USE_LIBOCFS2 = 1,
> + O2INFO_USE_IOCTL,
> + O2INFO_USE_NUMTYPES
> +};
> +
> +struct o2info_method {
> + enum o2info_method_type om_method;
> + char om_path[PATH_MAX];
> + union {
> + ocfs2_filesys *om_fs; /* Use libocfs2 for device */
> + int om_fd; /* Use ioctl for file */
> + };
> +};
> +
> +struct o2info_operation {
> + char *to_name;
> + int (*to_run)(struct o2info_operation *op,
> + struct o2info_method *om,
> + void *arg);
> + void *to_private;
> +};
> +
> +struct o2info_option {
> + struct option opt_option; /* For getopt_long(). If
> + there is no short
> + option, set .val to
> + CHAR_MAX. A unique
> + value will be inserted
> + by the code. */
> + struct o2info_operation *opt_op;
> +
> + char *opt_help; /* Help string */
> + int opt_set; /* Was this option seen */
> + int (*opt_handler)(struct o2info_option *opt, char *arg);
> + void *opt_private;
> +};
> +
> +struct o2info_op_task {
> + struct list_head o2p_list;
> + struct o2info_operation *o2p_task;
> +};
> +
> +#define __O2INFO_OP(_name, _run, _private) \
> +{ \
> + .to_name = #_name, \
> + .to_run = _run, \
> + .to_private = _private \
> +}
> +
> +#define DEFINE_O2INFO_OP(_name, _run, _private) \
> +struct o2info_operation _name##_op = \
> + __O2INFO_OP(_name, _run, _private)
> +
> +#endif /* __O2INFO_H__ */
> diff --git a/o2info/operations.c b/o2info/operations.c
> new file mode 100644
> index 0000000..ad719a4
> --- /dev/null
> +++ b/o2info/operations.c
> @@ -0,0 +1,61 @@
> +/* -*- mode: c; c-basic-offset: 8; -*-
> + * vim: noexpandtab sw=8 ts=8 sts=0:
> + *
> + * operations.c
> + *
> + * Implementations for all o2info's operation.
> + *
> + * Copyright (C) 2010 Oracle. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + */
> +
> +#define _XOPEN_SOURCE 600
> +#define _LARGEFILE64_SOURCE
> +#define _GNU_SOURCE /* Because libc really doesn't want us using O_DIRECT? */
> +
> +#include <errno.h>
> +#include <sys/raw.h>
> +#include <inttypes.h>
> +
> +#include "ocfs2/ocfs2.h"
> +#include "ocfs2/bitops.h"
> +#include "ocfs2-kernel/ocfs2_ioctl.h"
> +#include "ocfs2-kernel/kernel-list.h"
> +#include "tools-internal/verbose.h"
> +
> +#include "utils.h"
> +
> +extern void print_usage(int rc);
> +extern int cluster_coherent;
> +
> +static inline void o2info_fill_request(struct ocfs2_info_request *req,
> + size_t size,
> + enum ocfs2_info_type code,
> + int flags)
> +{
> + memset(req, 0, size);
> +
> + req->ir_magic = OCFS2_INFO_MAGIC;
> + req->ir_size = size;
> + req->ir_code = code,
> + req->ir_size = size;
> +}
> +
> +static void o2i_error(struct o2info_operation *op, const char *fmt, ...)
> +{
> + va_list ap;
> +
> + fprintf(stderr, "%s: ", op->to_name);
> + va_start(ap, fmt);
> + vfprintf(stderr, fmt, ap);
> +
> + return;
> +}
> diff --git a/o2info/utils.c b/o2info/utils.c
> new file mode 100644
> index 0000000..0911c50
> --- /dev/null
> +++ b/o2info/utils.c
> @@ -0,0 +1,109 @@
> +/* -*- mode: c; c-basic-offset: 8; -*-
> + * vim: noexpandtab sw=8 ts=8 sts=0:
> + *
> + * utils.c
> + *
> + * utility functions for o2info
> + *
> + * Copyright (C) 2010 Oracle. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + */
> +
> +#define _XOPEN_SOURCE 600
> +#define _LARGEFILE64_SOURCE
> +#define _GNU_SOURCE /* Because libc really doesn't want us using O_DIRECT? */
> +
> +#include <unistd.h>
> +#include <errno.h>
> +#include <pwd.h>
> +#include <grp.h>
> +
> +#include "ocfs2/ocfs2.h"
> +#include "tools-internal/verbose.h"
> +
> +#include "utils.h"
> +
> +errcode_t o2info_open(struct o2info_method *om, int flags)
> +{
> + errcode_t err = 0;
> + int fd, open_flags;
> + ocfs2_filesys *fs = NULL;
> +
> + if (om->om_method == O2INFO_USE_LIBOCFS2) {
> + open_flags = flags|OCFS2_FLAG_HEARTBEAT_DEV_OK|OCFS2_FLAG_RO;
> + err = ocfs2_open(om->om_path, open_flags, 0, 0, &fs);
> + if (err) {
> + tcom_err(err, "while opening device %s", om->om_path);
> + goto out;
> + }
> + om->om_fs = fs;
> + } else {
> + open_flags = flags | O_RDONLY;
> + fd = open(om->om_path, open_flags);
> + if (fd < 0) {
> + err = errno;
> + tcom_err(err, "while opening file %s", om->om_path);
> + goto out;
> + }
> + om->om_fd = fd;
> + }
> +
> +out:
> + return err;
> +}
> +
> +errcode_t o2info_close(struct o2info_method *om)
> +{
> + errcode_t err = 0;
> + int rc = 0;
> +
> + if (om->om_method == O2INFO_USE_LIBOCFS2) {
> + if (om->om_fs) {
> + err = ocfs2_close(om->om_fs);
> + if (err) {
> + tcom_err(err, "while closing device");
> + goto out;
> + }
> + }
> + } else {
> + if (om->om_fd >= 0) {
> + rc = close(om->om_fd);
> + if (rc < 0) {
> + rc = errno;
> + tcom_err(rc, "while closing fd: %d.\n",
> + om->om_fd);
> + err = rc;
> + }
> + }
> + }
> +
> +out:
> + return err;
> +}
> +
> +int o2info_method(const char *path)
> +{
> + int rc;
> + struct stat st;
> +
> + rc = stat(path, &st);
> + if (rc < 0) {
> + tcom_err(errno, "while stating %s", path);
> + goto out;
> + }
> +
> + rc = O2INFO_USE_IOCTL;
> + if ((S_ISBLK(st.st_mode)) || (S_ISCHR(st.st_mode)))
> + rc = O2INFO_USE_LIBOCFS2;
> +
> +out:
> + return rc;
> +}
> diff --git a/o2info/utils.h b/o2info/utils.h
> new file mode 100644
> index 0000000..6d55d39
> --- /dev/null
> +++ b/o2info/utils.h
> @@ -0,0 +1,30 @@
> +/* -*- mode: c; c-basic-offset: 8; -*-
> + * vim: noexpandtab sw=8 ts=8 sts=0:
> + *
> + * utils.h
> + *
> + * Common utility function prototypes
> + *
> + * Copyright (C) 2010 Oracle. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + */
> +
> +#ifndef __UTILS_H__
> +#define __UTILS_H__
> +
> +#include "o2info.h"
> +
> +int o2info_method(const char *path);
> +
> +errcode_t o2info_open(struct o2info_method *om, int flags);
> +errcode_t o2info_close(struct o2info_method *om);
> +
> +#endif /* __UTILS_H__ */
>
More information about the Ocfs2-tools-devel
mailing list