Whamcloud - gitweb
e12ff364e585f62a8f64c698f485c5c207598a54
[tools/e2fsprogs.git] / e2fsck / util.c
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>
13
14 #include "e2fsck.h"
15
16 #include <sys/time.h>
17 #include <sys/resource.h>
18
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) {
39                 sprintf(buf, "Can't allocate %s\n", description);
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);
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 (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
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);
117         }
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);
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
159 void preenhalt(ext2_filsys fs)
160 {
161         if (!preen)
162                 return;
163         fprintf(stderr, "\n\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
164                device_name);
165         if (fs != NULL) {
166                 fs->super->s_state |= EXT2_ERROR_FS;
167                 ext2fs_mark_super_dirty(fs);
168                 ext2fs_close(fs);
169         }
170         exit(FSCK_UNCORRECTED);
171 }
172
173 void init_resource_track(struct resource_track *track)
174 {
175 #ifdef HAVE_GETRUSAGE
176         struct rusage r;
177 #endif
178         
179         track->brk_start = sbrk(0);
180         gettimeofday(&track->time_start, 0);
181 #ifdef HAVE_GETRUSAGE
182         getrusage(RUSAGE_SELF, &r);
183         track->user_start = r.ru_utime;
184         track->system_start = r.ru_stime;
185 #else
186         track->user_start.tv_sec = track->user_start.tv_usec = 0;
187         track->system_start.tv_sec = track->system_start.tv_usec = 0;
188 #endif
189 }
190
191 static __inline__ float timeval_subtract(struct timeval *tv1,
192                                          struct timeval *tv2)
193 {
194         return ((tv1->tv_sec - tv2->tv_sec) +
195                 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
196 }
197
198 void print_resource_track(struct resource_track *track)
199 {
200 #ifdef HAVE_GETRUSAGE
201         struct rusage r;
202 #endif
203         struct timeval time_end;
204
205         gettimeofday(&time_end, 0);
206 #ifdef HAVE_GETRUSAGE
207         getrusage(RUSAGE_SELF, &r);
208
209         printf("Memory used: %d, elapsed time: %6.3f/%6.3f/%6.3f\n",
210                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)),
211                timeval_subtract(&time_end, &track->time_start),
212                timeval_subtract(&r.ru_utime, &track->user_start),
213                timeval_subtract(&r.ru_stime, &track->system_start));
214 #else
215         printf("Memory used: %d, elapsed time: %6.3f\n",
216                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)),
217                timeval_subtract(&time_end, &track->time_start));
218 #endif
219 }
220
221 void e2fsck_read_inode(ext2_filsys fs, unsigned long ino,
222                               struct ext2_inode * inode, const char *proc)
223 {
224         int retval;
225
226         retval = ext2fs_read_inode(fs, ino, inode);
227         if (retval) {
228                 com_err("ext2fs_read_inode", retval,
229                         "while reading inode %ld in %s", ino, proc);
230                 fatal_error(0);
231         }
232 }
233
234 extern void e2fsck_write_inode(ext2_filsys fs, unsigned long ino,
235                                struct ext2_inode * inode, const char *proc)
236 {
237         int retval;
238
239         retval = ext2fs_write_inode(fs, ino, inode);
240         if (retval) {
241                 com_err("ext2fs_write_inode", retval,
242                         "while writing inode %ld in %s", ino, proc);
243                 fatal_error(0);
244         }
245 }
246
247 /*
248  * This function returns 1 if the inode's block entries actually
249  * contain block entries.
250  */
251 int inode_has_valid_blocks(struct ext2_inode *inode)
252 {
253         /*
254          * Only directories, regular files, and some symbolic links
255          * have valid block entries.
256          */
257         if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) &&
258             !LINUX_S_ISLNK(inode->i_mode))
259                 return 0;
260         
261         /*
262          * If the symbolic link is a "fast symlink", then the symlink
263          * target is stored in the block entries.
264          */
265         if (LINUX_S_ISLNK (inode->i_mode) && inode->i_blocks == 0 &&
266             inode->i_size < EXT2_N_BLOCKS * sizeof (unsigned long))
267                 return 0;
268
269         return 1;
270 }
271
272 #ifdef MTRACE
273 void mtrace_print(char *mesg)
274 {
275         FILE    *malloc_get_mallstream();
276         FILE    *f = malloc_get_mallstream();
277
278         if (f)
279                 fprintf(f, "============= %s\n", mesg);
280 }
281 #endif
282
283