~daniel-mehrmann/e2fsprogs/master

« back to all changes in this revision

Viewing changes to .pc/git-update-to-3b0018beee/debugfs/debugfs.c

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2012-06-14 13:01:21 UTC
  • mfrom: (8.4.18 sid)
  • Revision ID: package-import@ubuntu.com-20120614130121-t2gct0d09jepx0y6
Tags: 1.42.4-3ubuntu1
* Merge from Debian unstable (LP: #978012), remainging changes:
  - debian/control.in: 
      Build-depend on gettext:any instead of on gettext for (cross-building)
      Drop build dependency on dc, which hasn't been needed for some time.
      Update maintainer field.
  - debian/rules:
      Block pkg-create-dbgsym from operating on this package.
      Build without dietlibc-dev, which is in universe 
  - debian/control:
      Regenerate with ./debian/rules debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * debugfs.c --- a program which allows you to attach an ext2fs
3
 
 * filesystem and play with it.
4
 
 *
5
 
 * Copyright (C) 1993 Theodore Ts'o.  This file may be redistributed
6
 
 * under the terms of the GNU Public License.
7
 
 *
8
 
 * Modifications by Robert Sanders <gt8134b@prism.gatech.edu>
9
 
 */
10
 
 
11
 
#include "config.h"
12
 
#include <stdio.h>
13
 
#include <unistd.h>
14
 
#include <stdlib.h>
15
 
#include <ctype.h>
16
 
#include <string.h>
17
 
#include <time.h>
18
 
#ifdef HAVE_GETOPT_H
19
 
#include <getopt.h>
20
 
#else
21
 
extern int optind;
22
 
extern char *optarg;
23
 
#endif
24
 
#ifdef HAVE_ERRNO_H
25
 
#include <errno.h>
26
 
#endif
27
 
#include <fcntl.h>
28
 
#include <sys/types.h>
29
 
#include <sys/stat.h>
30
 
 
31
 
#include "et/com_err.h"
32
 
#include "ss/ss.h"
33
 
#include "debugfs.h"
34
 
#include "uuid/uuid.h"
35
 
#include "e2p/e2p.h"
36
 
 
37
 
#include <ext2fs/ext2_ext_attr.h>
38
 
 
39
 
#include "../version.h"
40
 
#include "jfs_user.h"
41
 
 
42
 
extern ss_request_table debug_cmds;
43
 
ss_request_table *extra_cmds;
44
 
const char *debug_prog_name;
45
 
 
46
 
ext2_filsys     current_fs = NULL;
47
 
ext2_ino_t      root, cwd;
48
 
 
49
 
static void open_filesystem(char *device, int open_flags, blk64_t superblock,
50
 
                            blk64_t blocksize, int catastrophic,
51
 
                            char *data_filename)
52
 
{
53
 
        int     retval;
54
 
        io_channel data_io = 0;
55
 
 
56
 
        if (superblock != 0 && blocksize == 0) {
57
 
                com_err(device, 0, "if you specify the superblock, you must also specify the block size");
58
 
                current_fs = NULL;
59
 
                return;
60
 
        }
61
 
 
62
 
        if (data_filename) {
63
 
                if ((open_flags & EXT2_FLAG_IMAGE_FILE) == 0) {
64
 
                        com_err(device, 0,
65
 
                                "The -d option is only valid when reading an e2image file");
66
 
                        current_fs = NULL;
67
 
                        return;
68
 
                }
69
 
                retval = unix_io_manager->open(data_filename, 0, &data_io);
70
 
                if (retval) {
71
 
                        com_err(data_filename, 0, "while opening data source");
72
 
                        current_fs = NULL;
73
 
                        return;
74
 
                }
75
 
        }
76
 
 
77
 
        if (catastrophic && (open_flags & EXT2_FLAG_RW)) {
78
 
                com_err(device, 0,
79
 
                        "opening read-only because of catastrophic mode");
80
 
                open_flags &= ~EXT2_FLAG_RW;
81
 
        }
82
 
        if (catastrophic)
83
 
                open_flags |= EXT2_FLAG_SKIP_MMP;
84
 
 
85
 
        retval = ext2fs_open(device, open_flags, superblock, blocksize,
86
 
                             unix_io_manager, &current_fs);
87
 
        if (retval) {
88
 
                com_err(device, retval, "while opening filesystem");
89
 
                current_fs = NULL;
90
 
                return;
91
 
        }
92
 
        current_fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
93
 
 
94
 
        if (catastrophic)
95
 
                com_err(device, 0, "catastrophic mode - not reading inode or group bitmaps");
96
 
        else {
97
 
                retval = ext2fs_read_inode_bitmap(current_fs);
98
 
                if (retval) {
99
 
                        com_err(device, retval, "while reading inode bitmap");
100
 
                        goto errout;
101
 
                }
102
 
                retval = ext2fs_read_block_bitmap(current_fs);
103
 
                if (retval) {
104
 
                        com_err(device, retval, "while reading block bitmap");
105
 
                        goto errout;
106
 
                }
107
 
        }
108
 
 
109
 
        if (data_io) {
110
 
                retval = ext2fs_set_data_io(current_fs, data_io);
111
 
                if (retval) {
112
 
                        com_err(device, retval,
113
 
                                "while setting data source");
114
 
                        goto errout;
115
 
                }
116
 
        }
117
 
 
118
 
        root = cwd = EXT2_ROOT_INO;
119
 
        return;
120
 
 
121
 
errout:
122
 
        retval = ext2fs_close(current_fs);
123
 
        if (retval)
124
 
                com_err(device, retval, "while trying to close filesystem");
125
 
        current_fs = NULL;
126
 
}
127
 
 
128
 
void do_open_filesys(int argc, char **argv)
129
 
{
130
 
        int     c, err;
131
 
        int     catastrophic = 0;
132
 
        blk64_t superblock = 0;
133
 
        blk64_t blocksize = 0;
134
 
        int     open_flags = EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS; 
135
 
        char    *data_filename = 0;
136
 
 
137
 
        reset_getopt();
138
 
        while ((c = getopt (argc, argv, "iwfecb:s:d:D")) != EOF) {
139
 
                switch (c) {
140
 
                case 'i':
141
 
                        open_flags |= EXT2_FLAG_IMAGE_FILE;
142
 
                        break;
143
 
                case 'w':
144
 
#ifdef READ_ONLY
145
 
                        goto print_usage;
146
 
#else
147
 
                        open_flags |= EXT2_FLAG_RW;
148
 
#endif /* READ_ONLY */
149
 
                        break;
150
 
                case 'f':
151
 
                        open_flags |= EXT2_FLAG_FORCE;
152
 
                        break;
153
 
                case 'e':
154
 
                        open_flags |= EXT2_FLAG_EXCLUSIVE;
155
 
                        break;
156
 
                case 'c':
157
 
                        catastrophic = 1;
158
 
                        break;
159
 
                case 'd':
160
 
                        data_filename = optarg;
161
 
                        break;
162
 
                case 'D':
163
 
                        open_flags |= EXT2_FLAG_DIRECT_IO;
164
 
                        break;
165
 
                case 'b':
166
 
                        blocksize = parse_ulong(optarg, argv[0],
167
 
                                                "block size", &err);
168
 
                        if (err)
169
 
                                return;
170
 
                        break;
171
 
                case 's':
172
 
                        superblock = parse_ulong(optarg, argv[0],
173
 
                                                 "superblock number", &err);
174
 
                        if (err)
175
 
                                return;
176
 
                        break;
177
 
                default:
178
 
                        goto print_usage;
179
 
                }
180
 
        }
181
 
        if (optind != argc-1) {
182
 
                goto print_usage;
183
 
        }
184
 
        if (check_fs_not_open(argv[0]))
185
 
                return;
186
 
        open_filesystem(argv[optind], open_flags,
187
 
                        superblock, blocksize, catastrophic,
188
 
                        data_filename);
189
 
        return;
190
 
 
191
 
print_usage:
192
 
        fprintf(stderr, "%s: Usage: open [-s superblock] [-b blocksize] [-c] "
193
 
#ifndef READ_ONLY
194
 
                "[-w] "
195
 
#endif
196
 
                "<device>\n", argv[0]);
197
 
}
198
 
 
199
 
void do_lcd(int argc, char **argv)
200
 
{
201
 
        if (argc != 2) {
202
 
                com_err(argv[0], 0, "Usage: %s %s", argv[0], "<native dir>");
203
 
                return;
204
 
        }
205
 
 
206
 
        if (chdir(argv[1]) == -1) {
207
 
                com_err(argv[0], errno,
208
 
                        "while trying to change native directory to %s",
209
 
                        argv[1]);
210
 
                return;
211
 
        }
212
 
}
213
 
 
214
 
static void close_filesystem(NOARGS)
215
 
{
216
 
        int     retval;
217
 
 
218
 
        if (current_fs->flags & EXT2_FLAG_IB_DIRTY) {
219
 
                retval = ext2fs_write_inode_bitmap(current_fs);
220
 
                if (retval)
221
 
                        com_err("ext2fs_write_inode_bitmap", retval, 0);
222
 
        }
223
 
        if (current_fs->flags & EXT2_FLAG_BB_DIRTY) {
224
 
                retval = ext2fs_write_block_bitmap(current_fs);
225
 
                if (retval)
226
 
                        com_err("ext2fs_write_block_bitmap", retval, 0);
227
 
        }
228
 
        retval = ext2fs_close(current_fs);
229
 
        if (retval)
230
 
                com_err("ext2fs_close", retval, 0);
231
 
        current_fs = NULL;
232
 
        return;
233
 
}
234
 
 
235
 
void do_close_filesys(int argc, char **argv)
236
 
{
237
 
        int     c;
238
 
 
239
 
        if (check_fs_open(argv[0]))
240
 
                return;
241
 
 
242
 
        reset_getopt();
243
 
        while ((c = getopt (argc, argv, "a")) != EOF) {
244
 
                switch (c) {
245
 
                case 'a':
246
 
                        current_fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
247
 
                        break;
248
 
                default:
249
 
                        goto print_usage;
250
 
                }
251
 
        }
252
 
 
253
 
        if (argc > optind) {
254
 
        print_usage:
255
 
                com_err(0, 0, "Usage: close_filesys [-a]");
256
 
                return;
257
 
        }
258
 
 
259
 
        close_filesystem();
260
 
}
261
 
 
262
 
#ifndef READ_ONLY
263
 
void do_init_filesys(int argc, char **argv)
264
 
{
265
 
        struct ext2_super_block param;
266
 
        errcode_t       retval;
267
 
        int             err;
268
 
 
269
 
        if (common_args_process(argc, argv, 3, 3, "initialize",
270
 
                                "<device> <blocksize>", CHECK_FS_NOTOPEN))
271
 
                return;
272
 
 
273
 
        memset(&param, 0, sizeof(struct ext2_super_block));
274
 
        ext2fs_blocks_count_set(&param, parse_ulong(argv[2], argv[0],
275
 
                                                    "blocks count", &err));
276
 
        if (err)
277
 
                return;
278
 
        retval = ext2fs_initialize(argv[1], 0, &param,
279
 
                                   unix_io_manager, &current_fs);
280
 
        if (retval) {
281
 
                com_err(argv[1], retval, "while initializing filesystem");
282
 
                current_fs = NULL;
283
 
                return;
284
 
        }
285
 
        root = cwd = EXT2_ROOT_INO;
286
 
        return;
287
 
}
288
 
 
289
 
static void print_features(struct ext2_super_block * s, FILE *f)
290
 
{
291
 
        int     i, j, printed=0;
292
 
        __u32   *mask = &s->s_feature_compat, m;
293
 
 
294
 
        fputs("Filesystem features:", f);
295
 
        for (i=0; i <3; i++,mask++) {
296
 
                for (j=0,m=1; j < 32; j++, m<<=1) {
297
 
                        if (*mask & m) {
298
 
                                fprintf(f, " %s", e2p_feature2string(i, m));
299
 
                                printed++;
300
 
                        }
301
 
                }
302
 
        }
303
 
        if (printed == 0)
304
 
                fputs("(none)", f);
305
 
        fputs("\n", f);
306
 
}
307
 
#endif /* READ_ONLY */
308
 
 
309
 
static void print_bg_opts(ext2_filsys fs, dgrp_t group, int mask,
310
 
                          const char *str, int *first, FILE *f)
311
 
{
312
 
        if (ext2fs_bg_flags_test(fs, group, mask)) {
313
 
                if (*first) {
314
 
                        fputs("           [", f);
315
 
                        *first = 0;
316
 
                } else
317
 
                        fputs(", ", f);
318
 
                fputs(str, f);
319
 
        }
320
 
}
321
 
 
322
 
void do_show_super_stats(int argc, char *argv[])
323
 
{
324
 
        const char *units ="block";
325
 
        dgrp_t  i;
326
 
        FILE    *out;
327
 
        int     c, header_only = 0;
328
 
        int     numdirs = 0, first, gdt_csum;
329
 
 
330
 
        reset_getopt();
331
 
        while ((c = getopt (argc, argv, "h")) != EOF) {
332
 
                switch (c) {
333
 
                case 'h':
334
 
                        header_only++;
335
 
                        break;
336
 
                default:
337
 
                        goto print_usage;
338
 
                }
339
 
        }
340
 
        if (optind != argc) {
341
 
                goto print_usage;
342
 
        }
343
 
        if (check_fs_open(argv[0]))
344
 
                return;
345
 
        out = open_pager();
346
 
 
347
 
        if (EXT2_HAS_RO_COMPAT_FEATURE(current_fs->super,
348
 
                                       EXT4_FEATURE_RO_COMPAT_BIGALLOC))
349
 
                units = "cluster";
350
 
 
351
 
        list_super2(current_fs->super, out);
352
 
        for (i=0; i < current_fs->group_desc_count; i++)
353
 
                numdirs += ext2fs_bg_used_dirs_count(current_fs, i);
354
 
        fprintf(out, "Directories:              %d\n", numdirs);
355
 
 
356
 
        if (header_only) {
357
 
                close_pager(out);
358
 
                return;
359
 
        }
360
 
 
361
 
        gdt_csum = EXT2_HAS_RO_COMPAT_FEATURE(current_fs->super,
362
 
                                              EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
363
 
        for (i = 0; i < current_fs->group_desc_count; i++) {
364
 
                fprintf(out, " Group %2d: block bitmap at %llu, "
365
 
                        "inode bitmap at %llu, "
366
 
                        "inode table at %llu\n"
367
 
                        "           %u free %s%s, "
368
 
                        "%u free %s, "
369
 
                        "%u used %s%s",
370
 
                        i, ext2fs_block_bitmap_loc(current_fs, i),
371
 
                        ext2fs_inode_bitmap_loc(current_fs, i),
372
 
                        ext2fs_inode_table_loc(current_fs, i),
373
 
                        ext2fs_bg_free_blocks_count(current_fs, i), units,
374
 
                        ext2fs_bg_free_blocks_count(current_fs, i) != 1 ?
375
 
                        "s" : "",
376
 
                        ext2fs_bg_free_inodes_count(current_fs, i),
377
 
                        ext2fs_bg_free_inodes_count(current_fs, i) != 1 ?
378
 
                        "inodes" : "inode",
379
 
                        ext2fs_bg_used_dirs_count(current_fs, i),
380
 
                        ext2fs_bg_used_dirs_count(current_fs, i) != 1 ? "directories"
381
 
                                : "directory", gdt_csum ? ", " : "\n");
382
 
                if (gdt_csum)
383
 
                        fprintf(out, "%u unused %s\n",
384
 
                                ext2fs_bg_itable_unused(current_fs, i),
385
 
                                ext2fs_bg_itable_unused(current_fs, i) != 1 ?
386
 
                                "inodes" : "inode");
387
 
                first = 1;
388
 
                print_bg_opts(current_fs, i, EXT2_BG_INODE_UNINIT, "Inode not init",
389
 
                              &first, out);
390
 
                print_bg_opts(current_fs, i, EXT2_BG_BLOCK_UNINIT, "Block not init",
391
 
                              &first, out);
392
 
                if (gdt_csum) {
393
 
                        fprintf(out, "%sChecksum 0x%04x",
394
 
                                first ? "           [":", ", ext2fs_bg_checksum(current_fs, i));
395
 
                        first = 0;
396
 
                }
397
 
                if (!first)
398
 
                        fputs("]\n", out);
399
 
        }
400
 
        close_pager(out);
401
 
        return;
402
 
print_usage:
403
 
        fprintf(stderr, "%s: Usage: show_super [-h]\n", argv[0]);
404
 
}
405
 
 
406
 
#ifndef READ_ONLY
407
 
void do_dirty_filesys(int argc EXT2FS_ATTR((unused)),
408
 
                      char **argv EXT2FS_ATTR((unused)))
409
 
{
410
 
        if (check_fs_open(argv[0]))
411
 
                return;
412
 
        if (check_fs_read_write(argv[0]))
413
 
                return;
414
 
 
415
 
        if (argv[1] && !strcmp(argv[1], "-clean"))
416
 
                current_fs->super->s_state |= EXT2_VALID_FS;
417
 
        else
418
 
                current_fs->super->s_state &= ~EXT2_VALID_FS;
419
 
        ext2fs_mark_super_dirty(current_fs);
420
 
}
421
 
#endif /* READ_ONLY */
422
 
 
423
 
struct list_blocks_struct {
424
 
        FILE            *f;
425
 
        e2_blkcnt_t     total;
426
 
        blk64_t         first_block, last_block;
427
 
        e2_blkcnt_t     first_bcnt, last_bcnt;
428
 
        e2_blkcnt_t     first;
429
 
};
430
 
 
431
 
static void finish_range(struct list_blocks_struct *lb)
432
 
{
433
 
        if (lb->first_block == 0)
434
 
                return;
435
 
        if (lb->first)
436
 
                lb->first = 0;
437
 
        else
438
 
                fprintf(lb->f, ", ");
439
 
        if (lb->first_block == lb->last_block)
440
 
                fprintf(lb->f, "(%lld):%llu",
441
 
                        (long long)lb->first_bcnt, lb->first_block);
442
 
        else
443
 
                fprintf(lb->f, "(%lld-%lld):%llu-%llu",
444
 
                        (long long)lb->first_bcnt, (long long)lb->last_bcnt,
445
 
                        lb->first_block, lb->last_block);
446
 
        lb->first_block = 0;
447
 
}
448
 
 
449
 
static int list_blocks_proc(ext2_filsys fs EXT2FS_ATTR((unused)),
450
 
                            blk64_t *blocknr, e2_blkcnt_t blockcnt,
451
 
                            blk64_t ref_block EXT2FS_ATTR((unused)),
452
 
                            int ref_offset EXT2FS_ATTR((unused)),
453
 
                            void *private)
454
 
{
455
 
        struct list_blocks_struct *lb = (struct list_blocks_struct *) private;
456
 
 
457
 
        lb->total++;
458
 
        if (blockcnt >= 0) {
459
 
                /*
460
 
                 * See if we can add on to the existing range (if it exists)
461
 
                 */
462
 
                if (lb->first_block &&
463
 
                    (lb->last_block+1 == *blocknr) &&
464
 
                    (lb->last_bcnt+1 == blockcnt)) {
465
 
                        lb->last_block = *blocknr;
466
 
                        lb->last_bcnt = blockcnt;
467
 
                        return 0;
468
 
                }
469
 
                /*
470
 
                 * Start a new range.
471
 
                 */
472
 
                finish_range(lb);
473
 
                lb->first_block = lb->last_block = *blocknr;
474
 
                lb->first_bcnt = lb->last_bcnt = blockcnt;
475
 
                return 0;
476
 
        }
477
 
        /*
478
 
         * Not a normal block.  Always force a new range.
479
 
         */
480
 
        finish_range(lb);
481
 
        if (lb->first)
482
 
                lb->first = 0;
483
 
        else
484
 
                fprintf(lb->f, ", ");
485
 
        if (blockcnt == -1)
486
 
                fprintf(lb->f, "(IND):%llu", (unsigned long long) *blocknr);
487
 
        else if (blockcnt == -2)
488
 
                fprintf(lb->f, "(DIND):%llu", (unsigned long long) *blocknr);
489
 
        else if (blockcnt == -3)
490
 
                fprintf(lb->f, "(TIND):%llu", (unsigned long long) *blocknr);
491
 
        return 0;
492
 
}
493
 
 
494
 
static void dump_xattr_string(FILE *out, const char *str, int len)
495
 
{
496
 
        int printable = 0;
497
 
        int i;
498
 
 
499
 
        /* check: is string "printable enough?" */
500
 
        for (i = 0; i < len; i++)
501
 
                if (isprint(str[i]))
502
 
                        printable++;
503
 
 
504
 
        if (printable <= len*7/8)
505
 
                printable = 0;
506
 
 
507
 
        for (i = 0; i < len; i++)
508
 
                if (printable)
509
 
                        fprintf(out, isprint(str[i]) ? "%c" : "\\%03o",
510
 
                                (unsigned char)str[i]);
511
 
                else
512
 
                        fprintf(out, "%02x ", (unsigned char)str[i]);
513
 
}
514
 
 
515
 
static void internal_dump_inode_extra(FILE *out,
516
 
                                      const char *prefix EXT2FS_ATTR((unused)),
517
 
                                      ext2_ino_t inode_num EXT2FS_ATTR((unused)),
518
 
                                      struct ext2_inode_large *inode)
519
 
{
520
 
        struct ext2_ext_attr_entry *entry;
521
 
        __u32 *magic;
522
 
        char *start, *end;
523
 
        unsigned int storage_size;
524
 
 
525
 
        fprintf(out, "Size of extra inode fields: %u\n", inode->i_extra_isize);
526
 
        if (inode->i_extra_isize > EXT2_INODE_SIZE(current_fs->super) -
527
 
                        EXT2_GOOD_OLD_INODE_SIZE) {
528
 
                fprintf(stderr, "invalid inode->i_extra_isize (%u)\n",
529
 
                                inode->i_extra_isize);
530
 
                return;
531
 
        }
532
 
        storage_size = EXT2_INODE_SIZE(current_fs->super) -
533
 
                        EXT2_GOOD_OLD_INODE_SIZE -
534
 
                        inode->i_extra_isize;
535
 
        magic = (__u32 *)((char *)inode + EXT2_GOOD_OLD_INODE_SIZE +
536
 
                        inode->i_extra_isize);
537
 
        if (*magic == EXT2_EXT_ATTR_MAGIC) {
538
 
                fprintf(out, "Extended attributes stored in inode body: \n");
539
 
                end = (char *) inode + EXT2_INODE_SIZE(current_fs->super);
540
 
                start = (char *) magic + sizeof(__u32);
541
 
                entry = (struct ext2_ext_attr_entry *) start;
542
 
                while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
543
 
                        struct ext2_ext_attr_entry *next =
544
 
                                EXT2_EXT_ATTR_NEXT(entry);
545
 
                        if (entry->e_value_size > storage_size ||
546
 
                                        (char *) next >= end) {
547
 
                                fprintf(out, "invalid EA entry in inode\n");
548
 
                                return;
549
 
                        }
550
 
                        fprintf(out, "  ");
551
 
                        dump_xattr_string(out, EXT2_EXT_ATTR_NAME(entry),
552
 
                                          entry->e_name_len);
553
 
                        fprintf(out, " = \"");
554
 
                        dump_xattr_string(out, start + entry->e_value_offs,
555
 
                                                entry->e_value_size);
556
 
                        fprintf(out, "\" (%u)\n", entry->e_value_size);
557
 
                        entry = next;
558
 
                }
559
 
        }
560
 
}
561
 
 
562
 
static void dump_blocks(FILE *f, const char *prefix, ext2_ino_t inode)
563
 
{
564
 
        struct list_blocks_struct lb;
565
 
 
566
 
        fprintf(f, "%sBLOCKS:\n%s", prefix, prefix);
567
 
        lb.total = 0;
568
 
        lb.first_block = 0;
569
 
        lb.f = f;
570
 
        lb.first = 1;
571
 
        ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY, NULL,
572
 
                              list_blocks_proc, (void *)&lb);
573
 
        finish_range(&lb);
574
 
        if (lb.total)
575
 
                fprintf(f, "\n%sTOTAL: %lld\n", prefix, (long long)lb.total);
576
 
        fprintf(f,"\n");
577
 
}
578
 
 
579
 
