util.c revision 3f65f1acaa1f32740fdbc03affe3dc95f9668bad
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 17#ifdef HAVE_CONIO_H 18#undef HAVE_TERMIOS_H 19#include <conio.h> 20#define read_a_char() getch() 21#else 22#ifdef HAVE_TERMIOS_H 23#include <termios.h> 24#endif 25#include <stdio.h> 26#define read_a_char() getchar() 27#endif 28 29#ifdef HAVE_MALLOC_H 30#include <malloc.h> 31#endif 32 33#include "e2fsck.h" 34 35#include <sys/time.h> 36#include <sys/resource.h> 37 38void fatal_error(e2fsck_t ctx, const char *msg) 39{ 40 if (msg) 41 fprintf (stderr, "e2fsck: %s\n", msg); 42 if (ctx->fs && ctx->fs->io) 43 io_channel_flush(ctx->fs->io); 44 ctx->flags |= E2F_FLAG_ABORT; 45 if (ctx->flags & E2F_FLAG_SETJMP_OK) 46 longjmp(ctx->abort_loc, 1); 47 exit(FSCK_ERROR); 48} 49 50void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size, 51 const char *description) 52{ 53 void *ret; 54 char buf[256]; 55 56#ifdef DEBUG_ALLOCATE_MEMORY 57 printf("Allocating %d bytes for %s...\n", size, description); 58#endif 59 ret = malloc(size); 60 if (!ret) { 61 sprintf(buf, "Can't allocate %s\n", description); 62 fatal_error(ctx, buf); 63 } 64 memset(ret, 0, size); 65 return ret; 66} 67 68int ask_yn(const char * string, int def) 69{ 70 int c; 71 const char *defstr; 72 char *short_yes = _("yY"); 73 char *short_no = _("nN"); 74 75#ifdef HAVE_TERMIOS_H 76 struct termios termios, tmp; 77 78 tcgetattr (0, &termios); 79 tmp = termios; 80 tmp.c_lflag &= ~(ICANON | ECHO); 81 tmp.c_cc[VMIN] = 1; 82 tmp.c_cc[VTIME] = 0; 83 tcsetattr (0, TCSANOW, &tmp); 84#endif 85 86 if (def == 1) 87 defstr = _("<y>"); 88 else if (def == 0) 89 defstr = _("<n>"); 90 else 91 defstr = _(" (y/n)"); 92 printf("%s%s? ", string, defstr); 93 while (1) { 94 fflush (stdout); 95 if ((c = read_a_char()) == EOF) 96 break; 97 if (strchr(short_yes, (char) c)) { 98 def = 1; 99 break; 100 } 101 else if (strchr(short_no, (char) c)) { 102 def = 0; 103 break; 104 } 105 else if ((c == ' ' || c == '\n') && (def != -1)) 106 break; 107 } 108 if (def) 109 printf ("yes\n\n"); 110 else 111 printf ("no\n\n"); 112#ifdef HAVE_TERMIOS_H 113 tcsetattr (0, TCSANOW, &termios); 114#endif 115 return def; 116} 117 118int ask (e2fsck_t ctx, const char * string, int def) 119{ 120 if (ctx->options & E2F_OPT_NO) { 121 printf (_("%s? no\n\n"), string); 122 return 0; 123 } 124 if (ctx->options & E2F_OPT_YES) { 125 printf (_("%s? yes\n\n"), string); 126 return 1; 127 } 128 if (ctx->options & E2F_OPT_PREEN) { 129 printf ("%s? %s\n\n", string, def ? _("yes") : _("no")); 130 return def; 131 } 132 return ask_yn(string, def); 133} 134 135void e2fsck_read_bitmaps(e2fsck_t ctx) 136{ 137 ext2_filsys fs = ctx->fs; 138 errcode_t retval; 139 140 if (ctx->invalid_bitmaps) { 141 com_err(ctx->program_name, 0, 142 _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"), 143 ctx->device_name); 144 fatal_error(ctx, 0); 145 } 146 147 ehandler_operation(_("reading inode and block bitmaps")); 148 retval = ext2fs_read_bitmaps(fs); 149 ehandler_operation(0); 150 if (retval) { 151 com_err(ctx->program_name, retval, 152 _("while retrying to read bitmaps for %s"), 153 ctx->device_name); 154 fatal_error(ctx, 0); 155 } 156} 157 158void e2fsck_write_bitmaps(e2fsck_t ctx) 159{ 160 ext2_filsys fs = ctx->fs; 161 errcode_t retval; 162 163 if (ext2fs_test_bb_dirty(fs)) { 164 ehandler_operation(_("writing block bitmaps")); 165 retval = ext2fs_write_block_bitmap(fs); 166 ehandler_operation(0); 167 if (retval) { 168 com_err(ctx->program_name, retval, 169 _("while retrying to write block bitmaps for %s"), 170 ctx->device_name); 171 fatal_error(ctx, 0); 172 } 173 } 174 175 if (ext2fs_test_ib_dirty(fs)) { 176 ehandler_operation(_("writing inode bitmaps")); 177 retval = ext2fs_write_inode_bitmap(fs); 178 ehandler_operation(0); 179 if (retval) { 180 com_err(ctx->program_name, retval, 181 _("while retrying to write inode bitmaps for %s"), 182 ctx->device_name); 183 fatal_error(ctx, 0); 184 } 185 } 186} 187 188void preenhalt(e2fsck_t ctx) 189{ 190 ext2_filsys fs = ctx->fs; 191 192 if (!(ctx->options & E2F_OPT_PREEN)) 193 return; 194 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; " 195 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"), 196 ctx->device_name); 197 if (fs != NULL) { 198 fs->super->s_state |= EXT2_ERROR_FS; 199 ext2fs_mark_super_dirty(fs); 200 ext2fs_close(fs); 201 } 202 exit(FSCK_UNCORRECTED); 203} 204 205#ifdef RESOURCE_TRACK 206void init_resource_track(struct resource_track *track) 207{ 208#ifdef HAVE_GETRUSAGE 209 struct rusage r; 210#endif 211 212 track->brk_start = sbrk(0); 213 gettimeofday(&track->time_start, 0); 214#ifdef HAVE_GETRUSAGE 215#ifdef solaris 216 memcpy(&r, 0, sizeof(struct rusage)); 217#endif 218 getrusage(RUSAGE_SELF, &r); 219 track->user_start = r.ru_utime; 220 track->system_start = r.ru_stime; 221#else 222 track->user_start.tv_sec = track->user_start.tv_usec = 0; 223 track->system_start.tv_sec = track->system_start.tv_usec = 0; 224#endif 225} 226 227#ifdef __GNUC__ 228#define _INLINE_ __inline__ 229#else 230#define _INLINE_ 231#endif 232 233static _INLINE_ float timeval_subtract(struct timeval *tv1, 234 struct timeval *tv2) 235{ 236 return ((tv1->tv_sec - tv2->tv_sec) + 237 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000); 238} 239 240void print_resource_track(const char *desc, struct resource_track *track) 241{ 242#ifdef HAVE_GETRUSAGE 243 struct rusage r; 244#endif 245#ifdef HAVE_MALLINFO 246 struct mallinfo malloc_info; 247#endif 248 struct timeval time_end; 249 250 gettimeofday(&time_end, 0); 251 252 if (desc) 253 printf("%s: ", desc); 254 255#ifdef HAVE_MALLINFO 256#define kbytes(x) (((x) + 1023) / 1024) 257 258 malloc_info = mallinfo(); 259 printf(_("Memory used: %dk/%dk (%dk/%dk), "), 260 kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd), 261 kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks)); 262#else 263 printf(_("Memory used: %d, "), 264 (int) (((char *) sbrk(0)) - ((char *) track->brk_start))); 265#endif 266#ifdef HAVE_GETRUSAGE 267 getrusage(RUSAGE_SELF, &r); 268 269 printf(_("time: %5.2f/%5.2f/%5.2f\n"), 270 timeval_subtract(&time_end, &track->time_start), 271 timeval_subtract(&r.ru_utime, &track->user_start), 272 timeval_subtract(&r.ru_stime, &track->system_start)); 273#else 274 printf(_("elapsed time: %6.3f\n"), 275 timeval_subtract(&time_end, &track->time_start)); 276#endif 277} 278#endif /* RESOURCE_TRACK */ 279 280void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino, 281 struct ext2_inode * inode, const char *proc) 282{ 283 int retval; 284 285 retval = ext2fs_read_inode(ctx->fs, ino, inode); 286 if (retval) { 287 com_err("ext2fs_read_inode", retval, 288 _("while reading inode %ld in %s"), ino, proc); 289 fatal_error(ctx, 0); 290 } 291} 292 293extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino, 294 struct ext2_inode * inode, const char *proc) 295{ 296 int retval; 297 298 retval = ext2fs_write_inode(ctx->fs, ino, inode); 299 if (retval) { 300 com_err("ext2fs_write_inode", retval, 301 _("while writing inode %ld in %s"), ino, proc); 302 fatal_error(ctx, 0); 303 } 304} 305 306#ifdef MTRACE 307void mtrace_print(char *mesg) 308{ 309 FILE *malloc_get_mallstream(); 310 FILE *f = malloc_get_mallstream(); 311 312 if (f) 313 fprintf(f, "============= %s\n", mesg); 314} 315#endif 316 317blk_t get_backup_sb(ext2_filsys fs) 318{ 319 if (!fs || !fs->super) 320 return 8193; 321 return fs->super->s_blocks_per_group + fs->super->s_first_data_block; 322} 323 324/* 325 * Given a mode, return the ext2 file type 326 */ 327int ext2_file_type(unsigned int mode) 328{ 329 if (LINUX_S_ISREG(mode)) 330 return EXT2_FT_REG_FILE; 331 332 if (LINUX_S_ISDIR(mode)) 333 return EXT2_FT_DIR; 334 335 if (LINUX_S_ISCHR(mode)) 336 return EXT2_FT_CHRDEV; 337 338 if (LINUX_S_ISBLK(mode)) 339 return EXT2_FT_BLKDEV; 340 341 if (LINUX_S_ISLNK(mode)) 342 return EXT2_FT_SYMLINK; 343 344 if (LINUX_S_ISFIFO(mode)) 345 return EXT2_FT_FIFO; 346 347 if (LINUX_S_ISSOCK(mode)) 348 return EXT2_FT_SOCK; 349 350 return 0; 351} 352