Whamcloud - gitweb
Many files:
[tools/e2fsprogs.git] / e2fsck / util.c
1 /*
2  * util.c --- miscellaneous utilities
3  * 
4  * Copyright (C) 1993, 1994, 1995, 1996, 1997 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
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <termios.h>
17
18 #include "e2fsck.h"
19
20 #include <sys/time.h>
21 #include <sys/resource.h>
22
23 void fatal_error (const char *msg)
24 {
25         if (msg) 
26                 fprintf (stderr, "e2fsck: %s\n", msg);
27         exit(FSCK_ERROR);
28 }
29
30 void *allocate_memory(int size, const char *description)
31 {
32         void *ret;
33         char buf[256];
34
35 #ifdef DEBUG_ALLOCATE_MEMORY
36         printf("Allocating %d bytes for %s...\n", size, description);
37 #endif
38         ret = malloc(size);
39         if (!ret) {
40                 sprintf(buf, "Can't allocate %s\n", description);
41                 fatal_error(buf);
42         }
43         memset(ret, 0, size);
44         return ret;
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);
56         tmp.c_cc[VMIN] = 1;
57         tmp.c_cc[VTIME] = 0;
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 (e2fsck_t ctx, const char * string, int def)
92 {
93         if (ctx->options & E2F_OPT_NO) {
94                 printf ("%s? no\n\n", string);
95                 return 0;
96         }
97         if (ctx->options & E2F_OPT_YES) {
98                 printf ("%s? yes\n\n", string);
99                 return 1;
100         }
101         if (ctx->options & E2F_OPT_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(e2fsck_t ctx)
109 {
110         ext2_filsys fs = ctx->fs;
111         errcode_t       retval;
112
113         if (ctx->invalid_bitmaps) {
114                 com_err(ctx->program_name, 0,
115                         "read_bitmaps: illegal bitmap block(s) for %s",
116                         ctx->device_name);
117                 fatal_error(0);
118         }
119
120         ehandler_operation("reading inode and block bitmaps");
121         retval = ext2fs_read_bitmaps(fs);
122         ehandler_operation(0);
123         if (retval) {
124                 com_err(ctx->program_name, retval,
125                         "while retrying to read bitmaps for %s",
126                         ctx->device_name);
127                 fatal_error(0);
128         }
129 }
130
131 void write_bitmaps(e2fsck_t ctx)
132 {
133         ext2_filsys fs = ctx->fs;
134         errcode_t       retval;
135
136         if (ext2fs_test_bb_dirty(fs)) {
137                 ehandler_operation("writing block bitmaps");
138                 retval = ext2fs_write_block_bitmap(fs);
139                 ehandler_operation(0);
140                 if (retval) {
141                         com_err(ctx->program_name, retval,
142                                 "while retrying to write block bitmaps for %s",
143                                 ctx->device_name);
144                         fatal_error(0);
145                 }
146         }
147
148         if (ext2fs_test_ib_dirty(fs)) {
149                 ehandler_operation("writing inode bitmaps");
150                 retval = ext2fs_write_inode_bitmap(fs);
151                 ehandler_operation(0);
152                 if (retval) {
153                         com_err(ctx->program_name, retval,
154                                 "while retrying to write inode bitmaps for %s",
155                                 ctx->device_name);
156                         fatal_error(0);
157                 }
158         }
159 }
160
161 void preenhalt(e2fsck_t ctx)
162 {
163         ext2_filsys fs = ctx->fs;
164
165         if (!(ctx->options & E2F_OPT_PREEN))
166                 return;
167         fprintf(stderr, "\n\n%s: UNEXPECTED INCONSISTENCY; "
168                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n",
169                ctx->device_name);
170         if (fs != NULL) {
171                 fs->super->s_state |= EXT2_ERROR_FS;
172                 ext2fs_mark_super_dirty(fs);
173                 ext2fs_close(fs);
174         }
175         exit(FSCK_UNCORRECTED);
176 }
177
178 void init_resource_track(struct resource_track *track)
179 {
180 #ifdef HAVE_GETRUSAGE
181         struct rusage r;
182 #endif
183         
184         track->brk_start = sbrk(0);
185         gettimeofday(&track->time_start, 0);
186 #ifdef HAVE_GETRUSAGE
187 #ifdef solaris
188         memcpy(&r, 0, sizeof(struct rusage));
189 #endif
190         getrusage(RUSAGE_SELF, &r);
191         track->user_start = r.ru_utime;
192         track->system_start = r.ru_stime;
193 #else
194         track->user_start.tv_sec = track->user_start.tv_usec = 0;
195         track->system_start.tv_sec = track->system_start.tv_usec = 0;
196 #endif
197 }
198
199 #ifdef __GNUC__
200 #define _INLINE_ __inline__
201 #else
202 #define _INLINE_
203 #endif
204
205 static _INLINE_ float timeval_subtract(struct timeval *tv1,
206                                        struct timeval *tv2)
207 {
208         return ((tv1->tv_sec - tv2->tv_sec) +
209                 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
210 }
211
212 void print_resource_track(const char *desc, struct resource_track *track)
213 {
214 #ifdef HAVE_GETRUSAGE
215         struct rusage r;
216 #endif
217         struct timeval time_end;
218
219         gettimeofday(&time_end, 0);
220
221         if (desc)
222                 printf("%s :", desc);
223         
224 #ifdef HAVE_GETRUSAGE
225         getrusage(RUSAGE_SELF, &r);
226
227         printf("Memory used: %d, elapsed time: %6.3f/%6.3f/%6.3f\n",
228                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)),
229                timeval_subtract(&time_end, &track->time_start),
230                timeval_subtract(&r.ru_utime, &track->user_start),
231                timeval_subtract(&r.ru_stime, &track->system_start));
232 #else
233         printf("Memory used: %d, elapsed time: %6.3f\n",
234                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)),
235                timeval_subtract(&time_end, &track->time_start));
236 #endif
237 }
238
239 void e2fsck_read_inode(ext2_filsys fs, unsigned long ino,
240                               struct ext2_inode * inode, const char *proc)
241 {
242         int retval;
243
244         retval = ext2fs_read_inode(fs, ino, inode);
245         if (retval) {
246                 com_err("ext2fs_read_inode", retval,
247                         "while reading inode %ld in %s", ino, proc);
248                 fatal_error(0);
249         }
250 }
251
252 extern void e2fsck_write_inode(ext2_filsys fs, unsigned long ino,
253                                struct ext2_inode * inode, const char *proc)
254 {
255         int retval;
256
257         retval = ext2fs_write_inode(fs, ino, inode);
258         if (retval) {
259                 com_err("ext2fs_write_inode", retval,
260                         "while writing inode %ld in %s", ino, proc);
261                 fatal_error(0);
262         }
263 }
264
265 #ifdef MTRACE
266 void mtrace_print(char *mesg)
267 {
268         FILE    *malloc_get_mallstream();
269         FILE    *f = malloc_get_mallstream();
270
271         if (f)
272                 fprintf(f, "============= %s\n", mesg);
273 }
274 #endif
275
276 blk_t get_backup_sb(ext2_filsys fs)
277 {
278         if (!fs || !fs->super)
279                 return 8193;
280         return fs->super->s_blocks_per_group + 1;
281 }
282