]>
Commit | Line | Data |
---|---|---|
3839e657 TT |
1 | /* |
2 | * util.c --- miscellaneous utilities | |
3 | * | |
4 | * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be | |
5 | * redistributed under the terms of the GNU Public License. | |
6 | */ | |
7 | ||
8 | #include <stdlib.h> | |
9 | #include <unistd.h> | |
10 | #include <string.h> | |
11 | #include <ctype.h> | |
12 | #include <termios.h> | |
3839e657 TT |
13 | |
14 | #include "e2fsck.h" | |
15 | ||
50e1e10f TT |
16 | #include <sys/time.h> |
17 | #include <sys/resource.h> | |
18 | ||
3839e657 TT |
19 | const char * fix_msg[2] = { "IGNORED", "FIXED" }; |
20 | const char * clear_msg[2] = { "IGNORED", "CLEARED" }; | |
21 | ||
22 | void fatal_error (const char *msg) | |
23 | { | |
24 | if (msg) | |
25 | fprintf (stderr, "%s: %s\n", program_name, msg); | |
26 | exit(FSCK_ERROR); | |
27 | } | |
28 | ||
29 | void *allocate_memory(int size, const char *description) | |
30 | { | |
31 | void *ret; | |
32 | char buf[256]; | |
33 | ||
34 | #ifdef DEBUG_ALLOCATE_MEMORY | |
35 | printf("Allocating %d bytes for %s...\n", size, description); | |
36 | #endif | |
37 | ret = malloc(size); | |
38 | if (!ret) { | |
7f88b043 | 39 | sprintf(buf, "Can't allocate %s\n", description); |
3839e657 TT |
40 | fatal_error(buf); |
41 | } | |
42 | memset(ret, 0, size); | |
43 | return ret; | |
44 | } | |
45 | ||
46 | ||
47 | int ask_yn(const char * string, int def) | |
48 | { | |
49 | int c; | |
50 | struct termios termios, tmp; | |
51 | const char *defstr; | |
52 | ||
53 | tcgetattr (0, &termios); | |
54 | tmp = termios; | |
55 | tmp.c_lflag &= ~(ICANON | ECHO); | |
50e1e10f TT |
56 | tmp.c_cc[VMIN] = 1; |
57 | tmp.c_cc[VTIME] = 0; | |
3839e657 TT |
58 | tcsetattr (0, TCSANOW, &tmp); |
59 | ||
60 | if (def == 1) | |
61 | defstr = "<y>"; | |
62 | else if (def == 0) | |
63 | defstr = "<n>"; | |
64 | else | |
65 | defstr = " (y/n)"; | |
66 | printf("%s%s? ", string, defstr); | |
67 | while (1) { | |
68 | fflush (stdout); | |
69 | if ((c = getchar()) == EOF) | |
70 | break; | |
71 | c = toupper(c); | |
72 | if (c == 'Y') { | |
73 | def = 1; | |
74 | break; | |
75 | } | |
76 | else if (c == 'N') { | |
77 | def = 0; | |
78 | break; | |
79 | } | |
80 | else if ((c == ' ' || c == '\n') && (def != -1)) | |
81 | break; | |
82 | } | |
83 | if (def) | |
84 | printf ("yes\n\n"); | |
85 | else | |
86 | printf ("no\n\n"); | |
87 | tcsetattr (0, TCSANOW, &termios); | |
88 | return def; | |
89 | } | |
90 | ||
91 | int ask (const char * string, int def) | |
92 | { | |
93 | if (nflag) { | |
94 | printf ("%s? no\n\n", string); | |
95 | return 0; | |
96 | } | |
97 | if (yflag) { | |
98 | printf ("%s? yes\n\n", string); | |
99 | return 1; | |
100 | } | |
101 | if (preen) { | |
102 | printf ("%s? %s\n\n", string, def ? "yes" : "no"); | |
103 | return def; | |
104 | } | |
105 | return ask_yn(string, def); | |
106 | } | |
107 | ||
108 | void read_bitmaps(ext2_filsys fs) | |
109 | { | |
110 | errcode_t retval; | |
111 | ||
f3db3566 TT |
112 | if (invalid_bitmaps) { |
113 | com_err(program_name, 0, | |
114 | "read_bitmaps: illegal bitmap block(s) for %s", | |
115 | device_name); | |
116 | fatal_error(0); | |
3839e657 | 117 | } |
f3db3566 TT |
118 | |
119 | ehandler_operation("reading inode and block bitmaps"); | |
120 | retval = ext2fs_read_bitmaps(fs); | |
121 | ehandler_operation(0); | |
122 | if (retval) { | |
123 | com_err(program_name, retval, | |
124 | "while retrying to read bitmaps for %s", | |
125 | device_name); | |
126 | fatal_error(0); | |
3839e657 TT |
127 | } |
128 | } | |
129 | ||
130 | void write_bitmaps(ext2_filsys fs) | |
131 | { | |
132 | errcode_t retval; | |
133 | ||
134 | if (ext2fs_test_bb_dirty(fs)) { | |
135 | ehandler_operation("writing block bitmaps"); | |
136 | retval = ext2fs_write_block_bitmap(fs); | |
137 | ehandler_operation(0); | |
138 | if (retval) { | |
139 | com_err(program_name, retval, | |
140 | "while retrying to write block bitmaps for %s", | |
141 | device_name); | |
142 | fatal_error(0); | |
143 | } | |
144 | } | |
145 | ||
146 | if (ext2fs_test_ib_dirty(fs)) { | |
147 | ehandler_operation("writing inode bitmaps"); | |
148 | retval = ext2fs_write_inode_bitmap(fs); | |
149 | ehandler_operation(0); | |
150 | if (retval) { | |
151 | com_err(program_name, retval, | |
152 | "while retrying to write inode bitmaps for %s", | |
153 | device_name); | |
154 | fatal_error(0); | |
155 | } | |
156 | } | |
157 | } | |
158 | ||
50e1e10f | 159 | void preenhalt(ext2_filsys fs) |
3839e657 TT |
160 | { |
161 | if (!preen) | |
162 | return; | |
5c576477 TT |
163 | fprintf(stderr, "\n\n%s: UNEXPECTED INCONSISTENCY; " |
164 | "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n", | |
3839e657 | 165 | device_name); |
50e1e10f TT |
166 | if (fs != NULL) { |
167 | fs->super->s_state |= EXT2_ERROR_FS; | |
168 | ext2fs_mark_super_dirty(fs); | |
169 | ext2fs_close(fs); | |
170 | } | |
3839e657 TT |
171 | exit(FSCK_UNCORRECTED); |
172 | } | |
173 | ||
174 | void init_resource_track(struct resource_track *track) | |
175 | { | |
50e1e10f | 176 | #ifdef HAVE_GETRUSAGE |
3839e657 | 177 | struct rusage r; |
50e1e10f | 178 | #endif |
3839e657 TT |
179 | |
180 | track->brk_start = sbrk(0); | |
181 | gettimeofday(&track->time_start, 0); | |
50e1e10f | 182 | #ifdef HAVE_GETRUSAGE |
3839e657 TT |
183 | getrusage(RUSAGE_SELF, &r); |
184 | track->user_start = r.ru_utime; | |
185 | track->system_start = r.ru_stime; | |
50e1e10f TT |
186 | #else |
187 | track->user_start.tv_sec = track->user_start.tv_usec = 0; | |
188 | track->system_start.tv_sec = track->system_start.tv_usec = 0; | |
189 | #endif | |
3839e657 TT |
190 | } |
191 | ||
192 | static __inline__ float timeval_subtract(struct timeval *tv1, | |
193 | struct timeval *tv2) | |
194 | { | |
195 | return ((tv1->tv_sec - tv2->tv_sec) + | |
196 | ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000); | |
197 | } | |
198 | ||
199 | void print_resource_track(struct resource_track *track) | |
200 | { | |
50e1e10f | 201 | #ifdef HAVE_GETRUSAGE |
3839e657 | 202 | struct rusage r; |
50e1e10f | 203 | #endif |
3839e657 TT |
204 | struct timeval time_end; |
205 | ||
206 | gettimeofday(&time_end, 0); | |
50e1e10f | 207 | #ifdef HAVE_GETRUSAGE |
3839e657 TT |
208 | getrusage(RUSAGE_SELF, &r); |
209 | ||
210 | printf("Memory used: %d, elapsed time: %6.3f/%6.3f/%6.3f\n", | |
211 | (int) (((char *) sbrk(0)) - ((char *) track->brk_start)), | |
212 | timeval_subtract(&time_end, &track->time_start), | |
213 | timeval_subtract(&r.ru_utime, &track->user_start), | |
214 | timeval_subtract(&r.ru_stime, &track->system_start)); | |
50e1e10f TT |
215 | #else |
216 | printf("Memory used: %d, elapsed time: %6.3f\n", | |
217 | (int) (((char *) sbrk(0)) - ((char *) track->brk_start)), | |
218 | timeval_subtract(&time_end, &track->time_start)); | |
219 | #endif | |
3839e657 TT |
220 | } |
221 | ||
f3db3566 TT |
222 | void e2fsck_read_inode(ext2_filsys fs, unsigned long ino, |
223 | struct ext2_inode * inode, const char *proc) | |
224 | { | |
225 | int retval; | |
226 | ||
227 | retval = ext2fs_read_inode(fs, ino, inode); | |
228 | if (retval) { | |
229 | com_err("ext2fs_read_inode", retval, | |
230 | "while reading inode %ld in %s", ino, proc); | |
231 | fatal_error(0); | |
232 | } | |
233 | } | |
234 | ||
235 | extern void e2fsck_write_inode(ext2_filsys fs, unsigned long ino, | |
236 | struct ext2_inode * inode, const char *proc) | |
237 | { | |
238 | int retval; | |
239 | ||
240 | retval = ext2fs_write_inode(fs, ino, inode); | |
241 | if (retval) { | |
242 | com_err("ext2fs_write_inode", retval, | |
243 | "while writing inode %ld in %s", ino, proc); | |
244 | fatal_error(0); | |
245 | } | |
246 | } | |
247 | ||
3839e657 TT |
248 | /* |
249 | * This function returns 1 if the inode's block entries actually | |
250 | * contain block entries. | |
251 | */ | |
252 | int inode_has_valid_blocks(struct ext2_inode *inode) | |
253 | { | |
254 | /* | |
255 | * Only directories, regular files, and some symbolic links | |
256 | * have valid block entries. | |
257 | */ | |
50e1e10f TT |
258 | if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) && |
259 | !LINUX_S_ISLNK(inode->i_mode)) | |
3839e657 TT |
260 | return 0; |
261 | ||
262 | /* | |
263 | * If the symbolic link is a "fast symlink", then the symlink | |
264 | * target is stored in the block entries. | |
265 | */ | |
50e1e10f | 266 | if (LINUX_S_ISLNK (inode->i_mode) && inode->i_blocks == 0 && |
3839e657 TT |
267 | inode->i_size < EXT2_N_BLOCKS * sizeof (unsigned long)) |
268 | return 0; | |
269 | ||
270 | return 1; | |
271 | } | |
272 | ||
273 | #ifdef MTRACE | |
274 | void mtrace_print(char *mesg) | |
275 | { | |
276 | FILE *malloc_get_mallstream(); | |
277 | FILE *f = malloc_get_mallstream(); | |
278 | ||
279 | if (f) | |
280 | fprintf(f, "============= %s\n", mesg); | |
281 | } | |
282 | #endif | |
283 | ||
284 |