1    	#include <fcntl.h>
2    	#include <unistd.h>
3    	#include <string.h>
4    	#include "lang.h"
5    	#include "libgfs2.h"
6    	
7    	static void usage(const char *cmd)
8    	{
9    		printf("A language for modifying and querying a gfs2 file system.\n");
10   		printf("Usage: %s [options] <fs_path>\n", cmd);
11   		printf("Available options:\n");
12   		printf("  -h                Print this help message and exit\n");
13   		printf("  -f <script_path>  Path to script file or '-' for stdin (the default)\n");
14   		printf("  -T                Print a list of gfs2 structure types and exit\n");
15   		printf("  -F <type>         Print a list of fields belonging to a type and exit\n");
16   	}
17   	
18   	struct cmdopts {
19   		char *fspath;
20   		FILE *src;
21   		unsigned help:1;
22   	};
23   	
24   	static int metastrcmp(const void *a, const void *b)
25   	{
26   		const struct lgfs2_metadata *m1 = *(struct lgfs2_metadata **)a;
27   		const struct lgfs2_metadata *m2 = *(struct lgfs2_metadata **)b;
28   		return strcmp(m1->name, m2->name);
29   	}
30   	
31   	static int print_structs(void)
32   	{
33   		const struct lgfs2_metadata **mlist;
34   		int i;
35   	
36   		mlist = calloc(lgfs2_metadata_size, sizeof(struct lgfs2_metadata *));
37   		if (mlist == NULL) {
38   			perror("Failed to create metadata type array");
39   			return 1;
40   		}
41   		for (i = 0; i < lgfs2_metadata_size; i++)
42   			mlist[i] = &lgfs2_metadata[i];
43   	
44   		qsort(mlist, lgfs2_metadata_size, sizeof(struct lgfs2_metadata *), metastrcmp);
45   		for (i = 0; i < lgfs2_metadata_size; i++)
46   			if (mlist[i]->mh_type != GFS2_METATYPE_NONE)
47   				printf("%s\n", mlist[i]->name);
48   		free(mlist);
49   		return 0;
50   	}
51   	
52   	static void print_fields(const char *name)
53   	{
54   		const struct lgfs2_metadata *m = lgfs2_find_mtype_name(name);
55   		if (m != NULL) {
56   			const struct lgfs2_metafield *fields = m->fields;
57   			const unsigned nfields = m->nfields;
58   			int i;
59   			for (i = 0; i < nfields; i++)
60   				printf("0x%.4x %s\n", fields[i].offset, fields[i].name);
61   		}
62   	}
63   	
64   	static int getopts(int argc, char *argv[], struct cmdopts *opts)
65   	{
66   		int opt;
67   		opts->src = stdin;
68   		while ((opt = getopt(argc, argv, "F:f:hT")) != -1) {
69   			switch (opt) {
70   			case 'f':
71   				if (strcmp("-", optarg)) {
72   					opts->src = fopen(optarg, "r");
73   					if (opts->src == NULL) {
74   						perror("Failed to open source file");
75   						return 1;
76   					}
77   				}
78   				break;
79   			case 'T':
80   				exit(print_structs());
81   			case 'F':
82   				print_fields(optarg);
83   				exit(0);
84   			case 'h':
85   				opts->help = 1;
86   				return 0;
87   			default:
88   				fprintf(stderr, "Use -h for help\n");
89   				return 1;
90   			}
91   		}
92   	
93   		if (argc - optind != 1) {
94   			usage(argv[0]);
95   			fprintf(stderr, "Missing file system path. Use -h for help.\n");
96   			return 1;
97   		}
98   	
99   		opts->fspath = strdup(argv[optind]);
100  		if (opts->fspath == NULL) {
101  			perror("getopts");
102  			return 1;
103  		}
104  		return 0;
105  	}
106  	
107  	static int openfs(const char *path, struct lgfs2_sbd *sdp)
108  	{
109  		int fd;
110  		int ret;
111  		int ok;
112  		uint64_t count;
113  	
(1) Event allocation: Memory is allocated. [Note: The source code implementation of the function has been overridden by a user model.]
(2) Event assign: Assigning: "fd" = "open(path, 2)".
Also see events: [allocation][deallocator]
114  		fd = open(path, O_RDWR);
115  		if (fd < 0) {
116  			fprintf(stderr, "Failed to open %s\n", path);
117  			return 1;
118  		}
119  	
120  		memset(sdp, 0, sizeof(*sdp));
121  		sdp->sd_bsize = GFS2_BASIC_BLOCK;
CID (unavailable; MK=dc66fd9a476f451219cfc4d9a2d3f856) (#1 of 1): Resource not released (INCOMPLETE_DEALLOCATOR):
(3) Event allocation: The field "sdp->device_fd" is allocated, but not released in the identified deallocator.
Also see events: [allocation][assign][deallocator]
122  		sdp->device_fd = fd;
123  		ret = lgfs2_compute_constants(sdp);
124  		if (ret != 0) {
125  			perror("Bad constants");
126  			return 1;
127  		}
128  		ret = lgfs2_get_dev_info(fd, &sdp->dinfo);
129  		if (ret != 0) {
130  			perror("Failed to gather device info");
131  			return 1;
132  		}
133  		lgfs2_fix_device_geometry(sdp);
134  	
135  		ret = lgfs2_read_sb(sdp);
136  		if (ret != 0) {
137  			perror("Could not read sb");
138  			return 1;
139  		}
140  	
141  		sdp->master_dir = lgfs2_inode_read(sdp, sdp->sd_meta_dir.in_addr);
142  		sdp->md.riinode = lgfs2_lookupi(sdp->master_dir, "rindex", 6);
143  		sdp->fssize = sdp->device.length;
144  		if (sdp->md.riinode) {
145  			lgfs2_rindex_read(sdp, &count, &ok);
146  		} else {
147  			perror("Failed to look up rindex");
148  			return 1;
149  		}
150  		return 0;
151  	}
152  	
153  	int main(int argc, char *argv[])
154  	{
155  		int ret;
156  		struct cmdopts opts = {NULL, NULL};
157  		struct lgfs2_sbd sbd;
158  		struct lgfs2_lang_result *result;
159  		struct lgfs2_lang_state *state;
160  	
161  		if (getopts(argc, argv, &opts)) {
162  			exit(1);
163  		}
164  	
165  		if (opts.help) {
166  			usage(argv[0]);
167  			exit(0);
168  		}
169  	
170  		if (openfs(argv[optind], &sbd))
171  			exit(1);
172  	
173  		state = lgfs2_lang_init();
174  		if (state == NULL) {
175  			perror("lgfs2_lang_init failed");
176  			exit(1);
177  		}
178  	
179  		ret = lgfs2_lang_parsef(state, opts.src);
180  		if (ret != 0) {
181  			fprintf(stderr, "Parse failed\n");
182  			free(opts.fspath);
183  			return ret;
184  		}
185  	
186  		for (result = lgfs2_lang_result_next(state, &sbd);
187  		     result != NULL;
188  		     result = lgfs2_lang_result_next(state, &sbd)) {
189  			lgfs2_lang_result_print(result);
190  			lgfs2_lang_result_free(&result);
191  		}
192  	
193  		lgfs2_rgrp_free(&sbd, &sbd.rgtree);
194  		lgfs2_inode_put(&sbd.md.riinode);
195  		lgfs2_inode_put(&sbd.master_dir);
196  		lgfs2_lang_free(&state);
197  		free(opts.fspath);
198  		return 0;
199  	}
200