main.c revision 1ddf6367a3b5e8e586dee1bcbf9c363439ea3ec8
1/**
2 * main.c
3 *
4 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5 *             http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include "fsck.h"
12#include <libgen.h>
13
14struct f2fs_fsck gfsck = {
15	.sbi = { .fsck = &gfsck, },
16};
17
18void fsck_usage()
19{
20	MSG(0, "\nUsage: fsck.f2fs [options] device\n");
21	MSG(0, "[options]:\n");
22	MSG(0, "  -d debug level [default:0]\n");
23	exit(1);
24}
25
26void dump_usage()
27{
28	MSG(0, "\nUsage: dump.f2fs [options] device\n");
29	MSG(0, "[options]:\n");
30	MSG(0, "  -d debug level [default:0]\n");
31	MSG(0, "  -i inode no (hex)\n");
32	MSG(0, "  -s [SIT dump segno from #1~#2 (decimal), for all 0~-1]\n");
33	MSG(0, "  -a [SSA dump segno from #1~#2 (decimal), for all 0~-1]\n");
34	MSG(0, "  -b blk_addr (in 4KB)\n");
35
36	exit(1);
37}
38
39void f2fs_parse_options(int argc, char *argv[])
40{
41	int option = 0;
42	char *prog = basename(argv[0]);
43
44	if (!strcmp("fsck.f2fs", prog)) {
45		const char *option_string = "d:t";
46
47		config.func = FSCK;
48		while ((option = getopt(argc, argv, option_string)) != EOF) {
49			switch (option) {
50				case 'd':
51					config.dbg_lv = atoi(optarg);
52					MSG(0, "Info: Debug level = %d\n", config.dbg_lv);
53					break;
54				case 't':
55					config.dbg_lv = -1;
56					break;
57				default:
58					MSG(0, "\tError: Unknown option %c\n",option);
59					fsck_usage();
60					break;
61			}
62		}
63	} else if (!strcmp("dump.f2fs", prog)) {
64		const char *option_string = "d:i:s:a:b:";
65		static struct dump_option dump_opt = {
66			.nid = 3,	/* default root ino */
67			.start_sit = -1,
68			.end_sit = -1,
69			.start_ssa = -1,
70			.end_ssa = -1,
71			.blk_addr = -1,
72		};
73
74		config.func = DUMP;
75		while ((option = getopt(argc, argv, option_string)) != EOF) {
76			switch (option) {
77				case 'd':
78					config.dbg_lv = atoi(optarg);
79					MSG(0, "Info: Debug level = %d\n", config.dbg_lv);
80					break;
81				case 'i':
82					if (strncmp(optarg, "0x", 2))
83						sscanf(optarg, "%d", &dump_opt.nid);
84					else
85						sscanf(optarg, "%x", &dump_opt.nid);
86					break;
87				case 's':
88					sscanf(optarg, "%d~%d", &dump_opt.start_sit, &dump_opt.end_sit);
89					break;
90				case 'a':
91					sscanf(optarg, "%d~%d", &dump_opt.start_ssa, &dump_opt.end_ssa);
92					break;
93				case 'b':
94					if (strncmp(optarg, "0x", 2))
95						sscanf(optarg, "%d", &dump_opt.blk_addr);
96					else
97						sscanf(optarg, "%x", &dump_opt.blk_addr);
98					break;
99				default:
100					MSG(0, "\tError: Unknown option %c\n", option);
101					dump_usage();
102					break;
103			}
104		}
105
106		config.private = &dump_opt;
107	}
108
109	if ((optind + 1) != argc) {
110		MSG(0, "\tError: Device not specified\n");
111		if (config.func == FSCK)
112			fsck_usage();
113		else if (config.func == DUMP)
114			dump_usage();
115	}
116	config.device_name = argv[optind];
117}
118
119int do_fsck(struct f2fs_sb_info *sbi)
120{
121	u32 blk_cnt;
122	int ret;
123
124	ret = fsck_init(sbi);
125	if (ret < 0)
126		return ret;
127
128	fsck_chk_orphan_node(sbi);
129
130	/* Travses all block recursively from root inode  */
131	blk_cnt = 1;
132	ret = fsck_chk_node_blk(sbi,
133			NULL,
134			sbi->root_ino_num,
135			F2FS_FT_DIR,
136			TYPE_INODE,
137			&blk_cnt);
138	if (ret < 0)
139		goto out1;
140
141	ret = fsck_verify(sbi);
142
143out1:
144	fsck_free(sbi);
145	return ret;
146}
147
148int do_dump(struct f2fs_sb_info *sbi)
149{
150	struct dump_option *opt = (struct dump_option *)config.private;
151	int ret;
152
153	ret = fsck_init(sbi);
154	if (ret < 0)
155		return ret;
156
157	if (opt->end_sit == -1)
158		opt->end_sit = SM_I(sbi)->main_segments;
159	if (opt->end_ssa == -1)
160		opt->end_ssa = SM_I(sbi)->main_segments;
161	if (opt->start_sit != -1)
162		sit_dump(sbi, opt->start_sit, opt->end_sit);
163	if (opt->start_ssa != -1)
164		ssa_dump(sbi, opt->start_ssa, opt->end_ssa);
165	if (opt->blk_addr != -1) {
166		dump_inode_from_blkaddr(sbi, opt->blk_addr);
167		goto cleanup;
168	}
169
170	dump_node(sbi, opt->nid);
171
172cleanup:
173	fsck_free(sbi);
174	return 0;
175}
176
177int main (int argc, char **argv)
178{
179	struct f2fs_sb_info *sbi = &gfsck.sbi;
180	int ret = 0;
181
182	f2fs_init_configuration(&config);
183
184	f2fs_parse_options(argc, argv);
185
186	if (f2fs_dev_is_umounted(&config) < 0)
187		return -1;
188
189	/* Get device */
190	if (f2fs_get_device_info(&config) < 0)
191		return -1;
192
193	if (f2fs_do_mount(sbi) < 0)
194		return -1;
195
196	switch (config.func) {
197		case FSCK:
198			ret = do_fsck(sbi);
199			break;
200		case DUMP:
201			ret = do_dump(sbi);
202			break;
203	}
204
205	f2fs_do_umount(sbi);
206
207	f2fs_finalize_device(&config);
208
209	printf("\nDone.\n");
210	return ret;
211}
212