~ubuntu-branches/debian/jessie/ufsutils/jessie

« back to all changes in this revision

Viewing changes to sbin/fsdb/fsdbutil.c

  • Committer: Bazaar Package Importer
  • Author(s): Guillem Jover, Robert Millan, Guillem Jover, Peter Pentchev
  • Date: 2011-05-31 03:50:05 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20110531035005-wyiyk25p99ivd0k0
Tags: 8.2-1
[ Robert Millan ]
* Set ufsutils-udeb to kfreebsd-any.

[ Guillem Jover ]
* New upstream version (based on FreeBSD 8.2)
* Now using Standards-Version 3.9.2 (no changes needed).
* Switch to source format “3.0 (quilt)”.
  - Remove quilt from Build-Depends.
  - Remove patch target in debian/rules.
  - Remove now unneeded README.source.
  - Refresh all patches.
* Reorganize source code:
  - Switch from debian/upstream.sh to debian/rules get-orig-source target.
  - Switch from CVS to Subversion to retrieve the source code.
  - Use the same source layout as upstream (no more relocations),
    i.e. lib/, sbin/, sys/sys, sys/ufs.
  - Move libport/ to port/.
  - Merge libdisklabel/ into port/.
* Remove unneeded linking against libtermcap, thus removing the need for
  ncurses.
* Add an empty debian/watch file explaining that there's no packaged
  upstream releases. Suggested by Peter Pentchev.
* Update CVS to Subversion reference to upstream source code in
  debian/copyright.
* Remove unused lib variable from debian/rules.
* Use dpkg-buildflags to set CPPFLAGS, CFLAGS and LDFLAGS.
  Based on a patch by Peter Pentchev.
* Remove bogus reference to BSD license in /usr/share/common-licenses.
* Always set -I../../sys, even on GNU/kFreeBSD systems.

[ Peter Pentchev ]
* Remove duplicate section “utils” from ufsutils binary package.
* Remove XC- prefix from Package-Type.
* Honour CPPFLAGS and LDFLAGS and do not link with CFLAGS.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      $NetBSD: fsdbutil.c,v 1.2 1995/10/08 23:18:12 thorpej Exp $     */
 
2
 
 
3
/*
 
4
 *  Copyright (c) 1995 John T. Kohl
 
5
 *  All rights reserved.
 
6
 * 
 
7
 *  Redistribution and use in source and binary forms, with or without
 
8
 *  modification, are permitted provided that the following conditions
 
9
 *  are met:
 
10
 *  1. Redistributions of source code must retain the above copyright
 
11
 *     notice, this list of conditions and the following disclaimer.
 
12
 *  2. Redistributions in binary form must reproduce the above copyright
 
13
 *     notice, this list of conditions and the following disclaimer in the
 
14
 *     documentation and/or other materials provided with the distribution.
 
15
 *  3. The name of the author may not be used to endorse or promote products
 
16
 *     derived from this software without specific prior written permission.
 
17
 * 
 
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
 
19
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
20
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
21
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 
22
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
23
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
24
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
26
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 
27
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
28
 * POSSIBILITY OF SUCH DAMAGE.
 
29
 */
 
30
 
 
31
#ifndef lint
 
32
static const char rcsid[] =
 
33
  "$FreeBSD$";
 
34
#endif /* not lint */
 
35
 
 
36
#include <sys/param.h>
 
37
#include <ctype.h>
 
38
#include <err.h>
 
39
#include <grp.h>
 
40
#include <pwd.h>
 
41
#include <stdint.h>
 
42
#include <string.h>
 
43
#include <time.h>
 
44
 
 
45
#include <ufs/ufs/dinode.h>
 
46
#include <ufs/ffs/fs.h>
 
47
 
 
48
#include <sys/ioctl.h>
 
49
 
 
50
#include "fsdb.h"
 
51
#include "fsck.h"
 
52
 
 
53
static inline time_t
 
54
_time64_to_time(int64_t t64)
 
55
{
 
56
    return((time_t)t64);
 
57
}
 
58
    
 
59
static inline time_t
 
60
_time32_to_time(int32_t t32)
 
61
{
 
62
    return((time_t)t32);
 
63
}
 
64
    
 
65
static int charsperline(void);
 
66
static int printindir(ufs2_daddr_t blk, int level, char *bufp);
 
67
static void printblocks(ino_t inum, union dinode *dp);
 
