1 /**
2  * Copyright (c) 2008-2015 Alper Akcan <alper.akcan@gmail.com>
3  * Copyright (c) 2009 Renzo Davoli <renzo@cs.unibo.it>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program (in the main directory of the fuse-ext2
17  * distribution in the file COPYING); if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "fuse-ext2.h"
22 
23 static const char *HOME = "http://sourceforge.net/projects/fuse-ext2/";
24 
25 static const char *usage_msg =
26 "\n"
27 "%s %s %d - Probe EXT2FS volume mountability\n"
28 "\n"
29 "Copyright (C) 2008-2015 Alper Akcan <alper.akcan@gmail.com>\n"
30 "\n"
31 "Usage:    %s <--readonly|--readwrite> <device|image_file>\n"
32 "\n"
33 "Example:  fuse-ext2.probe --readwrite /dev/sda1\n"
34 "\n"
35 "%s\n"
36 "\n";
37 
38 static void usage (void)
39 {
40 	printf(usage_msg, PACKAGE, VERSION, fuse_version(), PACKAGE, HOME);
41 }
42 
43 static int parse_options (int argc, char *argv[], struct extfs_data *opts)
44 {
45 	int c;
46 
47 	static const char *sopt = "-rwd";
48 	static const struct option lopt[] = {
49 		{ "readonly",	 no_argument,	NULL, 'r' },
50 		{ "readwrite",	 no_argument,	NULL, 'w' },
51 		{ "debug",       no_argument,   NULL, 'd' },
52 		{ NULL,		 0,		NULL,  0  }
53 	};
54 
55 	opterr = 0; /* We'll handle the errors, thank you. */
56 
57 	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
58 		switch (c) {
59 			case 1:	/* A non-option argument */
60 				if (!opts->device) {
61 					opts->device = malloc(PATH_MAX + 1);
62 					if (!opts->device)
63 						return -1;
64 
65 					/* We don't want relative path in /etc/mtab. */
66 					if (optarg[0] != '/') {
67 						if (!realpath(optarg, opts->device)) {
68 							debugf_main("Cannot mount %s", optarg);
69 							free(opts->device);
70 							opts->device = NULL;
71 							return -1;
72 						}
73 					} else
74 						strcpy(opts->device, optarg);
75 				} else {
76 					debugf_main("You must specify exactly one device");
77 					return -1;
78 				}
79 				break;
80 			case 'r':
81 				opts->readonly = 1;
82 				break;
83 			case 'w':
84 				opts->readonly = 0;
85 				break;
86 			case 'd':
87 				opts->debug = 1;
88 				break;
89 			default:
90 				debugf_main("Unknown option '%s'", argv[optind - 1]);
91 				return -1;
92 		}
93 	}
94 
95 	if (!opts->device) {
96 		debugf_main("No device is specified");
97 		return -1;
98 	}
99 
100 	return 0;
101 }
102 
103 int main (int argc, char *argv[])
104 {
105 	int err = 0;
106 	struct stat sbuf;
107 	struct extfs_data opts;
108 
109 	memset(&opts, 0, sizeof(opts));
110 
111 	if (parse_options(argc, argv, &opts)) {
112 		usage();
113 		return -1;
114 	}
115 
116 	if (stat(opts.device, &sbuf)) {
117 		debugf_main("Failed to access '%s'", opts.device);
118 		err = -3;
119 		goto err_out;
120 	}
121 
122 	debugf_main("opts.device: %s", opts.device);
123 
124 	if (do_probe(&opts) != 0) {
125 		debugf_main("Probe failed");
126 		err = -4;
127 		goto err_out;
128 	}
129 
130 err_out:
131 	free(opts.device);
132 	free(opts.volname);
133 	free(opts.options);
134 	return err;
135 }
136