xref: /original-bsd/sys/stand.att/bmap.c (revision bacd16ee)
1 /*-
2  * Copyright (c) 1982, 1988, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  *
7  *	@(#)bmap.c	8.1 (Berkeley) 06/11/93
8  */
9 
10 #include <sys/param.h>
11 #include <stand.att/saio.h>
12 
13 #define	NBUFS	4
14 static char	b[NBUFS][MAXBSIZE];
15 static daddr_t	blknos[NBUFS];
16 
17 daddr_t
18 bmap(io, bn)
19 	register struct iob *io;
20 	daddr_t bn;
21 {
22 	register struct dinode *ip;
23 	int i, j, sh;
24 	daddr_t nb, *bap;
25 
26 	ip = &io->i_ino;
27 	if (bn < 0) {
28 		printf("bn negative\n");
29 		return ((daddr_t)0);
30 	}
31 
32 	/* The first NDADDR blocks are direct blocks. */
33 	if(bn < NDADDR) {
34 		nb = ip->di_db[bn];
35 		return (nb);
36 	}
37 
38 	/* Determine the number of levels of indirection. */
39 	sh = 1;
40 	bn -= NDADDR;
41 	for (j = NIADDR; j > 0; j--) {
42 		sh *= NINDIR(&io->i_fs);
43 		if (bn < sh)
44 			break;
45 		bn -= sh;
46 	}
47 	if (j == 0) {
48 		printf("bn ovf %ld\n", bn);
49 		return ((daddr_t)0);
50 	}
51 
52 	/* Get the first indirect block address. */
53 	nb = ip->di_ib[NIADDR - j];
54 	if (nb == 0) {
55 		printf("bn void %ld\n",bn);
56 		return ((daddr_t)0);
57 	}
58 
59 	/* Get the indirect blocks. */
60 	for (; j <= NIADDR; j++) {
61 		if (blknos[j] != nb) {
62 			io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
63 			io->i_ma = b[j];
64 			io->i_cc = io->i_fs.fs_bsize;
65 			if (devread(io) != io->i_fs.fs_bsize) {
66 				if (io->i_error)
67 					errno = io->i_error;
68 				printf("bn %ld: read error\n", io->i_bn);
69 				return ((daddr_t)0);
70 			}
71 			blknos[j] = nb;
72 		}
73 		bap = (daddr_t *)b[j];
74 		sh /= NINDIR(&io->i_fs);
75 		i = (bn / sh) % NINDIR(&io->i_fs);
76 		nb = bap[i];
77 		if(nb == 0) {
78 			printf("bn void %ld\n",bn);
79 			return ((daddr_t)0);
80 		}
81 	}
82 	return (nb);
83 }
84