static int int_log10(unsigned long long arg)
580
 
{
581
 
        int     l = 0;
582
 
 
583
 
        arg = arg / 10;
584
 
        while (arg) {
585
 
                l++;
586
 
                arg = arg / 10;
587
 
        }
588
 
        return l;
589
 
}
590
 
 
591
 
#define DUMP_LEAF_EXTENTS       0x01
592
 
#define DUMP_NODE_EXTENTS       0x02
593
 
#define DUMP_EXTENT_TABLE       0x04
594
 
 
595
 
static void dump_extents(FILE *f, const char *prefix, ext2_ino_t ino,
596
 
                         int flags, int logical_width, int physical_width)
597
 
{
598
 
        ext2_extent_handle_t    handle;
599
 
        struct ext2fs_extent    extent;
600
 
        struct ext2_extent_info info;
601
 
        int                     op = EXT2_EXTENT_ROOT;
602
 
        unsigned int            printed = 0;
603
 
        errcode_t               errcode;
604
 
 
605
 
        errcode = ext2fs_extent_open(current_fs, ino, &handle);
606
 
        if (errcode)
607
 
                return;
608
 
 
609
 
        if (flags & DUMP_EXTENT_TABLE)
610
 
                fprintf(f, "Level Entries %*s %*s Length Flags\n",
611
 
                        (logical_width*2)+3, "Logical",
612
 
                        (physical_width*2)+3, "Physical");
613
 
        else
614
 
                fprintf(f, "%sEXTENTS:\n%s", prefix, prefix);
615
 
 
616
 
        while (1) {
617
 
                errcode = ext2fs_extent_get(handle, op, &extent);
618
 
 
619
 
                if (errcode)
620
 
                        break;
621
 
 
622
 
                op = EXT2_EXTENT_NEXT;
623
 
 
624
 
                if (extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)
625
 
                        continue;
626
 
 
627
 
                if (extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) {
628
 
                        if ((flags & DUMP_LEAF_EXTENTS) == 0)
629
 
                                continue;
630
 
                } else {
631
 
                        if ((flags & DUMP_NODE_EXTENTS) == 0)
632
 
                                continue;
633
 
                }
634
 
 
635
 
                errcode = ext2fs_extent_get_info(handle, &info);
636
 
                if (errcode)
637
 
                        continue;
638
 
 
639
 
                if (!(extent.e_flags & EXT2_EXTENT_FLAGS_LEAF)) {
640
 
                        if (extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)
641
 
                                continue;
642
 
 
643
 
                        if (flags & DUMP_EXTENT_TABLE) {
644
 
                                fprintf(f, "%2d/%2d %3d/%3d %*llu - %*llu "
645
 
                                        "%*llu%*s %6u\n",
646
 
                                        info.curr_level, info.max_depth,
647
 
                                        info.curr_entry, info.num_entries,
648
 
                                        logical_width,
649
 
                                        extent.e_lblk,
650
 
                                        logical_width,
651
 
                                        extent.e_lblk + (extent.e_len - 1),
652
 
                                        physical_width,
653
 
                                        extent.e_pblk,
654
 
                                        physical_width+3, "", extent.e_len);
655
 
                                continue;
656
 
                        }
657
 
 
658
 
                        fprintf(f, "%s(ETB%d):%lld",
659
 
                                printed ? ", " : "", info.curr_level,
660
 
                                extent.e_pblk);
661
 
                        printed = 1;
662
 
                        continue;
663
 
                }
664
 
 
665
 
                if (flags & DUMP_EXTENT_TABLE) {
666
 
                        fprintf(f, "%2d/%2d %3d/%3d %*llu - %*llu "
667
 
                                "%*llu - %*llu %6u %s\n",
668
 
                                info.curr_level, info.max_depth,
669
 
                                info.curr_entry, info.num_entries,
670
 
                                logical_width,
671
 
                                extent.e_lblk,
672
 
                                logical_width,
673
 
                                extent.e_lblk + (extent.e_len - 1),
674
 
                                physical_width,
675
 
                                extent.e_pblk,
676
 
                                physical_width,
677
 
                                extent.e_pblk + (extent.e_len - 1),
678
 
                                extent.e_len,
679
 
                                extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ?
680
 
                                        "Uninit" : "");
681
 
                        continue;
682
 
                }
683
 
 
684
 
                if (extent.e_len == 0)
685
 
                        continue;
686
 
                else if (extent.e_len == 1)
687
 
                        fprintf(f,
688
 
                                "%s(%lld%s):%lld",
689
 
                                printed ? ", " : "",
690
 
                                extent.e_lblk,
691
 
                                extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ?
692
 
                                "[u]" : "",
693
 
                                extent.e_pblk);
694
 
                else
695
 
                        fprintf(f,
696
 
                                "%s(%lld-%lld%s):%lld-%lld",
697
 
                                printed ? ", " : "",
698
 
                                extent.e_lblk,
699
 
                                extent.e_lblk + (extent.e_len - 1),
700
 
                                extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ?
701
 
                                        "[u]" : "",
702
 
                                extent.e_pblk,
703
 
                                extent.e_pblk + (extent.e_len - 1));
704
 
                printed = 1;
705
 
        }
706
 
        if (printed)
707
 
                fprintf(f, "\n");
708
 
}
709
 
 
710
 
