[Ocfs2-tools-devel] [PATCH 2/7] O2info: Build a main framework for o2info.
Tristan Ye
tristan.ye at oracle.com
Thu May 6 01:43:52 PDT 2010
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..02058af
--- /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 = 0;
+}
+
+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..14214fe
--- /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_flags = flags;
+}
+
+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__ */
--
1.5.5
More information about the Ocfs2-tools-devel
mailing list