- register int i;
- int osize, nsize;
- struct buf *bp, *nbp;
- struct fs *fs;
- int j, sh;
- daddr_t nb, lbn, *bap, pref, blkpref();
+ register struct fs *fs;
+ register daddr_t nb;
+ struct buf *bp;
+ daddr_t *bap;
+ int i, j, sh;
+ int error;
+
+ if (bn < 0)
+ return (EFBIG);
+ fs = ip->i_fs;
+
+ /*
+ * The first NDADDR blocks are direct blocks
+ */
+ if (bn < NDADDR) {
+ nb = ip->i_db[bn];
+ if (nb == 0) {
+ *bnp = (daddr_t)-1;
+ return (0);
+ }
+ if (rablockp && rasizep) {
+ if (bn < NDADDR - 1) {
+ *rablockp = fsbtodb(fs, ip->i_db[bn + 1]);
+ *rasizep = blksize(fs, ip, bn + 1);
+ } else {
+ *rablockp = 0;
+ *rasizep = 0;
+ }
+ }
+ *bnp = fsbtodb(fs, nb);
+ return (0);
+ }
+
+ /*
+ * Determine how many levels of indirection.
+ */
+ sh = 1;
+ bn -= NDADDR;
+ for (j = NIADDR; j > 0; j--) {
+ sh *= NINDIR(fs);
+ if (bn < sh)
+ break;
+ bn -= sh;
+ }
+ if (j == 0)
+ return (EFBIG);
+
+ /*
+ * fetch the first indirect block
+ */
+ nb = ip->i_ib[NIADDR - j];
+ if (nb == 0) {
+ *bnp = (daddr_t)-1;
+ return (0);
+ }
+
+ /*
+ * fetch through the indirect blocks
+ */
+ for (; j <= NIADDR; j++) {
+ if (error = bread(ip->i_devvp, fsbtodb(fs, nb),
+ (int)fs->fs_bsize, &bp)) {
+ brelse(bp);
+ return (error);
+ }
+ bap = bp->b_un.b_daddr;
+ sh /= NINDIR(fs);
+ i = (bn / sh) % NINDIR(fs);
+ nb = bap[i];
+ if (nb == 0) {
+ *bnp = (daddr_t)-1;
+ brelse(bp);
+ return (0);
+ }
+ }