Gitweb:
http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=be4c9608...
Commit: be4c96088702582b49f9d0c28404606eee5bd055
Parent: 3d97bf215fb429aabec3fbe7553688aa5e6a9d00
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Thu Nov 8 10:32:37 2012 +0000
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Thu Nov 8 11:32:50 2012 +0000
libgfs2: Add a small testing language UI
This adds a minimal 'gfs2l' command to allow easy use of the testing
language. It takes one -f option to specify a script file and a single
argument to specify the path to the fs.
It can be used to build a rudimentary REPL e.g.
# while read s; do echo "$s" | gfs2l -f- /dev/foo; done
get sb
...
But it's mainly intended to be used as a component of in-tree test
scripts and will not be installed by the build system.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/libgfs2/Makefile.am | 6 ++
gfs2/libgfs2/gfs2l.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 152 insertions(+), 0 deletions(-)
diff --git a/gfs2/libgfs2/Makefile.am b/gfs2/libgfs2/Makefile.am
index 7103e09..9c4e96b 100644
--- a/gfs2/libgfs2/Makefile.am
+++ b/gfs2/libgfs2/Makefile.am
@@ -9,6 +9,8 @@ noinst_HEADERS = libgfs2.h lang.h
noinst_LTLIBRARIES = libgfs2.la
+noinst_PROGRAMS = gfs2l
+
libgfs2_la_SOURCES = block_list.c fs_bits.c gfs1.c misc.c rgrp.c super.c \
buf.c fs_geometry.c gfs2_disk_hash.c ondisk.c \
device_geometry.c fs_ops.c gfs2_log.c recovery.c \
@@ -19,6 +21,10 @@ libgfs2_la_CPPFLAGS = -D_FILE_OFFSET_BITS=64 \
-D_GNU_SOURCE \
-I$(top_srcdir)/gfs2/include
+gfs2l_SOURCES = gfs2l.c
+gfs2l_CPPFLAGS = -I$(top_srcdir)/gfs2/include
+gfs2l_LDADD = $(top_builddir)/gfs2/libgfs2/libgfs2.la
+
# Autotools can't handle header files output by flex so we have to generate it
manually
lexer.h: lexer.l
$(LEX) -o lexer.c $(AM_LFLAGS) $^
diff --git a/gfs2/libgfs2/gfs2l.c b/gfs2/libgfs2/gfs2l.c
new file mode 100644
index 0000000..2eacb2d
--- /dev/null
+++ b/gfs2/libgfs2/gfs2l.c
@@ -0,0 +1,146 @@
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include "libgfs2.h"
+
+static void usage(const char *cmd)
+{
+ fprintf(stderr, "Usage: %s -f <script_path> <fs_path>\n", cmd);
+ fprintf(stderr, "Use -f - for stdin\n");
+}
+
+struct cmdopts {
+ char *fspath;
+ FILE *src;
+};
+
+static int getopts(int argc, char *argv[], struct cmdopts *opts)
+{
+ int opt;
+ while ((opt = getopt(argc, argv, "f:")) != -1) {
+ switch (opt) {
+ case 'f':
+ if (!strcmp("-", optarg)) {
+ opts->src = stdin;
+ } else {
+ opts->src = fopen(optarg, "r");
+ if (opts->src == NULL) {
+ perror("Failed to open source file");
+ return 1;
+ }
+ }
+ break;
+ default:
+ usage(argv[0]);
+ return 1;
+ }
+ }
+
+ if (argc - optind != 1) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ opts->fspath = strdup(argv[optind]);
+ if (opts->fspath == NULL) {
+ perror("getopts");
+ return 1;
+ }
+ return 0;
+}
+
+static struct gfs2_sbd *openfs(const char *path)
+{
+ int fd;
+ int ret;
+ int sane;
+ int count;
+ struct gfs2_sbd *sdp = calloc(1, sizeof(struct gfs2_sbd));
+ if (sdp == NULL) {
+ perror("calloc");
+ return NULL;
+ }
+
+ fd = open(path, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s\n", path);
+ free(sdp);
+ return NULL;
+ }
+
+ memset(sdp, 0, sizeof(*sdp));
+ sdp->bsize = GFS2_BASIC_BLOCK;
+ sdp->device_fd = fd;
+ compute_constants(sdp);
+ lgfs2_get_dev_info(fd, &sdp->dinfo);
+ fix_device_geometry(sdp);
+
+ ret = read_sb(sdp);
+ if (ret != 0) {
+ perror("Could not read sb");
+ return NULL;
+ }
+
+ sdp->master_dir = lgfs2_inode_read(sdp, sdp->sd_sb.sb_master_dir.no_addr);
+ gfs2_lookupi(sdp->master_dir, "rindex", 6, &sdp->md.riinode);
+ sdp->fssize = sdp->device.length;
+ if (sdp->md.riinode) {
+ rindex_read(sdp, 0, &count, &sane);
+ } else {
+ perror("Failed to look up rindex");
+ free(sdp);
+ return NULL;
+ }
+ return sdp;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+ struct cmdopts opts = {NULL, NULL};
+ struct gfs2_sbd *sdp;
+ struct lgfs2_lang_result *result;
+ struct lgfs2_lang_state *state;
+
+ if (getopts(argc, argv, &opts)) {
+ exit(1);
+ }
+
+ sdp = openfs(argv[optind]);
+ if (sdp == NULL) {
+ exit(1);
+ }
+
+ state = lgfs2_lang_init();
+ if (state == NULL) {
+ perror("lgfs2_lang_init failed");
+ exit(1);
+ }
+
+ ret = lgfs2_lang_parsef(state, opts.src);
+ if (ret != 0) {
+ fprintf(stderr, "Parse failed\n");
+ return ret;
+ }
+
+ for (result = lgfs2_lang_result_next(state, sdp);
+ result != NULL;
+ result = lgfs2_lang_result_next(state, sdp)) {
+ if (result == NULL) {
+ fprintf(stderr, "Failed to interpret script\n");
+ return -1;
+ }
+ lgfs2_lang_result_print(result);
+ lgfs2_lang_result_free(&result);
+ }
+
+ gfs2_rgrp_free(&sdp->rgtree);
+ inode_put(&sdp->md.riinode);
+ inode_put(&sdp->master_dir);
+ lgfs2_lang_free(&state);
+ free(opts.fspath);
+ return 0;
+}
+
+// libgfs2 still requires an external print_it function
+void print_it(const char *label, const char *fmt, const char *fmt2, ...) { return; }