void internal_dump_inode(FILE *out, const char *prefix,
711
 
                         ext2_ino_t inode_num, struct ext2_inode *inode,
712
 
                         int do_dump_blocks)
713
 
{
714
 
        const char *i_type;
715
 
        char frag, fsize;
716
 
        int os = current_fs->super->s_creator_os;
717
 
        struct ext2_inode_large *large_inode;
718
 
        int is_large_inode = 0;
719
 
 
720
 
        if (EXT2_INODE_SIZE(current_fs->super) > EXT2_GOOD_OLD_INODE_SIZE)
721
 
                is_large_inode = 1;
722
 
        large_inode = (struct ext2_inode_large *) inode;
723
 
 
724
 
        if (LINUX_S_ISDIR(inode->i_mode)) i_type = "directory";
725
 
        else if (LINUX_S_ISREG(inode->i_mode)) i_type = "regular";
726
 
        else if (LINUX_S_ISLNK(inode->i_mode)) i_type = "symlink";
727
 
        else if (LINUX_S_ISBLK(inode->i_mode)) i_type = "block special";
728
 
        else if (LINUX_S_ISCHR(inode->i_mode)) i_type = "character special";
729
 
        else if (LINUX_S_ISFIFO(inode->i_mode)) i_type = "FIFO";
730
 
        else if (LINUX_S_ISSOCK(inode->i_mode)) i_type = "socket";
731
 
        else i_type = "bad type";
732
 
        fprintf(out, "%sInode: %u   Type: %s    ", prefix, inode_num, i_type);
733
 
        fprintf(out, "%sMode:  %04o   Flags: 0x%x\n",
734
 
                prefix, inode->i_mode & 0777, inode->i_flags);
735
 
        if (is_large_inode && large_inode->i_extra_isize >= 24) {
736
 
                fprintf(out, "%sGeneration: %u    Version: 0x%08x:%08x\n",
737
 
                        prefix, inode->i_generation, large_inode->i_version_hi,
738
 
                        inode->osd1.linux1.l_i_version);
739
 
        } else {
740
 
                fprintf(out, "%sGeneration: %u    Version: 0x%08x\n", prefix,
741
 
                        inode->i_generation, inode->osd1.linux1.l_i_version);
742
 
        }
743
 
        fprintf(out, "%sUser: %5d   Group: %5d   Size: ",
744
 
                prefix, inode_uid(*inode), inode_gid(*inode));
745
 
        if (LINUX_S_ISREG(inode->i_mode))
746
 
                fprintf(out, "%llu\n", EXT2_I_SIZE(inode));
747
 
        else
748
 
                fprintf(out, "%d\n", inode->i_size);
749
 
        if (os == EXT2_OS_HURD)
750
 
                fprintf(out,
751
 
                        "%sFile ACL: %d    Directory ACL: %d Translator: %d\n",
752
 
                        prefix,
753
 
                        inode->i_file_acl, LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0,
754
 
                        inode->osd1.hurd1.h_i_translator);
755
 
        else
756
 
                fprintf(out, "%sFile ACL: %llu    Directory ACL: %d\n",
757
 
                        prefix,
758
 
                        inode->i_file_acl | ((long long)
759
 
                                (inode->osd2.linux2.l_i_file_acl_high) << 32),
760
 
                        LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0);
761
 
        if (os == EXT2_OS_LINUX)
762
 
                fprintf(out, "%sLinks: %d   Blockcount: %llu\n",
763
 
                        prefix, inode->i_links_count,
764
 
                        (((unsigned long long)
765
 
                          inode->osd2.linux2.l_i_blocks_hi << 32)) +
766
 
                        inode->i_blocks);
767
 
        else
768
 
                fprintf(out, "%sLinks: %d   Blockcount: %u\n",
769
 
                        prefix, inode->i_links_count, inode->i_blocks);
770
 
        switch (os) {
771
 
            case EXT2_OS_HURD:
772
 
                frag = inode->osd2.hurd2.h_i_frag;
773
 
                fsize = inode->osd2.hurd2.h_i_fsize;
774
 
                break;
775
 
            default:
776
 
                frag = fsize = 0;
777
 
        }
778
 
        fprintf(out, "%sFragment:  Address: %d    Number: %d    Size: %d\n",
779
 
                prefix, inode->i_faddr, frag, fsize);
780
 
        if (is_large_inode && large_inode->i_extra_isize >= 24) {
781
 
                fprintf(out, "%s ctime: 0x%08x:%08x -- %s", prefix,
782
 
                        inode->i_ctime, large_inode->i_ctime_extra,
783
 
                        time_to_string(inode->i_ctime));
784
 
                fprintf(out, "%s atime: 0x%08x:%08x -- %s", prefix,
785
 
                        inode->i_atime, large_inode->i_atime_extra,
786
 
                        time_to_string(inode->i_atime));
787
 
                fprintf(out, "%s mtime: 0x%08x:%08x -- %s", prefix,
788
 
                        inode->i_mtime, large_inode->i_mtime_extra,
789
 
                        time_to_string(inode->i_mtime));
790
 
                fprintf(out, "%scrtime: 0x%08x:%08x -- %s", prefix,
791
 
                        large_inode->i_crtime, large_inode->i_crtime_extra,
792
 
                        time_to_string(large_inode->i_crtime));
793
 
        } else {
794
 
                fprintf(out, "%sctime: 0x%08x -- %s", prefix, inode->i_ctime,
795
 
                        time_to_string(inode->i_ctime));
796
 
                fprintf(out, "%satime: 0x%08x -- %s", prefix, inode->i_atime,
797
 
                        time_to_string(inode->i_atime));
798
 
                fprintf(out, "%smtime: 0x%08x -- %s", prefix, inode->i_mtime,
799
 
                        time_to_string(inode->i_mtime));
800
 
        }
801
 
        if (inode->i_dtime)
802
 
          fprintf(out, "%sdtime: 0x%08x -- %s", prefix, inode->i_dtime,
803
 
                  time_to_string(inode->i_dtime));
804
 
        if (EXT2_INODE_SIZE(current_fs->super) > EXT2_GOOD_OLD_INODE_SIZE)
805
 
                internal_dump_inode_extra(out, prefix, inode_num,
806
 
                                          (struct ext2_inode_large *) inode);
807
 
        if (LINUX_S_ISLNK(inode->i_mode) && ext2fs_inode_data_blocks(current_fs,inode) == 0)
808
 
                fprintf(out, "%sFast_link_dest: %.*s\n", prefix,
809
 
                        (int) inode->i_size, (char *)inode->i_block);
810
 
        else if (LINUX_S_ISBLK(inode->i_mode) || LINUX_S_ISCHR(inode->i_mode)) {
811
 
                int major, minor;
812
 
                const char *devnote;
813
 
 
814
 
                if (inode->i_block[0]) {
815
 
                        major = (inode->i_block[0] >> 8) & 255;
816
 
                        minor = inode->i_block[0] & 255;
817
 
                        devnote = "";
818
 
                } else {
819
 
                        major = (inode->i_block[1] & 0xfff00) >> 8;
820
 
                        minor = ((inode->i_block[1] & 0xff) |
821
 
                                 ((inode->i_block[1] >> 12) & 0xfff00));
822
 
                        devnote = "(New-style) ";
823
 
                }
824
 
                fprintf(out, "%sDevice major/minor number: %02d:%02d (hex %02x:%02x)\n",
825
 
                        devnote, major, minor, major, minor);
826
 
        } else if (do_dump_blocks) {
827
 
                if (inode->i_flags & EXT4_EXTENTS_FL)
828
 
                        dump_extents(out, prefix, inode_num,
829
 
                                     DUMP_LEAF_EXTENTS|DUMP_NODE_EXTENTS, 0, 0);
830
 
                else
831
 
                        dump_blocks(out, prefix, inode_num);
832
 
        }
833
 
}
834
 
 
835
 
static void dump_inode(ext2_ino_t inode_num, struct ext2_inode *inode)
836
 
{
837
 
        FILE    *out;
838
 
 
839
 
        out = open_pager();
840
 
        internal_dump_inode(out, "", inode_num, inode, 1);
841
 
        close_pager(out);
842
 
}
843
 
 
844
 
void do_stat(int argc, char *argv[])
845
 
{
846
 
        ext2_ino_t      inode;
847
 
        struct ext2_inode * inode_buf;
848
 
 
849
 
        if (check_fs_open(argv[0]))
850
 
                return;
851
 
 
852
 
        inode_buf = (struct ext2_inode *)
853
 
                        malloc(EXT2_INODE_SIZE(current_fs->super));
854
 
        if (!inode_buf) {
855
 
                fprintf(stderr, "do_stat: can't allocate buffer\n");
856
 
                return;
857
 
        }
858
 
 
859
 
        if (common_inode_args_process(argc, argv, &inode, 0)) {
860
 
                free(inode_buf);
861
 
                return;
862
 
        }
863
 
 
864
 
        if (debugfs_read_inode_full(inode, inode_buf, argv[0],
865
 
                                        EXT2_INODE_SIZE(current_fs->super))) {
866
 
                free(inode_buf);
867
 
                return;
868
 
        }
869
 
 
870
 
        dump_inode(inode, inode_buf);
871
 
        free(inode_buf);
872
 
        return;
873
 
}
874
 
 
875
 
void do_dump_extents(int argc, char **argv)
876
 