68
 
 
69
char **
 
70
crack(char *line, int *argc)
 
71
{
 
72
    static char *argv[8];
 
73
    int i;
 
74
    char *p, *val;
 
75
    for (p = line, i = 0; p != NULL && i < 8; i++) {
 
76
        while ((val = strsep(&p, " \t\n")) != NULL && *val == '\0')
 
77
            /**/;
 
78
        if (val)
 
79
            argv[i] = val;
 
80
        else
 
81
            break;
 
82
    }
 
83
    *argc = i;
 
84
    return argv;
 
85
}
 
86
 
 
87
char **
 
88
recrack(char *line, int *argc, int argc_max)
 
89
{
 
90
    static char *argv[8];
 
91
    int i;
 
92
    char *p, *val;
 
93
    for (p = line, i = 0; p != NULL && i < 8 && i < argc_max - 1; i++) {
 
94
        while ((val = strsep(&p, " \t\n")) != NULL && *val == '\0')
 
95
            /**/;
 
96
        if (val)
 
97
            argv[i] = val;
 
98
        else
 
99
            break;
 
100
    }
 
101
    argv[i] = argv[i - 1] + strlen(argv[i - 1]) + 1;
 
102
    argv[i][strcspn(argv[i], "\n")] = '\0';
 
103
    *argc = i + 1;
 
104
    return argv;
 
105
}
 
106
 
 
107
int
 
108
argcount(struct cmdtable *cmdp, int argc, char *argv[])
 
109
{
 
110
    if (cmdp->minargc == cmdp->maxargc)
 
111
        warnx("command `%s' takes %u arguments, got %u", cmdp->cmd,
 
112
            cmdp->minargc-1, argc-1);
 
113
    else
 
114
        warnx("command `%s' takes from %u to %u arguments",
 
115
              cmdp->cmd, cmdp->minargc-1, cmdp->maxargc-1);
 
116
            
 
117
    warnx("usage: %s: %s", cmdp->cmd, cmdp->helptxt);
 
118
    return 1;
 
119
}
 
120
 
 
121
void
 
122
printstat(const char *cp, ino_t inum, union dinode *dp)
 
123
{
 
124
    struct group *grp;
 
125
    struct passwd *pw;
 
126
    ufs2_daddr_t blocks;
 
127
    int64_t gen;
 
128
    char *p;
 
129
    time_t t;
 
130
 
 
131
    printf("%s: ", cp);
 
132
    switch (DIP(dp, di_mode) & IFMT) {
 
133
    case IFDIR:
 
134
        puts("directory");
 
135
        break;
 
136
    case IFREG:
 
137
        puts("regular file");
 
138
        break;
 
139
    case IFBLK:
 
140
        printf("block special (%d,%d)",
 
141
               major(DIP(dp, di_rdev)), minor(DIP(dp, di_rdev)));
 
142
        break;
 
143
    case IFCHR:
 
144
        printf("character special (%d,%d)",
 
145
               major(DIP(dp, di_rdev)), minor(DIP(dp, di_rdev)));
 
146
        break;
 
147
    case IFLNK:
 
148
        fputs("symlink",stdout);
 
149
        if (DIP(dp, di_size) > 0 &&
 
150
            DIP(dp, di_size) < sblock.fs_maxsymlinklen &&
 
151
            DIP(dp, di_blocks) == 0) {
 
152
            if (sblock.fs_magic == FS_UFS1_MAGIC)
 
153
                p = (caddr_t)dp->dp1.di_db;
 
154
            else
 
155
                p = (caddr_t)dp->dp2.di_db;
 
156
            printf(" to `%.*s'\n", (int) DIP(dp, di_size), p);
 
157
        } else {
 
158
            putchar('\n');
 
159
        }
 
160
        break;
 
161
    case IFSOCK:
 
162
        puts("socket");
 
163
        break;
 
164
    case IFIFO:
 
165
        puts("fifo");
 
166
        break;
 
167
    }
 
168
    printf("I=%lu MODE=%o SIZE=%ju", (u_long)inum, DIP(dp, di_mode),
 
169
        (uintmax_t)DIP(dp, di_size));
 
170
    if (sblock.fs_magic != FS_UFS1_MAGIC) {
 
171
        t = _time64_to_time(dp->dp2.di_birthtime);
 
172
        p = ctime(&t);
 
173
        printf("\n\tBTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
 
174
           dp->dp2.di_birthnsec);
 
175
    }
 
176
    if (sblock.fs_magic == FS_UFS1_MAGIC)
 
177
        t = _time32_to_time(dp->dp1.di_mtime);
 
178
    else
 
179
        t = _time64_to_time(dp->dp2.di_mtime);
 
180
    p = ctime(&t);
 
181
    printf("\n\tMTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
 
182
           DIP(dp, di_mtimensec));
 
183
    if (sblock.fs_magic == FS_UFS1_MAGIC)
 
184
        t = _time32_to_time(dp->dp1.di_ctime);
 
185
    else
 
186
        t = _time64_to_time(dp->dp2.di_ctime);
 
187
    p = ctime(&t);
 
188
    printf("\n\tCTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
 
189
           DIP(dp, di_ctimensec));
 
190
    if (sblock.fs_magic == FS_UFS1_MAGIC)
 
191
        t = _time32_to_time(dp->dp1.di_atime);
 
192
    else
 
193
        t = _time64_to_time(dp->dp2.di_atime);
 
194
    p = ctime(&t);
 
195
    printf("\n\tATIME=%15.15s %4.4s [%d nsec]\n", &p[4], &p[20],
 
196
           DIP(dp, di_atimensec));
 
197
 
 
198
    if ((pw = getpwuid(DIP(dp, di_uid))))
 
199
        printf("OWNER=%s ", pw->pw_name);
 
200
    else
 
201
        printf("OWNUID=%u ", DIP(dp, di_uid));
 
202
    if ((grp = getgrgid(DIP(dp, di_gid))))
 
203
        printf("GRP=%s ", grp->gr_name);
 
204
    else
 
205
        printf("GID=%u ", DIP(dp, di_gid));
 
206
 
 
207
    blocks = DIP(dp, di_blocks);
 
208
    gen = DIP(dp, di_gen);
 
209
    printf("LINKCNT=%hd FLAGS=%#x BLKCNT=%jx GEN=%jx\n", DIP(dp, di_nlink),
 
210
        DIP(dp, di_flags), (intmax_t)blocks, (intmax_t)gen);
 
211
}
 
