]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/diag/prtblknos/prtblknos.c
Import riscv DTS files
[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  * $FreeBSD$
27  */
28
29 #include <sys/param.h>
30 #include <ufs/ffs/fs.h>
31
32 #include <err.h>
33 #include <stdio.h>
34 #include <libufs.h>
35
36 union dinode {
37         struct ufs1_dinode dp1;
38         struct ufs2_dinode dp2;
39 };
40
41 void prtblknos(struct uufsd *disk, union dinode *dp);
42
43 static const char *distance(struct fs *, ufs2_daddr_t, ufs2_daddr_t);
44 static void  printblk(struct fs *, ufs_lbn_t, ufs2_daddr_t, int, ufs_lbn_t);
45 static void  indirprt(struct uufsd *, int, ufs_lbn_t, ufs_lbn_t, ufs2_daddr_t,
46                 ufs_lbn_t);
47
48 void
49 prtblknos(disk, dp)
50         struct uufsd *disk;
51         union dinode *dp;
52 {
53         int i, mode, frags;
54         ufs_lbn_t lbn, lastlbn, len, blksperindir;
55         ufs2_daddr_t blkno;
56         struct fs *fs;
57         off_t size;
58
59         fs = (struct fs *)&disk->d_sb;
60         if (fs->fs_magic == FS_UFS1_MAGIC) {
61                 size = dp->dp1.di_size;
62                 mode = dp->dp1.di_mode;
63         } else {
64                 size = dp->dp2.di_size;
65                 mode = dp->dp2.di_mode;
66         }
67         switch (mode & IFMT) {
68         default:
69                 printf("unknown inode type 0%d\n", (mode & IFMT));
70                 return;
71         case 0:
72                 printf("unallocated inode\n");
73                 return;
74         case IFIFO:
75                 printf("fifo\n");
76                 return;
77         case IFCHR:
78                 printf("character device\n");
79                 return;
80         case IFBLK:
81                 printf("block device\n");
82                 return;
83         case IFSOCK:
84                 printf("socket\n");
85                 return;
86         case IFWHT:
87                 printf("whiteout\n");
88                 return;
89         case IFLNK:
90                 if (size == 0) {
91                         printf("empty symbolic link\n");
92                         return;
93                 }
94                 if (size < fs->fs_maxsymlinklen) {
95                         printf("symbolic link referencing %s\n",
96                             (fs->fs_magic == FS_UFS1_MAGIC) ?
97                             (char *)dp->dp1.di_db :
98                             (char *)dp->dp2.di_db);
99                         return;
100                 }
101                 printf("symbolic link\n");
102                 break;
103         case IFREG:
104                 if (size == 0) {
105                         printf("empty file\n");
106                         return;
107                 }
108                 printf("regular file, size %jd\n", (intmax_t)size);
109                 break;
110         case IFDIR:
111                 if (size == 0) {
112                         printf("empty directory\n");
113                         return;
114                 }
115                 printf("directory, size %jd\n", (intmax_t)size);
116                 break;
117         }
118         lastlbn = howmany(size, fs->fs_bsize);
119         len = lastlbn < UFS_NDADDR ? lastlbn : UFS_NDADDR;
120         for (i = 0; i < len; i++) {
121                 if (i < lastlbn - 1)
122                         frags = fs->fs_frag;
123                 else
124                         frags = howmany(size - (lastlbn - 1) * fs->fs_bsize,
125                                           fs->fs_fsize);
126                 if (fs->fs_magic == FS_UFS1_MAGIC)
127                         blkno = dp->dp1.di_db[i];
128                 else
129                         blkno = dp->dp2.di_db[i];
130                 printblk(fs, i, blkno, frags, lastlbn);
131         }
132
133         blksperindir = 1;
134         len = lastlbn - UFS_NDADDR;
135         lbn = UFS_NDADDR;
136         for (i = 0; len > 0 && i < UFS_NIADDR; i++) {
137                 if (fs->fs_magic == FS_UFS1_MAGIC)
138                         blkno = dp->dp1.di_ib[i];
139                 else
140                         blkno = dp->dp2.di_ib[i];
141                 indirprt(disk, i, blksperindir, lbn, blkno, lastlbn);
142                 blksperindir *= NINDIR(fs);
143                 lbn += blksperindir;
144                 len -= blksperindir;
145         }
146
147         /* dummy print to flush out last extent */
148         printblk(fs, lastlbn, 0, frags, 0);
149 }
150
151 static void
152 indirprt(disk, level, blksperindir, lbn, blkno, lastlbn)
153         struct uufsd *disk;
154         int level;
155         ufs_lbn_t blksperindir;
156         ufs_lbn_t lbn;
157         ufs2_daddr_t blkno;
158         ufs_lbn_t lastlbn;
159 {
160         char indir[MAXBSIZE];
161         struct fs *fs;
162         ufs_lbn_t i, last;
163
164         fs = (struct fs *)&disk->d_sb;
165         if (blkno == 0) {
166                 printblk(fs, lbn, blkno,
167                     blksperindir * NINDIR(fs) * fs->fs_frag, lastlbn);
168                 return;
169         }
170         printblk(fs, lbn, blkno, fs->fs_frag, -level);
171         /* read in the indirect block. */
172         if (bread(disk, fsbtodb(fs, blkno), indir, fs->fs_bsize) == -1) {
173                 warn("Read of indirect block %jd failed", (intmax_t)blkno);
174                 /* List the unreadable part as a hole */
175                 printblk(fs, lbn, 0,
176                     blksperindir * NINDIR(fs) * fs->fs_frag, lastlbn);
177                 return;
178         }
179         last = howmany(lastlbn - lbn, blksperindir) < NINDIR(fs) ?
180             howmany(lastlbn - lbn, blksperindir) : NINDIR(fs);
181         if (blksperindir == 1) {
182                 for (i = 0; i < last; i++) {
183                         if (fs->fs_magic == FS_UFS1_MAGIC)
184                                 blkno = ((ufs1_daddr_t *)indir)[i];
185                         else
186                                 blkno = ((ufs2_daddr_t *)indir)[i];
187                         printblk(fs, lbn + i, blkno, fs->fs_frag, lastlbn);
188                 }
189                 return;
190         }
191         for (i = 0; i < last; i++) {
192                 if (fs->fs_magic == FS_UFS1_MAGIC)
193                         blkno = ((ufs1_daddr_t *)indir)[i];
194                 else
195                         blkno = ((ufs2_daddr_t *)indir)[i];
196                 indirprt(disk, level - 1, blksperindir / NINDIR(fs),
197                     lbn + blksperindir * i, blkno, lastlbn);
198         }
199 }
200
201 static const char *
202 distance(fs, lastblk, firstblk)
203         struct fs *fs;
204         ufs2_daddr_t lastblk;
205         ufs2_daddr_t firstblk;
206 {
207         ufs2_daddr_t delta;
208         int firstcg, lastcg;
209         static char buf[100];
210
211         if (lastblk == 0)
212                 return ("");
213         delta = firstblk - lastblk - 1;
214         firstcg = dtog(fs, firstblk);
215         lastcg = dtog(fs, lastblk);
216         if (firstcg == lastcg) {
217                 snprintf(buf, 100, " distance %jd", (intmax_t)delta);
218                 return (&buf[0]);
219         }
220         snprintf(buf, 100, " cg %d blk %jd to cg %d blk %jd",
221             lastcg, (intmax_t)dtogd(fs, lastblk), firstcg,
222             (intmax_t)dtogd(fs, firstblk));
223         return (&buf[0]);
224 }
225         
226
227 static const char *indirname[UFS_NIADDR] = { "First", "Second", "Third" };
228
229 static void
230 printblk(fs, lbn, blkno, numfrags, lastlbn)
231         struct fs *fs;
232         ufs_lbn_t lbn;
233         ufs2_daddr_t blkno;
234         int numfrags;
235         ufs_lbn_t lastlbn;
236 {
237         static int seq;
238         static ufs2_daddr_t totfrags, lastindirblk, lastblk, firstblk;
239
240         if (lastlbn <= 0)
241                 goto flush;
242         if (seq == 0) {
243                 seq = howmany(numfrags, fs->fs_frag);
244                 totfrags = numfrags;
245                 firstblk = blkno;
246                 return;
247         }
248         if (lbn == 0) {
249                 seq = howmany(numfrags, fs->fs_frag);
250                 totfrags = numfrags;
251                 lastblk = 0;
252                 firstblk = blkno;
253                 lastindirblk = 0;
254                 return;
255         }
256         if (lbn < lastlbn && ((firstblk == 0 && blkno == 0) ||
257             (firstblk == BLK_NOCOPY && blkno == BLK_NOCOPY) ||
258             (firstblk == BLK_SNAP && blkno == BLK_SNAP) ||
259             blkno == firstblk + seq * fs->fs_frag)) {
260                 seq += howmany(numfrags, fs->fs_frag);
261                 totfrags += numfrags;
262                 return;
263         }
264 flush:
265         if (seq == 0)
266                 goto prtindir;
267         if (firstblk <= BLK_SNAP) {
268                 if (seq == 1)
269                         printf("\tlbn %jd %s\n", (intmax_t)(lbn - seq),
270                             firstblk == 0 ? "hole" :
271                             firstblk == BLK_NOCOPY ? "nocopy" :
272                             "snapblk");
273                 else
274                         printf("\tlbn %jd-%jd %s\n",
275                             (intmax_t)lbn - seq, (intmax_t)lbn - 1,
276                             firstblk == 0 ? "hole" :
277                             firstblk == BLK_NOCOPY ? "nocopy" :
278                             "snapblk");
279         } else if (seq == 1) {
280                 if (totfrags == 1)
281                         printf("\tlbn %jd blkno %jd%s\n", (intmax_t)(lbn - seq),
282                            (intmax_t)firstblk, distance(fs, lastblk, firstblk));
283                 else
284                         printf("\tlbn %jd blkno %jd-%jd%s\n",
285                             (intmax_t)(lbn - seq), (intmax_t)firstblk,
286                             (intmax_t)(firstblk + totfrags - 1),
287                             distance(fs, lastblk, firstblk));
288                 lastblk = firstblk + totfrags - 1;
289         } else {
290                 printf("\tlbn %jd-%jd blkno %jd-%jd%s\n", (intmax_t)(lbn - seq),
291                     (intmax_t)(lbn - 1), (intmax_t)firstblk,
292                     (intmax_t)(firstblk + totfrags - 1),
293                     distance(fs, lastblk, firstblk));
294                 lastblk = firstblk + totfrags - 1;
295         }
296         if (lastlbn > 0 || blkno == 0) {
297                 seq = 1;
298                 totfrags = numfrags;
299                 firstblk = blkno;
300                 return;
301         }
302 prtindir:
303         if (seq != 0 && (fs->fs_metaspace == 0 || lastindirblk == 0))
304                 lastindirblk = lastblk;
305         printf("%s-level indirect, blkno %jd-%jd%s\n", indirname[-lastlbn],
306             (intmax_t)blkno, (intmax_t)(blkno + numfrags - 1),
307             distance(fs, lastindirblk, blkno));
308         lastindirblk = blkno + numfrags - 1;
309         if (fs->fs_metaspace == 0)
310                 lastblk = lastindirblk;
311         seq = 0;
312 }