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 (invalid_bitmaps) {
109                 com_err(program_name, 0,
110                         "read_bitmaps: illegal bitmap block(s) for %s",
111                         device_name);
112                 fatal_error(0);
113         }
114
115         ehandler_operation("reading inode and block bitmaps");
116         retval = ext2fs_read_bitmaps(fs);
117         ehandler_operation(0);
118         if (retval) {
119                 com_err(program_name, retval,
120                         "while retrying to read bitmaps for %s",
121                         device_name);
122                 fatal_error(0);
123         }
124 }
125
126 void write_bitmaps(ext2_filsys fs)
127 {
128         errcode_t       retval;
129
130         if (ext2fs_test_bb_dirty(fs)) {
131                 ehandler_operation("writing block bitmaps");
132                 retval = ext2fs_write_block_bitmap(fs);
133                 ehandler_operation(0);
134                 if (retval) {
135                         com_err(program_name, retval,
136                                 "while retrying to write block bitmaps for %s",
137                                 device_name);
138                         fatal_error(0);
139                 }
140         }
141
142         if (ext2fs_test_ib_dirty(fs)) {
143                 ehandler_operation("writing inode bitmaps");
144                 retval = ext2fs_write_inode_bitmap(fs);
145                 ehandler_operation(0);
146                 if (retval) {
147                         com_err(program_name, retval,
148                                 "while retrying to write inode bitmaps for %s",
149                                 device_name);
150                         fatal_error(0);
151                 }
152         }
153 }
154
155 void preenhalt(NOARGS)
156 {
157         if (!preen)
158                 return;
159         fprintf(stderr, "\n\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
160                device_name);
161         exit(FSCK_UNCORRECTED);
162 }
163
164 void init_resource_track(struct resource_track *track)
165 {
166         struct rusage r;
167         
168         track->brk_start = sbrk(0);
169         gettimeofday(&track->time_start, 0);
170         getrusage(RUSAGE_SELF, &r);
171         track->user_start = r.ru_utime;
172         track->system_start = r.ru_stime;
173 }
174
175 static __inline__ float timeval_subtract(struct timeval *tv1,
176                                          struct timeval *tv2)
177 {
178         return ((tv1->tv_sec - tv2->tv_sec) +
179                 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
180 }
181
182 void print_resource_track(struct resource_track *track)
183 {
184         struct rusage r;
185         struct timeval time_end;
186
187         gettimeofday(&time_end, 0);
188         getrusage(RUSAGE_SELF, &r);
189
190         printf("Memory used: %d, elapsed time: %6.3f/%6.3f/%6.3f\n",
191                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)),
192                timeval_subtract(&time_end, &track->time_start),
193                timeval_subtract(&r.ru_utime, &track->user_start),
194                timeval_subtract(&r.ru_stime, &track->system_start));
195 }
196
197 void e2fsck_read_inode(ext2_filsys fs, unsigned long ino,
198                               struct ext2_inode * inode, const char *proc)
199 {
200         int retval;
201
202         retval = ext2fs_read_inode(fs, ino, inode);
203         if (retval) {
204                 com_err("ext2fs_read_inode", retval,
205                         "while reading inode %ld in %s", ino, proc);
206                 fatal_error(0);
207         }
208 }
209
210 extern void e2fsck_write_inode(ext2_filsys fs, unsigned long ino,
211                                struct ext2_inode * inode, const char *proc)
212 {
213         int retval;
214
215         retval = ext2fs_write_inode(fs, ino, inode);
216         if (retval) {
217                 com_err("ext2fs_write_inode", retval,
218                         "while writing inode %ld in %s", ino, proc);
219                 fatal_error(0);
220         }
221 }
222
223 /*
224  * This function returns 1 if the inode's block entries actually
225  * contain block entries.
226  */
227 int inode_has_valid_blocks(struct ext2_inode *inode)
228 {
229         /*
230          * Only directories, regular files, and some symbolic links
231          * have valid block entries.
232          */
233         if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
234             !S_ISLNK(inode->i_mode))
235                 return 0;
236         
237         /*
238          * If the symbolic link is a "fast symlink", then the symlink
239          * target is stored in the block entries.
240          */
241         if (S_ISLNK (inode->i_mode) && inode->i_blocks == 0 &&
242             inode->i_size < EXT2_N_BLOCKS * sizeof (unsigned long))
243                 return 0;
244
245         return 1;
246 }
247
248 #ifdef MTRACE
249 void mtrace_print(char *mesg)
250 {
251         FILE    *malloc_get_mallstream();
252         FILE    *f = malloc_get_mallstream();
253
254         if (f)
255                 fprintf(f, "============= %s\n", mesg);
256 }
257 #endif
258
259