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(e2fsck_t ctx, const char *msg)
24 {
25         if (msg) 
26                 fprintf (stderr, "e2fsck: %s\n", msg);
27         ctx->flags |= E2F_FLAG_ABORT;
28         if (ctx->flags & E2F_FLAG_SETJMP_OK)
29                 longjmp(ctx->abort_loc, 1);
30         exit(FSCK_ERROR);
31 }
32
33 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
34                              const char *description)
35 {
36         void *ret;
37         char buf[256];
38
39 #ifdef DEBUG_ALLOCATE_MEMORY
40         printf("Allocating %d bytes for %s...\n", size, description);
41 #endif
42         ret = malloc(size);
43         if (!ret) {
44                 sprintf(buf, "Can't allocate %s\n", description);
45                 fatal_error(ctx, buf);
46         }
47         memset(ret, 0, size);
48         return ret;
49 }
50
51 int ask_yn(const char * string, int def)
52 {
53         int             c;
54         struct termios  termios, tmp;
55         const char      *defstr;
56
57         tcgetattr (0, &termios);
58         tmp = termios;
59         tmp.c_lflag &= ~(ICANON | ECHO);
60         tmp.c_cc[VMIN] = 1;
61         tmp.c_cc[VTIME] = 0;
62         tcsetattr (0, TCSANOW, &tmp);
63
64         if (def == 1)
65                 defstr = "<y>";
66         else if (def == 0)
67                 defstr = "<n>";
68         else
69                 defstr = " (y/n)";
70         printf("%s%s? ", string, defstr);
71         while (1) {
72                 fflush (stdout);
73                 if ((c = getchar()) == EOF)
74                         break;
75                 c = toupper(c);
76                 if (c == 'Y') {
77                         def = 1;
78                         break;
79                 }
80                 else if (c == 'N') {
81                         def = 0;
82                         break;
83                 }
84                 else if ((c == ' ' || c == '\n') && (def != -1))
85                         break;
86         }
87         if (def)
88                 printf ("yes\n\n");
89         else
90                 printf ("no\n\n");
91         tcsetattr (0, TCSANOW, &termios);
92         return def;
93 }
94
95 int ask (e2fsck_t ctx, const char * string, int def)
96 {
97         if (ctx->options & E2F_OPT_NO) {
98                 printf ("%s? no\n\n", string);
99                 return 0;
100         }
101         if (ctx->options & E2F_OPT_YES) {
102                 printf ("%s? yes\n\n", string);
103                 return 1;
104         }
105         if (ctx->options & E2F_OPT_PREEN) {
106                 printf ("%s? %s\n\n", string, def ? "yes" : "no");
107                 return def;
108         }
109         return ask_yn(string, def);
110 }
111
112 void e2fsck_read_bitmaps(e2fsck_t ctx)
113 {
114         ext2_filsys fs = ctx->fs;
115         errcode_t       retval;
116
117         if (ctx->invalid_bitmaps) {
118                 com_err(ctx->program_name, 0,
119                         "e2fsck_read_bitmaps: illegal bitmap block(s) for %s",
120                         ctx->device_name);
121                 fatal_error(ctx, 0);
122         }
123
124         ehandler_operation("reading inode and block bitmaps");
125         retval = ext2fs_read_bitmaps(fs);
126         ehandler_operation(0);
127         if (retval) {
128                 com_err(ctx->program_name, retval,
129                         "while retrying to read bitmaps for %s",
130                         ctx->device_name);
131                 fatal_error(ctx, 0);
132         }
133 }
134
135 void e2fsck_write_bitmaps(e2fsck_t ctx)
136 {
137         ext2_filsys fs = ctx->fs;
138         errcode_t       retval;
139
140         if (ext2fs_test_bb_dirty(fs)) {
141                 ehandler_operation("writing block bitmaps");
142                 retval = ext2fs_write_block_bitmap(fs);
143                 ehandler_operation(0);
144                 if (retval) {
145                         com_err(ctx->program_name, retval,
146                                 "while retrying to write block bitmaps for %s",
147                                 ctx->device_name);
148                         fatal_error(ctx, 0);
149                 }
150         }
151
152         if (ext2fs_test_ib_dirty(fs)) {
153                 ehandler_operation("writing inode bitmaps");
154                 retval = ext2fs_write_inode_bitmap(fs);
155                 ehandler_operation(0);
156                 if (retval) {
157                         com_err(ctx->program_name, retval,
158                                 "while retrying to write inode bitmaps for %s",
159                                 ctx->device_name);
160                         fatal_error(ctx, 0);
161                 }
162         }
163 }
164
165 void preenhalt(e2fsck_t ctx)
166 {
167         ext2_filsys fs = ctx->fs;
168
169         if (!(ctx->options & E2F_OPT_PREEN))
170                 return;
171         fprintf(stderr, "\n\n%s: UNEXPECTED INCONSISTENCY; "
172                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n",
173                ctx->device_name);
174         if (fs != NULL) {
175                 fs->super->s_state |= EXT2_ERROR_FS;
176                 ext2fs_mark_super_dirty(fs);
177                 ext2fs_close(fs);
178         }
179         exit(FSCK_UNCORRECTED);
180 }
181
182 #ifdef RESOURCE_TRACK
183 void init_resource_track(struct resource_track *track)
184 {
185 #ifdef HAVE_GETRUSAGE
186         struct rusage r;
187 #endif
188         
189         track->brk_start = sbrk(0);
190         gettimeofday(&track->time_start, 0);
191 #ifdef HAVE_GETRUSAGE
192 #ifdef solaris
193         memcpy(&r, 0, sizeof(struct rusage));
194 #endif
195         getrusage(RUSAGE_SELF, &r);
196         track->user_start = r.ru_utime;
197         track->system_start = r.ru_stime;
198 #else
199         track->user_start.tv_sec = track->user_start.tv_usec = 0;
200         track->system_start.tv_sec = track->system_start.tv_usec = 0;
201 #endif
202 }
203
204 #ifdef __GNUC__
205 #define _INLINE_ __inline__
206 #else
207 #define _INLINE_
208 #endif
209
210 static _INLINE_ float timeval_subtract(struct timeval *tv1,
211                                        struct timeval *tv2)
212 {
213         return ((tv1->tv_sec - tv2->tv_sec) +
214                 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
215 }
216
217 void print_resource_track(const char *desc, struct resource_track *track)
218 {
219 #ifdef HAVE_GETRUSAGE
220         struct rusage r;
221 #endif
222         struct timeval time_end;
223
224         gettimeofday(&time_end, 0);
225
226         if (desc)
227                 printf("%s :", desc);
228         
229 #ifdef HAVE_GETRUSAGE
230         getrusage(RUSAGE_SELF, &r);
231
232         printf("Memory used: %d, elapsed time: %6.3f/%6.3f/%6.3f\n",
233                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)),
234                timeval_subtract(&time_end, &track->time_start),
235                timeval_subtract(&r.ru_utime, &track->user_start),
236                timeval_subtract(&r.ru_stime, &track->system_start));
237 #else
238         printf("Memory used: %d, elapsed time: %6.3f\n",
239                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)),
240                timeval_subtract(&time_end, &track->time_start));
241 #endif
242 }
243 #endif /* RESOURCE_TRACK */
244
245 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
246                               struct ext2_inode * inode, const char *proc)
247 {
248         int retval;
249
250         retval = ext2fs_read_inode(ctx->fs, ino, inode);
251         if (retval) {
252                 com_err("ext2fs_read_inode", retval,
253                         "while reading inode %ld in %s", ino, proc);
254                 fatal_error(ctx, 0);
255         }
256 }
257
258 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
259                                struct ext2_inode * inode, const char *proc)
260 {
261         int retval;
262
263         retval = ext2fs_write_inode(ctx->fs, ino, inode);
264         if (retval) {
265                 com_err("ext2fs_write_inode", retval,
266                         "while writing inode %ld in %s", ino, proc);
267                 fatal_error(ctx, 0);
268         }
269 }
270
271 #ifdef MTRACE
272 void mtrace_print(char *mesg)
273 {
274         FILE    *malloc_get_mallstream();
275         FILE    *f = malloc_get_mallstream();
276
277         if (f)
278                 fprintf(f, "============= %s\n", mesg);
279 }
280 #endif
281
282 blk_t get_backup_sb(ext2_filsys fs)
283 {
284         if (!fs || !fs->super)
285                 return 8193;
286         return fs->super->s_blocks_per_group + 1;
287 }
288