blob: e75a8c3c4418db399a21146820c5aed0df39d37a [file] [log] [blame]
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +00001/*
2 * main.c --- ext2 resizer main program
3 *
4 * Copyright (C) 1997 Theodore Ts'o
5 *
6 * %Begin-Header%
7 * All rights reserved.
8 * %End-Header%
9 */
10
Theodore Ts'oc762c8e1997-06-17 03:52:12 +000011#ifdef HAVE_GETOPT_H
12#include <getopt.h>
13#endif
14#include <fcntl.h>
15#include <sys/ioctl.h>
16
17
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +000018#include "resize2fs.h"
19
Theodore Ts'o0e14f781998-02-27 06:04:23 +000020#include "../version.h"
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +000021
22char *program_name, *device_name;
23
Theodore Ts'oc762c8e1997-06-17 03:52:12 +000024static volatile void usage (char *prog)
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +000025{
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +000026 fprintf (stderr, "usage: %s [-d debug_flags] [-f] [-F] [-p] device new-size\n", prog);
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +000027 exit (1);
28}
29
Theodore Ts'o3b627e81998-02-24 20:24:49 +000030static errcode_t resize_progress_func(ext2_resize_t rfs, int pass,
31 unsigned long cur, unsigned long max)
Theodore Ts'o63b44fb1998-02-13 22:58:18 +000032{
33 ext2_sim_progmeter progress;
34 const char *label;
35 errcode_t retval;
36
37 progress = (ext2_sim_progmeter) rfs->prog_data;
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +000038 if (max == 0)
Theodore Ts'o3b627e81998-02-24 20:24:49 +000039 return 0;
Theodore Ts'o63b44fb1998-02-13 22:58:18 +000040 if (cur == 0) {
41 if (progress)
42 ext2fs_progress_close(progress);
43 progress = 0;
44 switch (pass) {
Theodore Ts'oa8519a21998-02-16 22:16:20 +000045 case E2_RSZ_EXTEND_ITABLE_PASS:
46 label = "Extending the inode table";
Theodore Ts'o63b44fb1998-02-13 22:58:18 +000047 break;
48 case E2_RSZ_BLOCK_RELOC_PASS:
49 label = "Relocating blocks";
50 break;
Theodore Ts'oa8519a21998-02-16 22:16:20 +000051 case E2_RSZ_INODE_SCAN_PASS:
52 label = "Scanning inode table";
Theodore Ts'o63b44fb1998-02-13 22:58:18 +000053 break;
54 case E2_RSZ_INODE_REF_UPD_PASS:
55 label = "Updating inode references";
56 break;
57 case E2_RSZ_MOVE_ITABLE_PASS:
58 label = "Moving inode table";
59 break;
Theodore Ts'oa8519a21998-02-16 22:16:20 +000060 default:
61 label = "Unknown pass?!?";
62 break;
Theodore Ts'o63b44fb1998-02-13 22:58:18 +000063 }
64 printf("Begin pass %d (max = %lu)\n", pass, max);
65 retval = ext2fs_progress_init(&progress, label, 30,
66 40, max, 0);
67 if (retval)
68 progress = 0;
69 rfs->prog_data = (void *) progress;
70 }
71 if (progress)
72 ext2fs_progress_update(progress, cur);
73 if (cur >= max) {
74 if (progress)
75 ext2fs_progress_close(progress);
76 progress = 0;
77 rfs->prog_data = 0;
78 }
Theodore Ts'o3b627e81998-02-24 20:24:49 +000079 return 0;
Theodore Ts'o63b44fb1998-02-13 22:58:18 +000080}
81
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +000082static void check_mount(char *device_name)
83{
84 errcode_t retval;
85 int mount_flags;
86
87 retval = ext2fs_check_if_mounted(device_name, &mount_flags);
88 if (retval) {
89 com_err("ext2fs_check_if_mount", retval,
90 "while determining whether %s is mounted.",
91 device_name);
92 return;
93 }
94 if (!(mount_flags & EXT2_MF_MOUNTED))
95 return;
96
97 fprintf(stderr, "%s is mounted; can't resize a "
98 "mounted filesystem!\n\n", device_name);
99 exit(1);
100}
101
102
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000103void main (int argc, char ** argv)
104{
105 errcode_t retval;
106 ext2_filsys fs;
107 int c;
Theodore Ts'o05e112a1997-06-14 07:28:44 +0000108 int flags = 0;
Theodore Ts'oc762c8e1997-06-17 03:52:12 +0000109 int flush = 0;
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000110 int force = 0;
Theodore Ts'oc762c8e1997-06-17 03:52:12 +0000111 int fd;
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000112 blk_t new_size = 0;
113 blk_t max_size = 0;
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000114 io_manager io_ptr;
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000115 char *tmp;
116
117 initialize_ext2_error_table();
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000118
119 fprintf (stderr, "resize2fs %s, %s for EXT2 FS %s, %s\n",
120 E2FSPROGS_VERSION, E2FSPROGS_DATE,
121 EXT2FS_VERSION, EXT2FS_DATE);
Theodore Ts'o59fa3691998-03-07 23:26:26 +0000122 fprintf(stderr, "Copyright 1998 by Theodore Ts'o and PowerQuest, Inc. All Rights Reserved.\n\n");
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000123 if (argc && *argv)
124 program_name = *argv;
125
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000126 while ((c = getopt (argc, argv, "d:fFhp")) != EOF) {
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000127 switch (c) {
128 case 'h':
129 usage(program_name);
130 break;
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000131 case 'f':
132 force = 1;
133 break;
Theodore Ts'oc762c8e1997-06-17 03:52:12 +0000134 case 'F':
135 flush = 1;
136 break;
Theodore Ts'o05e112a1997-06-14 07:28:44 +0000137 case 'd':
138 flags |= atoi(optarg);
139 break;
140 case 'p':
141 flags |= RESIZE_PERCENT_COMPLETE;
142 break;
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000143 default:
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000144 usage(program_name);
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000145 }
146 }
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000147 if (optind == argc)
148 usage(program_name);
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000149 device_name = argv[optind++];
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000150 if (optind < argc) {
151 new_size = strtoul(argv[optind++], &tmp, 0);
152 if (*tmp) {
153 com_err(program_name, 0, "bad filesystem size - %s",
154 argv[optind - 1]);
155 exit(1);
156 }
157 }
158 if (optind < argc)
159 usage(program_name);
160
161 check_mount(device_name);
162
Theodore Ts'oc762c8e1997-06-17 03:52:12 +0000163 if (flush) {
164#ifdef BLKFLSBUF
165 fd = open(device_name, O_RDONLY, 0);
166
167 if (fd < 0) {
168 com_err("open", errno, "while opening %s for flushing",
169 device_name);
170 exit(1);
171 }
172 if (ioctl(fd, BLKFLSBUF, 0) < 0) {
173 com_err("BLKFLSBUF", errno, "while trying to flush %s",
174 device_name);
175 exit(1);
176 }
177 close(fd);
178#else
179 fprintf(stderr, "BLKFLSBUF not supported");
180 exit(1);
181#endif /* BLKFLSBUF */
182 }
183
Theodore Ts'o05e112a1997-06-14 07:28:44 +0000184 if (flags & RESIZE_DEBUG_IO) {
185 io_ptr = test_io_manager;
186 test_io_backing_manager = unix_io_manager;
187 } else
188 io_ptr = unix_io_manager;
189
Theodore Ts'o1e1da291997-06-09 14:51:29 +0000190 retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0,
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000191 io_ptr, &fs);
192 if (retval) {
193 com_err (program_name, retval, "while trying to open %s",
194 device_name);
195 printf ("Couldn't find valid filesystem superblock.\n");
196 exit (1);
197 }
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000198
199 /*
200 * Get the size of the containing partition, and use this for
201 * defaults and for making sure the new filesystme doesn't
202 * exceed the partition size.
203 */
204 retval = ext2fs_get_device_size(device_name, fs->blocksize,
205 &max_size);
206 if (retval) {
207 com_err(program_name, retval,
208 "while trying to determine filesystem size");
209 exit(1);
210 }
211 if (!new_size)
212 new_size = max_size;
213 if (!force && (new_size > max_size)) {
214 fprintf(stderr, "The containing partition (or device)"
215 " is only %d blocks.\nYou requested a new size"
216 " of %d blocks.\n\n", max_size,
217 new_size);
218 exit(1);
219 }
220 if (new_size == fs->super->s_blocks_count) {
221 fprintf(stderr, "The filesystem is already %d blocks "
222 "long. Nothing to do!\n\n", new_size);
223 exit(0);
224 }
225 if (!force && (fs->super->s_lastcheck < fs->super->s_mtime)) {
226 fprintf(stderr, "Please run 'e2fsck -f %s' first.\n\n",
227 device_name);
228 exit(1);
229 }
Theodore Ts'oa8519a21998-02-16 22:16:20 +0000230 retval = resize_fs(fs, new_size, flags,
231 ((flags & RESIZE_PERCENT_COMPLETE) ?
232 resize_progress_func : 0));
Theodore Ts'o1e1da291997-06-09 14:51:29 +0000233 if (retval) {
234 com_err(program_name, retval, "while trying to resize %s",
235 device_name);
236 ext2fs_close (fs);
237 }
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000238 exit (0);
239}