Whamcloud - gitweb
Many files:
[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 #include <sys/resource.h>
14
15 #include "e2fsck.h"
16
17 const char * fix_msg[2] = { "IGNORED", "FIXED" };
18 const char * clear_msg[2] = { "IGNORED", "CLEARED" };
19
20 void fatal_error (const char *msg)
21 {
22         if (msg) 
23                 fprintf (stderr, "%s: %s\n", program_name, msg);
24         exit(FSCK_ERROR);
25 }
26
27 void *allocate_memory(int size, const char *description)
28 {
29         void *ret;
30         char buf[256];
31
32 #ifdef DEBUG_ALLOCATE_MEMORY
33         printf("Allocating %d bytes for %s...\n", size, description);
34 #endif
35         ret = malloc(size);
36         if (!ret) {
37                 sprintf(buf, "%%s: Can't allocate %s\n", description);
38                 fatal_error(buf);
39         }
40         memset(ret, 0, size);
41         return ret;
42 }
43
44
45 int ask_yn(const char * string, int def)
46 {
47         int             c;
48         struct termios  termios, tmp;
49         const char      *defstr;
50
51         tcgetattr (0, &termios);
52         tmp = termios;
53         tmp.c_lflag &= ~(ICANON | ECHO);
54         tcsetattr (0, TCSANOW, &tmp);
55
56         if (def == 1)
57                 defstr = "<y>";
58         else if (def == 0)
59                 defstr = "<n>";
60         else
61                 defstr = " (y/n)";
62         printf("%s%s? ", string, defstr);
63         while (1) {
64                 fflush (stdout);
65                 if ((c = getchar()) == EOF)
66                         break;
67                 c = toupper(c);
68                 if (c == 'Y') {
69                         def = 1;
70                         break;
71                 }
72                 else if (c == 'N') {
73                         def = 0;
74                         break;
75                 }
76                 else if ((c == ' ' || c == '\n') && (def != -1))
77                         break;
78         }
79         if (def)
80                 printf ("yes\n\n");
81         else
82                 printf ("no\n\n");
83         tcsetattr (0, TCSANOW, &termios);
84         return def;
85 }
86
87 int ask (const char * string, int def)
88 {
89         if (nflag) {
90                 printf ("%s? no\n\n", string);
91                 return 0;
92         }
93         if (yflag) {
94                 printf ("%s? yes\n\n", string);
95                 return 1;
96         }
97         if (preen) {
98                 printf ("%s? %s\n\n", string, def ? "yes" : "no");
99                 return def;
100         }
101         return ask_yn(string, def);
102 }
103
104 void read_bitmaps(ext2_filsys fs)
105 {
106         errcode_t       retval;
107
108         if (!fs->inode_map) {
109                 ehandler_operation("reading inode bitmaps");
110                 retval = ext2fs_read_inode_bitmap(fs);
111                 ehandler_operation(0);
112                 if (retval) {
113                         com_err(program_name, retval,
114                                 "while retrying to read inode bitmaps for %s",
115                                 device_name);
116                         fatal_error(0);
117                 }
118         }
119         
120         if (!fs->block_map) {
121                 ehandler_operation("reading block bitmaps");
122                 retval = ext2fs_read_block_bitmap(fs);
123                 ehandler_operation(0);
124                 if (retval) {
125                         com_err(program_name, retval,
126                                 "while retrying to read block bitmaps for %s",
127                                 device_name);
128                         fatal_error(0);
129                 }
130         }
131 }
132
133 void write_bitmaps(ext2_filsys fs)
134 {
135         errcode_t       retval;
136
137         if (ext2fs_test_bb_dirty(fs)) {
138                 ehandler_operation("writing block bitmaps");
139                 retval = ext2fs_write_block_bitmap(fs);
140                 ehandler_operation(0);
141                 if (retval) {
142                         com_err(program_name, retval,
143                                 "while retrying to write block bitmaps for %s",
144                                 device_name);
145                         fatal_error(0);
146                 }
147         }
148
149         if (ext2fs_test_ib_dirty(fs)) {
150                 ehandler_operation("writing inode bitmaps");
151                 retval = ext2fs_write_inode_bitmap(fs);
152                 ehandler_operation(0);
153                 if (retval) {
154                         com_err(program_name, retval,
155                                 "while retrying to write inode bitmaps for %s",
156                                 device_name);
157                         fatal_error(0);
158                 }
159         }
160 }
161
162 void preenhalt(NOARGS)
163 {
164         if (!preen)
165                 return;
166         fprintf(stderr, "\n\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
167                device_name);
168         exit(FSCK_UNCORRECTED);
169 }
170
171 void init_resource_track(struct resource_track *track)
172 {
173         struct rusage r;
174         
175         track->brk_start = sbrk(0);
176         gettimeofday(&track->time_start, 0);
177         getrusage(RUSAGE_SELF, &r);
178         track->user_start = r.ru_utime;
179         track->system_start = r.ru_stime;
180 }
181
182 static __inline__ float timeval_subtract(struct timeval *tv1,
183                                          struct timeval *tv2)
184 {
185         return ((tv1->tv_sec - tv2->tv_sec) +
186                 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
187 }
188
189 void print_resource_track(struct resource_track *track)
190 {
191         struct rusage r;
192         struct timeval time_end;
193
194         gettimeofday(&time_end, 0);
195         getrusage(RUSAGE_SELF, &r);
196
197         printf("Memory used: %d, elapsed time: %6.3f/%6.3f/%6.3f\n",
198                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)),
199                timeval_subtract(&time_end, &track->time_start),
200                timeval_subtract(&r.ru_utime, &track->user_start),
201                timeval_subtract(&r.ru_stime, &track->system_start));
202 }
203
204 /*
205  * This function returns 1 if the inode's block entries actually
206  * contain block entries.
207  */
208 int inode_has_valid_blocks(struct ext2_inode *inode)
209 {
210         /*
211          * Only directories, regular files, and some symbolic links
212          * have valid block entries.
213          */
214         if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
215             !S_ISLNK(inode->i_mode))
216                 return 0;
217         
218         /*
219          * If the symbolic link is a "fast symlink", then the symlink
220          * target is stored in the block entries.
221          */
222         if (S_ISLNK (inode->i_mode) && inode->i_blocks == 0 &&
223             inode->i_size < EXT2_N_BLOCKS * sizeof (unsigned long))
224                 return 0;
225
226         return 1;
227 }
228
229 #ifdef MTRACE
230 void mtrace_print(char *mesg)
231 {
232         FILE    *malloc_get_mallstream();
233         FILE    *f = malloc_get_mallstream();
234
235         if (f)
236                 fprintf(f, "============= %s\n", mesg);
237 }
238 #endif
239
240