{
877
 
        struct ext2_inode inode;
878
 
        ext2_ino_t      ino;
879
 
        FILE            *out;
880
 
        int             c, flags = 0;
881
 
        int             logical_width;
882
 
        int             physical_width;
883
 
 
884
 
        reset_getopt();
885
 
        while ((c = getopt(argc, argv, "nl")) != EOF) {
886
 
                switch (c) {
887
 
                case 'n':
888
 
                        flags |= DUMP_NODE_EXTENTS;
889
 
                        break;
890
 
                case 'l':
891
 
                        flags |= DUMP_LEAF_EXTENTS;
892
 
                        break;
893
 
                }
894
 
        }
895
 
 
896
 
        if (argc != optind + 1) {
897
 
                com_err(0, 0, "Usage: dump_extents [-n] [-l] file");
898
 
                return;
899
 
        }
900
 
 
901
 
        if (flags == 0)
902
 
                flags = DUMP_NODE_EXTENTS | DUMP_LEAF_EXTENTS;
903
 
        flags |= DUMP_EXTENT_TABLE;
904
 
 
905
 
        if (check_fs_open(argv[0]))
906
 
                return;
907
 
 
908
 
        ino = string_to_inode(argv[optind]);
909
 
        if (ino == 0)
910
 
                return;
911
 
 
912
 
        if (debugfs_read_inode(ino, &inode, argv[0]))
913
 
                return;
914
 
 
915
 
        if ((inode.i_flags & EXT4_EXTENTS_FL) == 0) {
916
 
                fprintf(stderr, "%s: does not uses extent block maps\n",
917
 
                        argv[optind]);
918
 
                return;
919
 
        }
920
 
 
921
 
        logical_width = int_log10((EXT2_I_SIZE(&inode)+current_fs->blocksize-1)/
922
 
                                  current_fs->blocksize) + 1;
923
 
        if (logical_width < 5)
924
 
                logical_width = 5;
925
 
        physical_width = int_log10(ext2fs_blocks_count(current_fs->super)) + 1;
926
 
        if (physical_width < 5)
927
 
                physical_width = 5;
928
 
 
929
 
        out = open_pager();
930
 
        dump_extents(out, "", ino, flags, logical_width, physical_width);
931
 
        close_pager(out);
932
 
        return;
933
 
}
934
 
 
935
 
static int print_blocks_proc(ext2_filsys fs EXT2FS_ATTR((unused)),
936
 
                             blk64_t *blocknr,
937
 
                             e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
938
 
                             blk64_t ref_block EXT2FS_ATTR((unused)),
939
 
                             int ref_offset EXT2FS_ATTR((unused)),
940
 
                             void *private EXT2FS_ATTR((unused)))
941
 
{
942
 
        printf("%llu ", *blocknr);
943
 
        return 0;
944
 
}
945
 
 
946
 
void do_blocks(int argc, char *argv[])
947
 
{
948
 
        ext2_ino_t      inode;
949
 
 
950
 
        if (check_fs_open(argv[0]))
951
 
                return;
952
 
 
953
 
        if (common_inode_args_process(argc, argv, &inode, 0)) {
954
 
                return;
955
 
        }
956
 
 
957
 
        ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY, NULL,
958
 
                              print_blocks_proc, NULL);
959
 
        fputc('\n', stdout);
960
 
        return;
961
 
}
962
 
 
963
 
void do_chroot(int argc, char *argv[])
964
 
{
965
 
        ext2_ino_t inode;
966
 
        int retval;
967
 
 
968
 
        if (common_inode_args_process(argc, argv, &inode, 0))
969
 
                return;
970
 
 
971
 
        retval = ext2fs_check_directory(current_fs, inode);
972
 
        if (retval)  {
973
 
                com_err(argv[1], retval, 0);
974
 
                return;
975
 
        }
976
 
        root = inode;
977
 
}
978
 
 
979
 
#ifndef READ_ONLY
980
 
void do_clri(int argc, char *argv[])
981
 
{
982
 
        ext2_ino_t inode;
983
 
        struct ext2_inode inode_buf;
984
 
 
985
 
        if (common_inode_args_process(argc, argv, &inode, CHECK_FS_RW))
986
 
                return;
987
 
 
988
 
        if (debugfs_read_inode(inode, &inode_buf, argv[0]))
989
 
                return;
990
 
        memset(&inode_buf, 0, sizeof(inode_buf));
991
 
        if (debugfs_write_inode(inode, &inode_buf, argv[0]))
992
 
                return;
993
 
}
994
 
 
995
 
void do_freei(int argc, char *argv[])
996
 
{
997
 
        unsigned int    len = 1;
998
 
        int             err = 0;
999
 
        ext2_ino_t      inode;
1000
 
 
1001
 
        if (common_args_process(argc, argv, 2, 3, argv[0], "<file> [num]",
1002
 
                                CHECK_FS_RW | CHECK_FS_BITMAPS))
1003
 
                return 1;
1004
 
        if (check_fs_read_write(argv[0]))
1005
 
                return;
1006
 
 
1007
 
        inode = string_to_inode(argv[1]);
1008
 
        if (!inode)
1009
 
                return;
1010
 
 
1011
 
        if (argc == 3) {
1012
 
                len = parse_ulong(argv[2], argv[0], "length", &err);
1013
 
                if (err)
1014
 
                        return;
1015
 
        }
1016
 
 
1017
 
        if (len == 1 &&
1018
 
            !ext2fs_test_inode_bitmap2(current_fs->inode_map,inode))
1019
 
                com_err(argv[0], 0, "Warning: inode already clear");
1020
 
        while (len-- > 0)
1021
 
                ext2fs_unmark_inode_bitmap2(current_fs->inode_map, inode);
1022
 
        ext2fs_mark_ib_dirty(current_fs);
1023
 
}
1024
 
 
1025
 
void do_seti(int argc, char *argv[])
1026
 
{
1027
 
        unsigned int    len = 1;
1028
 
        int             err = 0;
1029
 
        ext2_ino_t      inode;
1030
 
 
1031
 
        if (common_args_process(argc, argv, 2, 3, argv[0], "<file> [num]",
1032
 
                                CHECK_FS_RW | CHECK_FS_BITMAPS))
1033
 
                return;
1034
 
        if (check_fs_read_write(argv[0]))
1035
 
                return;
1036
 
 
1037
 
        inode = string_to_inode(argv[1]);
1038
 
        if (!inode)
1039
 
                return;
1040
 
 
1041
 
        if (argc == 3) {
1042
 
                len = parse_ulong(argv[2], argv[0], "length", &err);
1043
 
                if (err)
1044
 
                        return;
1045
 
        }
1046
 
 
1047
 
        if ((len == 1) &&
1048
 
            ext2fs_test_inode_bitmap2(current_fs->inode_map,inode))
1049
 
                com_err(argv[0], 0, "Warning: inode already set");
1050
 
        while (len-- > 0)
1051
 
                ext2fs_mark_inode_bitmap2(current_fs->inode_map, inode++);
1052
 
        ext2fs_mark_ib_dirty(current_fs);
1053
 
}
1054
 
#endif /* READ_ONLY */
1055
 
 
1056
 
void do_testi(int argc, char *argv[])
1057
 
{
1058
 
        ext2_ino_t inode;
1059
 
 
1060
 
        if (common_inode_args_process(argc, argv, &inode, CHECK_FS_BITMAPS))
1061
 
                return;
1062
 
 
1063
 
        if (ext2fs_test_inode_bitmap2(current_fs->inode_map,inode))
1064
 
                printf("Inode %u is marked in use\n", inode);
1065
 
        else
1066
 
                printf("Inode %u is not in use\n", inode);
1067
 
}
1068
 
 
1069
 
#ifndef READ_ONLY
1070
 
void do_freeb(int argc, char *argv[])
1071
 
{
1072
 
        blk64_t block;
1073
 
        blk64_t count = 1;
1074
 
 
1075
 
        if (common_block_args_process(argc, argv, &block, &count))
1076
 
                return;
1077
 
        if (check_fs_read_write(argv[0]))
1078
 
                return;
1079
 
        while (count-- > 0) {
1080
 
                if (!ext2fs_test_block_bitmap2(current_fs->block_map,block))
1081
 
                        com_err(argv[0], 0, "Warning: block %llu already clear",
1082
 
                                block);
1083
 
                ext2fs_unmark_block_bitmap2(current_fs->block_map,block);
1084
 
                block++;
1085
 
        }
1086
 
        ext2fs_mark_bb_dirty(current_fs);
1087
 
}
1088
 
 
1089
 
void do_setb(int argc, char *argv[])
1090
 
{
1091
 
        blk64_t block;
1092
 
        blk64_t count = 1;
1093
 
 
1094
 
        if (common_block_args_process(argc, argv, &block, &count))
1095
 
                return;
1096
 
        if (check_fs_read_write(argv[0]))
1097
 
                return;
1098
 
        while (count-- > 0) {
1099
 
                if (ext2fs_test_block_bitmap2(current_fs->block_map,block))
1100
 
                        com_err(argv[0], 0, "Warning: block %llu already set",
1101
 
                                block);
1102
 
                ext2fs_mark_block_bitmap2(current_fs->block_map,block);
1103
 
                block++;
1104
 
        }
1105
 
        ext2fs_mark_bb_dirty(current_fs);
1106
 
}
1107
 
#endif /* READ_ONLY */
1108
 
 
1109
 
void do_testb(int argc, char *argv[])
1110
 
{
1111
 
        blk64_t block;
1112
 
        blk64_t count = 1;
1113
 
 
1114
 
        if (common_block_args_process(argc, argv, &block, &count))
1115
 
                return;
1116
 
        while (count-- > 0) {
1117
 
                if (ext2fs_test_block_bitmap2(current_fs->block_map,block))
1118
 
                        printf("Block %llu marked in use\n", block);
1119
 
                else
1120
 
                        printf("Block %llu not in use\n", block);
1121
 
                block++;
1122
 
        }
1123
 
}
1124
 
 
1125
 
#ifndef READ_ONLY
1126
 
static void modify_u8(char *com, const char *prompt,
1127
 
                      const char *format, __u8 *val)
1128
 
{
1129
 
        char buf[200];
1130
 
        unsigned long v;
1131
 
        char *tmp;
1132
 
 
1133
 
        sprintf(buf, format, *val);
1134
 
        printf("%30s    [%s] ", prompt, buf);
1135
 
        if (!fgets(buf, sizeof(buf), stdin))
1136
 
                return;
1137
 
        if (buf[strlen (buf) - 1] == '\n')
1138
 
                buf[strlen (buf) - 1] = '\0';
1139
 
        if (!buf[0])
1140
 
                return;
1141
 
        v = strtoul(buf, &tmp, 0);
1142
 
        if (*tmp)
1143
 
                com_err(com, 0, "Bad value - %s", buf);
1144
 
        else
1145
 
                *val = v;
1146
 
}
1147
 
 
1148
 
static void modify_u16(char *com, const char *prompt,
1149
 
                       const char *format, __u16 *val)
1150
 
{
1151
 
        char buf[200];
1152
 
        unsigned long v;
1153
 
        char *tmp;
1154
 
 
1155
 
        sprintf(buf, format, *val);
1156
 
        printf("%30s    [%s] ", prompt, buf);
1157
 
        if (!fgets(buf, sizeof(buf), stdin))
1158
 
                return;
1159
 
        if (buf[strlen (buf) - 1] == '\n')
1160
 
                buf[strlen (buf) - 1] = '\0';
1161
 
        if (!buf[0])
1162
 
                return;
1163
 
        v = strtoul(buf, &tmp, 0);
1164
 
        if (*tmp)
1165
 
                com_err(com, 0, "Bad value - %s", buf);
1166
 
        else
1167
 
                *val = v;
1168
 
}
1169
 
 
1170
 
static void modify_u32(char *com, const char *prompt,
1171
 
                       const char *format, __u32 *val)
1172
 
{
1173
 
        char buf[200];
1174
 
        unsigned long v;
1175
 
        char *tmp;
1176
 
 
1177
 
        sprintf(buf, format, *val);
1178
 
        printf("%30s    [%s] ", prompt, buf);
1179
 
        if (!fgets(buf, sizeof(buf), stdin))
1180
 
                return;
1181
 
        if (buf[strlen (buf) - 1] == '\n')
1182
 
                buf[strlen (buf) - 1] = '\0';
1183
 
        if (!buf[0])
1184
 
                return;
1185
 
        v = strtoul(buf, &tmp, 0);
1186
 
        if (*tmp)
1187
 
                com_err(com, 0, "Bad value - %s", buf);
1188
 
        else
1189
 
                *val = v;
1190
 
}
1191
 
 
1192
 
 
1193
 
void do_modify_inode(int argc, char *argv[])
1194
 
