main.c revision 932f9845f6d6ab79815d80a1eb03b1b3509a4463
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:";
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				default:
55					MSG(0, "\tError: Unknown option %c\n",option);
56					fsck_usage();
57					break;
58			}
59		}
60	} else if (!strcmp("dump.f2fs", prog)) {
61		const char *option_string = "d:i:s:a:b:";
62		static struct dump_option dump_opt = {
63			.nid = 3,	/* default root ino */
64			.start_sit = -1,
65			.end_sit = -1,
66			.start_ssa = -1,
67			.end_ssa = -1,
68			.blk_addr = -1,
69		};
70
71		config.func = DUMP;
72		while ((option = getopt(argc, argv, option_string)) != EOF) {
73			switch (option) {
74				case 'd':
75					config.dbg_lv = atoi(optarg);
76					MSG(0, "Info: Debug level = %d\n", config.dbg_lv);
77					break;
78				case 'i':
79					if (strncmp(optarg, "0x", 2))
80						sscanf(optarg, "%d", &dump_opt.nid);
81					else
82						sscanf(optarg, "%x", &dump_opt.nid);
83					break;
84				case 's':
85					sscanf(optarg, "%d~%d", &dump_opt.start_sit, &dump_opt.end_sit);
86					break;
87				case 'a':
88					sscanf(optarg, "%d~%d", &dump_opt.start_ssa, &dump_opt.end_ssa);
89					break;
90				case 'b':
91					if (strncmp(optarg, "0x", 2))
92						sscanf(optarg, "%d", &dump_opt.blk_addr);
93					else
94						sscanf(optarg, "%x", &dump_opt.blk_addr);
95					break;
96				default:
97					MSG(0, "\tError: Unknown option %c\n", option);
98					dump_usage();
99					break;
100			}
101		}
102
103		config.private = &dump_opt;
104	}
105
106	if ((optind + 1) != argc) {
107		MSG(0, "\tError: Device not specified\n");
108		if (config.func == FSCK)
109			fsck_usage();
110		else if (config.func == DUMP)
111			dump_usage();
112	}
113	config.device_name = argv[optind];
114}
115
116int do_fsck(struct f2fs_sb_info *sbi)
117{
118	u32 blk_cnt;
119	int ret;
120
121	ret = fsck_init(sbi);
122	if (ret < 0)
123		return ret;
124
125	fsck_chk_orphan_node(sbi);
126
127	/* Travses all block recursively from root inode  */
128	blk_cnt = 1;
129	ret = fsck_chk_node_blk(sbi,
130			NULL,
131			sbi->root_ino_num,
132			F2FS_FT_DIR,
133			TYPE_INODE,
134			&blk_cnt);
135	if (ret < 0)
136		goto out1;
137
138	ret = fsck_verify(sbi);
139
140out1:
141	fsck_free(sbi);
142	return ret;
143}
144
145int do_dump(struct f2fs_sb_info *sbi)
146{
147	struct dump_option *opt = (struct dump_option *)config.private;
148	int ret;
149
150	ret = fsck_init(sbi);
151	if (ret < 0)
152		return ret;
153
154	if (opt->end_sit == -1)
155		opt->end_sit = SM_I(sbi)->main_segments;
156	if (opt->end_ssa == -1)
157		opt->end_ssa = SM_I(sbi)->main_segments;
158	if (opt->start_sit != -1)
159		sit_dump(sbi, opt->start_sit, opt->end_sit);
160	if (opt->start_ssa != -1)
161		ssa_dump(sbi, opt->start_ssa, opt->end_ssa);
162	if (opt->blk_addr != -1) {
163		dump_inode_from_blkaddr(sbi, opt->blk_addr);
164		goto cleanup;
165	}
166
167	dump_node(sbi, opt->nid);
168
169cleanup:
170	fsck_free(sbi);
171	return 0;
172}
173
174int main (int argc, char **argv)
175{
176	struct f2fs_sb_info *sbi = &gfsck.sbi;
177	int ret = 0;
178
179	f2fs_init_configuration(&config);
180
181	f2fs_parse_options(argc, argv);
182
183	if (f2fs_dev_is_mounted(&config) < 0)
184		return -1;
185
186	/* Get device */
187	if (f2fs_get_device_info(&config) < 0)
188		return -1;
189
190	if (f2fs_do_mount(sbi) < 0)
191		return -1;
192
193	switch (config.func) {
194		case FSCK:
195			ret = do_fsck(sbi);
196			break;
197		case DUMP:
198			ret = do_dump(sbi);
199			break;
200	}
201
202	f2fs_do_umount(sbi);
203	printf("\nDone.\n");
204	return ret;
205}
206