blob: 19d4685862ec8c6cf14389f82e569dd71c643d68 [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
2 * util.c --- miscellaneous utilities
3 *
Theodore Ts'o21c84b71997-04-29 16:15:03 +00004 * 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%
Theodore Ts'o3839e651997-04-26 13:21:57 +000010 */
11
12#include <stdlib.h>
13#include <unistd.h>
14#include <string.h>
15#include <ctype.h>
Theodore Ts'o9ecd8be1999-10-20 18:24:31 +000016
17#ifdef HAVE_CONIO_H
18#undef HAVE_TERMIOS_H
19#include <conio.h>
Theodore Ts'oe6597041999-10-26 02:30:16 +000020#define read_a_char() getch()
Theodore Ts'o9ecd8be1999-10-20 18:24:31 +000021#else
22#ifdef HAVE_TERMIOS_H
Theodore Ts'o3839e651997-04-26 13:21:57 +000023#include <termios.h>
Theodore Ts'o9ecd8be1999-10-20 18:24:31 +000024#endif
Theodore Ts'oe6597041999-10-26 02:30:16 +000025#include <stdio.h>
Theodore Ts'oc81c6ce1999-10-26 04:28:53 +000026#define read_a_char() getchar()
Theodore Ts'o9ecd8be1999-10-20 18:24:31 +000027#endif
28
Theodore Ts'o4a9f5931999-03-16 19:32:52 +000029#ifdef HAVE_MALLOC_H
30#include <malloc.h>
31#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +000032
33#include "e2fsck.h"
34
Theodore Ts'o50e1e101997-04-26 13:58:21 +000035#include <sys/time.h>
36#include <sys/resource.h>
37
Theodore Ts'of8188ff1997-11-14 05:23:04 +000038void fatal_error(e2fsck_t ctx, const char *msg)
Theodore Ts'o3839e651997-04-26 13:21:57 +000039{
40 if (msg)
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000041 fprintf (stderr, "e2fsck: %s\n", msg);
Theodore Ts'o58a75172001-01-12 20:59:19 +000042 if (ctx->fs && ctx->fs->io) {
Theodore Ts'oe39ac922001-05-05 06:47:24 +000043 if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
Theodore Ts'o58a75172001-01-12 20:59:19 +000044 io_channel_flush(ctx->fs->io);
45 else
46 fprintf(stderr, "e2fsck: io manager magic bad!\n");
47 }
Theodore Ts'of8188ff1997-11-14 05:23:04 +000048 ctx->flags |= E2F_FLAG_ABORT;
49 if (ctx->flags & E2F_FLAG_SETJMP_OK)
50 longjmp(ctx->abort_loc, 1);
Theodore Ts'o3839e651997-04-26 13:21:57 +000051 exit(FSCK_ERROR);
52}
53
Theodore Ts'of8188ff1997-11-14 05:23:04 +000054void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
55 const char *description)
Theodore Ts'o3839e651997-04-26 13:21:57 +000056{
57 void *ret;
58 char buf[256];
59
60#ifdef DEBUG_ALLOCATE_MEMORY
61 printf("Allocating %d bytes for %s...\n", size, description);
62#endif
63 ret = malloc(size);
64 if (!ret) {
Theodore Ts'o7f88b041997-04-26 14:48:50 +000065 sprintf(buf, "Can't allocate %s\n", description);
Theodore Ts'of8188ff1997-11-14 05:23:04 +000066 fatal_error(ctx, buf);
Theodore Ts'o3839e651997-04-26 13:21:57 +000067 }
68 memset(ret, 0, size);
69 return ret;
70}
71
Theodore Ts'o3839e651997-04-26 13:21:57 +000072int ask_yn(const char * string, int def)
73{
74 int c;
Theodore Ts'o3839e651997-04-26 13:21:57 +000075 const char *defstr;
Theodore Ts'o53ef44c2001-01-06 05:55:58 +000076 const char *short_yes = _("yY");
77 const char *short_no = _("nN");
Theodore Ts'o3839e651997-04-26 13:21:57 +000078
Theodore Ts'o9ecd8be1999-10-20 18:24:31 +000079#ifdef HAVE_TERMIOS_H
80 struct termios termios, tmp;
81
Theodore Ts'o3839e651997-04-26 13:21:57 +000082 tcgetattr (0, &termios);
83 tmp = termios;
84 tmp.c_lflag &= ~(ICANON | ECHO);
Theodore Ts'o50e1e101997-04-26 13:58:21 +000085 tmp.c_cc[VMIN] = 1;
86 tmp.c_cc[VTIME] = 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +000087 tcsetattr (0, TCSANOW, &tmp);
Theodore Ts'o9ecd8be1999-10-20 18:24:31 +000088#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +000089
90 if (def == 1)
Theodore Ts'o0c4a0722000-02-07 03:11:03 +000091 defstr = _("<y>");
Theodore Ts'o3839e651997-04-26 13:21:57 +000092 else if (def == 0)
Theodore Ts'o0c4a0722000-02-07 03:11:03 +000093 defstr = _("<n>");
Theodore Ts'o3839e651997-04-26 13:21:57 +000094 else
Theodore Ts'o0c4a0722000-02-07 03:11:03 +000095 defstr = _(" (y/n)");
Theodore Ts'o3839e651997-04-26 13:21:57 +000096 printf("%s%s? ", string, defstr);
97 while (1) {
98 fflush (stdout);
Theodore Ts'oe6597041999-10-26 02:30:16 +000099 if ((c = read_a_char()) == EOF)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000100 break;
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000101 if (strchr(short_yes, (char) c)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000102 def = 1;
103 break;
104 }
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000105 else if (strchr(short_no, (char) c)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000106 def = 0;
107 break;
108 }
109 else if ((c == ' ' || c == '\n') && (def != -1))
110 break;
111 }
112 if (def)
113 printf ("yes\n\n");
114 else
115 printf ("no\n\n");
Theodore Ts'o9ecd8be1999-10-20 18:24:31 +0000116#ifdef HAVE_TERMIOS_H
Theodore Ts'o3839e651997-04-26 13:21:57 +0000117 tcsetattr (0, TCSANOW, &termios);
Theodore Ts'o9ecd8be1999-10-20 18:24:31 +0000118#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +0000119 return def;
120}
121
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000122int ask (e2fsck_t ctx, const char * string, int def)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000123{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000124 if (ctx->options & E2F_OPT_NO) {
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000125 printf (_("%s? no\n\n"), string);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000126 return 0;
127 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000128 if (ctx->options & E2F_OPT_YES) {
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000129 printf (_("%s? yes\n\n"), string);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000130 return 1;
131 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000132 if (ctx->options & E2F_OPT_PREEN) {
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000133 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
Theodore Ts'o3839e651997-04-26 13:21:57 +0000134 return def;
135 }
136 return ask_yn(string, def);
137}
138
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000139void e2fsck_read_bitmaps(e2fsck_t ctx)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000140{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000141 ext2_filsys fs = ctx->fs;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000142 errcode_t retval;
143
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000144 if (ctx->invalid_bitmaps) {
145 com_err(ctx->program_name, 0,
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000146 _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000147 ctx->device_name);
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000148 fatal_error(ctx, 0);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000149 }
Theodore Ts'of3db3561997-04-26 13:34:30 +0000150
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000151 ehandler_operation(_("reading inode and block bitmaps"));
Theodore Ts'of3db3561997-04-26 13:34:30 +0000152 retval = ext2fs_read_bitmaps(fs);
153 ehandler_operation(0);
154 if (retval) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000155 com_err(ctx->program_name, retval,
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000156 _("while retrying to read bitmaps for %s"),
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000157 ctx->device_name);
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000158 fatal_error(ctx, 0);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000159 }
160}
161
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000162void e2fsck_write_bitmaps(e2fsck_t ctx)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000163{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000164 ext2_filsys fs = ctx->fs;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000165 errcode_t retval;
166
167 if (ext2fs_test_bb_dirty(fs)) {
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000168 ehandler_operation(_("writing block bitmaps"));
Theodore Ts'o3839e651997-04-26 13:21:57 +0000169 retval = ext2fs_write_block_bitmap(fs);
170 ehandler_operation(0);
171 if (retval) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000172 com_err(ctx->program_name, retval,
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000173 _("while retrying to write block bitmaps for %s"),
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000174 ctx->device_name);
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000175 fatal_error(ctx, 0);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000176 }
177 }
178
179 if (ext2fs_test_ib_dirty(fs)) {
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000180 ehandler_operation(_("writing inode bitmaps"));
Theodore Ts'o3839e651997-04-26 13:21:57 +0000181 retval = ext2fs_write_inode_bitmap(fs);
182 ehandler_operation(0);
183 if (retval) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000184 com_err(ctx->program_name, retval,
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000185 _("while retrying to write inode bitmaps for %s"),
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000186 ctx->device_name);
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000187 fatal_error(ctx, 0);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000188 }
189 }
190}
191
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000192void preenhalt(e2fsck_t ctx)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000193{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000194 ext2_filsys fs = ctx->fs;
195
196 if (!(ctx->options & E2F_OPT_PREEN))
Theodore Ts'o3839e651997-04-26 13:21:57 +0000197 return;
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000198 fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
199 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000200 ctx->device_name);
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000201 if (fs != NULL) {
202 fs->super->s_state |= EXT2_ERROR_FS;
203 ext2fs_mark_super_dirty(fs);
204 ext2fs_close(fs);
205 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000206 exit(FSCK_UNCORRECTED);
207}
208
Theodore Ts'o8bf191e1997-10-20 01:38:32 +0000209#ifdef RESOURCE_TRACK
Theodore Ts'o3839e651997-04-26 13:21:57 +0000210void init_resource_track(struct resource_track *track)
211{
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000212#ifdef HAVE_GETRUSAGE
Theodore Ts'o3839e651997-04-26 13:21:57 +0000213 struct rusage r;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000214#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +0000215
216 track->brk_start = sbrk(0);
217 gettimeofday(&track->time_start, 0);
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000218#ifdef HAVE_GETRUSAGE
Theodore Ts'o53ef44c2001-01-06 05:55:58 +0000219#ifdef sun
220 memset(&r, 0, sizeof(struct rusage));
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000221#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +0000222 getrusage(RUSAGE_SELF, &r);
223 track->user_start = r.ru_utime;
224 track->system_start = r.ru_stime;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000225#else
226 track->user_start.tv_sec = track->user_start.tv_usec = 0;
227 track->system_start.tv_sec = track->system_start.tv_usec = 0;
228#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +0000229}
230
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000231#ifdef __GNUC__
232#define _INLINE_ __inline__
233#else
234#define _INLINE_
235#endif
236
237static _INLINE_ float timeval_subtract(struct timeval *tv1,
238 struct timeval *tv2)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000239{
240 return ((tv1->tv_sec - tv2->tv_sec) +
241 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
242}
243
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000244void print_resource_track(const char *desc, struct resource_track *track)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000245{
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000246#ifdef HAVE_GETRUSAGE
Theodore Ts'o3839e651997-04-26 13:21:57 +0000247 struct rusage r;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000248#endif
Theodore Ts'o4a9f5931999-03-16 19:32:52 +0000249#ifdef HAVE_MALLINFO
250 struct mallinfo malloc_info;
251#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +0000252 struct timeval time_end;
253
254 gettimeofday(&time_end, 0);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000255
256 if (desc)
Theodore Ts'o7fdfabd1997-11-24 11:51:17 +0000257 printf("%s: ", desc);
Theodore Ts'o4a9f5931999-03-16 19:32:52 +0000258
259#ifdef HAVE_MALLINFO
Theodore Ts'o80c5d7e2000-02-08 23:19:32 +0000260#define kbytes(x) (((x) + 1023) / 1024)
261
Theodore Ts'o4a9f5931999-03-16 19:32:52 +0000262 malloc_info = mallinfo();
Theodore Ts'o80c5d7e2000-02-08 23:19:32 +0000263 printf(_("Memory used: %dk/%dk (%dk/%dk), "),
264 kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
265 kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
Theodore Ts'o4a9f5931999-03-16 19:32:52 +0000266#else
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000267 printf(_("Memory used: %d, "),
Theodore Ts'o4a9f5931999-03-16 19:32:52 +0000268 (int) (((char *) sbrk(0)) - ((char *) track->brk_start)));
269#endif
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000270#ifdef HAVE_GETRUSAGE
Theodore Ts'o3839e651997-04-26 13:21:57 +0000271 getrusage(RUSAGE_SELF, &r);
272
Theodore Ts'o80c5d7e2000-02-08 23:19:32 +0000273 printf(_("time: %5.2f/%5.2f/%5.2f\n"),
Theodore Ts'o3839e651997-04-26 13:21:57 +0000274 timeval_subtract(&time_end, &track->time_start),
275 timeval_subtract(&r.ru_utime, &track->user_start),
276 timeval_subtract(&r.ru_stime, &track->system_start));
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000277#else
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000278 printf(_("elapsed time: %6.3f\n"),
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000279 timeval_subtract(&time_end, &track->time_start));
280#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +0000281}
Theodore Ts'o8bf191e1997-10-20 01:38:32 +0000282#endif /* RESOURCE_TRACK */
Theodore Ts'o3839e651997-04-26 13:21:57 +0000283
Theodore Ts'o08b21301997-11-03 19:42:40 +0000284void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
Theodore Ts'of3db3561997-04-26 13:34:30 +0000285 struct ext2_inode * inode, const char *proc)
286{
287 int retval;
288
Theodore Ts'o08b21301997-11-03 19:42:40 +0000289 retval = ext2fs_read_inode(ctx->fs, ino, inode);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000290 if (retval) {
291 com_err("ext2fs_read_inode", retval,
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000292 _("while reading inode %ld in %s"), ino, proc);
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000293 fatal_error(ctx, 0);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000294 }
295}
296
Theodore Ts'o08b21301997-11-03 19:42:40 +0000297extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
Theodore Ts'of3db3561997-04-26 13:34:30 +0000298 struct ext2_inode * inode, const char *proc)
299{
300 int retval;
301
Theodore Ts'o08b21301997-11-03 19:42:40 +0000302 retval = ext2fs_write_inode(ctx->fs, ino, inode);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000303 if (retval) {
304 com_err("ext2fs_write_inode", retval,
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000305 _("while writing inode %ld in %s"), ino, proc);
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000306 fatal_error(ctx, 0);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000307 }
308}
309
Theodore Ts'o3839e651997-04-26 13:21:57 +0000310#ifdef MTRACE
311void mtrace_print(char *mesg)
312{
313 FILE *malloc_get_mallstream();
314 FILE *f = malloc_get_mallstream();
315
316 if (f)
317 fprintf(f, "============= %s\n", mesg);
318}
319#endif
320
Theodore Ts'of1a17612001-12-23 22:27:52 -0500321blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
322 io_manager manager)
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000323{
Theodore Ts'of1a17612001-12-23 22:27:52 -0500324 struct ext2_super_block *sb;
325 io_channel io = NULL;
Theodore Ts'ofae9bfa2001-12-23 22:56:12 -0500326 void *buf = NULL;
Theodore Ts'of1a17612001-12-23 22:27:52 -0500327 int blocksize;
328 blk_t superblock, ret_sb = 8193;
329
330 if (fs && fs->super) {
331 ret_sb = (fs->super->s_blocks_per_group +
332 fs->super->s_first_data_block);
333 if (ctx) {
334 ctx->superblock = ret_sb;
335 ctx->blocksize = fs->blocksize;
336 }
337 return ret_sb;
338 }
339
340 if (ctx) {
341 if (ctx->blocksize) {
342 ret_sb = ctx->blocksize * 8;
343 if (ctx->blocksize == 1024)
344 ret_sb++;
345 ctx->superblock = ret_sb;
346 return ret_sb;
347 }
348 ctx->superblock = ret_sb;
349 ctx->blocksize = 1024;
350 }
351
352 if (!name || !manager)
353 goto cleanup;
354
355 if (manager->open(name, 0, &io) != 0)
356 goto cleanup;
357
358 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
359 goto cleanup;
360 sb = (struct ext2_super_block *) buf;
361
Andreas Dilger932a4892002-05-16 03:20:07 -0600362 for (blocksize = EXT2_MIN_BLOCK_SIZE;
363 blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
Theodore Ts'of1a17612001-12-23 22:27:52 -0500364 superblock = blocksize*8;
365 if (blocksize == 1024)
366 superblock++;
367 io_channel_set_blksize(io, blocksize);
368 if (io_channel_read_blk(io, superblock,
369 -SUPERBLOCK_SIZE, buf))
370 continue;
371#ifdef EXT2FS_ENABLE_SWAPFS
372 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
373 ext2fs_swap_super(sb);
374#endif
375 if (sb->s_magic == EXT2_SUPER_MAGIC) {
376 ret_sb = ctx->superblock = superblock;
377 ctx->blocksize = blocksize;
378 break;
379 }
380 }
381
382cleanup:
383 if (io)
384 io_channel_close(io);
385 if (buf)
386 ext2fs_free_mem(&buf);
387 return (ret_sb);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000388}
Theodore Ts'o3839e651997-04-26 13:21:57 +0000389
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000390/*
391 * Given a mode, return the ext2 file type
392 */
393int ext2_file_type(unsigned int mode)
394{
395 if (LINUX_S_ISREG(mode))
396 return EXT2_FT_REG_FILE;
397
398 if (LINUX_S_ISDIR(mode))
399 return EXT2_FT_DIR;
400
401 if (LINUX_S_ISCHR(mode))
402 return EXT2_FT_CHRDEV;
403
404 if (LINUX_S_ISBLK(mode))
405 return EXT2_FT_BLKDEV;
406
407 if (LINUX_S_ISLNK(mode))
408 return EXT2_FT_SYMLINK;
409
410 if (LINUX_S_ISFIFO(mode))
411 return EXT2_FT_FIFO;
412
413 if (LINUX_S_ISSOCK(mode))
414 return EXT2_FT_SOCK;
415
416 return 0;
417}