Annotation of /trunk/mkinitrd-magellan/busybox/e2fsprogs/old_e2fsprogs/util.c
Parent Directory | Revision Log
Revision 816 -
(hide annotations)
(download)
Fri Apr 24 18:33:46 2009 UTC (15 years, 1 month ago) by niro
File MIME type: text/plain
File size: 7003 byte(s)
Fri Apr 24 18:33:46 2009 UTC (15 years, 1 month ago) by niro
File MIME type: text/plain
File size: 7003 byte(s)
-updated to busybox-1.13.4
1 | niro | 532 | /* vi: set sw=4 ts=4: */ |
2 | /* | ||
3 | * util.c --- helper functions used by tune2fs and mke2fs | ||
4 | * | ||
5 | * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o. | ||
6 | * | ||
7 | * %Begin-Header% | ||
8 | * This file may be redistributed under the terms of the GNU Public | ||
9 | * License. | ||
10 | * %End-Header% | ||
11 | */ | ||
12 | |||
13 | #include <stdio.h> | ||
14 | #include <string.h> | ||
15 | #include <errno.h> | ||
16 | #include <linux/major.h> | ||
17 | #include <sys/stat.h> | ||
18 | |||
19 | #include "e2fsbb.h" | ||
20 | #include "e2p/e2p.h" | ||
21 | #include "ext2fs/ext2_fs.h" | ||
22 | #include "ext2fs/ext2fs.h" | ||
23 | #include "blkid/blkid.h" | ||
24 | #include "util.h" | ||
25 | |||
26 | void proceed_question(void) | ||
27 | { | ||
28 | fputs("Proceed anyway? (y,n) ", stdout); | ||
29 | if (bb_ask_confirmation() == 0) | ||
30 | exit(1); | ||
31 | } | ||
32 | |||
33 | void check_plausibility(const char *device, int force) | ||
34 | { | ||
35 | int val; | ||
36 | struct stat s; | ||
37 | val = stat(device, &s); | ||
38 | if (force) | ||
39 | return; | ||
40 | niro | 816 | if (val == -1) |
41 | niro | 532 | bb_perror_msg_and_die("cannot stat %s", device); |
42 | if (!S_ISBLK(s.st_mode)) { | ||
43 | printf("%s is not a block special device.\n", device); | ||
44 | proceed_question(); | ||
45 | return; | ||
46 | } | ||
47 | |||
48 | #ifdef HAVE_LINUX_MAJOR_H | ||
49 | #ifndef MAJOR | ||
50 | #define MAJOR(dev) ((dev)>>8) | ||
51 | #define MINOR(dev) ((dev) & 0xff) | ||
52 | #endif | ||
53 | #ifndef SCSI_BLK_MAJOR | ||
54 | #ifdef SCSI_DISK0_MAJOR | ||
55 | #ifdef SCSI_DISK8_MAJOR | ||
56 | #define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \ | ||
57 | ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) || \ | ||
58 | ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR)) | ||
59 | #else | ||
60 | #define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \ | ||
61 | ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR)) | ||
62 | #endif /* defined(SCSI_DISK8_MAJOR) */ | ||
63 | #define SCSI_BLK_MAJOR(M) (SCSI_DISK_MAJOR((M)) || (M) == SCSI_CDROM_MAJOR) | ||
64 | #else | ||
65 | #define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR) | ||
66 | #endif /* defined(SCSI_DISK0_MAJOR) */ | ||
67 | #endif /* defined(SCSI_BLK_MAJOR) */ | ||
68 | if (((MAJOR(s.st_rdev) == HD_MAJOR && | ||
69 | MINOR(s.st_rdev)%64 == 0) || | ||
70 | (SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) && | ||
71 | MINOR(s.st_rdev)%16 == 0))) { | ||
72 | printf("%s is entire device, not just one partition!\n", device); | ||
73 | proceed_question(); | ||
74 | } | ||
75 | #endif | ||
76 | } | ||
77 | |||
78 | void check_mount(const char *device, int force, const char *type) | ||
79 | { | ||
80 | errcode_t retval; | ||
81 | int mount_flags; | ||
82 | |||
83 | retval = ext2fs_check_if_mounted(device, &mount_flags); | ||
84 | if (retval) { | ||
85 | bb_error_msg("cannot determine if %s is mounted", device); | ||
86 | return; | ||
87 | } | ||
88 | if (mount_flags & EXT2_MF_MOUNTED) { | ||
89 | bb_error_msg("%s is mounted !", device); | ||
90 | force_check: | ||
91 | if (force) | ||
92 | bb_error_msg("badblocks forced anyways"); | ||
93 | else | ||
94 | bb_error_msg_and_die("it's not safe to run badblocks!"); | ||
95 | } | ||
96 | |||
97 | if (mount_flags & EXT2_MF_BUSY) { | ||
98 | bb_error_msg("%s is apparently in use by the system", device); | ||
99 | goto force_check; | ||
100 | } | ||
101 | |||
102 | } | ||
103 | |||
104 | void parse_journal_opts(char **journal_device, int *journal_flags, | ||
105 | int *journal_size, const char *opts) | ||
106 | { | ||
107 | char *buf, *token, *next, *p, *arg; | ||
108 | int journal_usage = 0; | ||
109 | buf = xstrdup(opts); | ||
110 | for (token = buf; token && *token; token = next) { | ||
111 | p = strchr(token, ','); | ||
112 | next = 0; | ||
113 | if (p) { | ||
114 | *p = 0; | ||
115 | next = p+1; | ||
116 | } | ||
117 | arg = strchr(token, '='); | ||
118 | if (arg) { | ||
119 | *arg = 0; | ||
120 | arg++; | ||
121 | } | ||
122 | if (strcmp(token, "device") == 0) { | ||
123 | *journal_device = blkid_get_devname(NULL, arg, NULL); | ||
124 | if (!journal_device) { | ||
125 | journal_usage++; | ||
126 | continue; | ||
127 | } | ||
128 | } else if (strcmp(token, "size") == 0) { | ||
129 | if (!arg) { | ||
130 | journal_usage++; | ||
131 | continue; | ||
132 | } | ||
133 | (*journal_size) = strtoul(arg, &p, 0); | ||
134 | if (*p) | ||
135 | journal_usage++; | ||
136 | } else if (strcmp(token, "v1_superblock") == 0) { | ||
137 | (*journal_flags) |= EXT2_MKJOURNAL_V1_SUPER; | ||
138 | continue; | ||
139 | } else | ||
140 | journal_usage++; | ||
141 | } | ||
142 | if (journal_usage) | ||
143 | bb_error_msg_and_die( | ||
144 | "\nBad journal options specified.\n\n" | ||
145 | "Journal options are separated by commas, " | ||
146 | "and may take an argument which\n" | ||
147 | "\tis set off by an equals ('=') sign.\n\n" | ||
148 | "Valid journal options are:\n" | ||
149 | "\tsize=<journal size in megabytes>\n" | ||
150 | "\tdevice=<journal device>\n\n" | ||
151 | "The journal size must be between " | ||
152 | "1024 and 102400 filesystem blocks.\n\n"); | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Determine the number of journal blocks to use, either via | ||
157 | * user-specified # of megabytes, or via some intelligently selected | ||
158 | * defaults. | ||
159 | * | ||
160 | * Find a reasonable journal file size (in blocks) given the number of blocks | ||
161 | * in the filesystem. For very small filesystems, it is not reasonable to | ||
162 | * have a journal that fills more than half of the filesystem. | ||
163 | */ | ||
164 | int figure_journal_size(int size, ext2_filsys fs) | ||
165 | { | ||
166 | blk_t j_blocks; | ||
167 | |||
168 | if (fs->super->s_blocks_count < 2048) { | ||
169 | bb_error_msg("Filesystem too small for a journal"); | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | if (size >= 0) { | ||
174 | j_blocks = size * 1024 / (fs->blocksize / 1024); | ||
175 | if (j_blocks < 1024 || j_blocks > 102400) | ||
176 | bb_error_msg_and_die("\nThe requested journal " | ||
177 | "size is %d blocks;\n it must be " | ||
178 | "between 1024 and 102400 blocks; Aborting", | ||
179 | j_blocks); | ||
180 | if (j_blocks > fs->super->s_free_blocks_count) | ||
181 | bb_error_msg_and_die("Journal size too big for filesystem"); | ||
182 | return j_blocks; | ||
183 | } | ||
184 | |||
185 | if (fs->super->s_blocks_count < 32768) | ||
186 | j_blocks = 1024; | ||
187 | else if (fs->super->s_blocks_count < 256*1024) | ||
188 | j_blocks = 4096; | ||
189 | else if (fs->super->s_blocks_count < 512*1024) | ||
190 | j_blocks = 8192; | ||
191 | else if (fs->super->s_blocks_count < 1024*1024) | ||
192 | j_blocks = 16384; | ||
193 | else | ||
194 | j_blocks = 32768; | ||
195 | |||
196 | return j_blocks; | ||
197 | } | ||
198 | |||
199 | void print_check_message(ext2_filsys fs) | ||
200 | { | ||
201 | printf("This filesystem will be automatically " | ||
202 | "checked every %d mounts or\n" | ||
203 | "%g days, whichever comes first. " | ||
204 | "Use tune2fs -c or -i to override.\n", | ||
205 | fs->super->s_max_mnt_count, | ||
206 | (double)fs->super->s_checkinterval / (3600 * 24)); | ||
207 | } | ||
208 | |||
209 | void make_journal_device(char *journal_device, ext2_filsys fs, int quiet, int force) | ||
210 | { | ||
211 | errcode_t retval; | ||
212 | ext2_filsys jfs; | ||
213 | io_manager io_ptr; | ||
214 | |||
215 | check_plausibility(journal_device, force); | ||
216 | check_mount(journal_device, force, "journal"); | ||
217 | io_ptr = unix_io_manager; | ||
218 | retval = ext2fs_open(journal_device, EXT2_FLAG_RW| | ||
219 | EXT2_FLAG_JOURNAL_DEV_OK, 0, | ||
220 | fs->blocksize, io_ptr, &jfs); | ||
221 | if (retval) | ||
222 | bb_error_msg_and_die("cannot journal device %s", journal_device); | ||
223 | niro | 816 | if (!quiet) |
224 | niro | 532 | printf("Adding journal to device %s: ", journal_device); |
225 | fflush(stdout); | ||
226 | retval = ext2fs_add_journal_device(fs, jfs); | ||
227 | niro | 816 | if (retval) |
228 | niro | 532 | bb_error_msg_and_die("\nFailed to add journal to device %s", journal_device); |
229 | niro | 816 | if (!quiet) |
230 | niro | 532 | puts("done"); |
231 | ext2fs_close(jfs); | ||
232 | } | ||
233 | |||
234 | void make_journal_blocks(ext2_filsys fs, int journal_size, int journal_flags, int quiet) | ||
235 | { | ||
236 | unsigned long journal_blocks; | ||
237 | errcode_t retval; | ||
238 | |||
239 | journal_blocks = figure_journal_size(journal_size, fs); | ||
240 | if (!journal_blocks) { | ||
241 | fs->super->s_feature_compat &= | ||
242 | ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; | ||
243 | return; | ||
244 | } | ||
245 | niro | 816 | if (!quiet) |
246 | niro | 532 | printf("Creating journal (%ld blocks): ", journal_blocks); |
247 | fflush(stdout); | ||
248 | retval = ext2fs_add_journal_inode(fs, journal_blocks, | ||
249 | journal_flags); | ||
250 | niro | 816 | if (retval) |
251 | niro | 532 | bb_error_msg_and_die("cannot create journal"); |
252 | niro | 816 | if (!quiet) |
253 | niro | 532 | puts("done"); |
254 | } | ||
255 | |||
256 | char *e2fs_set_sbin_path(void) | ||
257 | { | ||
258 | char *oldpath = getenv("PATH"); | ||
259 | /* Update our PATH to include /sbin */ | ||
260 | #define PATH_SET "/sbin" | ||
261 | if (oldpath) | ||
262 | oldpath = xasprintf("%s:%s", PATH_SET, oldpath); | ||
263 | else | ||
264 | oldpath = PATH_SET; | ||
265 | niro | 816 | putenv(oldpath); |
266 | niro | 532 | return oldpath; |
267 | } |