Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sbin/dumpfs/dumpfs.c
39481 views
1
/*
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 2009 Robert N. M. Watson
5
* All rights reserved.
6
*
7
* This software was developed at the University of Cambridge Computer
8
* Laboratory with support from a grant from Google, Inc.
9
*
10
* Copyright (c) 2002 Networks Associates Technology, Inc.
11
* All rights reserved.
12
*
13
* This software was developed for the FreeBSD Project by Marshall
14
* Kirk McKusick and Network Associates Laboratories, the Security
15
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
16
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
17
* research program.
18
*
19
* Copyright (c) 1983, 1992, 1993
20
* The Regents of the University of California. All rights reserved.
21
*
22
* Redistribution and use in source and binary forms, with or without
23
* modification, are permitted provided that the following conditions
24
* are met:
25
* 1. Redistributions of source code must retain the above copyright
26
* notice, this list of conditions and the following disclaimer.
27
* 2. Redistributions in binary form must reproduce the above copyright
28
* notice, this list of conditions and the following disclaimer in the
29
* documentation and/or other materials provided with the distribution.
30
* 3. Neither the name of the University nor the names of its contributors
31
* may be used to endorse or promote products derived from this software
32
* without specific prior written permission.
33
*
34
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
35
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44
* SUCH DAMAGE.
45
*/
46
47
#include <sys/param.h>
48
#include <sys/time.h>
49
#include <sys/disklabel.h>
50
51
#include <ufs/ufs/dinode.h>
52
#include <ufs/ffs/fs.h>
53
54
#include <err.h>
55
#include <errno.h>
56
#include <fcntl.h>
57
#include <fstab.h>
58
#include <libufs.h>
59
#include <paths.h>
60
#include <stdint.h>
61
#include <stdio.h>
62
#include <stdlib.h>
63
#include <string.h>
64
#include <unistd.h>
65
66
#define afs disk.d_fs
67
#define acg disk.d_cg
68
69
static struct uufsd disk;
70
71
static int dumpfs(const char *, int);
72
static int dumpfsid(void);
73
static int dumpcg(void);
74
static int dumpfreespace(const char *, int);
75
static void dumpfreespacecg(int);
76
static int marshal(const char *);
77
static void pbits(void *, int);
78
static void pblklist(void *, int, off_t, int);
79
static const char *ufserr(void);
80
static void usage(void) __dead2;
81
82
int
83
main(int argc, char *argv[])
84
{
85
const char *name;
86
int ch, dofreespace, domarshal, dolabel, dosb, eval;
87
88
dofreespace = domarshal = dolabel = dosb = eval = 0;
89
90
while ((ch = getopt(argc, argv, "lfms")) != -1) {
91
switch (ch) {
92
case 'f':
93
dofreespace++;
94
break;
95
case 'm':
96
domarshal = 1;
97
break;
98
case 'l':
99
dolabel = 1;
100
break;
101
case 's':
102
dosb = 1;
103
break;
104
case '?':
105
default:
106
usage();
107
}
108
}
109
argc -= optind;
110
argv += optind;
111
112
if (argc < 1)
113
usage();
114
if (dofreespace && domarshal)
115
usage();
116
if (dofreespace > 2)
117
usage();
118
119
while ((name = *argv++) != NULL) {
120
if (ufs_disk_fillout_blank(&disk, name) == -1 ||
121
sbfind(&disk, 0) == -1) {
122
printf("\n%s: %s\n", name, ufserr());
123
eval |= 1;
124
continue;
125
}
126
if (dofreespace)
127
eval |= dumpfreespace(name, dofreespace);
128
else if (domarshal)
129
eval |= marshal(name);
130
else if (dolabel)
131
eval |= dumpfsid();
132
else
133
eval |= dumpfs(name, dosb);
134
ufs_disk_close(&disk);
135
}
136
exit(eval);
137
}
138
139
static int
140
dumpfsid(void)
141
{
142
143
printf("%sufsid/%08x%08x\n", _PATH_DEV, afs.fs_id[0], afs.fs_id[1]);
144
return 0;
145
}
146
147
static int
148
dumpfs(const char *name, int dosb)
149
{
150
time_t fstime, fsmtime;
151
int64_t fssize;
152
int32_t fsflags;
153
int i, ret;
154
155
switch (disk.d_ufs) {
156
case 2:
157
fssize = afs.fs_size;
158
fstime = afs.fs_time;
159
fsmtime = afs.fs_mtime;
160
printf("magic\t%x (UFS2)\n", afs.fs_magic);
161
printf("last mounted time\t%s", ctime(&fsmtime));
162
printf("last modified time\t%s", ctime(&fstime));
163
printf("superblock location\t%jd\tid\t[ %08x %08x ]\n",
164
(intmax_t)afs.fs_sblockloc, afs.fs_id[0], afs.fs_id[1]);
165
printf("ncg\t%d\tsize\t%jd\tblocks\t%jd\n",
166
afs.fs_ncg, (intmax_t)fssize, (intmax_t)afs.fs_dsize);
167
break;
168
case 1:
169
fssize = afs.fs_old_size;
170
fstime = afs.fs_old_time;
171
printf("magic\t%x (UFS1)\ttime\t%s",
172
afs.fs_magic, ctime(&fstime));
173
printf("id\t[ %08x %08x ]\n", afs.fs_id[0], afs.fs_id[1]);
174
printf("ncg\t%d\tsize\t%jd\tblocks\t%jd\n",
175
afs.fs_ncg, (intmax_t)fssize, (intmax_t)afs.fs_dsize);
176
break;
177
default:
178
printf("Unknown filesystem type %d\n", disk.d_ufs);
179
return (1);
180
}
181
printf("bsize\t%d\tshift\t%d\tmask\t0x%08x\n",
182
afs.fs_bsize, afs.fs_bshift, afs.fs_bmask);
183
printf("fsize\t%d\tshift\t%d\tmask\t0x%08x\n",
184
afs.fs_fsize, afs.fs_fshift, afs.fs_fmask);
185
printf("frag\t%d\tshift\t%d\tfsbtodb\t%d\n",
186
afs.fs_frag, afs.fs_fragshift, afs.fs_fsbtodb);
187
printf("minfree\t%d%%\toptim\t%s\tsymlinklen %d\n",
188
afs.fs_minfree, afs.fs_optim == FS_OPTSPACE ? "space" : "time",
189
afs.fs_maxsymlinklen);
190
switch (disk.d_ufs) {
191
case 2:
192
printf("%s %d\tmaxbpg\t%d\tmaxcontig %d\tcontigsumsize %d\n",
193
"maxbsize", afs.fs_maxbsize, afs.fs_maxbpg,
194
afs.fs_maxcontig, afs.fs_contigsumsize);
195
printf("nbfree\t%jd\tndir\t%jd\tnifree\t%jd\tnffree\t%jd\n",
196
(intmax_t)afs.fs_cstotal.cs_nbfree,
197
(intmax_t)afs.fs_cstotal.cs_ndir,
198
(intmax_t)afs.fs_cstotal.cs_nifree,
199
(intmax_t)afs.fs_cstotal.cs_nffree);
200
printf("bpg\t%d\tfpg\t%d\tipg\t%d\tunrefs\t%jd\n",
201
afs.fs_fpg / afs.fs_frag, afs.fs_fpg, afs.fs_ipg,
202
(intmax_t)afs.fs_unrefs);
203
printf("nindir\t%d\tinopb\t%d\tmaxfilesize\t%ju\n",
204
afs.fs_nindir, afs.fs_inopb,
205
(uintmax_t)afs.fs_maxfilesize);
206
printf("sbsize\t%d\tcgsize\t%d\tcsaddr\t%jd\tcssize\t%d\n",
207
afs.fs_sbsize, afs.fs_cgsize, (intmax_t)afs.fs_csaddr,
208
afs.fs_cssize);
209
break;
210
case 1:
211
printf("maxbpg\t%d\tmaxcontig %d\tcontigsumsize %d\n",
212
afs.fs_maxbpg, afs.fs_maxcontig, afs.fs_contigsumsize);
213
printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
214
afs.fs_old_cstotal.cs_nbfree, afs.fs_old_cstotal.cs_ndir,
215
afs.fs_old_cstotal.cs_nifree, afs.fs_old_cstotal.cs_nffree);
216
printf("cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n",
217
afs.fs_old_cpg, afs.fs_fpg / afs.fs_frag, afs.fs_fpg,
218
afs.fs_ipg);
219
printf("nindir\t%d\tinopb\t%d\tnspf\t%d\tmaxfilesize\t%ju\n",
220
afs.fs_nindir, afs.fs_inopb, afs.fs_old_nspf,
221
(uintmax_t)afs.fs_maxfilesize);
222
printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n",
223
afs.fs_sbsize, afs.fs_cgsize, afs.fs_old_cgoffset,
224
afs.fs_old_cgmask);
225
printf("csaddr\t%jd\tcssize\t%d\n",
226
(intmax_t)afs.fs_csaddr, afs.fs_cssize);
227
printf("rotdelay %dms\trps\t%d\ttrackskew %d\tinterleave %d\n",
228
afs.fs_old_rotdelay, afs.fs_old_rps, afs.fs_old_trackskew,
229
afs.fs_old_interleave);
230
printf("nsect\t%d\tnpsect\t%d\tspc\t%d\n",
231
afs.fs_old_nsect, afs.fs_old_npsect, afs.fs_old_spc);
232
break;
233
default:
234
printf("Unknown filesystem type %d\n", disk.d_ufs);
235
return (1);
236
}
237
printf("old_cpg\t%d\tsize_cg\t%zu\tCGSIZE\t%zu\n",
238
afs.fs_old_cpg, sizeof(struct cg), CGSIZE(&afs));
239
printf("sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n",
240
afs.fs_sblkno, afs.fs_cblkno, afs.fs_iblkno, afs.fs_dblkno);
241
printf("cgrotor\t%d\tfmod\t%d\tronly\t%d\tclean\t%d\n",
242
afs.fs_cgrotor, afs.fs_fmod, afs.fs_ronly, afs.fs_clean);
243
printf("metaspace %jd\tavgfpdir %d\tavgfilesize %d\n",
244
afs.fs_metaspace, afs.fs_avgfpdir, afs.fs_avgfilesize);
245
printf("flags\t");
246
if (afs.fs_old_flags & FS_FLAGS_UPDATED)
247
fsflags = afs.fs_flags;
248
else
249
fsflags = afs.fs_old_flags;
250
if (fsflags == 0)
251
printf("none");
252
if (fsflags & FS_UNCLEAN)
253
printf("unclean ");
254
if (fsflags & FS_DOSOFTDEP)
255
printf("soft-updates%s ", (fsflags & FS_SUJ) ? "+journal" : "");
256
if (fsflags & FS_NEEDSFSCK)
257
printf("needs-fsck-run ");
258
if (fsflags & FS_INDEXDIRS)
259
printf("indexed-directories ");
260
if (fsflags & FS_ACLS)
261
printf("acls ");
262
if (fsflags & FS_MULTILABEL)
263
printf("multilabel ");
264
if (fsflags & FS_GJOURNAL)
265
printf("gjournal ");
266
if (fsflags & FS_FLAGS_UPDATED)
267
printf("fs_flags-expanded ");
268
if (fsflags & FS_NFS4ACLS)
269
printf("nfsv4acls ");
270
if (fsflags & FS_TRIM)
271
printf("trim ");
272
fsflags &= ~(FS_UNCLEAN | FS_DOSOFTDEP | FS_NEEDSFSCK | FS_METACKHASH |
273
FS_ACLS | FS_MULTILABEL | FS_GJOURNAL | FS_FLAGS_UPDATED |
274
FS_NFS4ACLS | FS_SUJ | FS_TRIM | FS_INDEXDIRS);
275
if (fsflags != 0)
276
printf("unknown-flags (%#x)", fsflags);
277
putchar('\n');
278
if (afs.fs_flags & FS_METACKHASH) {
279
printf("check hashes\t");
280
fsflags = afs.fs_metackhash;
281
if (fsflags == 0)
282
printf("none");
283
if (fsflags & CK_SUPERBLOCK)
284
printf("superblock ");
285
if (fsflags & CK_CYLGRP)
286
printf("cylinder-groups ");
287
if (fsflags & CK_INODE)
288
printf("inodes ");
289
if (fsflags & CK_INDIR)
290
printf("indirect-blocks ");
291
if (fsflags & CK_DIR)
292
printf("directories ");
293
}
294
fsflags &= ~(CK_SUPERBLOCK | CK_CYLGRP | CK_INODE | CK_INDIR | CK_DIR);
295
if (fsflags != 0)
296
printf("unknown flags (%#x)", fsflags);
297
putchar('\n');
298
printf("fsmnt\t%s\n", afs.fs_fsmnt);
299
printf("volname\t%s\tswuid\t%ju\tprovidersize\t%ju\n",
300
afs.fs_volname, (uintmax_t)afs.fs_swuid,
301
(uintmax_t)afs.fs_providersize);
302
printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t");
303
for (i = 0; i < afs.fs_ncg; i++) {
304
struct csum *cs = &afs.fs_cs(&afs, i);
305
if (i && i % 4 == 0)
306
printf("\n\t");
307
printf("(%d,%d,%d,%d) ",
308
cs->cs_nbfree, cs->cs_ndir, cs->cs_nifree, cs->cs_nffree);
309
}
310
printf("\n");
311
if (fssize % afs.fs_fpg) {
312
if (disk.d_ufs == 1)
313
printf("cylinders in last group %d\n",
314
howmany(afs.fs_old_size % afs.fs_fpg,
315
afs.fs_old_spc / afs.fs_old_nspf));
316
printf("blocks in last group %ld\n\n",
317
(long)((fssize % afs.fs_fpg) / afs.fs_frag));
318
}
319
if (dosb)
320
return (0);
321
ret = 0;
322
while ((i = cgread(&disk)) != 0) {
323
if (i == -1) {
324
ret = 1;
325
printf("\ncg %d: %s\n", disk.d_lcg, ufserr());
326
} else if (dumpcg())
327
ret = 1;
328
}
329
return (ret);
330
}
331
332
static int
333
dumpcg(void)
334
{
335
time_t cgtime;
336
off_t cur;
337
int i, j;
338
339
printf("\ncg %d:\n", disk.d_lcg);
340
cur = fsbtodb(&afs, cgtod(&afs, disk.d_lcg)) * disk.d_bsize;
341
switch (disk.d_ufs) {
342
case 2:
343
cgtime = acg.cg_time;
344
printf("magic\t%x\ttell\t%jx\ttime\t%s",
345
acg.cg_magic, (intmax_t)cur, ctime(&cgtime));
346
printf("cgx\t%d\tndblk\t%d\tniblk\t%d\tinitiblk %d\tunrefs %d\n",
347
acg.cg_cgx, acg.cg_ndblk, acg.cg_niblk, acg.cg_initediblk,
348
acg.cg_unrefs);
349
break;
350
case 1:
351
cgtime = acg.cg_old_time;
352
printf("magic\t%x\ttell\t%jx\ttime\t%s",
353
acg.cg_magic, (intmax_t)cur, ctime(&cgtime));
354
printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n",
355
acg.cg_cgx, acg.cg_old_ncyl, acg.cg_old_niblk,
356
acg.cg_ndblk);
357
break;
358
default:
359
break;
360
}
361
printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
362
acg.cg_cs.cs_nbfree, acg.cg_cs.cs_ndir,
363
acg.cg_cs.cs_nifree, acg.cg_cs.cs_nffree);
364
printf("rotor\t%d\tirotor\t%d\tfrotor\t%d\nfrsum",
365
acg.cg_rotor, acg.cg_irotor, acg.cg_frotor);
366
for (i = 1, j = 0; i < afs.fs_frag; i++) {
367
printf("\t%d", acg.cg_frsum[i]);
368
j += i * acg.cg_frsum[i];
369
}
370
printf("\nsum of frsum: %d", j);
371
if (afs.fs_contigsumsize > 0) {
372
for (i = 1; i < afs.fs_contigsumsize; i++) {
373
if ((i - 1) % 8 == 0)
374
printf("\nclusters %d-%d:", i,
375
MIN(afs.fs_contigsumsize - 1, i + 7));
376
printf("\t%d", cg_clustersum(&acg)[i]);
377
}
378
printf("\nclusters size %d and over: %d\n",
379
afs.fs_contigsumsize,
380
cg_clustersum(&acg)[afs.fs_contigsumsize]);
381
printf("clusters free:\t");
382
pbits(cg_clustersfree(&acg), acg.cg_nclusterblks);
383
} else
384
printf("\n");
385
printf("inodes used:\t");
386
pbits(cg_inosused(&acg), afs.fs_ipg);
387
printf("blks free:\t");
388
pbits(cg_blksfree(&acg), afs.fs_fpg);
389
return (0);
390
}
391
392
static int
393
dumpfreespace(const char *name, int fflag)
394
{
395
intmax_t startblkno;
396
int i, ret;
397
398
ret = 0;
399
while ((i = cgread(&disk)) != 0) {
400
if (i != -1) {
401
dumpfreespacecg(fflag);
402
} else {
403
startblkno = disk.d_lcg * afs.fs_fpg;
404
printf("\nBlocks %jd-%jd of cg %d skipped: %s\n",
405
startblkno, startblkno + afs.fs_fpg - 1,
406
disk.d_lcg, ufserr());
407
ret = 1;
408
}
409
}
410
return (ret);
411
}
412
413
static void
414
dumpfreespacecg(int fflag)
415
{
416
417
pblklist(cg_blksfree(&acg), afs.fs_fpg, disk.d_lcg * afs.fs_fpg,
418
fflag);
419
}
420
421
static int
422
marshal(const char *name)
423
{
424
struct fs *fs;
425
426
fs = &disk.d_fs;
427
428
printf("# newfs command for %s (%s)\n", name, disk.d_name);
429
printf("newfs ");
430
if (fs->fs_volname[0] != '\0')
431
printf("-L %s ", fs->fs_volname);
432
printf("-O %d ", disk.d_ufs);
433
if (fs->fs_flags & FS_DOSOFTDEP)
434
printf("-U ");
435
printf("-a %d ", fs->fs_maxcontig);
436
printf("-b %d ", fs->fs_bsize);
437
/* -c is dumb */
438
printf("-d %d ", fs->fs_maxbsize);
439
printf("-e %d ", fs->fs_maxbpg);
440
printf("-f %d ", fs->fs_fsize);
441
printf("-g %d ", fs->fs_avgfilesize);
442
printf("-h %d ", fs->fs_avgfpdir);
443
printf("-i %jd ", fragroundup(fs, lblktosize(fs, fragstoblks(fs,
444
fs->fs_fpg)) / fs->fs_ipg));
445
if (fs->fs_flags & FS_SUJ)
446
printf("-j ");
447
if (fs->fs_flags & FS_GJOURNAL)
448
printf("-J ");
449
printf("-k %jd ", fs->fs_metaspace);
450
if (fs->fs_flags & FS_MULTILABEL)
451
printf("-l ");
452
printf("-m %d ", fs->fs_minfree);
453
/* -n unimplemented */
454
printf("-o ");
455
switch (fs->fs_optim) {
456
case FS_OPTSPACE:
457
printf("space ");
458
break;
459
case FS_OPTTIME:
460
printf("time ");
461
break;
462
default:
463
printf("unknown ");
464
break;
465
}
466
/* -p..r unimplemented */
467
printf("-s %jd ", (intmax_t)fsbtodb(fs, fs->fs_size));
468
if (fs->fs_flags & FS_TRIM)
469
printf("-t ");
470
printf("%s ", disk.d_name);
471
printf("\n");
472
473
return 0;
474
}
475
476
static void
477
pbits(void *vp, int max)
478
{
479
int i;
480
char *p;
481
int count, j;
482
483
for (count = i = 0, p = vp; i < max; i++)
484
if (isset(p, i)) {
485
if (count)
486
printf(",%s", count % 6 ? " " : "\n\t");
487
count++;
488
printf("%d", i);
489
j = i;
490
while ((i+1)<max && isset(p, i+1))
491
i++;
492
if (i != j)
493
printf("-%d", i);
494
}
495
printf("\n");
496
}
497
498
static void
499
pblklist(void *vp, int max, off_t offset, int fflag)
500
{
501
int i, j;
502
char *p;
503
504
for (i = 0, p = vp; i < max; i++) {
505
if (isset(p, i)) {
506
printf("%jd", (intmax_t)(i + offset));
507
if (fflag < 2) {
508
j = i;
509
while ((i+1)<max && isset(p, i+1))
510
i++;
511
if (i != j)
512
printf("-%jd", (intmax_t)(i + offset));
513
}
514
printf("\n");
515
}
516
}
517
}
518
519
static const char *
520
ufserr(void)
521
{
522
if (disk.d_error != NULL)
523
return(disk.d_error);
524
if (errno)
525
return (strerror(errno));
526
return ("unknown error");
527
}
528
529
static void
530
usage(void)
531
{
532
(void)fprintf(stderr, "usage: dumpfs [-flm] filesys | device\n");
533
exit(1);
534
}
535
536