{
1195
 
        struct ext2_inode inode;
1196
 
        ext2_ino_t      inode_num;
1197
 
        int             i;
1198
 
        unsigned char   *frag, *fsize;
1199
 
        char            buf[80];
1200
 
        int             os;
1201
 
        const char      *hex_format = "0x%x";
1202
 
        const char      *octal_format = "0%o";
1203
 
        const char      *decimal_format = "%d";
1204
 
        const char      *unsignedlong_format = "%lu";
1205
 
 
1206
 
        if (common_inode_args_process(argc, argv, &inode_num, CHECK_FS_RW))
1207
 
                return;
1208
 
 
1209
 
        os = current_fs->super->s_creator_os;
1210
 
 
1211
 
        if (debugfs_read_inode(inode_num, &inode, argv[1]))
1212
 
                return;
1213
 
 
1214
 
        modify_u16(argv[0], "Mode", octal_format, &inode.i_mode);
1215
 
        modify_u16(argv[0], "User ID", decimal_format, &inode.i_uid);
1216
 
        modify_u16(argv[0], "Group ID", decimal_format, &inode.i_gid);
1217
 
        modify_u32(argv[0], "Size", unsignedlong_format, &inode.i_size);
1218
 
        modify_u32(argv[0], "Creation time", decimal_format, &inode.i_ctime);
1219
 
        modify_u32(argv[0], "Modification time", decimal_format, &inode.i_mtime);
1220
 
        modify_u32(argv[0], "Access time", decimal_format, &inode.i_atime);
1221
 
        modify_u32(argv[0], "Deletion time", decimal_format, &inode.i_dtime);
1222
 
        modify_u16(argv[0], "Link count", decimal_format, &inode.i_links_count);
1223
 
        if (os == EXT2_OS_LINUX)
1224
 
                modify_u16(argv[0], "Block count high", unsignedlong_format,
1225
 
                           &inode.osd2.linux2.l_i_blocks_hi);
1226
 
        modify_u32(argv[0], "Block count", unsignedlong_format, &inode.i_blocks);
1227
 
        modify_u32(argv[0], "File flags", hex_format, &inode.i_flags);
1228
 
        modify_u32(argv[0], "Generation", hex_format, &inode.i_generation);
1229
 
#if 0
1230
 
        modify_u32(argv[0], "Reserved1", decimal_format, &inode.i_reserved1);
1231
 
#endif
1232
 
        modify_u32(argv[0], "File acl", decimal_format, &inode.i_file_acl);
1233
 
        if (LINUX_S_ISDIR(inode.i_mode))
1234
 
                modify_u32(argv[0], "Directory acl", decimal_format, &inode.i_dir_acl);
1235
 
        else
1236
 
                modify_u32(argv[0], "High 32bits of size", decimal_format, &inode.i_size_high);
1237
 
 
1238
 
        if (os == EXT2_OS_HURD)
1239
 
                modify_u32(argv[0], "Translator Block",
1240
 
                            decimal_format, &inode.osd1.hurd1.h_i_translator);
1241
 
 
1242
 
        modify_u32(argv[0], "Fragment address", decimal_format, &inode.i_faddr);
1243
 
        switch (os) {
1244
 
            case EXT2_OS_HURD:
1245
 
                frag = &inode.osd2.hurd2.h_i_frag;
1246
 
                fsize = &inode.osd2.hurd2.h_i_fsize;
1247
 
                break;
1248
 
            default:
1249
 
                frag = fsize = 0;
1250
 
        }
1251
 
        if (frag)
1252
 
                modify_u8(argv[0], "Fragment number", decimal_format, frag);
1253
 
        if (fsize)
1254
 
                modify_u8(argv[0], "Fragment size", decimal_format, fsize);
1255
 
 
1256
 
        for (i=0;  i < EXT2_NDIR_BLOCKS; i++) {
1257
 
                sprintf(buf, "Direct Block #%d", i);
1258
 
                modify_u32(argv[0], buf, decimal_format, &inode.i_block[i]);
1259
 
        }
1260
 
        modify_u32(argv[0], "Indirect Block", decimal_format,
1261
 
                    &inode.i_block[EXT2_IND_BLOCK]);
1262
 
        modify_u32(argv[0], "Double Indirect Block", decimal_format,
1263
 
                    &inode.i_block[EXT2_DIND_BLOCK]);
1264
 
        modify_u32(argv[0], "Triple Indirect Block", decimal_format,
1265
 
                    &inode.i_block[EXT2_TIND_BLOCK]);
1266
 
        if (debugfs_write_inode(inode_num, &inode, argv[1]))
1267
 
                return;
1268
 
}
1269
 
#endif /* READ_ONLY */
1270
 
 
1271
 
void do_change_working_dir(int argc, char *argv[])
1272
 
{
1273
 
        ext2_ino_t      inode;
1274
 
        int             retval;
1275
 
 
1276
 
        if (common_inode_args_process(argc, argv, &inode, 0))
1277
 
                return;
1278
 
 
1279
 
        retval = ext2fs_check_directory(current_fs, inode);
1280
 
        if (retval) {
1281
 
                com_err(argv[1], retval, 0);
1282
 
                return;
1283
 
        }
1284
 
        cwd = inode;
1285
 
        return;
1286
 
}
1287
 
 
1288
 
void do_print_working_directory(int argc, char *argv[])
1289
 
{
1290
 
        int     retval;
1291
 
        char    *pathname = NULL;
1292
 
 
1293
 
        if (common_args_process(argc, argv, 1, 1,
1294
 
                                "print_working_directory", "", 0))
1295
 
                return;
1296
 
 
1297
 
        retval = ext2fs_get_pathname(current_fs, cwd, 0, &pathname);
1298
 
        if (retval) {
1299
 
                com_err(argv[0], retval,
1300
 
                        "while trying to get pathname of cwd");
1301
 
        }
1302
 
        printf("[pwd]   INODE: %6u  PATH: %s\n",
1303
 
               cwd, pathname ? pathname : "NULL");
1304
 
        if (pathname) {
1305
 
                free(pathname);
1306
 
                pathname = NULL;
1307
 
        }
1308
 
        retval = ext2fs_get_pathname(current_fs, root, 0, &pathname);
1309
 
        if (retval) {
1310
 
                com_err(argv[0], retval,
1311
 
                        "while trying to get pathname of root");
1312
 
        }
1313
 
        printf("[root]  INODE: %6u  PATH: %s\n",
1314
 
               root, pathname ? pathname : "NULL");
1315
 
        if (pathname) {
1316
 
                free(pathname);
1317
 
                pathname = NULL;
1318
 
        }
1319
 
        return;
1320
 
}
1321
 
 
1322
 
#ifndef READ_ONLY
1323
 
static void make_link(char *sourcename, char *destname)
1324
 
{
1325
 
        ext2_ino_t      ino;
1326
 
        struct ext2_inode inode;
1327
 
        int             retval;
1328
 
        ext2_ino_t      dir;
1329
 
        char            *dest, *cp, *base_name;
1330
 
 
1331
 
        /*
1332
 
         * Get the source inode
1333
 
         */
1334
 
        ino = string_to_inode(sourcename);
1335
 
        if (!ino)
1336
 
                return;
1337
 
        base_name = strrchr(sourcename, '/');
1338
 
        if (base_name)
1339
 
                base_name++;
1340
 
        else
1341
 
                base_name = sourcename;
1342
 
        /*
1343
 
         * Figure out the destination.  First see if it exists and is
1344
 
         * a directory.
1345
 
         */
1346
 
        if (! (retval=ext2fs_namei(current_fs, root, cwd, destname, &dir)))
1347
 
                dest = base_name;
1348
 
        else {
1349
 
                /*
1350
 
                 * OK, it doesn't exist.  See if it is
1351
 
                 * '<dir>/basename' or 'basename'
1352
 
                 */
1353
 
                cp = strrchr(destname, '/');
1354
 
                if (cp) {
1355
 
                        *cp = 0;
1356
 
                        dir = string_to_inode(destname);
1357
 
                        if (!dir)
1358
 
                                return;
1359
 
                        dest = cp+1;
1360
 
                } else {
1361
 
                        dir = cwd;
1362
 
                        dest = destname;
1363
 
                }
1364
 
        }
1365
 
 
1366
 
        if (debugfs_read_inode(ino, &inode, sourcename))
1367
 
                return;
1368
 
 
1369
 
        retval = ext2fs_link(current_fs, dir, dest, ino,
1370
 
                             ext2_file_type(inode.i_mode));
1371
 
        if (retval)
1372
 
                com_err("make_link", retval, 0);
1373
 
        return;
1374
 
}
1375
 
 
1376
 
 
1377
 
void do_link(int argc, char *argv[])
1378
 
{
1379
 
        if (common_args_process(argc, argv, 3, 3, "link",
1380
 
                                "<source file> <dest_name>", CHECK_FS_RW))
1381
 
                return;
1382
 
 
1383
 
        make_link(argv[1], argv[2]);
1384
 
}
1385
 
 
1386
 
static int mark_blocks_proc(ext2_filsys fs, blk64_t *blocknr,
1387
 
                            e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
1388
 
                            blk64_t ref_block EXT2FS_ATTR((unused)),
1389
 
                            int ref_offset EXT2FS_ATTR((unused)),
1390
 
                            void *private EXT2FS_ATTR((unused)))
1391
 
{
1392
 
        blk64_t block;
1393
 
 
1394
 
        block = *blocknr;
1395
 
        ext2fs_block_alloc_stats2(fs, block, +1);
1396
 
        return 0;
1397
 
}
1398
 
 
1399
 
void do_undel(int argc, char *argv[])
1400
 
{
1401
 
        ext2_ino_t      ino;
1402
 
        struct ext2_inode inode;
1403
 
 
1404
 
        if (common_args_process(argc, argv, 2, 3, "undelete",
1405
 
                                "<inode_num> [dest_name]",
1406
 
                                CHECK_FS_RW | CHECK_FS_BITMAPS))
1407
 
                return;
1408
 
 
1409
 
        ino = string_to_inode(argv[1]);
1410
 
        if (!ino)
1411
 
                return;
1412
 
 
1413
 
        if (debugfs_read_inode(ino, &inode, argv[1]))
1414
 
                return;
1415
 
 
1416
 
        if (ext2fs_test_inode_bitmap2(current_fs->inode_map, ino)) {
1417
 
                com_err(argv[1], 0, "Inode is not marked as deleted");
1418
 
                return;
1419
 
        }
1420
 
 
1421
 
        /*
1422
 
         * XXX this function doesn't handle changing the links count on the
1423
 
         * parent directory when undeleting a directory.
1424
 
         */
1425
 
        inode.i_links_count = LINUX_S_ISDIR(inode.i_mode) ? 2 : 1;
1426
 
        inode.i_dtime = 0;
1427
 
 
1428
 
        if (debugfs_write_inode(ino, &inode, argv[0]))
1429
 
                return;
1430
 
 
1431
 
        ext2fs_block_iterate3(current_fs, ino, BLOCK_FLAG_READ_ONLY, NULL,
1432
 
                              mark_blocks_proc, NULL);
1433
 
 
1434
 
        ext2fs_inode_alloc_stats2(current_fs, ino, +1, 0);
1435
 
 
1436
 
        if (argc > 2)
1437
 
                make_link(argv[1], argv[2]);
1438
 
}
1439
 
 
1440
 
static void unlink_file_by_name(char *filename)
1441
 
{
1442
 
        int             retval;
1443
 
        ext2_ino_t      dir;
1444
 
        char            *base_name;
1445
 
 
1446
 
        base_name = strrchr(filename, '/');
1447
 
        if (base_name) {
1448
 
                *base_name++ = '\0';
1449
 
                dir = string_to_inode(filename);
1450
 
                if (!dir)
1451
 
                        return;
1452
 
        } else {
1453
 
                dir = cwd;
1454
 
                base_name = filename;
1455
 
        }
1456
 
        retval = ext2fs_unlink(current_fs, dir, base_name, 0, 0);
1457
 
        if (retval)
1458
 
                com_err("unlink_file_by_name", retval, 0);
1459
 
        return;
1460
 
}
1461
 
 
1462
 
void do_unlink(int argc, char *argv[])
1463
 
{
1464
 
        if (common_args_process(argc, argv, 2, 2, "link",
1465
 
                                "<pathname>", CHECK_FS_RW))
1466
 
                return;
1467
 
 
1468
 
        unlink_file_by_name(argv[1]);
1469
 
}
1470
 
#endif /* READ_ONLY */
1471
 
 
1472
 
void do_find_free_block(int argc, char *argv[])
1473
 