212
 
 
213
 
 
214
/*
 
215
 * Determine the number of characters in a
 
216
 * single line.
 
217
 */
 
218
 
 
219
static int
 
220
charsperline(void)
 
221
{
 
222
        int columns;
 
223
        char *cp;
 
224
        struct winsize ws;
 
225
 
 
226
        columns = 0;
 
227
        if (ioctl(0, TIOCGWINSZ, &ws) != -1)
 
228
                columns = ws.ws_col;
 
229
        if (columns == 0 && (cp = getenv("COLUMNS")))
 
230
                columns = atoi(cp);
 
231
        if (columns == 0)
 
232
                columns = 80;   /* last resort */
 
233
        return (columns);
 
234
}
 
235
 
 
236
 
 
237
/*
 
238
 * Recursively print a list of indirect blocks.
 
239
 */
 
240
static int
 
241
printindir(ufs2_daddr_t blk, int level, char *bufp)
 
242
{
 
243
    struct bufarea buf, *bp;
 
244
    char tempbuf[32];           /* enough to print an ufs2_daddr_t */
 
245
    int i, j, cpl, charssofar;
 
246
    ufs2_daddr_t blkno;
 
247
 
 
248
    if (level == 0) {
 
249
        /* for the final indirect level, don't use the cache */
 
250
        bp = &buf;
 
251
        bp->b_un.b_buf = bufp;
 
252
        bp->b_prev = bp->b_next = bp;
 
253
        initbarea(bp);
 
254
 
 
255
        getblk(bp, blk, sblock.fs_bsize);
 
256
    } else
 
257
        bp = getdatablk(blk, sblock.fs_bsize);
 
258
 
 
259
    cpl = charsperline();
 
260
    for (i = charssofar = 0; i < NINDIR(&sblock); i++) {
 
261
        if (sblock.fs_magic == FS_UFS1_MAGIC)
 
262
                blkno = bp->b_un.b_indir1[i];
 
263
        else
 
264
                blkno = bp->b_un.b_indir2[i];
 
265
        if (blkno == 0) {
 
266
            if (level == 0)
 
267
                putchar('\n');
 
268
            return 0;
 
269
        }
 
270
        j = sprintf(tempbuf, "%jd", (intmax_t)blkno);
 
271
        if (level == 0) {
 
272
            charssofar += j;
 
273
            if (charssofar >= cpl - 2) {
 
274
                putchar('\n');
 
275
                charssofar = j;
 
276
            }
 
277
        }
 
278
        fputs(tempbuf, stdout);
 
279
        if (level == 0) {
 
280
            printf(", ");
 
281
            charssofar += 2;
 
282
        } else {
 
283
            printf(" =>\n");
 
284
            if (printindir(blkno, level - 1, bufp) == 0)
 
285
                return 0;
 
286
        }
 
287
    }
 
288
    if (level == 0)
 
289
        putchar('\n');
 
290
    return 1;
 
291
}
 
