1 /*
2     resizefs.c -- reiserfs filesystem resize program.
3     Copyright (C) 2001, 2002 Yury Umanets <torque@ukrpost.net>, see COPYING for
4     licensing and copyright details.
5 */
6 
7 #ifdef HAVE_CONFIG_H
8 #  include <config.h>
9 #endif
10 
11 #include "getopt.h"
12 
13 #include <stdio.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <fcntl.h>
17 
18 #include <dal/file.h>
19 
20 #include <reiserfs/reiserfs.h>
21 #include <reiserfs/libprogs_tools.h>
22 
23 #if ENABLE_NLS
24 #  include <locale.h>
25 #  include <libintl.h>
26 #  define _(String) dgettext (PACKAGE, String)
27 #else
28 #  define _(String) (String)
29 #endif
30 
resizefs_print_usage(void)31 static void resizefs_print_usage(void) {
32     fprintf(stderr, _("Usage: resizefs.reiserfs [ options ] DEV [+|-]size[K|M|G]\n"
33     "Usage: resizefs.reiserfs [ options ] FILE start[K|M|G] end[K|M|G]\n"
34 	"Options:\n"
35 	"  -v | --version                  prints current version\n"
36 	"  -u | --usage                    prints program usage\n"
37 	"  -j FILE | --journal-device=FILE journal device for separated journal\n"
38 	"  -n | --no-journal-available     no journal device available now\n"
39 	"  -f | --force                    force resizer to resize partition anyway\n"
40 	"  -q | --quiet                    non-interactive mode\n"));
41 }
42 
main(int argc,char * argv[])43 int main(int argc, char *argv[]) {
44     long dev_len;
45     long start = 0, end = 0;
46 
47     int quiet = 0, force = 0;
48     int choice = 0, journal = 1, error = 0;
49 
50     dal_t *host_dal = NULL, *journal_dal = NULL;
51     char *host_dev = NULL, *journal_dev = NULL;
52     char *start_str = NULL, *end_str = NULL;
53 
54     reiserfs_fs_t *fs;
55     reiserfs_gauge_t *gauge = NULL;
56 
57     static struct option long_options[] = {
58 	{"version", no_argument, NULL, 'v'},
59 	{"usage", no_argument, NULL, 'u'},
60 	{"journal-device", required_argument, NULL, 'j'},
61 	{"no-journal-available", required_argument, NULL, 'n'},
62 	{"force", no_argument, NULL, 'f'},
63 	{"quiet", no_argument, NULL, 'q'},
64 	{0, 0, 0, 0}
65     };
66 
67 #ifdef ENABLE_NLS
68     setlocale(LC_ALL, "");
69     bindtextdomain(PACKAGE, LOCALEDIR);
70     textdomain(PACKAGE);
71 #endif
72 
73     while ((choice = getopt_long_only(argc, argv, "-uvj:nqf0123456789KMG",
74 	long_options, (int *)0)) != EOF)
75     {
76 	switch (choice) {
77 	    case 'u': {
78 		resizefs_print_usage();
79 		return 0;
80 	    }
81 	    case 'v': {
82 		printf("%s %s\n", argv[0], VERSION);
83 		return 0;
84 	    }
85 	    case 'n': {
86 		journal = 0;
87 		break;
88 	    }
89 	    case 'q': {
90 	    	quiet = 1;
91 		break;
92 	    }
93 	    case 'f': {
94 		force = 1;
95 		break;
96 	    }
97 	    case 'j': {
98 		if (!progs_dev_check((journal_dev = optarg))) {
99 		    libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
100 			_("Device %s doesn't exists or invalid."), journal_dev);
101 		    return 0;
102 		}
103 	    }
104 	    case '0': case '1':	case '2': case '3':	case '4':
105 	    case '5': case '6': case '7': case '8':	case '9':
106 	    case 'K': case 'M':	case 'G': break;
107 
108 	    case '?': {
109 		resizefs_print_usage();
110 		return 0xfe;
111 	    }
112 	}
113     }
114 
115     choice = argc - 1;
116     end_str = argv[choice--];
117 
118     if (!progs_digit_check(end_str)) {
119 	resizefs_print_usage();
120 	return 0xfe;
121     }
122 
123     start_str = argv[choice--];
124 
125     if (!progs_digit_check(start_str)) {
126 	libreiserfs_exception_fetch_all();
127 	if (progs_dev_check(start_str)) {
128 	    libreiserfs_exception_leave_all();
129 	    host_dev = start_str;
130 	    start_str = NULL;
131 	} else {
132 	    libreiserfs_exception_leave_all();
133 	    libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
134 		_("Device %s doesn't exists or invalid."), start_str);
135 	    return 0xfe;
136 	}
137     } else
138     	host_dev = argv[choice];
139 
140     /* Checking given device for validness */
141     if (!progs_dev_check(host_dev)) {
142         libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
143 	   _("Device %s doesn't exists or invalid."), host_dev);
144 	return 0xfe;
145     }
146 
147     /* Creating device abstraction layer */
148     if (!(host_dal = file_open(host_dev, DEFAULT_BLOCK_SIZE,
149         O_RDWR)))
150     {
151 	libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
152 	    _("Couldn't open device %s. %s."), host_dev, strerror(errno));
153     	goto error;
154     }
155 
156     if (journal_dev) {
157     	if (!strcmp(journal_dev, host_dev))
158 	   journal_dal = NULL;
159 	else {
160 	    if (!(journal_dal = file_open(journal_dev, dal_get_blocksize(host_dal),
161 		O_RDONLY)))
162 	    {
163 		libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
164 		    _("Couldn't open device %s. %s."), journal_dev, strerror(errno));
165 		goto error_free_host_dal;
166 	    }
167 	}
168     }
169 
170     if (!(fs = reiserfs_fs_open(host_dal,
171 	(!journal ? NULL : (journal_dal ? journal_dal : host_dal)))))
172     {
173     	libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
174 	    _("Couldn't open reiserfs on device %s."), host_dev);
175 	goto error_free_journal_dal;
176     }
177 
178     if ((start_str && !(start = progs_digit_parse(start_str,
179 	reiserfs_fs_block_size(fs), &error)) && error) || start < 0)
180     {
181 	libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
182 	    _("Invalid \"start\" modificator (%s)."), start_str);
183 	goto error_free_fs;
184     }
185 
186     if (!(end = progs_digit_parse(end_str,
187 	reiserfs_fs_block_size(fs), &error)) && error)
188     {
189 	libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
190 	    _("Invalid \"end\" modificator (%s)."), end_str);
191 	goto error_free_fs;
192     }
193 
194     if (end_str[0] == '-' || end_str[0] == '+')
195 	end += reiserfs_fs_size(fs);
196 
197     if (end < 0) {
198 	libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
199 	    _("Invalid filesystem size (%d)."), end_str);
200 	goto error_free_fs;
201     }
202 
203     dev_len = dal_len(host_dal);
204 
205     if (force) {
206 	if (end > dev_len)
207 	    end = dev_len;
208 
209 	if ((blk_t)end < reiserfs_fs_min_size(fs))
210 	    end = reiserfs_fs_min_size(fs);
211     } else {
212 	if (end > dev_len) {
213 	    libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
214 		_("Can't resize filesystem outside the device."));
215 	    goto error_free_fs;
216 	}
217     }
218 
219     choice = 'y';
220     if (!quiet) {
221 	if (!(choice = progs_choose("ynYN", _("Please select (y/n) "),
222 		_("Are you ready (y/n) "))))
223 	    goto error_free_fs;
224     }
225 
226     if (choice == 'n' || choice == 'N')
227 	goto error_free_fs;
228 
229     fprintf(stderr, _("Resizing %s\n"), host_dev);
230     fflush(stderr);
231 
232     if (!(gauge = libreiserfs_gauge_create(REISERFS_GAUGE_PERCENTAGE, NULL, NULL)))
233 	goto error_free_fs;
234 
235     libreiserfs_set_gauge(gauge);
236 
237     if (!(start == 0 ? reiserfs_fs_resize_dumb(fs, end) :
238 	reiserfs_fs_resize_smart(fs, start, end)))
239     {
240 	libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
241 	    _("Couldn't resize filesystem on %s to %lu - %lu blocks."), host_dev,
242 	    start, end);
243 	goto error_free_gauge;
244     }
245 
246     libreiserfs_gauge_free(gauge);
247     libreiserfs_set_gauge(NULL);
248 
249     reiserfs_fs_close(fs);
250 
251     if (!(gauge = libreiserfs_gauge_create(REISERFS_GAUGE_SILENT, _("syncing"), NULL)))
252 	goto error_free_journal_dal;
253 
254     libreiserfs_set_gauge(gauge);
255 
256     if (journal_dal) {
257 	if (!dal_sync(journal_dal)) {
258 	    libreiserfs_exception_throw(EXCEPTION_WARNING, EXCEPTION_OK,
259 		"Can't synchronize device %s. %s.",
260 		dal_name(journal_dal), dal_error(journal_dal));
261 	}
262 	file_close(journal_dal);
263     }
264 
265     if (!dal_sync(host_dal)) {
266 	libreiserfs_exception_throw(EXCEPTION_WARNING, EXCEPTION_OK,
267 	    "Can't synchronize device %s. %s.",
268 	    dal_name(host_dal), dal_error(host_dal));
269     }
270     file_close(host_dal);
271 
272     libreiserfs_gauge_finish(gauge, 1);
273     libreiserfs_gauge_free(gauge);
274     libreiserfs_set_gauge(NULL);
275 
276     return 0;
277 
278 error_free_gauge:
279     libreiserfs_gauge_free(gauge);
280     libreiserfs_set_gauge(NULL);
281 error_free_fs:
282     reiserfs_fs_close(fs);
283 error_free_journal_dal:
284     if (journal_dal)
285 	file_close(journal_dal);
286 error_free_host_dal:
287     file_close(host_dal);
288 error:
289     return 0xff;
290 }
291 
292