{
1474
 
        blk64_t free_blk, goal, first_free = 0;
1475
 
        int             count;
1476
 
        errcode_t       retval;
1477
 
        char            *tmp;
1478
 
 
1479
 
        if ((argc > 3) || (argc==2 && *argv[1] == '?')) {
1480
 
                com_err(argv[0], 0, "Usage: find_free_block [count [goal]]");
1481
 
                return;
1482
 
        }
1483
 
        if (check_fs_open(argv[0]))
1484
 
                return;
1485
 
 
1486
 
        if (argc > 1) {
1487
 
                count = strtol(argv[1],&tmp,0);
1488
 
                if (*tmp) {
1489
 
                        com_err(argv[0], 0, "Bad count - %s", argv[1]);
1490
 
                        return;
1491
 
                }
1492
 
        } else
1493
 
                count = 1;
1494
 
 
1495
 
        if (argc > 2) {
1496
 
                goal = strtol(argv[2], &tmp, 0);
1497
 
                if (*tmp) {
1498
 
                        com_err(argv[0], 0, "Bad goal - %s", argv[1]);
1499
 
                        return;
1500
 
                }
1501
 
        }
1502
 
        else
1503
 
                goal = current_fs->super->s_first_data_block;
1504
 
 
1505
 
        printf("Free blocks found: ");
1506
 
        free_blk = goal - 1;
1507
 
        while (count-- > 0) {
1508
 
                retval = ext2fs_new_block2(current_fs, free_blk + 1, 0,
1509
 
                                           &free_blk);
1510
 
                if (first_free) {
1511
 
                        if (first_free == free_blk)
1512
 
                                break;
1513
 
                } else
1514
 
                        first_free = free_blk;
1515
 
                if (retval) {
1516
 
                        com_err("ext2fs_new_block", retval, 0);
1517
 
                        return;
1518
 
                } else
1519
 
                        printf("%llu ", free_blk);
1520
 
        }
1521
 
        printf("\n");
1522
 
}
1523
 
 
1524
 
void do_find_free_inode(int argc, char *argv[])
1525
 
{
1526
 
        ext2_ino_t      free_inode, dir;
1527
 
        int             mode;
1528
 
        int             retval;
1529
 
        char            *tmp;
1530
 
 
1531
 
        if (argc > 3 || (argc>1 && *argv[1] == '?')) {
1532
 
                com_err(argv[0], 0, "Usage: find_free_inode [dir] [mode]");
1533
 
                return;
1534
 
        }
1535
 
        if (check_fs_open(argv[0]))
1536
 
                return;
1537
 
 
1538
 
        if (argc > 1) {
1539
 
                dir = strtol(argv[1], &tmp, 0);
1540
 
                if (*tmp) {
1541
 
                        com_err(argv[0], 0, "Bad dir - %s", argv[1]);
1542
 
                        return;
1543
 
                }
1544
 
        }
1545
 
        else
1546
 
                dir = root;
1547
 
        if (argc > 2) {
1548
 
                mode = strtol(argv[2], &tmp, 0);
1549
 
                if (*tmp) {
1550
 
                        com_err(argv[0], 0, "Bad mode - %s", argv[2]);
1551
 
                        return;
1552
 
                }
1553
 
        } else
1554
 
                mode = 010755;
1555
 
 
1556
 
        retval = ext2fs_new_inode(current_fs, dir, mode, 0, &free_inode);
1557
 
        if (retval)
1558
 
                com_err("ext2fs_new_inode", retval, 0);
1559
 
        else
1560
 
                printf("Free inode found: %u\n", free_inode);
1561
 
}
1562
 
 
1563
 
#ifndef READ_ONLY
1564
 
static errcode_t copy_file(int fd, ext2_ino_t newfile)
1565
 
{
1566
 
        ext2_file_t     e2_file;
1567
 
        errcode_t       retval;
1568
 
        int             got;
1569
 
        unsigned int    written;
1570
 
        char            buf[8192];
1571
 
        char            *ptr;
1572
 
 
1573
 
        retval = ext2fs_file_open(current_fs, newfile,
1574
 
                                  EXT2_FILE_WRITE, &e2_file);
1575
 
        if (retval)
1576
 
                return retval;
1577
 
 
1578
 
        while (1) {
1579
 
                got = read(fd, buf, sizeof(buf));
1580
 
                if (got == 0)
1581
 
                        break;
1582
 
                if (got < 0) {
1583
 
                        retval = errno;
1584
 
                        goto fail;
1585
 
                }
1586
 
                ptr = buf;
1587
 
                while (got > 0) {
1588
 
                        retval = ext2fs_file_write(e2_file, ptr,
1589
 
                                                   got, &written);
1590
 
                        if (retval)
1591
 
                                goto fail;
1592
 
 
1593
 
                        got -= written;
1594
 
                        ptr += written;
1595
 
                }
1596
 
        }
1597
 
        retval = ext2fs_file_close(e2_file);
1598
 
        return retval;
1599
 
 
1600
 
fail:
1601
 
        (void) ext2fs_file_close(e2_file);
1602
 
        return retval;
1603
 
}
1604
 
 
1605
 
 
1606
 
void do_write(int argc, char *argv[])
1607
 
{
1608
 
        int             fd;
1609
 
        struct stat     statbuf;
1610
 
        ext2_ino_t      newfile;
1611
 
        errcode_t       retval;
1612
 
        struct ext2_inode inode;
1613
 
 
1614
 
        if (common_args_process(argc, argv, 3, 3, "write",
1615
 
                                "<native file> <new file>", CHECK_FS_RW))
1616
 
                return;
1617
 
 
1618
 
        fd = open(argv[1], O_RDONLY);
1619
 
        if (fd < 0) {
1620
 
                com_err(argv[1], errno, 0);
1621
 
                return;
1622
 
        }
1623
 
        if (fstat(fd, &statbuf) < 0) {
1624
 
                com_err(argv[1], errno, 0);
1625
 
                close(fd);
1626
 
                return;
1627
 
        }
1628
 
 
1629
 
        retval = ext2fs_namei(current_fs, root, cwd, argv[2], &newfile);
1630
 
        if (retval == 0) {
1631
 
                com_err(argv[0], 0, "The file '%s' already exists\n", argv[2]);
1632
 
                close(fd);
1633
 
                return;
1634
 
        }
1635
 
 
1636
 
        retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile);
1637
 
        if (retval) {
1638
 
                com_err(argv[0], retval, 0);
1639
 
                close(fd);
1640
 
                return;
1641
 
        }
1642
 
        printf("Allocated inode: %u\n", newfile);
1643
 
        retval = ext2fs_link(current_fs, cwd, argv[2], newfile,
1644
 
                             EXT2_FT_REG_FILE);
1645
 
        if (retval == EXT2_ET_DIR_NO_SPACE) {
1646
 
                retval = ext2fs_expand_dir(current_fs, cwd);
1647
 
                if (retval) {
1648
 
                        com_err(argv[0], retval, "while expanding directory");
1649
 
                        close(fd);
1650
 
                        return;
1651
 
                }
1652
 
                retval = ext2fs_link(current_fs, cwd, argv[2], newfile,
1653
 
                                     EXT2_FT_REG_FILE);
1654
 
        }
1655
 
        if (retval) {
1656
 
                com_err(argv[2], retval, 0);
1657
 
                close(fd);
1658
 
                return;
1659
 
        }
1660
 
        if (ext2fs_test_inode_bitmap2(current_fs->inode_map,newfile))
1661
 
                com_err(argv[0], 0, "Warning: inode already set");
1662
 
        ext2fs_inode_alloc_stats2(current_fs, newfile, +1, 0);
1663
 
        memset(&inode, 0, sizeof(inode));
1664
 
        inode.i_mode = (statbuf.st_mode & ~LINUX_S_IFMT) | LINUX_S_IFREG;
1665
 
        inode.i_atime = inode.i_ctime = inode.i_mtime =
1666
 
                current_fs->now ? current_fs->now : time(0);
1667
 
        inode.i_links_count = 1;
1668
 
        inode.i_size = statbuf.st_size;
1669
 
        if (current_fs->super->s_feature_incompat &
1670
 
            EXT3_FEATURE_INCOMPAT_EXTENTS)
1671
 
                inode.i_flags |= EXT4_EXTENTS_FL;
1672
 
        if (debugfs_write_new_inode(newfile, &inode, argv[0])) {
1673
 
                close(fd);
1674
 
                return;
1675
 
        }
1676
 
        if (LINUX_S_ISREG(inode.i_mode)) {
1677
 
                retval = copy_file(fd, newfile);
1678
 
                if (retval)
1679
 
                        com_err("copy_file", retval, 0);
1680
 
        }
1681
 
        close(fd);
1682
 
}
1683
 
 
1684
 
void do_mknod(int argc, char *argv[])
1685
 
{
1686
 
        unsigned long   mode, major, minor;
1687
 
        ext2_ino_t      newfile;
1688
 
        errcode_t       retval;
1689
 
        struct ext2_inode inode;
1690
 
        int             filetype, nr;
1691
 
 
1692
 
        if (check_fs_open(argv[0]))
1693
 
                return;
1694
 
        if (argc < 3 || argv[2][1]) {
1695
 
        usage:
1696
 
                com_err(argv[0], 0, "Usage: mknod <name> [p| [c|b] <major> <minor>]");
1697
 
                return;
1698
 
        }
1699
 
        mode = minor = major = 0;
1700
 
        switch (argv[2][0]) {
1701
 
                case 'p':
1702
 
                        mode = LINUX_S_IFIFO;
1703
 
                        filetype = EXT2_FT_FIFO;
1704
 
                        nr = 3;
1705
 
                        break;
1706
 
                case 'c':
1707
 
                        mode = LINUX_S_IFCHR;
1708
 
                        filetype = EXT2_FT_CHRDEV;
1709
 
                        nr = 5;
1710
 
                        break;
1711
 
                case 'b':
1712
 
                        mode = LINUX_S_IFBLK;
1713
 
                        filetype = EXT2_FT_BLKDEV;
1714
 
                        nr = 5;
1715
 
                        break;
1716
 
                default:
1717
 
                        filetype = 0;
1718
 
                        nr = 0;
1719
 
        }
1720
 
        if (nr == 5) {
1721
 
                major = strtoul(argv[3], argv+3, 0);
1722
 
                minor = strtoul(argv[4], argv+4, 0);
1723
 
                if (major > 65535 || minor > 65535 || argv[3][0] || argv[4][0])
1724
 
                        nr = 0;
1725
 
        }
1726
 
        if (argc != nr)
1727
 
                goto usage;
1728
 
        if (check_fs_read_write(argv[0]))
1729
 
                return;
1730
 
        retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile);
1731
 
        if (retval) {
1732
 
                com_err(argv[0], retval, 0);
1733
 
                return;
1734
 
        }
1735
 
        printf("Allocated inode: %u\n", newfile);
1736
 
        retval = ext2fs_link(current_fs, cwd, argv[1], newfile, filetype);
1737
 
        if (retval == EXT2_ET_DIR_NO_SPACE) {
1738
 
                retval = ext2fs_expand_dir(current_fs, cwd);
1739
 
                if (retval) {
1740
 
                        com_err(argv[0], retval, "while expanding directory");
1741
 
                        return;
1742
 
                }
1743
 
                retval = ext2fs_link(current_fs, cwd, argv[1], newfile,
1744
 
                                     filetype);
1745
 
        }
1746
 
        if (retval) {
1747
 
                com_err(argv[1], retval, 0);
1748
 
                return;
1749
 
        }
1750
 
        if (ext2fs_test_inode_bitmap2(current_fs->inode_map,newfile))
1751
 
                com_err(argv[0], 0, "Warning: inode already set");
1752
 
        ext2fs_mark_inode_bitmap2(current_fs->inode_map, newfile);
1753
 
        ext2fs_mark_ib_dirty(current_fs);
1754
 
        memset(&inode, 0, sizeof(inode));
1755
 
        inode.i_mode = mode;
1756
 
        inode.i_atime = inode.i_ctime = inode.i_mtime =
1757
 
                current_fs->now ? current_fs->now : time(0);
1758
 
        if ((major < 256) && (minor < 256)) {
1759
 
                inode.i_block[0] = major*256+minor;
1760
 
                inode.i_block[1] = 0;
1761
 
        } else {
1762
 
                inode.i_block[0] = 0;
1763
 
                inode.i_block[1] = (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);
1764
 
        }
1765
 
        inode.i_links_count = 1;
1766
 
        if (debugfs_write_new_inode(newfile, &inode, argv[0]))
1767
 
                return;
1768
 
}
1769
 
 
1770
 
void do_mkdir(int argc, char *argv[])
1771
 
{
1772
 
        char    *cp;
1773
 
        ext2_ino_t      parent;
1774
 
        char    *name;
1775
 
        errcode_t retval;
1776
 
 
1777
 
        if (common_args_process(argc, argv, 2, 2, "mkdir",
1778
 
                                "<filename>", CHECK_FS_RW))
1779
 
                return;
1780
 
 
1781
 
        cp = strrchr(argv[1], '/');
1782
 
        if (cp) {
1783
 
                *cp = 0;
1784
 
                parent = string_to_inode(argv[1]);
1785
 
                if (!parent) {
1786
 
                        com_err(argv[1], ENOENT, 0);
1787
 
                        return;
1788
 
                }
1789
 
                name = cp+1;
1790
 
        } else {
1791
 
                parent = cwd;
1792
 
                name = argv[1];
1793
 
        }
1794
 
 
1795
 
try_again:
1796
 
        retval = ext2fs_mkdir(current_fs, parent, 0, name);
1797
 
        if (retval == EXT2_ET_DIR_NO_SPACE) {
1798
 
                retval = ext2fs_expand_dir(current_fs, parent);
1799
 
                if (retval) {
1800
 
                        com_err(argv[0], retval, "while expanding directory");
1801
 
                        return;
1802
 
                }
1803
 
                goto try_again;
1804
 
        }
1805
 
        if (retval) {
1806
 
                com_err("ext2fs_mkdir", retval, 0);
1807
 
                return;
1808
 
        }
1809
 
 
1810
 
}
1811
 
 
1812
 
