blob: 42e78b651cbd9dcf4a269e871d0481f3646d6ad8 [file] [log] [blame]
Theodore Ts'o63985322001-01-03 17:02:13 +00001/*
2 * util.c --- helper functions used by tune2fs and mke2fs
3 *
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
Theodore Ts'o6ef39202001-11-13 18:49:09 -050012#define _LARGEFILE_SOURCE
13#define _LARGEFILE64_SOURCE
14
Theodore Ts'o63985322001-01-03 17:02:13 +000015#include <stdio.h>
16#include <string.h>
17#ifdef HAVE_ERRNO_H
18#include <errno.h>
19#endif
Theodore Ts'o63985322001-01-03 17:02:13 +000020#ifdef HAVE_LINUX_MAJOR_H
21#include <linux/major.h>
Theodore Ts'od71a4952001-05-07 16:53:26 +000022#endif
23#ifdef HAVE_SYS_STAT_H
Theodore Ts'o63985322001-01-03 17:02:13 +000024#include <sys/stat.h>
25#endif
26
27#include "et/com_err.h"
28#include "e2p/e2p.h"
Theodore Ts'o54c637d2001-05-14 11:45:38 +000029#include "ext2fs/ext2_fs.h"
Theodore Ts'o63985322001-01-03 17:02:13 +000030#include "ext2fs/ext2fs.h"
31#include "nls-enable.h"
Andreas Dilger2d155762001-08-17 03:48:11 -060032#include "get_device_by_label.h"
Theodore Ts'o63985322001-01-03 17:02:13 +000033#include "util.h"
34
35#ifndef HAVE_STRCASECMP
36int strcasecmp (char *s1, char *s2)
37{
38 while (*s1 && *s2) {
39 int ch1 = *s1++, ch2 = *s2++;
40 if (isupper (ch1))
41 ch1 = tolower (ch1);
42 if (isupper (ch2))
43 ch2 = tolower (ch2);
44 if (ch1 != ch2)
45 return ch1 - ch2;
46 }
47 return *s1 ? 1 : *s2 ? -1 : 0;
48}
49#endif
50
Andreas Dilger0072f8d2002-02-25 23:11:26 -070051/*
52 * Given argv[0], return the program name.
53 */
54char *get_progname(char *argv_zero)
55{
56 char *cp;
57
58 cp = strrchr(argv_zero, '/');
59 if (!cp )
60 return argv_zero;
61 else
62 return cp+1;
63}
64
Theodore Ts'o63985322001-01-03 17:02:13 +000065void proceed_question(void)
66{
67 char buf[256];
Theodore Ts'oc8c071a2001-01-11 16:08:23 +000068 const char *short_yes = _("yY");
Theodore Ts'o63985322001-01-03 17:02:13 +000069
70 fflush(stdout);
71 fflush(stderr);
72 printf(_("Proceed anyway? (y,n) "));
73 buf[0] = 0;
74 fgets(buf, sizeof(buf), stdin);
75 if (strchr(short_yes, buf[0]) == 0)
76 exit(1);
77}
78
79void check_plausibility(const char *device)
80{
81 int val;
Theodore Ts'o6ef39202001-11-13 18:49:09 -050082#ifdef HAVE_OPEN64
83 struct stat64 s;
84
85 val = stat64(device, &s);
86#else
Theodore Ts'o63985322001-01-03 17:02:13 +000087 struct stat s;
88
89 val = stat(device, &s);
Theodore Ts'o6ef39202001-11-13 18:49:09 -050090#endif
Theodore Ts'o63985322001-01-03 17:02:13 +000091
92 if(val == -1) {
93 fprintf(stderr, _("Could not stat %s --- %s\n"),
94 device, error_message(errno));
95 if (errno == ENOENT)
96 fprintf(stderr, _("\nThe device apparently does "
97 "not exist; did you specify it correctly?\n"));
98 exit(1);
99 }
100 if (!S_ISBLK(s.st_mode)) {
101 printf(_("%s is not a block special device.\n"), device);
102 proceed_question();
103 return;
104 }
105
106#ifdef HAVE_LINUX_MAJOR_H
107#ifndef MAJOR
108#define MAJOR(dev) ((dev)>>8)
109#define MINOR(dev) ((dev) & 0xff)
110#endif
111#ifndef SCSI_BLK_MAJOR
112#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR)
113#endif
114 if (((MAJOR(s.st_rdev) == HD_MAJOR &&
115 MINOR(s.st_rdev)%64 == 0) ||
116 (SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) &&
117 MINOR(s.st_rdev)%16 == 0))) {
118 printf(_("%s is entire device, not just one partition!\n"),
119 device);
120 proceed_question();
121 }
122#endif
123}
124
125void check_mount(const char *device, int force, const char *type)
126{
127 errcode_t retval;
128 int mount_flags;
129
130 retval = ext2fs_check_if_mounted(device, &mount_flags);
131 if (retval) {
132 com_err("ext2fs_check_if_mount", retval,
133 _("while determining whether %s is mounted."),
134 device);
135 return;
136 }
137 if (!(mount_flags & EXT2_MF_MOUNTED))
138 return;
139
140 fprintf(stderr, _("%s is mounted; "), device);
141 if (force) {
142 fprintf(stderr, _("mke2fs forced anyway. "
143 "Hope /etc/mtab is incorrect.\n"));
144 } else {
145 fprintf(stderr, _("will not make a %s here!\n"), type);
146 exit(1);
147 }
148}
149
150void parse_journal_opts(const char *opts)
151{
152 char *buf, *token, *next, *p, *arg;
153 int len;
154 int journal_usage = 0;
155
156 len = strlen(opts);
157 buf = malloc(len+1);
158 if (!buf) {
159 fprintf(stderr, _("Couldn't allocate memory to parse "
160 "journal options!\n"));
161 exit(1);
162 }
163 strcpy(buf, opts);
164 for (token = buf; token && *token; token = next) {
165 p = strchr(token, ',');
166 next = 0;
167 if (p) {
168 *p = 0;
169 next = p+1;
170 }
171 arg = strchr(token, '=');
172 if (arg) {
173 *arg = 0;
174 arg++;
175 }
176#if 0
177 printf("Journal option=%s, argument=%s\n", token,
178 arg ? arg : "NONE");
179#endif
180 if (strcmp(token, "device") == 0) {
Andreas Dilger2d155762001-08-17 03:48:11 -0600181 journal_device = interpret_spec(arg);
182 if (!journal_device) {
Theodore Ts'o63985322001-01-03 17:02:13 +0000183 journal_usage++;
184 continue;
185 }
Theodore Ts'o63985322001-01-03 17:02:13 +0000186 } else if (strcmp(token, "size") == 0) {
187 if (!arg) {
188 journal_usage++;
189 continue;
190 }
191 journal_size = strtoul(arg, &p, 0);
Theodore Ts'o2537b6d2001-03-26 20:07:13 +0000192 if (*p)
Theodore Ts'o63985322001-01-03 17:02:13 +0000193 journal_usage++;
Theodore Ts'o63985322001-01-03 17:02:13 +0000194 } else if (strcmp(token, "v1_superblock") == 0) {
195 journal_flags |= EXT2_MKJOURNAL_V1_SUPER;
196 continue;
Theodore Ts'od6a27e02001-04-17 02:34:41 +0000197 } else
198 journal_usage++;
Theodore Ts'o63985322001-01-03 17:02:13 +0000199 }
200 if (journal_usage) {
201 fprintf(stderr, _("\nBad journal options specified.\n\n"
202 "Journal options are separated by commas, "
203 "and may take an argument which\n"
204 "\tis set off by an equals ('=') sign.\n\n"
205 "Valid raid options are:\n"
206 "\tsize=<journal size in megabytes>\n"
207 "\tdevice=<journal device>\n\n"
Theodore Ts'o2537b6d2001-03-26 20:07:13 +0000208 "The journal size must be between "
209 "1024 and 102400 filesystem blocks.\n\n" ));
Theodore Ts'o63985322001-01-03 17:02:13 +0000210 exit(1);
211 }
212}
213
Theodore Ts'o5683e6e2001-01-18 01:47:48 +0000214/*
Theodore Ts'o2537b6d2001-03-26 20:07:13 +0000215 * Determine the number of journal blocks to use, either via
216 * user-specified # of megabytes, or via some intelligently selected
217 * defaults.
218 *
Theodore Ts'o5683e6e2001-01-18 01:47:48 +0000219 * Find a reasonable journal file size (in blocks) given the number of blocks
220 * in the filesystem. For very small filesystems, it is not reasonable to
221 * have a journal that fills more than half of the filesystem.
222 */
Theodore Ts'o4ea7bd02001-12-16 23:23:37 -0500223int figure_journal_size(int size, ext2_filsys fs)
Theodore Ts'o5683e6e2001-01-18 01:47:48 +0000224{
225 blk_t j_blocks;
226
Theodore Ts'o2537b6d2001-03-26 20:07:13 +0000227 if (fs->super->s_blocks_count < 2048) {
228 fprintf(stderr, _("\nFilesystem too small for a journal\n"));
229 return 0;
230 }
231
Theodore Ts'o4ea7bd02001-12-16 23:23:37 -0500232 if (size >= 0) {
233 j_blocks = size * 1024 / (fs->blocksize / 1024);
Theodore Ts'o2537b6d2001-03-26 20:07:13 +0000234 if (j_blocks < 1024 || j_blocks > 102400) {
235 fprintf(stderr, _("\nThe requested journal "
236 "size is %d blocks; it must be\n"
237 "between 1024 and 102400 blocks. "
238 "Aborting.\n"),
239 j_blocks);
240 exit(1);
241 }
242 if (j_blocks > fs->super->s_free_blocks_count) {
243 fprintf(stderr, _("\nJournal size too big "
244 "for filesystem.\n"));
245 exit(1);
246 }
247 return j_blocks;
248 }
249
250 if (fs->super->s_blocks_count < 32768)
Theodore Ts'o5683e6e2001-01-18 01:47:48 +0000251 j_blocks = 1024;
Theodore Ts'o2537b6d2001-03-26 20:07:13 +0000252 else if (fs->super->s_blocks_count < 262144)
Theodore Ts'o5683e6e2001-01-18 01:47:48 +0000253 j_blocks = 4096;
254 else
255 j_blocks = 8192;
256
257 return j_blocks;
258}
Theodore Ts'o2537b6d2001-03-26 20:07:13 +0000259
Theodore Ts'o66cf2f62001-06-14 06:42:44 +0000260void print_check_message(ext2_filsys fs)
261{
262 printf(_("This filesystem will be automatically "
263 "checked every %d mounts or\n"
264 "%g days, whichever comes first. "
265 "Use tune2fs -c or -i to override.\n"),
266 fs->super->s_max_mnt_count,
267 (double)fs->super->s_checkinterval / (3600 * 24));
268}