[Ocfs2-tools-devel] [PATCH 10/24] tunefs rework: Add op_query.c
Joel Becker
joel.becker at oracle.com
Wed Aug 13 15:57:05 PDT 2008
The query operation allows users to print information about the
ocfs2 filesystem with a printf-style format string.
This is the tunefs operation '-Q'.
Signed-off-by: Joel Becker <joel.becker at oracle.com>
Signed-off-by: Mark Fasheh <mfasheh at suse.com>
---
tunefs.ocfs2/op_query.c | 360 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 360 insertions(+), 0 deletions(-)
create mode 100644 tunefs.ocfs2/op_query.c
diff --git a/tunefs.ocfs2/op_query.c b/tunefs.ocfs2/op_query.c
new file mode 100644
index 0000000..91daf1f
--- /dev/null
+++ b/tunefs.ocfs2/op_query.c
@@ -0,0 +1,360 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * op_query.c - query operation for tunefs
+ *
+ * Copyright (C) 2004, 2008 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 _GNU_SOURCE /* For asprintf() */
+#include <stdio.h>
+#include <string.h>
+#include <printf.h>
+
+#include "ocfs2/ocfs2.h"
+
+#include "libocfs2ne.h"
+
+/* To get around passing arguments to printf() */
+static ocfs2_filesys *query_fs;
+
+
+static void tunefs_inprog_flag_in_str(uint32_t flag, char *buf, size_t len)
+{
+ errcode_t err;
+
+ err = ocfs2_snprint_tunefs_flags(buf, len, flag);
+ if (err)
+ tcom_err(err, "while processing inprog flags");
+}
+
+static void incompat_flag_in_str(uint32_t flag, char *buf, size_t len)
+{
+ errcode_t err;
+ ocfs2_fs_options flags = {
+ .opt_incompat = flag,
+ };
+
+ err = ocfs2_snprint_feature_flags(buf, len, &flags);
+ if (err)
+ tcom_err(err, "while processing feature flags");
+}
+
+static void compat_flag_in_str(uint32_t flag, char *buf, size_t len)
+{
+ errcode_t err;
+ ocfs2_fs_options flags = {
+ .opt_compat = flag,
+ };
+
+ err = ocfs2_snprint_feature_flags(buf, len, &flags);
+ if (err)
+ tcom_err(err, "while processing feature flags");
+}
+
+static void ro_compat_flag_in_str(uint32_t flag, char *buf, size_t len)
+{
+ errcode_t err;
+ ocfs2_fs_options flags = {
+ .opt_ro_compat = flag,
+ };
+
+ err = ocfs2_snprint_feature_flags(buf, len, &flags);
+ if (err)
+ tcom_err(err, "while processing feature flags");
+}
+
+static int print_ulong(FILE *stream, const struct printf_info *info,
+ const void *const *args, unsigned long val)
+{
+ char *buffer;
+ int len;
+
+ len = asprintf(&buffer, "%lu", val);
+ if (len == -1)
+ return -1;
+
+ len = fprintf(stream, "%*s", (info->left ? -info->width : info->width),
+ buffer);
+ free(buffer);
+ return len;
+}
+
+static int print_string(FILE *stream, const struct printf_info *info,
+ const void *const *args, char *val)
+{
+ char *buffer;
+ int len;
+
+ len = asprintf(&buffer, "%s", val);
+ if (len == -1)
+ return -1;
+
+ len = fprintf(stream, "%*s", (info->left ? -info->width : info->width),
+ buffer);
+ free(buffer);
+ return len;
+}
+
+static int handle_blocksize(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ return print_ulong(stream, info, args, query_fs->fs_blocksize);
+}
+
+static int handle_clustersize(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ return print_ulong(stream, info, args, query_fs->fs_clustersize);
+}
+
+static int handle_numslots(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ return print_ulong(stream, info, args,
+ OCFS2_RAW_SB(query_fs->fs_super)->s_max_slots);
+}
+
+static int handle_rootdir(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ return print_ulong(stream, info, args,
+ OCFS2_RAW_SB(query_fs->fs_super)->s_root_blkno);
+}
+
+static int handle_sysdir(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ return print_ulong(stream, info, args,
+ OCFS2_RAW_SB(query_fs->fs_super)->s_system_dir_blkno);
+}
+
+static int handle_clustergroup(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ return print_ulong(stream, info, args,
+ OCFS2_RAW_SB(query_fs->fs_super)->s_first_cluster_group);
+}
+
+static int handle_label(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ char label[OCFS2_MAX_VOL_LABEL_LEN + 1];
+
+ snprintf(label, OCFS2_MAX_VOL_LABEL_LEN + 1,
+ (char *)OCFS2_RAW_SB(query_fs->fs_super)->s_label);
+
+ return print_string(stream, info, args, label);
+}
+
+static int handle_uuid(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ return print_string(stream, info, args, query_fs->uuid_str);
+}
+
+static int handle_flag(FILE *stream, const struct printf_info *info,
+ const void *const *args, uint32_t flag,
+ void(*flag_func)(uint32_t flag, char *buf, size_t len))
+{
+ char buf[PATH_MAX]; /* Should be big enough */
+ int len = 0;
+
+ *buf = '\0';
+ (flag_func)(flag, buf, PATH_MAX);
+
+ if (*buf)
+ len = print_string(stream, info, args, buf);
+
+ return len;
+}
+
+static int handle_compat(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ int len;
+ len = handle_flag(stream, info, args,
+ OCFS2_RAW_SB(query_fs->fs_super)->s_feature_compat,
+ compat_flag_in_str);
+ if (!len)
+ len = print_string(stream, info, args, "None");
+ return len;
+}
+
+static int handle_incompat(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ int len;
+
+ len = handle_flag(stream, info, args,
+ OCFS2_RAW_SB(query_fs->fs_super)->s_feature_incompat,
+ incompat_flag_in_str);
+
+ if (OCFS2_RAW_SB(query_fs->fs_super)->s_tunefs_flag)
+ len += handle_flag(stream, info, args,
+ OCFS2_RAW_SB(query_fs->fs_super)->s_tunefs_flag,
+ tunefs_inprog_flag_in_str);
+
+ if (!len)
+ len = print_string(stream, info, args, "None");
+ return len;
+}
+
+static int handle_ro_compat(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ int len;
+
+ len = handle_flag(stream, info, args,
+ OCFS2_RAW_SB(query_fs->fs_super)->s_feature_ro_compat,
+ ro_compat_flag_in_str);
+ if (!len)
+ len = print_string(stream, info, args, "None");
+ return len;
+}
+
+static int handle_arginfo(const struct printf_info *info, size_t n, int *types)
+{
+ return 0;
+}
+
+/*
+ * \a=0x07, \b=0x08, \t=0x09, \n=0x0a, \v=0x0b, \f=0x0c, \r=0x0d
+ */
+static char * process_escapes(char *queryfmt)
+{
+ char *fmt;
+ int i, j;
+ int len;
+
+ len = strlen(queryfmt);
+
+ if (ocfs2_malloc0(len + 1, &fmt))
+ return NULL;
+
+ for(i = 0, j = 0; i < len; ) {
+ if (queryfmt[i] != '\\')
+ fmt[j++] = queryfmt[i++];
+ else {
+ switch(queryfmt[i + 1]) {
+ case 'a':
+ fmt[j++] = 0x07;
+ break;
+ case 'b':
+ fmt[j++] = 0x08;
+ break;
+ case 't':
+ fmt[j++] = 0x09;
+ break;
+ case 'n':
+ fmt[j++] = 0x0A;
+ break;
+ case 'v':
+ fmt[j++] = 0x0B;
+ break;
+ case 'f':
+ fmt[j++] = 0x0C;
+ break;
+ case 'r':
+ fmt[j++] = 0x0D;
+ break;
+ default:
+ fmt[j++] = queryfmt[i];
+ fmt[j++] = queryfmt[i + 1];
+ break;
+ }
+ i += 2;
+ }
+ }
+
+ return fmt;
+}
+
+static int query_parse_option(struct tunefs_operation *op, char *arg)
+{
+ int argtype;
+
+ if (!arg) {
+ errorf("No query format specified\n");
+ return 1;
+ }
+
+ /*
+ * We want to make sure that there are no "standard" specifiers in
+ * the format, only our own.
+ */
+ if (parse_printf_format(arg, 1, &argtype)) {
+ errorf("Unknown type specifier in the query format: "
+ "\"%s\"\n",
+ arg);
+ return 1;
+ }
+
+ op->to_private = arg;
+
+ return 0;
+}
+
+
+/*
+ * When creating printf fields for ourselves, we need to avoid the
+ * standard specifiers. All lowercase specifiers are reserved by C99.
+ * Reserved uppercase specifiers are: E, F, G, A, C, S, X, L
+ */
+static int query_run(struct tunefs_operation *op, ocfs2_filesys *fs,
+ int flags)
+{
+ char *queryfmt = op->to_private;
+ char *fmt;
+
+ fmt = process_escapes(queryfmt);
+ if (!fmt) {
+ tcom_err(TUNEFS_ET_NO_MEMORY,
+ "while escaping the query format");
+ return 1;
+ }
+
+ register_printf_function('B', handle_blocksize, handle_arginfo);
+ register_printf_function('T', handle_clustersize, handle_arginfo);
+ register_printf_function('N', handle_numslots, handle_arginfo);
+ register_printf_function('R', handle_rootdir, handle_arginfo);
+ register_printf_function('Y', handle_sysdir, handle_arginfo);
+ register_printf_function('P', handle_clustergroup, handle_arginfo);
+
+ register_printf_function('V', handle_label, handle_arginfo);
+ register_printf_function('U', handle_uuid, handle_arginfo);
+
+ register_printf_function('M', handle_compat, handle_arginfo);
+ register_printf_function('H', handle_incompat, handle_arginfo);
+ register_printf_function('O', handle_ro_compat, handle_arginfo);
+
+ query_fs = fs;
+ fprintf(stdout, fmt);
+ query_fs = NULL;
+
+ ocfs2_free(&fmt);
+
+ return 0;
+}
+
+DEFINE_TUNEFS_OP(query,
+ "Usage: op_query [opts] <device> <query-format>\n",
+ TUNEFS_FLAG_RO,
+ query_parse_option,
+ query_run);
+
+#ifdef DEBUG_EXE
+int main(int argc, char *argv[])
+{
+ return tunefs_op_main(argc, argv, &query_op);
+}
+#endif
--
1.5.6.3
More information about the Ocfs2-tools-devel
mailing list