292
 
 
293
 
 
294
/*
 
295
 * Print the block pointers for one inode.
 
296
 */
 
297
static void
 
298
printblocks(ino_t inum, union dinode *dp)
 
299
{
 
300
    char *bufp;
 
301
    int i, nfrags;
 
302
    long ndb, offset;
 
303
    ufs2_daddr_t blkno;
 
304
 
 
305
    printf("Blocks for inode %d:\n", inum);
 
306
    printf("Direct blocks:\n");
 
307
    ndb = howmany(DIP(dp, di_size), sblock.fs_bsize);
 
308
    for (i = 0; i < NDADDR; i++) {
 
309
        if (DIP(dp, di_db[i]) == 0) {
 
310
            putchar('\n');
 
311
            return;
 
312
        }
 
313
        if (i > 0)
 
314
            printf(", ");
 
315
        blkno = DIP(dp, di_db[i]);
 
316
        printf("%jd", (intmax_t)blkno);
 
317
        if (--ndb == 0 && (offset = blkoff(&sblock, DIP(dp, di_size))) != 0) {
 
318
            nfrags = numfrags(&sblock, fragroundup(&sblock, offset));
 
319
            printf(" (%d frag%s)", nfrags, nfrags > 1? "s": "");
 
320
        }
 
321
    }
 
322
    putchar('\n');
 
323
    if (DIP(dp, di_ib[0]) == 0)
 
324
        return;
 
325
 
 
326
    bufp = malloc((unsigned int)sblock.fs_bsize);
 
327
    if (bufp == 0)
 
328
        errx(EEXIT, "cannot allocate indirect block buffer");
 
329
    printf("Indirect blocks:\n");
 
330
    for (i = 0; i < NIADDR; i++)
 
331
        if (printindir(DIP(dp, di_ib[i]), i, bufp) == 0)
 
332
            break;
 
333
    free(bufp);
 
334
}
 
335
 
 
336
 
 
337
int
 
338
checkactive(void)
 
339
{
 
340
    if (!curinode) {
 
341
        warnx("no current inode\n");
 
342
        return 0;
 
343
    }
 
344
    return 1;
 
345
}
 
346
 
 
347
int
 
348
checkactivedir(void)
 
349
{
 
350
    if (!curinode) {
 
351
        warnx("no current inode\n");
 
352
        return 0;
 
353
    }
 
354
    if ((DIP(curinode, di_mode) & IFMT) != IFDIR) {
 
355
        warnx("inode %d not a directory", curinum);
 
356
        return 0;
 
357
    }
 
358
    return 1;
 
359
}
 
360
 
 
361
int
 
362
printactive(int doblocks)
 
363
{
 
364
    if (!checkactive())
 
365
        return 1;
 
366
    switch (DIP(curinode, di_mode) & IFMT) {
 
367
    case IFDIR:
 
368
    case IFREG:
 
369
    case IFBLK:
 
370
    case IFCHR:
 
371
    case IFLNK:
 
372
    case IFSOCK:
 
373
    case IFIFO:
 
374
        if (doblocks)
 
375
            printblocks(curinum, curinode);
 
376
        else
 
377
            printstat("current inode", curinum, curinode);
 
378
        break;
 
379
    case 0:
 
380
        printf("current inode %d: unallocated inode\n", curinum);
 
381
        break;
 
382
    default:
 
383
        printf("current inode %d: screwy itype 0%o (mode 0%o)?\n",
 
384
               curinum, DIP(curinode, di_mode) & IFMT, DIP(curinode, di_mode));
 
385
        break;
 
386
    }
 
387
    return 0;
 
388
}