]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/diag/prtblknos/prtblknos.c
Remove $FreeBSD$: two-line .h pattern
[FreeBSD/FreeBSD.git] / tools / diag / prtblknos / prtblknos.c
1 /*
2  * Copyright (c) 1998, 2003, 2013, 2018 Marshall Kirk McKusick.
3  * All Rights Reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY MARSHALL KIRK MCKUSICK ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL MARSHALL KIRK MCKUSICK BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/param.h>
28 #include <ufs/ffs/fs.h>
29
30 #include <err.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <libufs.h>
34
35 #ifdef PRTBLKNOS
36 union dinode {
37         struct ufs1_dinode dp1;
38         struct ufs2_dinode dp2;
39 };
40 extern struct uufsd disk;
41 #else /* used by fsdb */
42 #include <fsck.h>
43 static struct bufarea *bp;
44 #endif
45
46 void prtblknos(struct fs *fs, union dinode *dp);
47
48 static const char *distance(struct fs *, ufs2_daddr_t, ufs2_daddr_t);
49 static void  printblk(struct fs *, ufs_lbn_t, ufs2_daddr_t, int, ufs_lbn_t);
50 static void  indirprt(struct fs *, int, ufs_lbn_t, ufs_lbn_t, ufs2_daddr_t,
51                 ufs_lbn_t);
52
53 void
54 prtblknos(struct fs *fs, union dinode *dp)
55 {
56         int i, mode, frags;
57         ufs_lbn_t lbn, lastlbn, len, blksperindir;
58         ufs2_daddr_t blkno;
59         off_t size;
60
61         if (fs->fs_magic == FS_UFS1_MAGIC) {
62                 size = dp->dp1.di_size;
63                 mode = dp->dp1.di_mode;
64         } else {
65                 size = dp->dp2.di_size;
66                 mode = dp->dp2.di_mode;
67         }
68         switch (mode & IFMT) {
69         default:
70                 printf("unknown inode type 0%d\n", (mode & IFMT));
71                 return;
72         case 0:
73                 printf("unallocated inode\n");
74                 return;
75         case IFIFO:
76                 printf("fifo\n");
77                 return;
78         case IFCHR:
79                 printf("character device\n");
80                 return;
81         case IFBLK:
82                 printf("block device\n");
83                 return;
84         case IFSOCK:
85                 printf("socket\n");
86                 return;
87         case IFWHT:
88                 printf("whiteout\n");
89                 return;
90         case IFLNK:
91                 if (size == 0) {
92                         printf("empty symbolic link\n");
93                         return;
94                 }
95                 if (size < fs->fs_maxsymlinklen) {
96                         printf("symbolic link referencing %s\n",
97                             (fs->fs_magic == FS_UFS1_MAGIC) ?
98                             dp->dp1.di_shortlink :
99                             dp->dp2.di_shortlink);
100                         return;
101                 }
102                 printf("symbolic link\n");
103                 break;
104         case IFREG:
105                 if (size == 0) {
106                         printf("empty file\n");
107                         return;
108                 }
109                 printf("regular file, size %jd\n", (intmax_t)size);
110                 break;
111         case IFDIR:
112                 if (size == 0) {
113                         printf("empty directory\n");
114                         return;
115                 }
116                 printf("directory, size %jd\n", (intmax_t)size);
117                 break;
118         }
119         lastlbn = howmany(size, fs->fs_bsize);
120         len = lastlbn < UFS_NDADDR ? lastlbn : UFS_NDADDR;
121         for (i = 0; i < len; i++) {
122                 if (i < lastlbn - 1)
123                         frags = fs->fs_frag;
124                 else
125                         frags = howmany(size - (lastlbn - 1) * fs->fs_bsize,
126                                           fs->fs_fsize);
127                 if (fs->fs_magic == FS_UFS1_MAGIC)
128                         blkno = dp->dp1.di_db[i];
129                 else
130                         blkno = dp->dp2.di_db[i];
131                 printblk(fs, i, blkno, frags, lastlbn);
132         }
133
134         blksperindir = 1;
135         len = lastlbn - UFS_NDADDR;
136         lbn = UFS_NDADDR;
137         for (i = 0; len > 0 && i < UFS_NIADDR; i++) {
138                 if (fs->fs_magic == FS_UFS1_MAGIC)
139                         blkno = dp->dp1.di_ib[i];
140                 else
141                         blkno = dp->dp2.di_ib[i];
142                 indirprt(fs, i, blksperindir, lbn, blkno, lastlbn);
143                 blksperindir *= NINDIR(fs);
144                 lbn += blksperindir;
145                 len -= blksperindir;
146         }
147
148         /* dummy print to flush out last extent */
149         printblk(fs, lastlbn, 0, frags, 0);
150 }
151
152 static void
153 indirprt(struct fs *fs, int level, ufs_lbn_t blksperindir, ufs_lbn_t lbn,
154         ufs2_daddr_t blkno, ufs_lbn_t lastlbn)
155 {
156         char indir[MAXBSIZE];
157         ufs_lbn_t i, last;
158
159         if (blkno == 0) {
160                 printblk(fs, lbn, blkno,
161                     blksperindir * NINDIR(fs) * fs->fs_frag, lastlbn);
162                 return;
163         }
164         printblk(fs, lbn, blkno, fs->fs_frag, -level);
165         /* read in the indirect block. */
166 #ifdef PRTBLKNOS
167         if (bread(&disk, fsbtodb(fs, blkno), indir, fs->fs_bsize) == -1) {
168 #else /* used by fsdb */
169         bp = getdatablk(blkno, fs->fs_bsize, BT_LEVEL1 + level);
170         if (bp->b_errs == 0) {
171                 memcpy(indir, bp->b_un.b_buf, fs->fs_bsize);
172         } else {
173 #endif
174                 warn("Read of indirect block %jd failed", (intmax_t)blkno);
175                 /* List the unreadable part as a hole */
176                 printblk(fs, lbn, 0,
177                     blksperindir * NINDIR(fs) * fs->fs_frag, lastlbn);
178                 return;
179         }
180         last = howmany(lastlbn - lbn, blksperindir) < NINDIR(fs) ?
181             howmany(lastlbn - lbn, blksperindir) : NINDIR(fs);
182         if (blksperindir == 1) {
183                 for (i = 0; i < last; i++) {
184                         if (fs->fs_magic == FS_UFS1_MAGIC)
185                                 blkno = ((ufs1_daddr_t *)indir)[i];
186                         else
187                                 blkno = ((ufs2_daddr_t *)indir)[i];
188                         printblk(fs, lbn + i, blkno, fs->fs_frag, lastlbn);
189                 }
190                 return;
191         }
192         for (i = 0; i < last; i++) {
193                 if (fs->fs_magic == FS_UFS1_MAGIC)
194                         blkno = ((ufs1_daddr_t *)indir)[i];
195                 else
196                         blkno = ((ufs2_daddr_t *)indir)[i];
197                 indirprt(fs, level - 1, blksperindir / NINDIR(fs),
198                     lbn + blksperindir * i, blkno, lastlbn);
199         }
200 }
201
202 static const char *
203 distance(struct fs *fs, ufs2_daddr_t lastblk, ufs2_daddr_t firstblk)
204 {
205         ufs2_daddr_t delta;
206         int firstcg, lastcg;
207         static char buf[100];
208
209         if (lastblk == 0)
210                 return ("");
211         delta = firstblk - lastblk - 1;
212         firstcg = dtog(fs, firstblk);
213         lastcg = dtog(fs, lastblk);
214         if (firstcg == lastcg) {
215                 snprintf(buf, 100, " distance %jd", (intmax_t)delta);
216                 return (&buf[0]);
217         }
218         snprintf(buf, 100, " cg %d blk %jd to cg %d blk %jd",
219             lastcg, (intmax_t)dtogd(fs, lastblk), firstcg,
220             (intmax_t)dtogd(fs, firstblk));
221         return (&buf[0]);
222 }
223         
224
225 static const char *indirname[UFS_NIADDR] = { "First", "Second", "Third" };
226
227 static void
228 printblk(struct fs *fs, ufs_lbn_t lbn, ufs2_daddr_t blkno, int numfrags,
229         ufs_lbn_t lastlbn)
230 {
231         static int seq;
232         static ufs2_daddr_t totfrags, lastindirblk, lastblk, firstblk;
233
234         if (lastlbn <= 0)
235                 goto flush;
236         if (seq == 0) {
237                 seq = howmany(numfrags, fs->fs_frag);
238                 totfrags = numfrags;
239                 firstblk = blkno;
240                 return;
241         }
242         if (lbn == 0) {
243                 seq = howmany(numfrags, fs->fs_frag);
244                 totfrags = numfrags;
245                 lastblk = 0;
246                 firstblk = blkno;
247                 lastindirblk = 0;
248                 return;
249         }
250         if (lbn < lastlbn && ((firstblk == 0 && blkno == 0) ||
251             (firstblk == BLK_NOCOPY && blkno == BLK_NOCOPY) ||
252             (firstblk == BLK_SNAP && blkno == BLK_SNAP) ||
253             blkno == firstblk + seq * fs->fs_frag)) {
254                 seq += howmany(numfrags, fs->fs_frag);
255                 totfrags += numfrags;
256                 return;
257         }
258 flush:
259         if (seq == 0)
260                 goto prtindir;
261         if (firstblk <= BLK_SNAP) {
262                 if (seq == 1)
263                         printf("\tlbn %jd %s\n", (intmax_t)(lbn - seq),
264                             firstblk == 0 ? "hole" :
265                             firstblk == BLK_NOCOPY ? "nocopy" :
266                             "snapblk");
267                 else
268                         printf("\tlbn %jd-%jd %s\n",
269                             (intmax_t)lbn - seq, (intmax_t)lbn - 1,
270                             firstblk == 0 ? "hole" :
271                             firstblk == BLK_NOCOPY ? "nocopy" :
272                             "snapblk");
273         } else if (seq == 1) {
274                 if (totfrags == 1)
275                         printf("\tlbn %jd blkno %jd%s\n", (intmax_t)(lbn - seq),
276                            (intmax_t)firstblk, distance(fs, lastblk, firstblk));
277                 else
278                         printf("\tlbn %jd blkno %jd-%jd%s\n",
279                             (intmax_t)(lbn - seq), (intmax_t)firstblk,
280                             (intmax_t)(firstblk + totfrags - 1),
281                             distance(fs, lastblk, firstblk));
282                 lastblk = firstblk + totfrags - 1;
283         } else {
284                 printf("\tlbn %jd-%jd blkno %jd-%jd%s\n", (intmax_t)(lbn - seq),
285                     (intmax_t)(lbn - 1), (intmax_t)firstblk,
286                     (intmax_t)(firstblk + totfrags - 1),
287                     distance(fs, lastblk, firstblk));
288                 lastblk = firstblk + totfrags - 1;
289         }
290         if (lastlbn > 0 || blkno == 0) {
291                 seq = 1;
292                 totfrags = numfrags;
293                 firstblk = blkno;
294                 return;
295         }
296 prtindir:
297         if (seq != 0 && (fs->fs_metaspace == 0 || lastindirblk == 0))
298                 lastindirblk = lastblk;
299         printf("%s-level indirect, blkno %jd-%jd%s\n", indirname[-lastlbn],
300             (intmax_t)blkno, (intmax_t)(blkno + numfrags - 1),
301             distance(fs, lastindirblk, blkno));
302         lastindirblk = blkno + numfrags - 1;
303         if (fs->fs_metaspace == 0)
304                 lastblk = lastindirblk;
305         seq = 0;
306 }