]>
Commit | Line | Data |
---|---|---|
63985320 TT |
1 | /* |
2 | * util.c --- helper functions used by tune2fs and mke2fs | |
efc6f628 | 3 | * |
63985320 TT |
4 | * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o. |
5 | * | |
6 | * %Begin-Header% | |
7 | * This file may be redistributed under the terms of the GNU Public | |
8 | * License. | |
9 | * %End-Header% | |
10 | */ | |
11 | ||
f1644c32 | 12 | #ifndef _LARGEFILE_SOURCE |
6ef3920a | 13 | #define _LARGEFILE_SOURCE |
f1644c32 TT |
14 | #endif |
15 | #ifndef _LARGEFILE64_SOURCE | |
6ef3920a | 16 | #define _LARGEFILE64_SOURCE |
f1644c32 | 17 | #endif |
6ef3920a | 18 | |
d1154eb4 | 19 | #include "config.h" |
802146c0 | 20 | #include <fcntl.h> |
f83f4132 TT |
21 | #include <setjmp.h> |
22 | #include <signal.h> | |
63985320 TT |
23 | #include <stdio.h> |
24 | #include <string.h> | |
25 | #ifdef HAVE_ERRNO_H | |
26 | #include <errno.h> | |
27 | #endif | |
7fd53740 AD |
28 | #if HAVE_UNISTD_H |
29 | #include <unistd.h> | |
30 | #endif | |
63985320 TT |
31 | #ifdef HAVE_LINUX_MAJOR_H |
32 | #include <linux/major.h> | |
d71a495d | 33 | #endif |
802146c0 | 34 | #include <sys/types.h> |
d71a495d | 35 | #ifdef HAVE_SYS_STAT_H |
63985320 TT |
36 | #include <sys/stat.h> |
37 | #endif | |
3120a50e AD |
38 | #ifdef HAVE_UNISTD_H |
39 | #include <unistd.h> | |
40 | #endif | |
0f5eba75 | 41 | #include <time.h> |
63985320 TT |
42 | |
43 | #include "et/com_err.h" | |
44 | #include "e2p/e2p.h" | |
54c637d4 | 45 | #include "ext2fs/ext2_fs.h" |
63985320 | 46 | #include "ext2fs/ext2fs.h" |
99ceb8ec | 47 | #include "support/nls-enable.h" |
ed1b33e8 | 48 | #include "blkid/blkid.h" |
63985320 TT |
49 | #include "util.h" |
50 | ||
b818205f TT |
51 | char *journal_location_string = NULL; |
52 | ||
63985320 TT |
53 | #ifndef HAVE_STRCASECMP |
54 | int strcasecmp (char *s1, char *s2) | |
55 | { | |
56 | while (*s1 && *s2) { | |
57 | int ch1 = *s1++, ch2 = *s2++; | |
58 | if (isupper (ch1)) | |
59 | ch1 = tolower (ch1); | |
60 | if (isupper (ch2)) | |
61 | ch2 = tolower (ch2); | |
62 | if (ch1 != ch2) | |
63 | return ch1 - ch2; | |
64 | } | |
65 | return *s1 ? 1 : *s2 ? -1 : 0; | |
66 | } | |
67 | #endif | |
68 | ||
0072f8de AD |
69 | /* |
70 | * Given argv[0], return the program name. | |
71 | */ | |
72 | char *get_progname(char *argv_zero) | |
73 | { | |
74 | char *cp; | |
75 | ||
76 | cp = strrchr(argv_zero, '/'); | |
77 | if (!cp ) | |
78 | return argv_zero; | |
79 | else | |
80 | return cp+1; | |
81 | } | |
82 | ||
f83f4132 TT |
83 | static jmp_buf alarm_env; |
84 | ||
25f291c9 | 85 | static void alarm_signal(int signal EXT2FS_ATTR((unused))) |
f83f4132 TT |
86 | { |
87 | longjmp(alarm_env, 1); | |
88 | } | |
89 | ||
90 | void proceed_question(int delay) | |
63985320 TT |
91 | { |
92 | char buf[256]; | |
c8c071a0 | 93 | const char *short_yes = _("yY"); |
63985320 TT |
94 | |
95 | fflush(stdout); | |
96 | fflush(stderr); | |
f83f4132 TT |
97 | if (delay > 0) { |
98 | if (setjmp(alarm_env)) { | |
99 | signal(SIGALRM, SIG_IGN); | |
3120a50e | 100 | printf("%s", _("<proceeding>\n")); |
f83f4132 TT |
101 | return; |
102 | } | |
103 | signal(SIGALRM, alarm_signal); | |
c3c7edcb | 104 | printf(_("Proceed anyway (or wait %d seconds to proceed) ? (y,N) "), |
f83f4132 TT |
105 | delay); |
106 | alarm(delay); | |
107 | } else | |
57fd2036 | 108 | fputs(_("Proceed anyway? (y,N) "), stdout); |
63985320 | 109 | buf[0] = 0; |
d9039ae0 | 110 | if (!fgets(buf, sizeof(buf), stdin) || |
f83f4132 TT |
111 | strchr(short_yes, buf[0]) == 0) { |
112 | putc('\n', stdout); | |
63985320 | 113 | exit(1); |
f83f4132 TT |
114 | } |
115 | signal(SIGALRM, SIG_IGN); | |
63985320 TT |
116 | } |
117 | ||
63985320 TT |
118 | void check_mount(const char *device, int force, const char *type) |
119 | { | |
120 | errcode_t retval; | |
121 | int mount_flags; | |
122 | ||
123 | retval = ext2fs_check_if_mounted(device, &mount_flags); | |
124 | if (retval) { | |
125 | com_err("ext2fs_check_if_mount", retval, | |
126 | _("while determining whether %s is mounted."), | |
127 | device); | |
128 | return; | |
129 | } | |
2fa8f37f TT |
130 | if (mount_flags & EXT2_MF_MOUNTED) { |
131 | fprintf(stderr, _("%s is mounted; "), device); | |
82896cbe | 132 | if (force >= 2) { |
2fa8f37f TT |
133 | fputs(_("mke2fs forced anyway. Hope /etc/mtab is " |
134 | "incorrect.\n"), stderr); | |
135 | return; | |
136 | } | |
137 | abort_mke2fs: | |
63985320 TT |
138 | fprintf(stderr, _("will not make a %s here!\n"), type); |
139 | exit(1); | |
140 | } | |
2fa8f37f TT |
141 | if (mount_flags & EXT2_MF_BUSY) { |
142 | fprintf(stderr, _("%s is apparently in use by the system; "), | |
143 | device); | |
82896cbe | 144 | if (force >= 2) { |
2fa8f37f TT |
145 | fputs(_("mke2fs forced anyway.\n"), stderr); |
146 | return; | |
147 | } | |
148 | goto abort_mke2fs; | |
149 | } | |
63985320 TT |
150 | } |
151 | ||
152 | void parse_journal_opts(const char *opts) | |
153 | { | |
154 | char *buf, *token, *next, *p, *arg; | |
155 | int len; | |
156 | int journal_usage = 0; | |
157 | ||
158 | len = strlen(opts); | |
159 | buf = malloc(len+1); | |
160 | if (!buf) { | |
54434927 TT |
161 | fputs(_("Couldn't allocate memory to parse journal " |
162 | "options!\n"), stderr); | |
63985320 TT |
163 | exit(1); |
164 | } | |
165 | strcpy(buf, opts); | |
166 | for (token = buf; token && *token; token = next) { | |
167 | p = strchr(token, ','); | |
168 | next = 0; | |
169 | if (p) { | |
170 | *p = 0; | |
171 | next = p+1; | |
efc6f628 | 172 | } |
63985320 TT |
173 | arg = strchr(token, '='); |
174 | if (arg) { | |
175 | *arg = 0; | |
176 | arg++; | |
177 | } | |
178 | #if 0 | |
179 | printf("Journal option=%s, argument=%s\n", token, | |
180 | arg ? arg : "NONE"); | |
181 | #endif | |
182 | if (strcmp(token, "device") == 0) { | |
ed1b33e8 | 183 | journal_device = blkid_get_devname(NULL, arg, NULL); |
2d15576d | 184 | if (!journal_device) { |
1bb14a22 ES |
185 | if (arg) |
186 | fprintf(stderr, _("\nCould not find " | |
187 | "journal device matching %s\n"), | |
188 | arg); | |
63985320 TT |
189 | journal_usage++; |
190 | continue; | |
191 | } | |
63985320 TT |
192 | } else if (strcmp(token, "size") == 0) { |
193 | if (!arg) { | |
194 | journal_usage++; | |
195 | continue; | |
196 | } | |
197 | journal_size = strtoul(arg, &p, 0); | |
2537b6d0 | 198 | if (*p) |
63985320 | 199 | journal_usage++; |
b818205f TT |
200 | } else if (!strcmp(token, "location")) { |
201 | if (!arg) { | |
202 | journal_usage++; | |
203 | continue; | |
204 | } | |
205 | journal_location_string = strdup(arg); | |
63985320 TT |
206 | } else if (strcmp(token, "v1_superblock") == 0) { |
207 | journal_flags |= EXT2_MKJOURNAL_V1_SUPER; | |
208 | continue; | |
d6a27e00 TT |
209 | } else |
210 | journal_usage++; | |
63985320 TT |
211 | } |
212 | if (journal_usage) { | |
54434927 | 213 | fputs(_("\nBad journal options specified.\n\n" |
63985320 TT |
214 | "Journal options are separated by commas, " |
215 | "and may take an argument which\n" | |
216 | "\tis set off by an equals ('=') sign.\n\n" | |
ddc32a04 | 217 | "Valid journal options are:\n" |
63985320 | 218 | "\tsize=<journal size in megabytes>\n" |
b818205f TT |
219 | "\tdevice=<journal device>\n" |
220 | "\tlocation=<journal location>\n\n" | |
2537b6d0 | 221 | "The journal size must be between " |
7087bbec | 222 | "1024 and 10240000 filesystem blocks.\n\n"), stderr); |
45415c2d | 223 | free(buf); |
63985320 TT |
224 | exit(1); |
225 | } | |
45415c2d | 226 | free(buf); |
efc6f628 | 227 | } |
63985320 | 228 | |
5683e6e2 | 229 | /* |
2537b6d0 TT |
230 | * Determine the number of journal blocks to use, either via |
231 | * user-specified # of megabytes, or via some intelligently selected | |
232 | * defaults. | |
efc6f628 | 233 | * |
5683e6e2 TT |
234 | * Find a reasonable journal file size (in blocks) given the number of blocks |
235 | * in the filesystem. For very small filesystems, it is not reasonable to | |
236 | * have a journal that fills more than half of the filesystem. | |
237 | */ | |
d4e0b1c6 | 238 | unsigned int figure_journal_size(int size, ext2_filsys fs) |
5683e6e2 | 239 | { |
56d12367 | 240 | int j_blocks; |
5683e6e2 | 241 | |
4efbac6f | 242 | j_blocks = ext2fs_default_journal_size(ext2fs_blocks_count(fs->super)); |
56d12367 | 243 | if (j_blocks < 0) { |
54434927 | 244 | fputs(_("\nFilesystem too small for a journal\n"), stderr); |
2537b6d0 TT |
245 | return 0; |
246 | } | |
efc6f628 | 247 | |
9dc6ad1e | 248 | if (size > 0) { |
4ea7bd04 | 249 | j_blocks = size * 1024 / (fs->blocksize / 1024); |
f331acbe | 250 | if (j_blocks < 1024 || j_blocks > 10240000) { |
2537b6d0 TT |
251 | fprintf(stderr, _("\nThe requested journal " |
252 | "size is %d blocks; it must be\n" | |
f331acbe | 253 | "between 1024 and 10240000 blocks. " |
2537b6d0 TT |
254 | "Aborting.\n"), |
255 | j_blocks); | |
256 | exit(1); | |
257 | } | |
4efbac6f | 258 | if ((unsigned) j_blocks > ext2fs_free_blocks_count(fs->super) / 2) { |
54434927 TT |
259 | fputs(_("\nJournal size too big for filesystem.\n"), |
260 | stderr); | |
2537b6d0 TT |
261 | exit(1); |
262 | } | |
2537b6d0 | 263 | } |
5683e6e2 TT |
264 | return j_blocks; |
265 | } | |
2537b6d0 | 266 | |
14b283ae | 267 | void print_check_message(int mnt, unsigned int check) |
66cf2f60 | 268 | { |
14b283ae TT |
269 | if (mnt < 0) |
270 | mnt = 0; | |
271 | if (!mnt && !check) | |
272 | return; | |
66cf2f60 TT |
273 | printf(_("This filesystem will be automatically " |
274 | "checked every %d mounts or\n" | |
275 | "%g days, whichever comes first. " | |
276 | "Use tune2fs -c or -i to override.\n"), | |
faa2dcda | 277 | mnt, ((double) check) / (3600 * 24)); |
66cf2f60 | 278 | } |
0f5eba75 AD |
279 | |
280 | void dump_mmp_msg(struct mmp_struct *mmp, const char *msg) | |
281 | { | |
282 | ||
283 | if (msg) | |
284 | printf("MMP check failed: %s\n", msg); | |
285 | if (mmp) { | |
286 | time_t t = mmp->mmp_time; | |
287 | ||
288 | printf("MMP error info: last update: %s node: %s device: %s\n", | |
289 | ctime(&t), mmp->mmp_nodename, mmp->mmp_bdevname); | |
290 | } | |
291 | } |