static int release_blocks_proc(ext2_filsys fs, blk64_t *blocknr,
1813
 
                               e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
1814
 
                               blk64_t ref_block EXT2FS_ATTR((unused)),
1815
 
                               int ref_offset EXT2FS_ATTR((unused)),
1816
 
                               void *private EXT2FS_ATTR((unused)))
1817
 
{
1818
 
        blk64_t block;
1819
 
 
1820
 
        block = *blocknr;
1821
 
        ext2fs_block_alloc_stats2(fs, block, -1);
1822
 
        return 0;
1823
 
}
1824
 
 
1825
 
static void kill_file_by_inode(ext2_ino_t inode)
1826
 
{
1827
 
        struct ext2_inode inode_buf;
1828
 
 
1829
 
        if (debugfs_read_inode(inode, &inode_buf, 0))
1830
 
                return;
1831
 
        inode_buf.i_dtime = current_fs->now ? current_fs->now : time(0);
1832
 
        if (debugfs_write_inode(inode, &inode_buf, 0))
1833
 
                return;
1834
 
        if (!ext2fs_inode_has_valid_blocks2(current_fs, &inode_buf))
1835
 
                return;
1836
 
 
1837
 
        ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY, NULL,
1838
 
                              release_blocks_proc, NULL);
1839
 
        printf("\n");
1840
 
        ext2fs_inode_alloc_stats2(current_fs, inode, -1,
1841
 
                                  LINUX_S_ISDIR(inode_buf.i_mode));
1842
 
}
1843
 
 
1844
 
 
1845
 
void do_kill_file(int argc, char *argv[])
1846
 
{
1847
 
        ext2_ino_t inode_num;
1848
 
 
1849
 
        if (common_inode_args_process(argc, argv, &inode_num, CHECK_FS_RW))
1850
 
                return;
1851
 
 
1852
 
        kill_file_by_inode(inode_num);
1853
 
}
1854
 
 
1855
 
void do_rm(int argc, char *argv[])
1856
 
{
1857
 
        int retval;
1858
 
        ext2_ino_t inode_num;
1859
 
        struct ext2_inode inode;
1860
 
 
1861
 
        if (common_args_process(argc, argv, 2, 2, "rm",
1862
 
                                "<filename>", CHECK_FS_RW))
1863
 
                return;
1864
 
 
1865
 
        retval = ext2fs_namei(current_fs, root, cwd, argv[1], &inode_num);
1866
 
        if (retval) {
1867
 
                com_err(argv[0], retval, "while trying to resolve filename");
1868
 
                return;
1869
 
        }
1870
 
 
1871
 
        if (debugfs_read_inode(inode_num, &inode, argv[0]))
1872
 
                return;
1873
 
 
1874
 
        if (LINUX_S_ISDIR(inode.i_mode)) {
1875
 
                com_err(argv[0], 0, "file is a directory");
1876
 
                return;
1877
 
        }
1878
 
 
1879
 
        --inode.i_links_count;
1880
 
        if (debugfs_write_inode(inode_num, &inode, argv[0]))
1881
 
                return;
1882
 
 
1883
 
        unlink_file_by_name(argv[1]);
1884
 
        if (inode.i_links_count == 0)
1885
 
                kill_file_by_inode(inode_num);
1886
 
}
1887
 
 
1888
 
struct rd_struct {
1889
 
        ext2_ino_t      parent;
1890
 
        int             empty;
1891
 
};
1892
 
 
1893
 
static int rmdir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
1894
 
                      int       entry EXT2FS_ATTR((unused)),
1895
 
                      struct ext2_dir_entry *dirent,
1896
 
                      int       offset EXT2FS_ATTR((unused)),
1897
 
                      int       blocksize EXT2FS_ATTR((unused)),
1898
 
                      char      *buf EXT2FS_ATTR((unused)),
1899
 
                      void      *private)
1900
 
{
1901
 
        struct rd_struct *rds = (struct rd_struct *) private;
1902
 
 
1903
 
        if (dirent->inode == 0)
1904
 
                return 0;
1905
 
        if (((dirent->name_len&0xFF) == 1) && (dirent->name[0] == '.'))
1906
 
                return 0;
1907
 
        if (((dirent->name_len&0xFF) == 2) && (dirent->name[0] == '.') &&
1908
 
            (dirent->name[1] == '.')) {
1909
 
                rds->parent = dirent->inode;
1910
 
                return 0;
1911
 
        }
1912
 
        rds->empty = 0;
1913
 
        return 0;
1914
 
}
1915
 
 
1916
 
void do_rmdir(int argc, char *argv[])
1917
 
{
1918
 
        int retval;
1919
 
        ext2_ino_t inode_num;
1920
 
        struct ext2_inode inode;
1921
 
        struct rd_struct rds;
1922
 
 
1923
 
        if (common_args_process(argc, argv, 2, 2, "rmdir",
1924
 
                                "<filename>", CHECK_FS_RW))
1925
 
                return;
1926
 
 
1927
 
        retval = ext2fs_namei(current_fs, root, cwd, argv[1], &inode_num);
1928
 
        if (retval) {
1929
 
                com_err(argv[0], retval, "while trying to resolve filename");
1930
 
                return;
1931
 
        }
1932
 
 
1933
 
        if (debugfs_read_inode(inode_num, &inode, argv[0]))
1934
 
                return;
1935
 
 
1936
 
        if (!LINUX_S_ISDIR(inode.i_mode)) {
1937
 
                com_err(argv[0], 0, "file is not a directory");
1938
 
                return;
1939
 
        }
1940
 
 
1941
 
        rds.parent = 0;
1942
 
        rds.empty = 1;
1943
 
 
1944
 
        retval = ext2fs_dir_iterate2(current_fs, inode_num, 0,
1945
 
                                    0, rmdir_proc, &rds);
1946
 
        if (retval) {
1947
 
                com_err(argv[0], retval, "while iterating over directory");
1948
 
                return;
1949
 
        }
1950
 
        if (rds.empty == 0) {
1951
 
                com_err(argv[0], 0, "directory not empty");
1952
 
                return;
1953
 
        }
1954
 
 
1955
 
        inode.i_links_count = 0;
1956
 
        if (debugfs_write_inode(inode_num, &inode, argv[0]))
1957
 
                return;
1958
 
 
1959
 
        unlink_file_by_name(argv[1]);
1960
 
        kill_file_by_inode(inode_num);
1961
 
 
1962
 
        if (rds.parent) {
1963
 
                if (debugfs_read_inode(rds.parent, &inode, argv[0]))
1964
 
                        return;
1965
 
                if (inode.i_links_count > 1)
1966
 
                        inode.i_links_count--;
1967
 
                if (debugfs_write_inode(rds.parent, &inode, argv[0]))
1968
 
                        return;
1969
 
        }
1970
 
}
1971
 
#endif /* READ_ONLY */
1972
 
 
1973
 
void do_show_debugfs_params(int argc EXT2FS_ATTR((unused)),
1974
 
                            char *argv[] EXT2FS_ATTR((unused)))
1975
 
{
1976
 
        FILE *out = stdout;
1977
 
 
1978
 
        if (current_fs)
1979
 
                fprintf(out, "Open mode: read-%s\n",
1980
 
                        current_fs->flags & EXT2_FLAG_RW ? "write" : "only");
1981
 
        fprintf(out, "Filesystem in use: %s\n",
1982
 
                current_fs ? current_fs->device_name : "--none--");
1983
 
}
1984
 
 
1985
 
#ifndef READ_ONLY
1986
 
void do_expand_dir(int argc, char *argv[])
1987
 
{
1988
 
        ext2_ino_t inode;
1989
 
        int retval;
1990
 
 
1991
 
        if (common_inode_args_process(argc, argv, &inode, CHECK_FS_RW))
1992
 
                return;
1993
 
 
1994
 
        retval = ext2fs_expand_dir(current_fs, inode);
1995
 
        if (retval)
1996
 
                com_err("ext2fs_expand_dir", retval, 0);
1997
 
        return;
1998
 
}
1999
 
 
2000
 
void do_features(int argc, char *argv[])
2001
 
{
2002
 
        int     i;
2003
 
 
2004
 
        if (check_fs_open(argv[0]))
2005
 
                return;
2006
 
 
2007
 
        if ((argc != 1) && check_fs_read_write(argv[0]))
2008
 
                return;
2009
 
        for (i=1; i < argc; i++) {
2010
 
                if (e2p_edit_feature(argv[i],
2011
 
                                     &current_fs->super->s_feature_compat, 0))
2012
 
                        com_err(argv[0], 0, "Unknown feature: %s\n",
2013
 
                                argv[i]);
2014
 
                else
2015
 
                        ext2fs_mark_super_dirty(current_fs);
2016
 
        }
2017
 
        print_features(current_fs->super, stdout);
2018
 
}
2019
 
#endif /* READ_ONLY */
2020
 
 
2021
 
void do_bmap(int argc, char *argv[])
2022
 
{
2023
 
        ext2_ino_t      ino;
2024
 
        blk64_t         blk, pblk;
2025
 
        int             err;
2026
 
        errcode_t       errcode;
2027
 
 
2028
 
        if (common_args_process(argc, argv, 3, 3, argv[0],
2029
 
                                "<file> logical_blk", 0))
2030
 
                return;
2031
 
 
2032
 
        ino = string_to_inode(argv[1]);
2033
 
        if (!ino)
2034
 
                return;
2035
 
        blk = parse_ulong(argv[2], argv[0], "logical_block", &err);
2036
 
 
2037
 
        errcode = ext2fs_bmap2(current_fs, ino, 0, 0, 0, blk, 0, &pblk);
2038
 
        if (errcode) {
2039
 
                com_err("argv[0]", errcode,
2040
 
                        "while mapping logical block %llu\n", blk);
2041
 
                return;
2042
 
        }
2043
 
        printf("%llu\n", pblk);
2044
 
}
2045
 
 
2046
 
void do_imap(int argc, char *argv[])
2047
 
{
2048
 
        ext2_ino_t      ino;
2049
 
        unsigned long   group, block, block_nr, offset;
2050
 
 
2051
 
        if (common_args_process(argc, argv, 2, 2, argv[0],
2052
 
                                "<file>", 0))
2053
 
                return;
2054
 
        ino = string_to_inode(argv[1]);
2055
 
        if (!ino)
2056
 
                return;
2057
 
 
2058
 
        group = (ino - 1) / EXT2_INODES_PER_GROUP(current_fs->super);
2059
 
        offset = ((ino - 1) % EXT2_INODES_PER_GROUP(current_fs->super)) *
2060
 
                EXT2_INODE_SIZE(current_fs->super);
2061
 
        block = offset >> EXT2_BLOCK_SIZE_BITS(current_fs->super);
2062
 
        if (!ext2fs_inode_table_loc(current_fs, (unsigned)group)) {
2063
 
                com_err(argv[0], 0, "Inode table for group %lu is missing\n",
2064
 
                        group);
2065
 
                return;
2066
 
        }
2067
 
        block_nr = ext2fs_inode_table_loc(current_fs, (unsigned)group) +
2068
 
                block;
2069
 
        offset &= (EXT2_BLOCK_SIZE(current_fs->super) - 1);
2070
 
 
2071
 
        printf("Inode %d is part of block group %lu\n"
2072
 
               "\tlocated at block %lu, offset 0x%04lx\n", ino, group,
2073
 
               block_nr, offset);
2074
 
 
2075
 
}
2076
 
 
2077
 
#ifndef READ_ONLY
2078
 
void do_set_current_time(int argc, char *argv[])
2079
 
{
2080
 
        time_t now;
2081
 
 
2082
 
        if (common_args_process(argc, argv, 2, 2, argv[0],
2083
 
                                "<time>", 0))
2084
 
                return;
2085
 
 
2086
 
        now = string_to_time(argv[1]);
2087
 
        if (now == ((time_t) -1)) {
2088
 
                com_err(argv[0], 0, "Couldn't parse argument as a time: %s\n",
2089
 
                        argv[1]);
2090
 
                return;
2091
 
 
2092
 
        } else {
2093
 
                printf("Setting current time to %s\n", time_to_string(now));
2094
 
                current_fs->now = now;
2095
 
        }
2096
 
}
2097
 
#endif /* READ_ONLY */
2098
 
 
2099
 
static int find_supp_feature(__u32 *supp, int feature_type, char *name)
2100
 
