1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * main.c --- ext2 resizer main program
3*6a54128fSAndroid Build Coastguard Worker *
4*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 1997, 1998 by Theodore Ts'o and
5*6a54128fSAndroid Build Coastguard Worker * PowerQuest, Inc.
6*6a54128fSAndroid Build Coastguard Worker *
7*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 by Theodore Ts'o
8*6a54128fSAndroid Build Coastguard Worker *
9*6a54128fSAndroid Build Coastguard Worker * %Begin-Header%
10*6a54128fSAndroid Build Coastguard Worker * This file may be redistributed under the terms of the GNU Public
11*6a54128fSAndroid Build Coastguard Worker * License.
12*6a54128fSAndroid Build Coastguard Worker * %End-Header%
13*6a54128fSAndroid Build Coastguard Worker */
14*6a54128fSAndroid Build Coastguard Worker
15*6a54128fSAndroid Build Coastguard Worker #ifndef _LARGEFILE_SOURCE
16*6a54128fSAndroid Build Coastguard Worker #define _LARGEFILE_SOURCE
17*6a54128fSAndroid Build Coastguard Worker #endif
18*6a54128fSAndroid Build Coastguard Worker #ifndef _LARGEFILE64_SOURCE
19*6a54128fSAndroid Build Coastguard Worker #define _LARGEFILE64_SOURCE
20*6a54128fSAndroid Build Coastguard Worker #endif
21*6a54128fSAndroid Build Coastguard Worker
22*6a54128fSAndroid Build Coastguard Worker #include "config.h"
23*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_GETOPT_H
24*6a54128fSAndroid Build Coastguard Worker #include <getopt.h>
25*6a54128fSAndroid Build Coastguard Worker #else
26*6a54128fSAndroid Build Coastguard Worker extern char *optarg;
27*6a54128fSAndroid Build Coastguard Worker extern int optind;
28*6a54128fSAndroid Build Coastguard Worker #endif
29*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
30*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_STDLIB_H
31*6a54128fSAndroid Build Coastguard Worker #include <stdlib.h>
32*6a54128fSAndroid Build Coastguard Worker #endif
33*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
34*6a54128fSAndroid Build Coastguard Worker #include <sys/stat.h>
35*6a54128fSAndroid Build Coastguard Worker #include <fcntl.h>
36*6a54128fSAndroid Build Coastguard Worker #include <libgen.h>
37*6a54128fSAndroid Build Coastguard Worker
38*6a54128fSAndroid Build Coastguard Worker #include "e2p/e2p.h"
39*6a54128fSAndroid Build Coastguard Worker
40*6a54128fSAndroid Build Coastguard Worker #include "resize2fs.h"
41*6a54128fSAndroid Build Coastguard Worker
42*6a54128fSAndroid Build Coastguard Worker #include "../version.h"
43*6a54128fSAndroid Build Coastguard Worker
44*6a54128fSAndroid Build Coastguard Worker char *program_name;
45*6a54128fSAndroid Build Coastguard Worker static char *device_name, *io_options;
46*6a54128fSAndroid Build Coastguard Worker
usage(char * prog)47*6a54128fSAndroid Build Coastguard Worker static void usage (char *prog)
48*6a54128fSAndroid Build Coastguard Worker {
49*6a54128fSAndroid Build Coastguard Worker fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] "
50*6a54128fSAndroid Build Coastguard Worker "[-p] device [-b|-s|new_size] [-S RAID-stride] "
51*6a54128fSAndroid Build Coastguard Worker "[-z undo_file]\n\n"),
52*6a54128fSAndroid Build Coastguard Worker prog ? prog : "resize2fs");
53*6a54128fSAndroid Build Coastguard Worker
54*6a54128fSAndroid Build Coastguard Worker exit (1);
55*6a54128fSAndroid Build Coastguard Worker }
56*6a54128fSAndroid Build Coastguard Worker
resize_progress_func(ext2_resize_t rfs,int pass,unsigned long cur,unsigned long max)57*6a54128fSAndroid Build Coastguard Worker static errcode_t resize_progress_func(ext2_resize_t rfs, int pass,
58*6a54128fSAndroid Build Coastguard Worker unsigned long cur, unsigned long max)
59*6a54128fSAndroid Build Coastguard Worker {
60*6a54128fSAndroid Build Coastguard Worker ext2_sim_progmeter progress;
61*6a54128fSAndroid Build Coastguard Worker const char *label;
62*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
63*6a54128fSAndroid Build Coastguard Worker
64*6a54128fSAndroid Build Coastguard Worker progress = (ext2_sim_progmeter) rfs->prog_data;
65*6a54128fSAndroid Build Coastguard Worker if (max == 0)
66*6a54128fSAndroid Build Coastguard Worker return 0;
67*6a54128fSAndroid Build Coastguard Worker if (cur == 0) {
68*6a54128fSAndroid Build Coastguard Worker if (progress)
69*6a54128fSAndroid Build Coastguard Worker ext2fs_progress_close(progress);
70*6a54128fSAndroid Build Coastguard Worker progress = 0;
71*6a54128fSAndroid Build Coastguard Worker switch (pass) {
72*6a54128fSAndroid Build Coastguard Worker case E2_RSZ_EXTEND_ITABLE_PASS:
73*6a54128fSAndroid Build Coastguard Worker label = _("Extending the inode table");
74*6a54128fSAndroid Build Coastguard Worker break;
75*6a54128fSAndroid Build Coastguard Worker case E2_RSZ_BLOCK_RELOC_PASS:
76*6a54128fSAndroid Build Coastguard Worker label = _("Relocating blocks");
77*6a54128fSAndroid Build Coastguard Worker break;
78*6a54128fSAndroid Build Coastguard Worker case E2_RSZ_INODE_SCAN_PASS:
79*6a54128fSAndroid Build Coastguard Worker label = _("Scanning inode table");
80*6a54128fSAndroid Build Coastguard Worker break;
81*6a54128fSAndroid Build Coastguard Worker case E2_RSZ_INODE_REF_UPD_PASS:
82*6a54128fSAndroid Build Coastguard Worker label = _("Updating inode references");
83*6a54128fSAndroid Build Coastguard Worker break;
84*6a54128fSAndroid Build Coastguard Worker case E2_RSZ_MOVE_ITABLE_PASS:
85*6a54128fSAndroid Build Coastguard Worker label = _("Moving inode table");
86*6a54128fSAndroid Build Coastguard Worker break;
87*6a54128fSAndroid Build Coastguard Worker default:
88*6a54128fSAndroid Build Coastguard Worker label = _("Unknown pass?!?");
89*6a54128fSAndroid Build Coastguard Worker break;
90*6a54128fSAndroid Build Coastguard Worker }
91*6a54128fSAndroid Build Coastguard Worker printf(_("Begin pass %d (max = %lu)\n"), pass, max);
92*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_progress_init(&progress, label, 30,
93*6a54128fSAndroid Build Coastguard Worker 40, max, 0);
94*6a54128fSAndroid Build Coastguard Worker if (retval)
95*6a54128fSAndroid Build Coastguard Worker progress = 0;
96*6a54128fSAndroid Build Coastguard Worker rfs->prog_data = (void *) progress;
97*6a54128fSAndroid Build Coastguard Worker }
98*6a54128fSAndroid Build Coastguard Worker if (progress)
99*6a54128fSAndroid Build Coastguard Worker ext2fs_progress_update(progress, cur);
100*6a54128fSAndroid Build Coastguard Worker if (cur >= max) {
101*6a54128fSAndroid Build Coastguard Worker if (progress)
102*6a54128fSAndroid Build Coastguard Worker ext2fs_progress_close(progress);
103*6a54128fSAndroid Build Coastguard Worker progress = 0;
104*6a54128fSAndroid Build Coastguard Worker rfs->prog_data = 0;
105*6a54128fSAndroid Build Coastguard Worker }
106*6a54128fSAndroid Build Coastguard Worker return 0;
107*6a54128fSAndroid Build Coastguard Worker }
108*6a54128fSAndroid Build Coastguard Worker
determine_fs_stride(ext2_filsys fs)109*6a54128fSAndroid Build Coastguard Worker static void determine_fs_stride(ext2_filsys fs)
110*6a54128fSAndroid Build Coastguard Worker {
111*6a54128fSAndroid Build Coastguard Worker unsigned int group;
112*6a54128fSAndroid Build Coastguard Worker unsigned long long sum;
113*6a54128fSAndroid Build Coastguard Worker unsigned int has_sb, prev_has_sb = 0, num;
114*6a54128fSAndroid Build Coastguard Worker unsigned int flexbg_size = 1U << fs->super->s_log_groups_per_flex;
115*6a54128fSAndroid Build Coastguard Worker int i_stride, b_stride;
116*6a54128fSAndroid Build Coastguard Worker
117*6a54128fSAndroid Build Coastguard Worker if (fs->stride)
118*6a54128fSAndroid Build Coastguard Worker return;
119*6a54128fSAndroid Build Coastguard Worker num = 0; sum = 0;
120*6a54128fSAndroid Build Coastguard Worker for (group = 0; group < fs->group_desc_count; group++) {
121*6a54128fSAndroid Build Coastguard Worker has_sb = ext2fs_bg_has_super(fs, group);
122*6a54128fSAndroid Build Coastguard Worker if (group == 0 || has_sb != prev_has_sb)
123*6a54128fSAndroid Build Coastguard Worker goto next;
124*6a54128fSAndroid Build Coastguard Worker b_stride = ext2fs_block_bitmap_loc(fs, group) -
125*6a54128fSAndroid Build Coastguard Worker ext2fs_block_bitmap_loc(fs, group - 1) -
126*6a54128fSAndroid Build Coastguard Worker fs->super->s_blocks_per_group;
127*6a54128fSAndroid Build Coastguard Worker i_stride = ext2fs_inode_bitmap_loc(fs, group) -
128*6a54128fSAndroid Build Coastguard Worker ext2fs_inode_bitmap_loc(fs, group - 1) -
129*6a54128fSAndroid Build Coastguard Worker fs->super->s_blocks_per_group;
130*6a54128fSAndroid Build Coastguard Worker if (b_stride != i_stride ||
131*6a54128fSAndroid Build Coastguard Worker b_stride < 0 ||
132*6a54128fSAndroid Build Coastguard Worker (flexbg_size > 1 && (group % flexbg_size == 0)))
133*6a54128fSAndroid Build Coastguard Worker goto next;
134*6a54128fSAndroid Build Coastguard Worker
135*6a54128fSAndroid Build Coastguard Worker /* printf("group %d has stride %d\n", group, b_stride); */
136*6a54128fSAndroid Build Coastguard Worker sum += b_stride;
137*6a54128fSAndroid Build Coastguard Worker num++;
138*6a54128fSAndroid Build Coastguard Worker
139*6a54128fSAndroid Build Coastguard Worker next:
140*6a54128fSAndroid Build Coastguard Worker prev_has_sb = has_sb;
141*6a54128fSAndroid Build Coastguard Worker }
142*6a54128fSAndroid Build Coastguard Worker
143*6a54128fSAndroid Build Coastguard Worker if (fs->group_desc_count > 12 && num < 3)
144*6a54128fSAndroid Build Coastguard Worker sum = 0;
145*6a54128fSAndroid Build Coastguard Worker
146*6a54128fSAndroid Build Coastguard Worker if (num)
147*6a54128fSAndroid Build Coastguard Worker fs->stride = sum / num;
148*6a54128fSAndroid Build Coastguard Worker else
149*6a54128fSAndroid Build Coastguard Worker fs->stride = 0;
150*6a54128fSAndroid Build Coastguard Worker
151*6a54128fSAndroid Build Coastguard Worker fs->super->s_raid_stride = fs->stride;
152*6a54128fSAndroid Build Coastguard Worker ext2fs_mark_super_dirty(fs);
153*6a54128fSAndroid Build Coastguard Worker
154*6a54128fSAndroid Build Coastguard Worker #if 0
155*6a54128fSAndroid Build Coastguard Worker if (fs->stride)
156*6a54128fSAndroid Build Coastguard Worker printf("Using RAID stride of %d\n", fs->stride);
157*6a54128fSAndroid Build Coastguard Worker #endif
158*6a54128fSAndroid Build Coastguard Worker }
159*6a54128fSAndroid Build Coastguard Worker
bigalloc_check(ext2_filsys fs,int force)160*6a54128fSAndroid Build Coastguard Worker static void bigalloc_check(ext2_filsys fs, int force)
161*6a54128fSAndroid Build Coastguard Worker {
162*6a54128fSAndroid Build Coastguard Worker if (!force && ext2fs_has_feature_bigalloc(fs->super)) {
163*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "%s", _("\nResizing bigalloc file systems has "
164*6a54128fSAndroid Build Coastguard Worker "not been fully tested. Proceed at\n"
165*6a54128fSAndroid Build Coastguard Worker "your own risk! Use the force option "
166*6a54128fSAndroid Build Coastguard Worker "if you want to go ahead anyway.\n\n"));
167*6a54128fSAndroid Build Coastguard Worker exit(1);
168*6a54128fSAndroid Build Coastguard Worker }
169*6a54128fSAndroid Build Coastguard Worker }
170*6a54128fSAndroid Build Coastguard Worker
resize2fs_setup_tdb(const char * device,char * undo_file,io_manager * io_ptr)171*6a54128fSAndroid Build Coastguard Worker static int resize2fs_setup_tdb(const char *device, char *undo_file,
172*6a54128fSAndroid Build Coastguard Worker io_manager *io_ptr)
173*6a54128fSAndroid Build Coastguard Worker {
174*6a54128fSAndroid Build Coastguard Worker errcode_t retval = ENOMEM;
175*6a54128fSAndroid Build Coastguard Worker const char *tdb_dir = NULL;
176*6a54128fSAndroid Build Coastguard Worker char *tdb_file = NULL;
177*6a54128fSAndroid Build Coastguard Worker char *dev_name, *tmp_name;
178*6a54128fSAndroid Build Coastguard Worker
179*6a54128fSAndroid Build Coastguard Worker /* (re)open a specific undo file */
180*6a54128fSAndroid Build Coastguard Worker if (undo_file && undo_file[0] != 0) {
181*6a54128fSAndroid Build Coastguard Worker retval = set_undo_io_backing_manager(*io_ptr);
182*6a54128fSAndroid Build Coastguard Worker if (retval)
183*6a54128fSAndroid Build Coastguard Worker goto err;
184*6a54128fSAndroid Build Coastguard Worker *io_ptr = undo_io_manager;
185*6a54128fSAndroid Build Coastguard Worker retval = set_undo_io_backup_file(undo_file);
186*6a54128fSAndroid Build Coastguard Worker if (retval)
187*6a54128fSAndroid Build Coastguard Worker goto err;
188*6a54128fSAndroid Build Coastguard Worker printf(_("Overwriting existing filesystem; this can be undone "
189*6a54128fSAndroid Build Coastguard Worker "using the command:\n"
190*6a54128fSAndroid Build Coastguard Worker " e2undo %s %s\n\n"),
191*6a54128fSAndroid Build Coastguard Worker undo_file, device);
192*6a54128fSAndroid Build Coastguard Worker return retval;
193*6a54128fSAndroid Build Coastguard Worker }
194*6a54128fSAndroid Build Coastguard Worker
195*6a54128fSAndroid Build Coastguard Worker /*
196*6a54128fSAndroid Build Coastguard Worker * Configuration via a conf file would be
197*6a54128fSAndroid Build Coastguard Worker * nice
198*6a54128fSAndroid Build Coastguard Worker */
199*6a54128fSAndroid Build Coastguard Worker tdb_dir = getenv("E2FSPROGS_UNDO_DIR");
200*6a54128fSAndroid Build Coastguard Worker if (!tdb_dir)
201*6a54128fSAndroid Build Coastguard Worker tdb_dir = "/var/lib/e2fsprogs";
202*6a54128fSAndroid Build Coastguard Worker
203*6a54128fSAndroid Build Coastguard Worker if (!strcmp(tdb_dir, "none") || (tdb_dir[0] == 0) ||
204*6a54128fSAndroid Build Coastguard Worker access(tdb_dir, W_OK))
205*6a54128fSAndroid Build Coastguard Worker return 0;
206*6a54128fSAndroid Build Coastguard Worker
207*6a54128fSAndroid Build Coastguard Worker tmp_name = strdup(device);
208*6a54128fSAndroid Build Coastguard Worker if (!tmp_name)
209*6a54128fSAndroid Build Coastguard Worker goto errout;
210*6a54128fSAndroid Build Coastguard Worker dev_name = basename(tmp_name);
211*6a54128fSAndroid Build Coastguard Worker tdb_file = malloc(strlen(tdb_dir) + 11 + strlen(dev_name) + 7 + 1);
212*6a54128fSAndroid Build Coastguard Worker if (!tdb_file) {
213*6a54128fSAndroid Build Coastguard Worker free(tmp_name);
214*6a54128fSAndroid Build Coastguard Worker goto errout;
215*6a54128fSAndroid Build Coastguard Worker }
216*6a54128fSAndroid Build Coastguard Worker sprintf(tdb_file, "%s/resize2fs-%s.e2undo", tdb_dir, dev_name);
217*6a54128fSAndroid Build Coastguard Worker free(tmp_name);
218*6a54128fSAndroid Build Coastguard Worker
219*6a54128fSAndroid Build Coastguard Worker if ((unlink(tdb_file) < 0) && (errno != ENOENT)) {
220*6a54128fSAndroid Build Coastguard Worker retval = errno;
221*6a54128fSAndroid Build Coastguard Worker com_err(program_name, retval,
222*6a54128fSAndroid Build Coastguard Worker _("while trying to delete %s"), tdb_file);
223*6a54128fSAndroid Build Coastguard Worker goto errout;
224*6a54128fSAndroid Build Coastguard Worker }
225*6a54128fSAndroid Build Coastguard Worker
226*6a54128fSAndroid Build Coastguard Worker retval = set_undo_io_backing_manager(*io_ptr);
227*6a54128fSAndroid Build Coastguard Worker if (retval)
228*6a54128fSAndroid Build Coastguard Worker goto errout;
229*6a54128fSAndroid Build Coastguard Worker *io_ptr = undo_io_manager;
230*6a54128fSAndroid Build Coastguard Worker retval = set_undo_io_backup_file(tdb_file);
231*6a54128fSAndroid Build Coastguard Worker if (retval)
232*6a54128fSAndroid Build Coastguard Worker goto errout;
233*6a54128fSAndroid Build Coastguard Worker printf(_("Overwriting existing filesystem; this can be undone "
234*6a54128fSAndroid Build Coastguard Worker "using the command:\n"
235*6a54128fSAndroid Build Coastguard Worker " e2undo %s %s\n\n"), tdb_file, device);
236*6a54128fSAndroid Build Coastguard Worker
237*6a54128fSAndroid Build Coastguard Worker free(tdb_file);
238*6a54128fSAndroid Build Coastguard Worker return 0;
239*6a54128fSAndroid Build Coastguard Worker errout:
240*6a54128fSAndroid Build Coastguard Worker free(tdb_file);
241*6a54128fSAndroid Build Coastguard Worker err:
242*6a54128fSAndroid Build Coastguard Worker com_err(program_name, retval, "%s",
243*6a54128fSAndroid Build Coastguard Worker _("while trying to setup undo file\n"));
244*6a54128fSAndroid Build Coastguard Worker return retval;
245*6a54128fSAndroid Build Coastguard Worker }
246*6a54128fSAndroid Build Coastguard Worker
main(int argc,char ** argv)247*6a54128fSAndroid Build Coastguard Worker int main (int argc, char ** argv)
248*6a54128fSAndroid Build Coastguard Worker {
249*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
250*6a54128fSAndroid Build Coastguard Worker ext2_filsys fs;
251*6a54128fSAndroid Build Coastguard Worker int c;
252*6a54128fSAndroid Build Coastguard Worker int flags = 0;
253*6a54128fSAndroid Build Coastguard Worker int flush = 0;
254*6a54128fSAndroid Build Coastguard Worker int force = 0;
255*6a54128fSAndroid Build Coastguard Worker int io_flags = 0;
256*6a54128fSAndroid Build Coastguard Worker int force_min_size = 0;
257*6a54128fSAndroid Build Coastguard Worker int print_min_size = 0;
258*6a54128fSAndroid Build Coastguard Worker int fd, ret;
259*6a54128fSAndroid Build Coastguard Worker int open_flags = O_RDWR;
260*6a54128fSAndroid Build Coastguard Worker blk64_t new_size = 0;
261*6a54128fSAndroid Build Coastguard Worker blk64_t max_size = 0;
262*6a54128fSAndroid Build Coastguard Worker blk64_t min_size = 0;
263*6a54128fSAndroid Build Coastguard Worker io_manager io_ptr;
264*6a54128fSAndroid Build Coastguard Worker char *new_size_str = 0;
265*6a54128fSAndroid Build Coastguard Worker int use_stride = -1;
266*6a54128fSAndroid Build Coastguard Worker ext2fs_struct_stat st_buf;
267*6a54128fSAndroid Build Coastguard Worker __s64 new_file_size;
268*6a54128fSAndroid Build Coastguard Worker unsigned int sys_page_size = 4096;
269*6a54128fSAndroid Build Coastguard Worker unsigned int blocksize;
270*6a54128fSAndroid Build Coastguard Worker long sysval;
271*6a54128fSAndroid Build Coastguard Worker int len, mount_flags;
272*6a54128fSAndroid Build Coastguard Worker char *mtpt, *undo_file = NULL;
273*6a54128fSAndroid Build Coastguard Worker dgrp_t new_group_desc_count;
274*6a54128fSAndroid Build Coastguard Worker unsigned long new_desc_blocks;
275*6a54128fSAndroid Build Coastguard Worker
276*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_NLS
277*6a54128fSAndroid Build Coastguard Worker setlocale(LC_MESSAGES, "");
278*6a54128fSAndroid Build Coastguard Worker setlocale(LC_CTYPE, "");
279*6a54128fSAndroid Build Coastguard Worker bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
280*6a54128fSAndroid Build Coastguard Worker textdomain(NLS_CAT_NAME);
281*6a54128fSAndroid Build Coastguard Worker set_com_err_gettext(gettext);
282*6a54128fSAndroid Build Coastguard Worker #endif
283*6a54128fSAndroid Build Coastguard Worker
284*6a54128fSAndroid Build Coastguard Worker add_error_table(&et_ext2_error_table);
285*6a54128fSAndroid Build Coastguard Worker
286*6a54128fSAndroid Build Coastguard Worker fprintf (stderr, "resize2fs %s (%s)\n",
287*6a54128fSAndroid Build Coastguard Worker E2FSPROGS_VERSION, E2FSPROGS_DATE);
288*6a54128fSAndroid Build Coastguard Worker if (argc && *argv)
289*6a54128fSAndroid Build Coastguard Worker program_name = *argv;
290*6a54128fSAndroid Build Coastguard Worker else
291*6a54128fSAndroid Build Coastguard Worker usage(NULL);
292*6a54128fSAndroid Build Coastguard Worker
293*6a54128fSAndroid Build Coastguard Worker while ((c = getopt(argc, argv, "d:fFhMPpS:bsz:")) != EOF) {
294*6a54128fSAndroid Build Coastguard Worker switch (c) {
295*6a54128fSAndroid Build Coastguard Worker case 'h':
296*6a54128fSAndroid Build Coastguard Worker usage(program_name);
297*6a54128fSAndroid Build Coastguard Worker break;
298*6a54128fSAndroid Build Coastguard Worker case 'f':
299*6a54128fSAndroid Build Coastguard Worker force = 1;
300*6a54128fSAndroid Build Coastguard Worker break;
301*6a54128fSAndroid Build Coastguard Worker case 'F':
302*6a54128fSAndroid Build Coastguard Worker flush = 1;
303*6a54128fSAndroid Build Coastguard Worker break;
304*6a54128fSAndroid Build Coastguard Worker case 'M':
305*6a54128fSAndroid Build Coastguard Worker force_min_size = 1;
306*6a54128fSAndroid Build Coastguard Worker break;
307*6a54128fSAndroid Build Coastguard Worker case 'P':
308*6a54128fSAndroid Build Coastguard Worker print_min_size = 1;
309*6a54128fSAndroid Build Coastguard Worker break;
310*6a54128fSAndroid Build Coastguard Worker case 'd':
311*6a54128fSAndroid Build Coastguard Worker flags |= atoi(optarg);
312*6a54128fSAndroid Build Coastguard Worker break;
313*6a54128fSAndroid Build Coastguard Worker case 'p':
314*6a54128fSAndroid Build Coastguard Worker flags |= RESIZE_PERCENT_COMPLETE;
315*6a54128fSAndroid Build Coastguard Worker break;
316*6a54128fSAndroid Build Coastguard Worker case 'S':
317*6a54128fSAndroid Build Coastguard Worker use_stride = atoi(optarg);
318*6a54128fSAndroid Build Coastguard Worker break;
319*6a54128fSAndroid Build Coastguard Worker case 'b':
320*6a54128fSAndroid Build Coastguard Worker flags |= RESIZE_ENABLE_64BIT;
321*6a54128fSAndroid Build Coastguard Worker break;
322*6a54128fSAndroid Build Coastguard Worker case 's':
323*6a54128fSAndroid Build Coastguard Worker flags |= RESIZE_DISABLE_64BIT;
324*6a54128fSAndroid Build Coastguard Worker break;
325*6a54128fSAndroid Build Coastguard Worker case 'z':
326*6a54128fSAndroid Build Coastguard Worker undo_file = optarg;
327*6a54128fSAndroid Build Coastguard Worker break;
328*6a54128fSAndroid Build Coastguard Worker default:
329*6a54128fSAndroid Build Coastguard Worker usage(program_name);
330*6a54128fSAndroid Build Coastguard Worker }
331*6a54128fSAndroid Build Coastguard Worker }
332*6a54128fSAndroid Build Coastguard Worker if (optind == argc)
333*6a54128fSAndroid Build Coastguard Worker usage(program_name);
334*6a54128fSAndroid Build Coastguard Worker
335*6a54128fSAndroid Build Coastguard Worker device_name = argv[optind++];
336*6a54128fSAndroid Build Coastguard Worker if (optind < argc)
337*6a54128fSAndroid Build Coastguard Worker new_size_str = argv[optind++];
338*6a54128fSAndroid Build Coastguard Worker if (optind < argc)
339*6a54128fSAndroid Build Coastguard Worker usage(program_name);
340*6a54128fSAndroid Build Coastguard Worker
341*6a54128fSAndroid Build Coastguard Worker io_options = strchr(device_name, '?');
342*6a54128fSAndroid Build Coastguard Worker if (io_options)
343*6a54128fSAndroid Build Coastguard Worker *io_options++ = 0;
344*6a54128fSAndroid Build Coastguard Worker
345*6a54128fSAndroid Build Coastguard Worker /*
346*6a54128fSAndroid Build Coastguard Worker * Figure out whether or not the device is mounted, and if it is
347*6a54128fSAndroid Build Coastguard Worker * where it is mounted.
348*6a54128fSAndroid Build Coastguard Worker */
349*6a54128fSAndroid Build Coastguard Worker len=80;
350*6a54128fSAndroid Build Coastguard Worker while (1) {
351*6a54128fSAndroid Build Coastguard Worker mtpt = malloc(len);
352*6a54128fSAndroid Build Coastguard Worker if (!mtpt)
353*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
354*6a54128fSAndroid Build Coastguard Worker mtpt[len-1] = 0;
355*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_check_mount_point(device_name, &mount_flags,
356*6a54128fSAndroid Build Coastguard Worker mtpt, len);
357*6a54128fSAndroid Build Coastguard Worker if (retval) {
358*6a54128fSAndroid Build Coastguard Worker com_err("ext2fs_check_mount_point", retval,
359*6a54128fSAndroid Build Coastguard Worker _("while determining whether %s is mounted."),
360*6a54128fSAndroid Build Coastguard Worker device_name);
361*6a54128fSAndroid Build Coastguard Worker exit(1);
362*6a54128fSAndroid Build Coastguard Worker }
363*6a54128fSAndroid Build Coastguard Worker if (!(mount_flags & EXT2_MF_MOUNTED) || (mtpt[len-1] == 0))
364*6a54128fSAndroid Build Coastguard Worker break;
365*6a54128fSAndroid Build Coastguard Worker free(mtpt);
366*6a54128fSAndroid Build Coastguard Worker len = 2 * len;
367*6a54128fSAndroid Build Coastguard Worker }
368*6a54128fSAndroid Build Coastguard Worker
369*6a54128fSAndroid Build Coastguard Worker if (print_min_size)
370*6a54128fSAndroid Build Coastguard Worker open_flags = O_RDONLY;
371*6a54128fSAndroid Build Coastguard Worker
372*6a54128fSAndroid Build Coastguard Worker fd = ext2fs_open_file(device_name, open_flags, 0);
373*6a54128fSAndroid Build Coastguard Worker if (fd < 0) {
374*6a54128fSAndroid Build Coastguard Worker com_err("open", errno, _("while opening %s"),
375*6a54128fSAndroid Build Coastguard Worker device_name);
376*6a54128fSAndroid Build Coastguard Worker exit(1);
377*6a54128fSAndroid Build Coastguard Worker }
378*6a54128fSAndroid Build Coastguard Worker
379*6a54128fSAndroid Build Coastguard Worker ret = ext2fs_fstat(fd, &st_buf);
380*6a54128fSAndroid Build Coastguard Worker if (ret < 0) {
381*6a54128fSAndroid Build Coastguard Worker com_err("open", errno,
382*6a54128fSAndroid Build Coastguard Worker _("while getting stat information for %s"),
383*6a54128fSAndroid Build Coastguard Worker device_name);
384*6a54128fSAndroid Build Coastguard Worker exit(1);
385*6a54128fSAndroid Build Coastguard Worker }
386*6a54128fSAndroid Build Coastguard Worker
387*6a54128fSAndroid Build Coastguard Worker if (flush) {
388*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_sync_device(fd, 1);
389*6a54128fSAndroid Build Coastguard Worker if (retval) {
390*6a54128fSAndroid Build Coastguard Worker com_err(argv[0], retval,
391*6a54128fSAndroid Build Coastguard Worker _("while trying to flush %s"),
392*6a54128fSAndroid Build Coastguard Worker device_name);
393*6a54128fSAndroid Build Coastguard Worker exit(1);
394*6a54128fSAndroid Build Coastguard Worker }
395*6a54128fSAndroid Build Coastguard Worker }
396*6a54128fSAndroid Build Coastguard Worker
397*6a54128fSAndroid Build Coastguard Worker if (!S_ISREG(st_buf.st_mode )) {
398*6a54128fSAndroid Build Coastguard Worker close(fd);
399*6a54128fSAndroid Build Coastguard Worker fd = -1;
400*6a54128fSAndroid Build Coastguard Worker }
401*6a54128fSAndroid Build Coastguard Worker
402*6a54128fSAndroid Build Coastguard Worker #ifdef CONFIG_TESTIO_DEBUG
403*6a54128fSAndroid Build Coastguard Worker if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
404*6a54128fSAndroid Build Coastguard Worker io_ptr = test_io_manager;
405*6a54128fSAndroid Build Coastguard Worker test_io_backing_manager = unix_io_manager;
406*6a54128fSAndroid Build Coastguard Worker } else
407*6a54128fSAndroid Build Coastguard Worker #endif
408*6a54128fSAndroid Build Coastguard Worker io_ptr = unix_io_manager;
409*6a54128fSAndroid Build Coastguard Worker
410*6a54128fSAndroid Build Coastguard Worker if (!(mount_flags & EXT2_MF_MOUNTED) && !print_min_size)
411*6a54128fSAndroid Build Coastguard Worker io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE;
412*6a54128fSAndroid Build Coastguard Worker
413*6a54128fSAndroid Build Coastguard Worker io_flags |= EXT2_FLAG_64BITS | EXT2_FLAG_THREADS;
414*6a54128fSAndroid Build Coastguard Worker if (undo_file) {
415*6a54128fSAndroid Build Coastguard Worker retval = resize2fs_setup_tdb(device_name, undo_file, &io_ptr);
416*6a54128fSAndroid Build Coastguard Worker if (retval)
417*6a54128fSAndroid Build Coastguard Worker exit(1);
418*6a54128fSAndroid Build Coastguard Worker }
419*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_open2(device_name, io_options, io_flags,
420*6a54128fSAndroid Build Coastguard Worker 0, 0, io_ptr, &fs);
421*6a54128fSAndroid Build Coastguard Worker if (retval) {
422*6a54128fSAndroid Build Coastguard Worker com_err(program_name, retval, _("while trying to open %s"),
423*6a54128fSAndroid Build Coastguard Worker device_name);
424*6a54128fSAndroid Build Coastguard Worker printf("%s", _("Couldn't find valid filesystem superblock.\n"));
425*6a54128fSAndroid Build Coastguard Worker exit (1);
426*6a54128fSAndroid Build Coastguard Worker }
427*6a54128fSAndroid Build Coastguard Worker fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
428*6a54128fSAndroid Build Coastguard Worker
429*6a54128fSAndroid Build Coastguard Worker /*
430*6a54128fSAndroid Build Coastguard Worker * Before acting on an unmounted filesystem, make sure it's ok,
431*6a54128fSAndroid Build Coastguard Worker * unless the user is forcing it.
432*6a54128fSAndroid Build Coastguard Worker *
433*6a54128fSAndroid Build Coastguard Worker * We do ERROR and VALID checks even if we're only printing the
434*6a54128fSAndroid Build Coastguard Worker * minimum size, because traversal of a badly damaged filesystem
435*6a54128fSAndroid Build Coastguard Worker * can cause issues as well. We don't require it to be fscked after
436*6a54128fSAndroid Build Coastguard Worker * the last mount time in this case, though, as this is a bit less
437*6a54128fSAndroid Build Coastguard Worker * risky.
438*6a54128fSAndroid Build Coastguard Worker */
439*6a54128fSAndroid Build Coastguard Worker if (!force && !(mount_flags & EXT2_MF_MOUNTED)) {
440*6a54128fSAndroid Build Coastguard Worker int checkit = 0;
441*6a54128fSAndroid Build Coastguard Worker
442*6a54128fSAndroid Build Coastguard Worker if (fs->super->s_state & EXT2_ERROR_FS)
443*6a54128fSAndroid Build Coastguard Worker checkit = 1;
444*6a54128fSAndroid Build Coastguard Worker
445*6a54128fSAndroid Build Coastguard Worker if ((fs->super->s_state & EXT2_VALID_FS) == 0)
446*6a54128fSAndroid Build Coastguard Worker checkit = 1;
447*6a54128fSAndroid Build Coastguard Worker
448*6a54128fSAndroid Build Coastguard Worker if ((fs->super->s_lastcheck < fs->super->s_mtime) &&
449*6a54128fSAndroid Build Coastguard Worker !print_min_size)
450*6a54128fSAndroid Build Coastguard Worker checkit = 1;
451*6a54128fSAndroid Build Coastguard Worker
452*6a54128fSAndroid Build Coastguard Worker if ((ext2fs_free_blocks_count(fs->super) >
453*6a54128fSAndroid Build Coastguard Worker ext2fs_blocks_count(fs->super)) ||
454*6a54128fSAndroid Build Coastguard Worker (fs->super->s_free_inodes_count > fs->super->s_inodes_count))
455*6a54128fSAndroid Build Coastguard Worker checkit = 1;
456*6a54128fSAndroid Build Coastguard Worker
457*6a54128fSAndroid Build Coastguard Worker if ((fs->super->s_last_orphan != 0) ||
458*6a54128fSAndroid Build Coastguard Worker ext2fs_has_feature_journal_needs_recovery(fs->super))
459*6a54128fSAndroid Build Coastguard Worker checkit = 1;
460*6a54128fSAndroid Build Coastguard Worker
461*6a54128fSAndroid Build Coastguard Worker if (checkit) {
462*6a54128fSAndroid Build Coastguard Worker fprintf(stderr,
463*6a54128fSAndroid Build Coastguard Worker _("Please run 'e2fsck -f %s' first.\n\n"),
464*6a54128fSAndroid Build Coastguard Worker device_name);
465*6a54128fSAndroid Build Coastguard Worker goto errout;
466*6a54128fSAndroid Build Coastguard Worker }
467*6a54128fSAndroid Build Coastguard Worker }
468*6a54128fSAndroid Build Coastguard Worker
469*6a54128fSAndroid Build Coastguard Worker /*
470*6a54128fSAndroid Build Coastguard Worker * Check for compatibility with the feature sets. We need to
471*6a54128fSAndroid Build Coastguard Worker * be more stringent than ext2fs_open().
472*6a54128fSAndroid Build Coastguard Worker */
473*6a54128fSAndroid Build Coastguard Worker if (fs->super->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) {
474*6a54128fSAndroid Build Coastguard Worker com_err(program_name, EXT2_ET_UNSUPP_FEATURE,
475*6a54128fSAndroid Build Coastguard Worker "(%s)", device_name);
476*6a54128fSAndroid Build Coastguard Worker goto errout;
477*6a54128fSAndroid Build Coastguard Worker }
478*6a54128fSAndroid Build Coastguard Worker
479*6a54128fSAndroid Build Coastguard Worker min_size = calculate_minimum_resize_size(fs, flags);
480*6a54128fSAndroid Build Coastguard Worker
481*6a54128fSAndroid Build Coastguard Worker if (print_min_size) {
482*6a54128fSAndroid Build Coastguard Worker printf(_("Estimated minimum size of the filesystem: %llu\n"),
483*6a54128fSAndroid Build Coastguard Worker (unsigned long long) min_size);
484*6a54128fSAndroid Build Coastguard Worker success_exit:
485*6a54128fSAndroid Build Coastguard Worker (void) ext2fs_close_free(&fs);
486*6a54128fSAndroid Build Coastguard Worker remove_error_table(&et_ext2_error_table);
487*6a54128fSAndroid Build Coastguard Worker exit(0);
488*6a54128fSAndroid Build Coastguard Worker }
489*6a54128fSAndroid Build Coastguard Worker
490*6a54128fSAndroid Build Coastguard Worker /* Determine the system page size if possible */
491*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYSCONF
492*6a54128fSAndroid Build Coastguard Worker #if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
493*6a54128fSAndroid Build Coastguard Worker #define _SC_PAGESIZE _SC_PAGE_SIZE
494*6a54128fSAndroid Build Coastguard Worker #endif
495*6a54128fSAndroid Build Coastguard Worker #ifdef _SC_PAGESIZE
496*6a54128fSAndroid Build Coastguard Worker sysval = sysconf(_SC_PAGESIZE);
497*6a54128fSAndroid Build Coastguard Worker if (sysval > 0)
498*6a54128fSAndroid Build Coastguard Worker sys_page_size = sysval;
499*6a54128fSAndroid Build Coastguard Worker #endif /* _SC_PAGESIZE */
500*6a54128fSAndroid Build Coastguard Worker #endif /* HAVE_SYSCONF */
501*6a54128fSAndroid Build Coastguard Worker
502*6a54128fSAndroid Build Coastguard Worker /*
503*6a54128fSAndroid Build Coastguard Worker * Get the size of the containing partition, and use this for
504*6a54128fSAndroid Build Coastguard Worker * defaults and for making sure the new filesystem doesn't
505*6a54128fSAndroid Build Coastguard Worker * exceed the partition size.
506*6a54128fSAndroid Build Coastguard Worker */
507*6a54128fSAndroid Build Coastguard Worker blocksize = fs->blocksize;
508*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_device_size2(device_name, blocksize,
509*6a54128fSAndroid Build Coastguard Worker &max_size);
510*6a54128fSAndroid Build Coastguard Worker if (retval) {
511*6a54128fSAndroid Build Coastguard Worker com_err(program_name, retval, "%s",
512*6a54128fSAndroid Build Coastguard Worker _("while trying to determine filesystem size"));
513*6a54128fSAndroid Build Coastguard Worker goto errout;
514*6a54128fSAndroid Build Coastguard Worker }
515*6a54128fSAndroid Build Coastguard Worker if (force_min_size)
516*6a54128fSAndroid Build Coastguard Worker new_size = min_size;
517*6a54128fSAndroid Build Coastguard Worker else if (new_size_str) {
518*6a54128fSAndroid Build Coastguard Worker new_size = parse_num_blocks2(new_size_str,
519*6a54128fSAndroid Build Coastguard Worker fs->super->s_log_block_size);
520*6a54128fSAndroid Build Coastguard Worker if (new_size == 0) {
521*6a54128fSAndroid Build Coastguard Worker com_err(program_name, 0,
522*6a54128fSAndroid Build Coastguard Worker _("Invalid new size: %s\n"), new_size_str);
523*6a54128fSAndroid Build Coastguard Worker goto errout;
524*6a54128fSAndroid Build Coastguard Worker }
525*6a54128fSAndroid Build Coastguard Worker } else {
526*6a54128fSAndroid Build Coastguard Worker new_size = max_size;
527*6a54128fSAndroid Build Coastguard Worker /* Round down to an even multiple of a pagesize */
528*6a54128fSAndroid Build Coastguard Worker if (sys_page_size > blocksize)
529*6a54128fSAndroid Build Coastguard Worker new_size &= ~((blk64_t)((sys_page_size / blocksize)-1));
530*6a54128fSAndroid Build Coastguard Worker }
531*6a54128fSAndroid Build Coastguard Worker /* If changing 64bit, don't change the filesystem size. */
532*6a54128fSAndroid Build Coastguard Worker if (flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT)) {
533*6a54128fSAndroid Build Coastguard Worker new_size = ext2fs_blocks_count(fs->super);
534*6a54128fSAndroid Build Coastguard Worker }
535*6a54128fSAndroid Build Coastguard Worker if (!ext2fs_has_feature_64bit(fs->super)) {
536*6a54128fSAndroid Build Coastguard Worker /* Take 16T down to 2^32-1 blocks */
537*6a54128fSAndroid Build Coastguard Worker if (new_size == (1ULL << 32))
538*6a54128fSAndroid Build Coastguard Worker new_size--;
539*6a54128fSAndroid Build Coastguard Worker else if (new_size > (1ULL << 32)) {
540*6a54128fSAndroid Build Coastguard Worker com_err(program_name, 0, "%s",
541*6a54128fSAndroid Build Coastguard Worker _("New size too large to be "
542*6a54128fSAndroid Build Coastguard Worker "expressed in 32 bits\n"));
543*6a54128fSAndroid Build Coastguard Worker goto errout;
544*6a54128fSAndroid Build Coastguard Worker }
545*6a54128fSAndroid Build Coastguard Worker }
546*6a54128fSAndroid Build Coastguard Worker
547*6a54128fSAndroid Build Coastguard Worker /* If using cluster allocations, trim down to a cluster boundary */
548*6a54128fSAndroid Build Coastguard Worker if (ext2fs_has_feature_bigalloc(fs->super)) {
549*6a54128fSAndroid Build Coastguard Worker new_size &= ~((blk64_t)(1ULL << fs->cluster_ratio_bits) - 1);
550*6a54128fSAndroid Build Coastguard Worker }
551*6a54128fSAndroid Build Coastguard Worker
552*6a54128fSAndroid Build Coastguard Worker new_group_desc_count = ext2fs_div64_ceil(new_size -
553*6a54128fSAndroid Build Coastguard Worker fs->super->s_first_data_block,
554*6a54128fSAndroid Build Coastguard Worker EXT2_BLOCKS_PER_GROUP(fs->super));
555*6a54128fSAndroid Build Coastguard Worker new_desc_blocks = ext2fs_div_ceil(new_group_desc_count,
556*6a54128fSAndroid Build Coastguard Worker EXT2_DESC_PER_BLOCK(fs->super));
557*6a54128fSAndroid Build Coastguard Worker if ((new_desc_blocks + fs->super->s_first_data_block) >
558*6a54128fSAndroid Build Coastguard Worker EXT2_BLOCKS_PER_GROUP(fs->super)) {
559*6a54128fSAndroid Build Coastguard Worker com_err(program_name, 0,
560*6a54128fSAndroid Build Coastguard Worker _("New size results in too many block group "
561*6a54128fSAndroid Build Coastguard Worker "descriptors.\n"));
562*6a54128fSAndroid Build Coastguard Worker goto errout;
563*6a54128fSAndroid Build Coastguard Worker }
564*6a54128fSAndroid Build Coastguard Worker
565*6a54128fSAndroid Build Coastguard Worker if (!force && new_size < min_size) {
566*6a54128fSAndroid Build Coastguard Worker com_err(program_name, 0,
567*6a54128fSAndroid Build Coastguard Worker _("New size smaller than minimum (%llu)\n"),
568*6a54128fSAndroid Build Coastguard Worker (unsigned long long) min_size);
569*6a54128fSAndroid Build Coastguard Worker goto errout;
570*6a54128fSAndroid Build Coastguard Worker }
571*6a54128fSAndroid Build Coastguard Worker if (use_stride >= 0) {
572*6a54128fSAndroid Build Coastguard Worker if (use_stride >= (int) fs->super->s_blocks_per_group) {
573*6a54128fSAndroid Build Coastguard Worker com_err(program_name, 0, "%s",
574*6a54128fSAndroid Build Coastguard Worker _("Invalid stride length"));
575*6a54128fSAndroid Build Coastguard Worker goto errout;
576*6a54128fSAndroid Build Coastguard Worker }
577*6a54128fSAndroid Build Coastguard Worker fs->stride = fs->super->s_raid_stride = use_stride;
578*6a54128fSAndroid Build Coastguard Worker ext2fs_mark_super_dirty(fs);
579*6a54128fSAndroid Build Coastguard Worker } else
580*6a54128fSAndroid Build Coastguard Worker determine_fs_stride(fs);
581*6a54128fSAndroid Build Coastguard Worker
582*6a54128fSAndroid Build Coastguard Worker /*
583*6a54128fSAndroid Build Coastguard Worker * If we are resizing a plain file, and it's not big enough,
584*6a54128fSAndroid Build Coastguard Worker * automatically extend it in a sparse fashion by writing the
585*6a54128fSAndroid Build Coastguard Worker * last requested block.
586*6a54128fSAndroid Build Coastguard Worker */
587*6a54128fSAndroid Build Coastguard Worker new_file_size = ((__u64) new_size) * blocksize;
588*6a54128fSAndroid Build Coastguard Worker if ((__u64) new_file_size >
589*6a54128fSAndroid Build Coastguard Worker (((__u64) 1) << (sizeof(st_buf.st_size)*8 - 1)) - 1)
590*6a54128fSAndroid Build Coastguard Worker fd = -1;
591*6a54128fSAndroid Build Coastguard Worker if ((new_file_size > st_buf.st_size) &&
592*6a54128fSAndroid Build Coastguard Worker (fd > 0)) {
593*6a54128fSAndroid Build Coastguard Worker if ((ext2fs_llseek(fd, new_file_size-1, SEEK_SET) >= 0) &&
594*6a54128fSAndroid Build Coastguard Worker (write(fd, "0", 1) == 1))
595*6a54128fSAndroid Build Coastguard Worker max_size = new_size;
596*6a54128fSAndroid Build Coastguard Worker }
597*6a54128fSAndroid Build Coastguard Worker if (!force && (new_size > max_size)) {
598*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, _("The containing partition (or device)"
599*6a54128fSAndroid Build Coastguard Worker " is only %llu (%dk) blocks.\nYou requested a new size"
600*6a54128fSAndroid Build Coastguard Worker " of %llu blocks.\n\n"), (unsigned long long) max_size,
601*6a54128fSAndroid Build Coastguard Worker blocksize / 1024, (unsigned long long) new_size);
602*6a54128fSAndroid Build Coastguard Worker goto errout;
603*6a54128fSAndroid Build Coastguard Worker }
604*6a54128fSAndroid Build Coastguard Worker if ((flags & RESIZE_DISABLE_64BIT) && (flags & RESIZE_ENABLE_64BIT)) {
605*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, _("Cannot set and unset 64bit feature.\n"));
606*6a54128fSAndroid Build Coastguard Worker goto errout;
607*6a54128fSAndroid Build Coastguard Worker } else if (flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT)) {
608*6a54128fSAndroid Build Coastguard Worker if (new_size >= (1ULL << 32)) {
609*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, _("Cannot change the 64bit feature "
610*6a54128fSAndroid Build Coastguard Worker "on a filesystem that is larger than "
611*6a54128fSAndroid Build Coastguard Worker "2^32 blocks.\n"));
612*6a54128fSAndroid Build Coastguard Worker goto errout;
613*6a54128fSAndroid Build Coastguard Worker }
614*6a54128fSAndroid Build Coastguard Worker if (mount_flags & EXT2_MF_MOUNTED) {
615*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, _("Cannot change the 64bit feature "
616*6a54128fSAndroid Build Coastguard Worker "while the filesystem is mounted.\n"));
617*6a54128fSAndroid Build Coastguard Worker goto errout;
618*6a54128fSAndroid Build Coastguard Worker }
619*6a54128fSAndroid Build Coastguard Worker if (flags & RESIZE_ENABLE_64BIT &&
620*6a54128fSAndroid Build Coastguard Worker !ext2fs_has_feature_extents(fs->super)) {
621*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, _("Please enable the extents feature "
622*6a54128fSAndroid Build Coastguard Worker "with tune2fs before enabling the 64bit "
623*6a54128fSAndroid Build Coastguard Worker "feature.\n"));
624*6a54128fSAndroid Build Coastguard Worker goto errout;
625*6a54128fSAndroid Build Coastguard Worker }
626*6a54128fSAndroid Build Coastguard Worker } else {
627*6a54128fSAndroid Build Coastguard Worker adjust_new_size(fs, &new_size);
628*6a54128fSAndroid Build Coastguard Worker if (new_size == ext2fs_blocks_count(fs->super)) {
629*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, _("The filesystem is already "
630*6a54128fSAndroid Build Coastguard Worker "%llu (%dk) blocks long. "
631*6a54128fSAndroid Build Coastguard Worker "Nothing to do!\n\n"),
632*6a54128fSAndroid Build Coastguard Worker (unsigned long long) new_size,
633*6a54128fSAndroid Build Coastguard Worker blocksize / 1024);
634*6a54128fSAndroid Build Coastguard Worker goto success_exit;
635*6a54128fSAndroid Build Coastguard Worker }
636*6a54128fSAndroid Build Coastguard Worker }
637*6a54128fSAndroid Build Coastguard Worker if ((flags & RESIZE_ENABLE_64BIT) &&
638*6a54128fSAndroid Build Coastguard Worker ext2fs_has_feature_64bit(fs->super)) {
639*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, _("The filesystem is already 64-bit.\n"));
640*6a54128fSAndroid Build Coastguard Worker goto success_exit;
641*6a54128fSAndroid Build Coastguard Worker }
642*6a54128fSAndroid Build Coastguard Worker if ((flags & RESIZE_DISABLE_64BIT) &&
643*6a54128fSAndroid Build Coastguard Worker !ext2fs_has_feature_64bit(fs->super)) {
644*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, _("The filesystem is already 32-bit.\n"));
645*6a54128fSAndroid Build Coastguard Worker goto success_exit;
646*6a54128fSAndroid Build Coastguard Worker }
647*6a54128fSAndroid Build Coastguard Worker if (new_size < ext2fs_blocks_count(fs->super) &&
648*6a54128fSAndroid Build Coastguard Worker ext2fs_has_feature_stable_inodes(fs->super)) {
649*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, _("Cannot shrink this filesystem "
650*6a54128fSAndroid Build Coastguard Worker "because it has the stable_inodes feature flag.\n"));
651*6a54128fSAndroid Build Coastguard Worker goto errout;
652*6a54128fSAndroid Build Coastguard Worker }
653*6a54128fSAndroid Build Coastguard Worker if (mount_flags & EXT2_MF_MOUNTED) {
654*6a54128fSAndroid Build Coastguard Worker retval = online_resize_fs(fs, mtpt, &new_size, flags);
655*6a54128fSAndroid Build Coastguard Worker } else {
656*6a54128fSAndroid Build Coastguard Worker bigalloc_check(fs, force);
657*6a54128fSAndroid Build Coastguard Worker if (flags & RESIZE_ENABLE_64BIT)
658*6a54128fSAndroid Build Coastguard Worker printf(_("Converting the filesystem to 64-bit.\n"));
659*6a54128fSAndroid Build Coastguard Worker else if (flags & RESIZE_DISABLE_64BIT)
660*6a54128fSAndroid Build Coastguard Worker printf(_("Converting the filesystem to 32-bit.\n"));
661*6a54128fSAndroid Build Coastguard Worker else
662*6a54128fSAndroid Build Coastguard Worker printf(_("Resizing the filesystem on "
663*6a54128fSAndroid Build Coastguard Worker "%s to %llu (%dk) blocks.\n"),
664*6a54128fSAndroid Build Coastguard Worker device_name, (unsigned long long) new_size,
665*6a54128fSAndroid Build Coastguard Worker blocksize / 1024);
666*6a54128fSAndroid Build Coastguard Worker retval = resize_fs(fs, &new_size, flags,
667*6a54128fSAndroid Build Coastguard Worker ((flags & RESIZE_PERCENT_COMPLETE) ?
668*6a54128fSAndroid Build Coastguard Worker resize_progress_func : 0));
669*6a54128fSAndroid Build Coastguard Worker }
670*6a54128fSAndroid Build Coastguard Worker free(mtpt);
671*6a54128fSAndroid Build Coastguard Worker if (retval) {
672*6a54128fSAndroid Build Coastguard Worker com_err(program_name, retval, _("while trying to resize %s"),
673*6a54128fSAndroid Build Coastguard Worker device_name);
674*6a54128fSAndroid Build Coastguard Worker fprintf(stderr,
675*6a54128fSAndroid Build Coastguard Worker _("Please run 'e2fsck -fy %s' to fix the filesystem\n"
676*6a54128fSAndroid Build Coastguard Worker "after the aborted resize operation.\n"),
677*6a54128fSAndroid Build Coastguard Worker device_name);
678*6a54128fSAndroid Build Coastguard Worker goto errout;
679*6a54128fSAndroid Build Coastguard Worker }
680*6a54128fSAndroid Build Coastguard Worker printf(_("The filesystem on %s is now %llu (%dk) blocks long.\n\n"),
681*6a54128fSAndroid Build Coastguard Worker device_name, (unsigned long long) new_size, blocksize / 1024);
682*6a54128fSAndroid Build Coastguard Worker
683*6a54128fSAndroid Build Coastguard Worker if ((st_buf.st_size > new_file_size) &&
684*6a54128fSAndroid Build Coastguard Worker (fd > 0)) {
685*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_FTRUNCATE64
686*6a54128fSAndroid Build Coastguard Worker retval = ftruncate64(fd, new_file_size);
687*6a54128fSAndroid Build Coastguard Worker #else
688*6a54128fSAndroid Build Coastguard Worker retval = 0;
689*6a54128fSAndroid Build Coastguard Worker /* Only truncate if new_file_size doesn't overflow off_t */
690*6a54128fSAndroid Build Coastguard Worker if (((off_t) new_file_size) == new_file_size)
691*6a54128fSAndroid Build Coastguard Worker retval = ftruncate(fd, (off_t) new_file_size);
692*6a54128fSAndroid Build Coastguard Worker #endif
693*6a54128fSAndroid Build Coastguard Worker if (retval)
694*6a54128fSAndroid Build Coastguard Worker com_err(program_name, retval,
695*6a54128fSAndroid Build Coastguard Worker _("while trying to truncate %s"),
696*6a54128fSAndroid Build Coastguard Worker device_name);
697*6a54128fSAndroid Build Coastguard Worker }
698*6a54128fSAndroid Build Coastguard Worker if (fd > 0)
699*6a54128fSAndroid Build Coastguard Worker close(fd);
700*6a54128fSAndroid Build Coastguard Worker remove_error_table(&et_ext2_error_table);
701*6a54128fSAndroid Build Coastguard Worker return 0;
702*6a54128fSAndroid Build Coastguard Worker errout:
703*6a54128fSAndroid Build Coastguard Worker (void) ext2fs_close_free(&fs);
704*6a54128fSAndroid Build Coastguard Worker remove_error_table(&et_ext2_error_table);
705*6a54128fSAndroid Build Coastguard Worker return 1;
706*6a54128fSAndroid Build Coastguard Worker }
707