blob: c9e63960f26fcabb0ce17d772cfffd6e5eead2a2 [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
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
17const char * fix_msg[2] = { "IGNORED", "FIXED" };
18const char * clear_msg[2] = { "IGNORED", "CLEARED" };
19
20void fatal_error (const char *msg)
21{
22 if (msg)
23 fprintf (stderr, "%s: %s\n", program_name, msg);
24 exit(FSCK_ERROR);
25}
26
27void *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
45int 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
87int 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
104void 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
133void 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
162void 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
171void 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
182static __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
189void 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 */
208int 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
230void 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