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