2 * util.c --- miscellaneous utilities
4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
7 * This file may be redistributed under the terms of the GNU Public
20 #define read_a_char() getch()
34 extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
37 #include <sys/resource.h>
39 void fatal_error(e2fsck_t ctx, const char *msg)
42 fprintf (stderr, "e2fsck: %s\n", msg);
43 if (ctx->fs && ctx->fs->io) {
44 if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
45 io_channel_flush(ctx->fs->io);
47 fprintf(stderr, "e2fsck: io manager magic bad!\n");
49 ctx->flags |= E2F_FLAG_ABORT;
50 if (ctx->flags & E2F_FLAG_SETJMP_OK)
51 longjmp(ctx->abort_loc, 1);
55 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
56 const char *description)
61 #ifdef DEBUG_ALLOCATE_MEMORY
62 printf("Allocating %d bytes for %s...\n", size, description);
66 sprintf(buf, "Can't allocate %s\n", description);
67 fatal_error(ctx, buf);
73 char *string_copy(e2fsck_t ctx EXT2FS_ATTR((unused)),
74 const char *str, int len)
84 strncpy(ret, str, len);
92 * Incredibly, libc5 doesn't appear to have strnlen. So we have to
95 int e2fsck_strnlen(const char * s, int count)
99 while (count-- && *cp)
106 static int read_a_char(void)
113 if (e2fsck_global_ctx &&
114 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
127 int ask_yn(const char * string, int def)
131 const char *short_yes = _("yY");
132 const char *short_no = _("nN");
134 #ifdef HAVE_TERMIOS_H
135 struct termios termios, tmp;
137 tcgetattr (0, &termios);
139 tmp.c_lflag &= ~(ICANON | ECHO);
142 tcsetattr (0, TCSANOW, &tmp);
146 defstr = _(_("<y>"));
148 defstr = _(_("<n>"));
150 defstr = _(" (y/n)");
151 printf("%s%s? ", string, defstr);
154 if ((c = read_a_char()) == EOF)
157 #ifdef HAVE_TERMIOS_H
158 tcsetattr (0, TCSANOW, &termios);
160 if (e2fsck_global_ctx &&
161 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
163 longjmp(e2fsck_global_ctx->abort_loc, 1);
165 puts(_("cancelled!\n"));
168 if (strchr(short_yes, (char) c)) {
172 else if (strchr(short_no, (char) c)) {
176 else if ((c == ' ' || c == '\n') && (def != -1))
183 #ifdef HAVE_TERMIOS_H
184 tcsetattr (0, TCSANOW, &termios);
189 int ask (e2fsck_t ctx, const char * string, int def)
191 if (ctx->options & E2F_OPT_NO) {
192 printf (_("%s? no\n\n"), string);
195 if (ctx->options & E2F_OPT_YES) {
196 printf (_("%s? yes\n\n"), string);
199 if (ctx->options & E2F_OPT_PREEN) {
200 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
203 return ask_yn(string, def);
206 void e2fsck_read_bitmaps(e2fsck_t ctx)
208 ext2_filsys fs = ctx->fs;
211 if (ctx->invalid_bitmaps) {
212 com_err(ctx->program_name, 0,
213 _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
218 ehandler_operation(_("reading inode and block bitmaps"));
219 retval = ext2fs_read_bitmaps(fs);
220 ehandler_operation(0);
222 com_err(ctx->program_name, retval,
223 _("while retrying to read bitmaps for %s"),
229 void e2fsck_write_bitmaps(e2fsck_t ctx)
231 ext2_filsys fs = ctx->fs;
234 if (ext2fs_test_bb_dirty(fs)) {
235 ehandler_operation(_("writing block bitmaps"));
236 retval = ext2fs_write_block_bitmap(fs);
237 ehandler_operation(0);
239 com_err(ctx->program_name, retval,
240 _("while retrying to write block bitmaps for %s"),
246 if (ext2fs_test_ib_dirty(fs)) {
247 ehandler_operation(_("writing inode bitmaps"));
248 retval = ext2fs_write_inode_bitmap(fs);
249 ehandler_operation(0);
251 com_err(ctx->program_name, retval,
252 _("while retrying to write inode bitmaps for %s"),
259 void preenhalt(e2fsck_t ctx)
261 ext2_filsys fs = ctx->fs;
263 if (!(ctx->options & E2F_OPT_PREEN))
265 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
266 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
269 fs->super->s_state |= EXT2_ERROR_FS;
270 ext2fs_mark_super_dirty(fs);
273 exit(FSCK_UNCORRECTED);
276 #ifdef RESOURCE_TRACK
277 void init_resource_track(struct resource_track *track)
279 #ifdef HAVE_GETRUSAGE
283 track->brk_start = sbrk(0);
284 gettimeofday(&track->time_start, 0);
285 #ifdef HAVE_GETRUSAGE
287 memset(&r, 0, sizeof(struct rusage));
289 getrusage(RUSAGE_SELF, &r);
290 track->user_start = r.ru_utime;
291 track->system_start = r.ru_stime;
293 track->user_start.tv_sec = track->user_start.tv_usec = 0;
294 track->system_start.tv_sec = track->system_start.tv_usec = 0;
299 #define _INLINE_ __inline__
304 static _INLINE_ float timeval_subtract(struct timeval *tv1,
307 return ((tv1->tv_sec - tv2->tv_sec) +
308 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
311 void print_resource_track(const char *desc, struct resource_track *track)
313 #ifdef HAVE_GETRUSAGE
317 struct mallinfo malloc_info;
319 struct timeval time_end;
321 gettimeofday(&time_end, 0);
324 printf("%s: ", desc);
327 #define kbytes(x) (((x) + 1023) / 1024)
329 malloc_info = mallinfo();
330 printf(_("Memory used: %dk/%dk (%dk/%dk), "),
331 kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
332 kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
334 printf(_("Memory used: %d, "),
335 (int) (((char *) sbrk(0)) - ((char *) track->brk_start)));
337 #ifdef HAVE_GETRUSAGE
338 getrusage(RUSAGE_SELF, &r);
340 printf(_("time: %5.2f/%5.2f/%5.2f\n"),
341 timeval_subtract(&time_end, &track->time_start),
342 timeval_subtract(&r.ru_utime, &track->user_start),
343 timeval_subtract(&r.ru_stime, &track->system_start));
345 printf(_("elapsed time: %6.3f\n"),
346 timeval_subtract(&time_end, &track->time_start));
349 #endif /* RESOURCE_TRACK */
351 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
352 struct ext2_inode * inode, const char *proc)
356 retval = ext2fs_read_inode(ctx->fs, ino, inode);
358 com_err("ext2fs_read_inode", retval,
359 _("while reading inode %ld in %s"), ino, proc);
364 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
365 struct ext2_inode * inode, int bufsize,
370 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
372 com_err("ext2fs_write_inode", retval,
373 _("while writing inode %ld in %s"), ino, proc);
378 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
379 struct ext2_inode * inode, const char *proc)
383 retval = ext2fs_write_inode(ctx->fs, ino, inode);
385 com_err("ext2fs_write_inode", retval,
386 _("while writing inode %ld in %s"), ino, proc);
392 void mtrace_print(char *mesg)
394 FILE *malloc_get_mallstream();
395 FILE *f = malloc_get_mallstream();
398 fprintf(f, "============= %s\n", mesg);
402 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
405 struct ext2_super_block *sb;
406 io_channel io = NULL;
409 blk_t superblock, ret_sb = 8193;
411 if (fs && fs->super) {
412 ret_sb = (fs->super->s_blocks_per_group +
413 fs->super->s_first_data_block);
415 ctx->superblock = ret_sb;
416 ctx->blocksize = fs->blocksize;
422 if (ctx->blocksize) {
423 ret_sb = ctx->blocksize * 8;
424 if (ctx->blocksize == 1024)
426 ctx->superblock = ret_sb;
429 ctx->superblock = ret_sb;
430 ctx->blocksize = 1024;
433 if (!name || !manager)
436 if (manager->open(name, 0, &io) != 0)
439 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
441 sb = (struct ext2_super_block *) buf;
443 for (blocksize = EXT2_MIN_BLOCK_SIZE;
444 blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
445 superblock = blocksize*8;
446 if (blocksize == 1024)
448 io_channel_set_blksize(io, blocksize);
449 if (io_channel_read_blk(io, superblock,
450 -SUPERBLOCK_SIZE, buf))
452 #ifdef EXT2FS_ENABLE_SWAPFS
453 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
454 ext2fs_swap_super(sb);
456 if (sb->s_magic == EXT2_SUPER_MAGIC) {
459 ctx->superblock = superblock;
460 ctx->blocksize = blocksize;
468 io_channel_close(io);
470 ext2fs_free_mem(&buf);
475 * Given a mode, return the ext2 file type
477 int ext2_file_type(unsigned int mode)
479 if (LINUX_S_ISREG(mode))
480 return EXT2_FT_REG_FILE;
482 if (LINUX_S_ISDIR(mode))
485 if (LINUX_S_ISCHR(mode))
486 return EXT2_FT_CHRDEV;
488 if (LINUX_S_ISBLK(mode))
489 return EXT2_FT_BLKDEV;
491 if (LINUX_S_ISLNK(mode))
492 return EXT2_FT_SYMLINK;
494 if (LINUX_S_ISFIFO(mode))
497 if (LINUX_S_ISSOCK(mode))