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