{
2101
 
        int compat, bit, ret;
2102
 
        unsigned int feature_mask;
2103
 
 
2104
 
        if (name) {
2105
 
                if (feature_type == E2P_FS_FEATURE)
2106
 
                        ret = e2p_string2feature(name, &compat, &feature_mask);
2107
 
                else
2108
 
                        ret = e2p_jrnl_string2feature(name, &compat,
2109
 
                                                      &feature_mask);
2110
 
                if (ret)
2111
 
                        return ret;
2112
 
 
2113
 
                if (!(supp[compat] & feature_mask))
2114
 
                        return 1;
2115
 
        } else {
2116
 
                for (compat = 0; compat < 3; compat++) {
2117
 
                        for (bit = 0, feature_mask = 1; bit < 32;
2118
 
                             bit++, feature_mask <<= 1) {
2119
 
                                if (supp[compat] & feature_mask) {
2120
 
                                        if (feature_type == E2P_FS_FEATURE)
2121
 
                                                fprintf(stdout, " %s",
2122
 
                                                e2p_feature2string(compat,
2123
 
                                                feature_mask));
2124
 
                                        else
2125
 
                                                fprintf(stdout, " %s",
2126
 
                                                e2p_jrnl_feature2string(compat,
2127
 
                                                feature_mask));
2128
 
                                }
2129
 
                        }
2130
 
                }
2131
 
                fprintf(stdout, "\n");
2132
 
        }
2133
 
 
2134
 
        return 0;
2135
 
}
2136
 
 
2137
 
void do_supported_features(int argc, char *argv[])
2138
 
{
2139
 
        int     ret;
2140
 
        __u32   supp[3] = { EXT2_LIB_FEATURE_COMPAT_SUPP,
2141
 
                            EXT2_LIB_FEATURE_INCOMPAT_SUPP,
2142
 
                            EXT2_LIB_FEATURE_RO_COMPAT_SUPP };
2143
 
        __u32   jrnl_supp[3] = { JFS_KNOWN_COMPAT_FEATURES,
2144
 
                                 JFS_KNOWN_INCOMPAT_FEATURES,
2145
 
                                 JFS_KNOWN_ROCOMPAT_FEATURES };
2146
 
 
2147
 
        if (argc > 1) {
2148
 
                ret = find_supp_feature(supp, E2P_FS_FEATURE, argv[1]);
2149
 
                if (ret) {
2150
 
                        ret = find_supp_feature(jrnl_supp, E2P_JOURNAL_FEATURE,
2151
 
                                                argv[1]);
2152
 
                }
2153
 
                if (ret)
2154
 
                        com_err(argv[0], 0, "Unknown feature: %s\n", argv[1]);
2155
 
                else
2156
 
                        fprintf(stdout, "Supported feature: %s\n", argv[1]);
2157
 
        } else {
2158
 
                fprintf(stdout, "Supported features:");
2159
 
                ret = find_supp_feature(supp, E2P_FS_FEATURE, NULL);
2160
 
                ret = find_supp_feature(jrnl_supp, E2P_JOURNAL_FEATURE, NULL);
2161
 
        }
2162
 
}
2163
 
 
2164
 
#ifndef READ_ONLY
2165
 
void do_punch(int argc, char *argv[])
2166
 
{
2167
 
        ext2_ino_t      ino;
2168
 
        blk64_t         start, end;
2169
 
        int             err;
2170
 
        errcode_t       errcode;
2171
 
 
2172
 
        if (common_args_process(argc, argv, 3, 4, argv[0],
2173
 
                                "<file> start_blk [end_blk]",
2174
 
                                CHECK_FS_RW | CHECK_FS_BITMAPS))
2175
 
                return;
2176
 
 
2177
 
        ino = string_to_inode(argv[1]);
2178
 
        if (!ino)
2179
 
                return;
2180
 
        start = parse_ulong(argv[2], argv[0], "logical_block", &err);
2181
 
        if (argc == 4)
2182
 
                end = parse_ulong(argv[3], argv[0], "logical_block", &err);
2183
 
        else
2184
 
                end = ~0;
2185
 
 
2186
 
        errcode = ext2fs_punch(current_fs, ino, 0, 0, start, end);
2187
 
 
2188
 
        if (errcode) {
2189
 
                com_err(argv[0], errcode,
2190
 
                        "while truncating inode %u from %llu to %llu\n", ino,
2191
 
                        (unsigned long long) start, (unsigned long long) end);
2192
 
                return;
2193
 
        }
2194
 
}
2195
 
#endif /* READ_ONLY */
2196
 
 
2197
 
void do_dump_mmp(int argc EXT2FS_ATTR((unused)), char *argv[])
2198
 
{
2199
 
        struct ext2_super_block *sb;
2200
 
        struct mmp_struct *mmp_s;
2201
 
        time_t t;
2202
 
        errcode_t retval = 0;
2203
 
 
2204
 
        if (check_fs_open(argv[0]))
2205
 
                return;
2206
 
 
2207
 
        sb  = current_fs->super;
2208
 
        if (sb->s_mmp_block <= sb->s_first_data_block ||
2209
 
            sb->s_mmp_block >= ext2fs_blocks_count(sb)) {
2210
 
                com_err(argv[0], EXT2_ET_MMP_BAD_BLOCK, "while dumping it.\n");
2211
 
                return;
2212
 
        }
2213
 
 
2214
 
        if (current_fs->mmp_buf == NULL) {
2215
 
                retval = ext2fs_get_mem(current_fs->blocksize,
2216
 
                                        &current_fs->mmp_buf);
2217
 
                if (retval) {
2218
 
                        com_err(argv[0], retval, "allocating MMP buffer.\n");
2219
 
                        return;
2220
 
                }
2221
 
        }
2222
 
 
2223
 
        mmp_s = current_fs->mmp_buf;
2224
 
 
2225
 
        retval = ext2fs_mmp_read(current_fs, current_fs->super->s_mmp_block,
2226
 
                                 current_fs->mmp_buf);
2227
 
        if (retval) {
2228
 
                com_err(argv[0], retval, "reading MMP block.\n");
2229
 
                return;
2230
 
        }
2231
 
 
2232
 
        t = mmp_s->mmp_time;
2233
 
        fprintf(stdout, "block_number: %llu\n", current_fs->super->s_mmp_block);
2234
 
        fprintf(stdout, "update_interval: %d\n",
2235
 
                current_fs->super->s_mmp_update_interval);
2236
 
        fprintf(stdout, "check_interval: %d\n", mmp_s->mmp_check_interval);
2237
 
        fprintf(stdout, "sequence: %08x\n", mmp_s->mmp_seq);
2238
 
        fprintf(stdout, "time: %lld -- %s", mmp_s->mmp_time, ctime(&t));
2239
 
        fprintf(stdout, "node_name: %s\n", mmp_s->mmp_nodename);
2240
 
        fprintf(stdout, "device_name: %s\n", mmp_s->mmp_bdevname);
2241
 
        fprintf(stdout, "magic: 0x%x\n", mmp_s->mmp_magic);
2242
 
}
2243
 
 
2244
 
static int source_file(const char *cmd_file, int sci_idx)
2245
 
{
2246
 
        FILE            *f;
2247
 
        char            buf[256];
2248
 
        char            *cp;
2249
 
        int             exit_status = 0;
2250
 
        int             retval;
2251
 
 
2252
 
        if (strcmp(cmd_file, "-") == 0)
2253
 
                f = stdin;
2254
 
        else {
2255
 
                f = fopen(cmd_file, "r");
2256
 
                if (!f) {
2257
 
                        perror(cmd_file);
2258
 
                        exit(1);
2259
 
                }
2260
 
        }
2261
 
        fflush(stdout);
2262
 
        fflush(stderr);
2263
 
        setbuf(stdout, NULL);
2264
 
        setbuf(stderr, NULL);
2265
 
        while (!feof(f)) {
2266
 
                if (fgets(buf, sizeof(buf), f) == NULL)
2267
 
                        break;
2268
 
                cp = strchr(buf, '\n');
2269
 
                if (cp)
2270
 
                        *cp = 0;
2271
 
                cp = strchr(buf, '\r');
2272
 
                if (cp)
2273
 
                        *cp = 0;
2274
 
                printf("debugfs: %s\n", buf);
2275
 
                retval = ss_execute_line(sci_idx, buf);
2276
 
                if (retval) {
2277
 
                        ss_perror(sci_idx, retval, buf);
2278
 
                        exit_status++;
2279
 
                }
2280
 
        }
2281
 
        if (f != stdin)
2282
 
                fclose(f);
2283
 
        return exit_status;
2284
 
}
2285
 
 
2286
 
int main(int argc, char **argv)
2287
 
{
2288
 
        int             retval;
2289
 
        int             sci_idx;
2290
 
        const char      *usage = 
2291
 
                "Usage: %s [-b blocksize] [-s superblock] [-f cmd_file] "
2292
 
                "[-R request] [-V] ["
2293
 
#ifndef READ_ONLY
2294
 
                "[-w] "
2295
 
#endif
2296
 
                "[-c] device]";
2297
 
        int             c;
2298
 
        int             open_flags = EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS;
2299
 
        char            *request = 0;
2300
 
        int             exit_status = 0;
2301
 
        char            *cmd_file = 0;
2302
 
        blk64_t         superblock = 0;
2303
 
        blk64_t         blocksize = 0;
2304
 
        int             catastrophic = 0;
2305
 
        char            *data_filename = 0;
2306
 
#ifdef READ_ONLY
2307
 
        const char      *opt_string = "icR:f:b:s:Vd:D";
2308
 
#else
2309
 
        const char      *opt_string = "iwcR:f:b:s:Vd:D";
2310
 
#endif
2311
 
 
2312
 
        if (debug_prog_name == 0)
2313
 
#ifdef READ_ONLY
2314
 
                debug_prog_name = "rdebugfs";
2315
 
#else
2316
 
                debug_prog_name = "debugfs";
2317
 
#endif
2318
 
        add_error_table(&et_ext2_error_table);
2319
 
        fprintf (stderr, "%s %s (%s)\n", debug_prog_name,
2320
 
                 E2FSPROGS_VERSION, E2FSPROGS_DATE);
2321
 
 
2322
 
        while ((c = getopt (argc, argv, opt_string)) != EOF) {
2323
 
                switch (c) {
2324
 
                case 'R':
2325
 
                        request = optarg;
2326
 
                        break;
2327
 
                case 'f':
2328
 
                        cmd_file = optarg;
2329
 
                        break;
2330
 
                case 'd':
2331
 
                        data_filename = optarg;
2332
 
                        break;
2333
 
                case 'i':
2334
 
                        open_flags |= EXT2_FLAG_IMAGE_FILE;
2335
 
                        break;
2336
 
#ifndef READ_ONLY
2337
 
                case 'w':
2338
 
                        open_flags |= EXT2_FLAG_RW;
2339
 
                        break;
2340
 
#endif
2341
 
                case 'D':
2342
 
                        open_flags |= EXT2_FLAG_DIRECT_IO;
2343
 
                        break;
2344
 
                case 'b':
2345
 
                        blocksize = parse_ulong(optarg, argv[0],
2346
 
                                                "block size", 0);
2347
 
                        break;
2348
 
                case 's':
2349
 
                        superblock = parse_ulong(optarg, argv[0],
2350
 
                                                 "superblock number", 0);
2351
 
                        break;
2352
 
                case 'c':
2353
 
                        catastrophic = 1;
2354
 
                        break;
2355
 
                case 'V':
2356
 
                        /* Print version number and exit */
2357
 
                        fprintf(stderr, "\tUsing %s\n",
2358
 
                                error_message(EXT2_ET_BASE));
2359
 
                        exit(0);
2360
 
                default:
2361
 
                        com_err(argv[0], 0, usage, debug_prog_name);
2362
 
                        return 1;
2363
 
                }
2364
 
        }
2365
 
        if (optind < argc)
2366
 
                open_filesystem(argv[optind], open_flags,
2367
 
                                superblock, blocksize, catastrophic,
2368
 
                                data_filename);
2369
 
 
2370
 
        sci_idx = ss_create_invocation(debug_prog_name, "0.0", (char *) NULL,
2371
 
                                       &debug_cmds, &retval);
2372
 
        if (retval) {
2373
 
                ss_perror(sci_idx, retval, "creating invocation");
2374
 
                exit(1);
2375
 
        }
2376
 
        ss_get_readline(sci_idx);
2377
 
 
2378
 
        (void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &retval);
2379
 
        if (retval) {
2380
 
                ss_perror(sci_idx, retval, "adding standard requests");
2381
 
                exit (1);
2382
 
        }
2383
 
        if (extra_cmds)
2384
 
                ss_add_request_table (sci_idx, extra_cmds, 1, &retval);
2385
 
        if (retval) {
2386
 
                ss_perror(sci_idx, retval, "adding extra requests");
2387
 
                exit (1);
2388
 
        }
2389
 
        if (request) {
2390
 
                retval = 0;
2391
 
                retval = ss_execute_line(sci_idx, request);
2392
 
                if (retval) {
2393
 
                        ss_perror(sci_idx, retval, request);
2394
 
                        exit_status++;
2395
 
                }
2396
 
        } else if (cmd_file) {
2397
 
                exit_status = source_file(cmd_file, sci_idx);
2398
 
        } else {
2399
 
                ss_listen(sci_idx);
2400
 
        }
2401
 
 
2402
 
        ss_delete_invocation(sci_idx);
2403
 
 
2404
 
        if (current_fs)
2405
 
                close_filesystem();
2406
 
 
2407
 
        remove_error_table(&et_ext2_error_table);
2408
 
        return exit_status;
2409
 
}