]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame - e2fsck/util.c
Shorten compile commands run by the build system
[thirdparty/e2fsprogs.git] / e2fsck / util.c
CommitLineData
3839e657
TT
1/*
2 * util.c --- miscellaneous utilities
efc6f628 3 *
21c84b71
TT
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%
3839e657
TT
10 */
11
d1154eb4 12#include "config.h"
3839e657 13#include <stdlib.h>
80875db5 14#include <stdio.h>
3839e657
TT
15#include <unistd.h>
16#include <string.h>
17#include <ctype.h>
80875db5
TT
18#ifdef __linux__
19#include <sys/utsname.h>
20#endif
9ecd8bec
TT
21
22#ifdef HAVE_CONIO_H
23#undef HAVE_TERMIOS_H
24#include <conio.h>
e6597048 25#define read_a_char() getch()
9ecd8bec
TT
26#else
27#ifdef HAVE_TERMIOS_H
3839e657 28#include <termios.h>
9ecd8bec
TT
29#endif
30#endif
31
4a9f5936
TT
32#ifdef HAVE_MALLOC_H
33#include <malloc.h>
34#endif
3839e657 35
49a7360b
JS
36#ifdef HAVE_ERRNO_H
37#include <errno.h>
38#endif
39
3839e657
TT
40#include "e2fsck.h"
41
aa75eccc 42extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
542867fb 43
50e1e10f
TT
44#include <sys/time.h>
45#include <sys/resource.h>
46
f8188fff 47void fatal_error(e2fsck_t ctx, const char *msg)
3839e657 48{
efc6f628 49 if (msg)
1b6bf175 50 fprintf (stderr, "e2fsck: %s\n", msg);
58a75177 51 if (ctx->fs && ctx->fs->io) {
e39ac922 52 if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
58a75177
TT
53 io_channel_flush(ctx->fs->io);
54 else
55 fprintf(stderr, "e2fsck: io manager magic bad!\n");
56 }
f8188fff
TT
57 ctx->flags |= E2F_FLAG_ABORT;
58 if (ctx->flags & E2F_FLAG_SETJMP_OK)
59 longjmp(ctx->abort_loc, 1);
3839e657
TT
60 exit(FSCK_ERROR);
61}
62
f8188fff
TT
63void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
64 const char *description)
3839e657
TT
65{
66 void *ret;
67 char buf[256];
68
69#ifdef DEBUG_ALLOCATE_MEMORY
611378fe 70 printf("Allocating %u bytes for %s...\n", size, description);
3839e657
TT
71#endif
72 ret = malloc(size);
73 if (!ret) {
7f88b043 74 sprintf(buf, "Can't allocate %s\n", description);
f8188fff 75 fatal_error(ctx, buf);
3839e657
TT
76 }
77 memset(ret, 0, size);
78 return ret;
79}
80
efc6f628 81char *string_copy(e2fsck_t ctx EXT2FS_ATTR((unused)),
54434927 82 const char *str, int len)
f364093b
TT
83{
84 char *ret;
efc6f628 85
f364093b
TT
86 if (!str)
87 return NULL;
88 if (!len)
89 len = strlen(str);
90 ret = malloc(len+1);
91 if (ret) {
92 strncpy(ret, str, len);
93 ret[len] = 0;
94 }
95 return ret;
96}
97
98#ifndef HAVE_STRNLEN
99/*
100 * Incredibly, libc5 doesn't appear to have strnlen. So we have to
101 * provide our own.
102 */
103int e2fsck_strnlen(const char * s, int count)
104{
105 const char *cp = s;
106
107 while (count-- && *cp)
108 cp++;
109 return cp - s;
110}
111#endif
112
542867fb 113#ifndef HAVE_CONIO_H
3e699064 114static int read_a_char(void)
542867fb
TT
115{
116 char c;
117 int r;
118 int fail = 0;
119
120 while(1) {
121 if (e2fsck_global_ctx &&
122 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
123 return 3;
124 }
125 r = read(0, &c, 1);
126 if (r == 1)
127 return c;
128 if (fail++ > 100)
129 break;
130 }
131 return EOF;
132}
133#endif
134
3839e657
TT
135int ask_yn(const char * string, int def)
136{
137 int c;
3839e657 138 const char *defstr;
53ef44c4
TT
139 const char *short_yes = _("yY");
140 const char *short_no = _("nN");
3839e657 141
9ecd8bec
TT
142#ifdef HAVE_TERMIOS_H
143 struct termios termios, tmp;
144
3839e657
TT
145 tcgetattr (0, &termios);
146 tmp = termios;
147 tmp.c_lflag &= ~(ICANON | ECHO);
50e1e10f
TT
148 tmp.c_cc[VMIN] = 1;
149 tmp.c_cc[VTIME] = 0;
3839e657 150 tcsetattr (0, TCSANOW, &tmp);
9ecd8bec 151#endif
3839e657
TT
152
153 if (def == 1)
542867fb 154 defstr = _(_("<y>"));
3839e657 155 else if (def == 0)
542867fb 156 defstr = _(_("<n>"));
3839e657 157 else
0c4a0726 158 defstr = _(" (y/n)");
3839e657
TT
159 printf("%s%s? ", string, defstr);
160 while (1) {
161 fflush (stdout);
e6597048 162 if ((c = read_a_char()) == EOF)
3839e657 163 break;
542867fb
TT
164 if (c == 3) {
165#ifdef HAVE_TERMIOS_H
166 tcsetattr (0, TCSANOW, &termios);
167#endif
168 if (e2fsck_global_ctx &&
169 e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
170 puts("\n");
171 longjmp(e2fsck_global_ctx->abort_loc, 1);
172 }
173 puts(_("cancelled!\n"));
174 return 0;
175 }
0c4a0726 176 if (strchr(short_yes, (char) c)) {
3839e657
TT
177 def = 1;
178 break;
179 }
0c4a0726 180 else if (strchr(short_no, (char) c)) {
3839e657
TT
181 def = 0;
182 break;
183 }
1760d167 184 else if ((c == 27 || c == ' ' || c == '\n') && (def != -1))
3839e657
TT
185 break;
186 }
187 if (def)
542867fb 188 puts(_("yes\n"));
3839e657 189 else
542867fb 190 puts (_("no\n"));
9ecd8bec 191#ifdef HAVE_TERMIOS_H
3839e657 192 tcsetattr (0, TCSANOW, &termios);
9ecd8bec 193#endif
3839e657
TT
194 return def;
195}
196
1b6bf175 197int ask (e2fsck_t ctx, const char * string, int def)
3839e657 198{
1b6bf175 199 if (ctx->options & E2F_OPT_NO) {
0c4a0726 200 printf (_("%s? no\n\n"), string);
3839e657
TT
201 return 0;
202 }
1b6bf175 203 if (ctx->options & E2F_OPT_YES) {
0c4a0726 204 printf (_("%s? yes\n\n"), string);
3839e657
TT
205 return 1;
206 }
1b6bf175 207 if (ctx->options & E2F_OPT_PREEN) {
0c4a0726 208 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
3839e657
TT
209 return def;
210 }
211 return ask_yn(string, def);
212}
213
f8188fff 214void e2fsck_read_bitmaps(e2fsck_t ctx)
3839e657 215{
1b6bf175 216 ext2_filsys fs = ctx->fs;
3839e657 217 errcode_t retval;
e94bc631 218 const char *old_op;
3839e657 219
1b6bf175
TT
220 if (ctx->invalid_bitmaps) {
221 com_err(ctx->program_name, 0,
0c4a0726 222 _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
1b6bf175 223 ctx->device_name);
f8188fff 224 fatal_error(ctx, 0);
3839e657 225 }
f3db3566 226
e94bc631 227 old_op = ehandler_operation(_("reading inode and block bitmaps"));
f3db3566 228 retval = ext2fs_read_bitmaps(fs);
e94bc631 229 ehandler_operation(old_op);
f3db3566 230 if (retval) {
1b6bf175 231 com_err(ctx->program_name, retval,
0c4a0726 232 _("while retrying to read bitmaps for %s"),
1b6bf175 233 ctx->device_name);
f8188fff 234 fatal_error(ctx, 0);
3839e657
TT
235 }
236}
237
f8188fff 238void e2fsck_write_bitmaps(e2fsck_t ctx)
3839e657 239{
1b6bf175 240 ext2_filsys fs = ctx->fs;
3839e657 241 errcode_t retval;
e94bc631 242 const char *old_op;
3839e657 243
1bb6f6c8
AD
244 old_op = ehandler_operation(_("writing block and inode bitmaps"));
245 retval = ext2fs_write_bitmaps(fs);
246 ehandler_operation(old_op);
247 if (retval) {
248 com_err(ctx->program_name, retval,
249 _("while rewriting block and inode bitmaps for %s"),
250 ctx->device_name);
251 fatal_error(ctx, 0);
3839e657
TT
252 }
253}
254
1b6bf175 255void preenhalt(e2fsck_t ctx)
3839e657 256{
1b6bf175
TT
257 ext2_filsys fs = ctx->fs;
258
259 if (!(ctx->options & E2F_OPT_PREEN))
3839e657 260 return;
0c4a0726
TT
261 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
262 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
1b6bf175 263 ctx->device_name);
79cc3362 264 ctx->flags |= E2F_FLAG_EXITING;
50e1e10f
TT
265 if (fs != NULL) {
266 fs->super->s_state |= EXT2_ERROR_FS;
267 ext2fs_mark_super_dirty(fs);
268 ext2fs_close(fs);
269 }
3839e657
TT
270 exit(FSCK_UNCORRECTED);
271}
272
8bf191e8 273#ifdef RESOURCE_TRACK
6d96b00d 274void init_resource_track(struct resource_track *track, io_channel channel)
3839e657 275{
50e1e10f 276#ifdef HAVE_GETRUSAGE
3839e657 277 struct rusage r;
50e1e10f 278#endif
6d96b00d 279 io_stats io_start = 0;
efc6f628 280
3839e657
TT
281 track->brk_start = sbrk(0);
282 gettimeofday(&track->time_start, 0);
50e1e10f 283#ifdef HAVE_GETRUSAGE
53ef44c4
TT
284#ifdef sun
285 memset(&r, 0, sizeof(struct rusage));
1b6bf175 286#endif
3839e657
TT
287 getrusage(RUSAGE_SELF, &r);
288 track->user_start = r.ru_utime;
289 track->system_start = r.ru_stime;
50e1e10f
TT
290#else
291 track->user_start.tv_sec = track->user_start.tv_usec = 0;
292 track->system_start.tv_sec = track->system_start.tv_usec = 0;
293#endif
6d96b00d
TT
294 track->bytes_read = 0;
295 track->bytes_written = 0;
296 if (channel && channel->manager && channel->manager->get_stats)
297 channel->manager->get_stats(channel, &io_start);
298 if (io_start) {
299 track->bytes_read = io_start->bytes_read;
300 track->bytes_written = io_start->bytes_written;
301 }
3839e657
TT
302}
303
21c84b71
TT
304#ifdef __GNUC__
305#define _INLINE_ __inline__
306#else
307#define _INLINE_
308#endif
309
310static _INLINE_ float timeval_subtract(struct timeval *tv1,
311 struct timeval *tv2)
3839e657
TT
312{
313 return ((tv1->tv_sec - tv2->tv_sec) +
314 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
315}
316
9facd076
KC
317void print_resource_track(e2fsck_t ctx, const char *desc,
318 struct resource_track *track, io_channel channel)
3839e657 319{
50e1e10f 320#ifdef HAVE_GETRUSAGE
3839e657 321 struct rusage r;
4a9f5936
TT
322#endif
323#ifdef HAVE_MALLINFO
324 struct mallinfo malloc_info;
50e1e10f 325#endif
3839e657
TT
326 struct timeval time_end;
327
9facd076
KC
328 if ((desc && !(ctx->options & E2F_OPT_TIME2)) ||
329 (!desc && !(ctx->options & E2F_OPT_TIME)))
330 return;
331
332 e2fsck_clear_progbar(ctx);
3839e657 333 gettimeofday(&time_end, 0);
1b6bf175
TT
334
335 if (desc)
7fdfabd3 336 printf("%s: ", desc);
4a9f5936
TT
337
338#ifdef HAVE_MALLINFO
70eabde9 339#define kbytes(x) (((unsigned long)(x) + 1023) / 1024)
efc6f628 340
4a9f5936 341 malloc_info = mallinfo();
70eabde9 342 printf(_("Memory used: %luk/%luk (%luk/%luk), "),
80c5d7e4
TT
343 kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
344 kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
4a9f5936 345#else
70eabde9
AD
346 printf(_("Memory used: %lu, "),
347 (unsigned long) (((char *) sbrk(0)) -
348 ((char *) track->brk_start)));
efc6f628 349#endif
50e1e10f 350#ifdef HAVE_GETRUSAGE
3839e657
TT
351 getrusage(RUSAGE_SELF, &r);
352
80c5d7e4 353 printf(_("time: %5.2f/%5.2f/%5.2f\n"),
3839e657
TT
354 timeval_subtract(&time_end, &track->time_start),
355 timeval_subtract(&r.ru_utime, &track->user_start),
356 timeval_subtract(&r.ru_stime, &track->system_start));
50e1e10f 357#else
0c4a0726 358 printf(_("elapsed time: %6.3f\n"),
50e1e10f
TT
359 timeval_subtract(&time_end, &track->time_start));
360#endif
6d96b00d
TT
361#define mbytes(x) (((x) + 1048575) / 1048576)
362 if (channel && channel->manager && channel->manager->get_stats) {
363 io_stats delta = 0;
364 unsigned long long bytes_read = 0;
365 unsigned long long bytes_written = 0;
366
367 if (desc)
368 printf("%s: ", desc);
369
370 channel->manager->get_stats(channel, &delta);
371 if (delta) {
372 bytes_read = delta->bytes_read - track->bytes_read;
efc6f628 373 bytes_written = delta->bytes_written -
6d96b00d
TT
374 track->bytes_written;
375 }
376 printf("I/O read: %lluMB, write: %lluMB, rate: %.2fMB/s\n",
377 mbytes(bytes_read), mbytes(bytes_written),
378 (double)mbytes(bytes_read + bytes_written) /
379 timeval_subtract(&time_end, &track->time_start));
380 }
3839e657 381}
8bf191e8 382#endif /* RESOURCE_TRACK */
3839e657 383
08b21301 384void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
f3db3566
TT
385 struct ext2_inode * inode, const char *proc)
386{
387 int retval;
388
08b21301 389 retval = ext2fs_read_inode(ctx->fs, ino, inode);
f3db3566
TT
390 if (retval) {
391 com_err("ext2fs_read_inode", retval,
611378fe 392 _("while reading inode %lu in %s"), ino, proc);
f8188fff 393 fatal_error(ctx, 0);
f3db3566
TT
394 }
395}
396
fefaef39
AD
397void e2fsck_read_inode_full(e2fsck_t ctx, unsigned long ino,
398 struct ext2_inode *inode, int bufsize,
399 const char *proc)
400{
401 int retval;
402
403 retval = ext2fs_read_inode_full(ctx->fs, ino, inode, bufsize);
404 if (retval) {
405 com_err("ext2fs_read_inode_full", retval,
611378fe 406 _("while reading inode %lu in %s"), ino, proc);
fefaef39
AD
407 fatal_error(ctx, 0);
408 }
409}
410
cebe48a1
TT
411extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
412 struct ext2_inode * inode, int bufsize,
413 const char *proc)
414{
415 int retval;
416
417 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
418 if (retval) {
419 com_err("ext2fs_write_inode", retval,
611378fe 420 _("while writing inode %lu in %s"), ino, proc);
cebe48a1
TT
421 fatal_error(ctx, 0);
422 }
423}
424
08b21301 425extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
f3db3566
TT
426 struct ext2_inode * inode, const char *proc)
427{
428 int retval;
429
08b21301 430 retval = ext2fs_write_inode(ctx->fs, ino, inode);
f3db3566
TT
431 if (retval) {
432 com_err("ext2fs_write_inode", retval,
611378fe 433 _("while writing inode %lu in %s"), ino, proc);
f8188fff 434 fatal_error(ctx, 0);
f3db3566
TT
435 }
436}
437
3839e657
TT
438#ifdef MTRACE
439void mtrace_print(char *mesg)
440{
441 FILE *malloc_get_mallstream();
442 FILE *f = malloc_get_mallstream();
443
444 if (f)
445 fprintf(f, "============= %s\n", mesg);
446}
447#endif
448
f1a1761d
TT
449blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
450 io_manager manager)
1b6bf175 451{
f1a1761d
TT
452 struct ext2_super_block *sb;
453 io_channel io = NULL;
fae9bfaa 454 void *buf = NULL;
f1a1761d
TT
455 int blocksize;
456 blk_t superblock, ret_sb = 8193;
efc6f628 457
f1a1761d
TT
458 if (fs && fs->super) {
459 ret_sb = (fs->super->s_blocks_per_group +
460 fs->super->s_first_data_block);
461 if (ctx) {
462 ctx->superblock = ret_sb;
463 ctx->blocksize = fs->blocksize;
464 }
465 return ret_sb;
466 }
efc6f628 467
f1a1761d
TT
468 if (ctx) {
469 if (ctx->blocksize) {
470 ret_sb = ctx->blocksize * 8;
471 if (ctx->blocksize == 1024)
472 ret_sb++;
473 ctx->superblock = ret_sb;
474 return ret_sb;
475 }
476 ctx->superblock = ret_sb;
477 ctx->blocksize = 1024;
478 }
479
480 if (!name || !manager)
481 goto cleanup;
482
483 if (manager->open(name, 0, &io) != 0)
484 goto cleanup;
485
486 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
487 goto cleanup;
488 sb = (struct ext2_super_block *) buf;
489
932a489c
AD
490 for (blocksize = EXT2_MIN_BLOCK_SIZE;
491 blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
f1a1761d
TT
492 superblock = blocksize*8;
493 if (blocksize == 1024)
494 superblock++;
495 io_channel_set_blksize(io, blocksize);
24a117ab 496 if (io_channel_read_blk64(io, superblock,
f1a1761d
TT
497 -SUPERBLOCK_SIZE, buf))
498 continue;
2eae0930 499#ifdef WORDS_BIGENDIAN
f1a1761d
TT
500 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
501 ext2fs_swap_super(sb);
502#endif
e7b5d3c0
DD
503 if ((sb->s_magic == EXT2_SUPER_MAGIC) &&
504 (EXT2_BLOCK_SIZE(sb) == blocksize)) {
557ddb2f
TT
505 ret_sb = superblock;
506 if (ctx) {
507 ctx->superblock = superblock;
508 ctx->blocksize = blocksize;
509 }
f1a1761d
TT
510 break;
511 }
512 }
513
514cleanup:
515 if (io)
516 io_channel_close(io);
517 if (buf)
518 ext2fs_free_mem(&buf);
519 return (ret_sb);
1b6bf175 520}
3839e657 521
6fdc7a32
TT
522/*
523 * Given a mode, return the ext2 file type
524 */
525int ext2_file_type(unsigned int mode)
526{
527 if (LINUX_S_ISREG(mode))
528 return EXT2_FT_REG_FILE;
529
530 if (LINUX_S_ISDIR(mode))
531 return EXT2_FT_DIR;
efc6f628 532
6fdc7a32
TT
533 if (LINUX_S_ISCHR(mode))
534 return EXT2_FT_CHRDEV;
efc6f628 535
6fdc7a32
TT
536 if (LINUX_S_ISBLK(mode))
537 return EXT2_FT_BLKDEV;
efc6f628 538
6fdc7a32
TT
539 if (LINUX_S_ISLNK(mode))
540 return EXT2_FT_SYMLINK;
541
542 if (LINUX_S_ISFIFO(mode))
543 return EXT2_FT_FIFO;
efc6f628 544
6fdc7a32
TT
545 if (LINUX_S_ISSOCK(mode))
546 return EXT2_FT_SOCK;
efc6f628 547
6fdc7a32
TT
548 return 0;
549}
49a7360b
JS
550
551#define STRIDE_LENGTH 8
552/*
553 * Helper function which zeros out _num_ blocks starting at _blk_. In
554 * case of an error, the details of the error is returned via _ret_blk_
555 * and _ret_count_ if they are non-NULL pointers. Returns 0 on
556 * success, and an error code on an error.
557 *
558 * As a special case, if the first argument is NULL, then it will
559 * attempt to free the static zeroizing buffer. (This is to keep
560 * programs that check for memory leaks happy.)
561 */
562errcode_t e2fsck_zero_blocks(ext2_filsys fs, blk_t blk, int num,
563 blk_t *ret_blk, int *ret_count)
564{
565 int j, count, next_update, next_update_incr;
566 static char *buf;
567 errcode_t retval;
568
569 /* If fs is null, clean up the static buffer and return */
570 if (!fs) {
571 if (buf) {
572 free(buf);
573 buf = 0;
574 }
575 return 0;
576 }
577 /* Allocate the zeroizing buffer if necessary */
578 if (!buf) {
579 buf = malloc(fs->blocksize * STRIDE_LENGTH);
580 if (!buf) {
581 com_err("malloc", ENOMEM,
582 _("while allocating zeroizing buffer"));
583 exit(1);
584 }
585 memset(buf, 0, fs->blocksize * STRIDE_LENGTH);
586 }
587 /* OK, do the write loop */
588 next_update = 0;
589 next_update_incr = num / 100;
590 if (next_update_incr < 1)
591 next_update_incr = 1;
592 for (j = 0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
593 count = num - j;
594 if (count > STRIDE_LENGTH)
595 count = STRIDE_LENGTH;
24a117ab 596 retval = io_channel_write_blk64(fs->io, blk, count, buf);
49a7360b
JS
597 if (retval) {
598 if (ret_count)
599 *ret_count = count;
600 if (ret_blk)
601 *ret_blk = blk;
602 return retval;
603 }
604 }
605 return 0;
606}
80875db5
TT
607
608/*
609 * Check to see if a filesystem is in /proc/filesystems.
610 * Returns 1 if found, 0 if not
611 */
612int fs_proc_check(const char *fs_name)
613{
614 FILE *f;
615 char buf[80], *cp, *t;
616
617 f = fopen("/proc/filesystems", "r");
618 if (!f)
619 return (0);
620 while (!feof(f)) {
621 if (!fgets(buf, sizeof(buf), f))
622 break;
623 cp = buf;
624 if (!isspace(*cp)) {
625 while (*cp && !isspace(*cp))
626 cp++;
627 }
628 while (*cp && isspace(*cp))
629 cp++;
630 if ((t = strchr(cp, '\n')) != NULL)
631 *t = 0;
632 if ((t = strchr(cp, '\t')) != NULL)
633 *t = 0;
634 if ((t = strchr(cp, ' ')) != NULL)
635 *t = 0;
636 if (!strcmp(fs_name, cp)) {
637 fclose(f);
638 return (1);
639 }
640 }
641 fclose(f);
642 return (0);
643}
644
645/*
646 * Check to see if a filesystem is available as a module
647 * Returns 1 if found, 0 if not
648 */
649int check_for_modules(const char *fs_name)
650{
651#ifdef __linux__
652 struct utsname uts;
653 FILE *f;
654 char buf[1024], *cp, *t;
655 int i;
656
657 if (uname(&uts))
658 return (0);
659 snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release);
660
661 f = fopen(buf, "r");
662 if (!f)
663 return (0);
664 while (!feof(f)) {
665 if (!fgets(buf, sizeof(buf), f))
666 break;
667 if ((cp = strchr(buf, ':')) != NULL)
668 *cp = 0;
669 else
670 continue;
671 if ((cp = strrchr(buf, '/')) != NULL)
672 cp++;
f2fe5da3
ES
673 else
674 cp = buf;
80875db5
TT
675 i = strlen(cp);
676 if (i > 3) {
677 t = cp + i - 3;
678 if (!strcmp(t, ".ko"))
679 *t = 0;
680 }
681 if (!strcmp(cp, fs_name)) {
682 fclose(f);
683 return (1);
684 }
685 }
686 fclose(f);
687#endif /* __linux__ */
688 return (0);
689}
b0258cbc
TT
690
691/*
692 * Helper function that does the right thing if write returns a
693 * partial write, or an EGAIN/EINTR error.
694 */
695int write_all(int fd, char *buf, size_t count)
696{
697 ssize_t ret;
698 int c = 0;
699
700 while (count > 0) {
701 ret = write(fd, buf, count);
702 if (ret < 0) {
703 if ((errno == EAGAIN) || (errno == EINTR))
704 continue;
705 return -1;
706 }
707 count -= ret;
708 buf += ret;
709 c += ret;
710 }
711 return c;
712}