int readit(char *buffer, int count) { int logno, off, size; int cnt2, bnum2; struct fs *fs_copy; int n = 0; if (poff + count > inode.i_size) count = inode.i_size - poff; while (count > 0 && poff < inode.i_size) { fs_copy = fs; off = blkoff(fs_copy, poff); logno = lblkno(fs_copy, poff); cnt2 = size = blksize(fs_copy, &inode, logno); bnum2 = fsbtodb(fs_copy, block_map(logno)) + boff; if ( (!off) && (size <= count)) { devread(buffer, bnum2, cnt2); } else { size -= off; if (size > count) size = count; devread(iobuf, bnum2, cnt2); bcopy(iobuf+off, buffer, size); } buffer += size; count -= size; poff += size; n += size; } return n; }
static int find(char *path) { char *rest, ch; int block, off, loc, ino = ROOTINO; struct dirent *dp; char list_only; list_only = (path[0] == '?' && path[1] == '\0'); loop: devread(iobuf, fsbtodb(fs, ino_to_fsba(fs, ino)) + boff, fs->fs_bsize); bcopy((void *)&((struct dinode *)iobuf)[ino % fs->fs_inopb], (void *)&inode.i_din, sizeof (struct dinode)); if (!*path) return 1; while (*path == '/') path++; if (!inode.i_size || ((inode.i_mode&IFMT) != IFDIR)) return 0; for (rest = path; (ch = *rest) && ch != '/'; rest++) ; *rest = 0; loc = 0; do { if (loc >= inode.i_size) { if (list_only) { putchar('\n'); return -1; } else { return 0; } } if (!(off = blkoff(fs, loc))) { block = lblkno(fs, loc); devread(iobuf, fsbtodb(fs, block_map(block)) + boff, blksize(fs, &inode, block)); } dp = (struct dirent *)(iobuf + off); loc += dp->d_reclen; if (dp->d_fileno && list_only) { puts(dp->d_name); putchar(' '); } } while (!dp->d_fileno || strcmp(path, dp->d_name)); ino = dp->d_fileno; *(path = rest) = ch; goto loop; }
/* * Parse the DOS partition table to set the bounds of the slice we * are writing to. */ int readmbr(int slice) { struct doslabel doslabel; int cc; if (slice < 1 || slice > 4) { fprintf(stderr, "Slice must be 1, 2, 3, or 4\n"); return 1; } if ((cc = devread(outfd, doslabel.pad2, DOSPARTSIZE)) < 0) { perror("Could not read DOS label"); return 1; } if (cc != DOSPARTSIZE) { fprintf(stderr, "Could not get the entire DOS label\n"); return 1; } if (doslabel.magic != BOOT_MAGIC) { fprintf(stderr, "Wrong magic number in DOS partition table\n"); return 1; } outputminsec = doslabel.parts[slice-1].dp_start; outputmaxsec = doslabel.parts[slice-1].dp_start + doslabel.parts[slice-1].dp_size; outputmaxsize = (long long)sectobytes(outputmaxsec - outputminsec); if (debug) { fprintf(stderr, "Slice Mode: S:%d min:%ld max:%ld size:%qd\n", slice, outputminsec, outputmaxsec, outputmaxsize); } return 0; }
static struct dir_entry * vstafs_nextdir (void) { if (current_direntry > 15) { current_direntry = 0; if (++current_blockpos > (a1[curr_ext].a_len - 1)) { current_blockpos = 0; curr_ext++; } if (curr_ext < FILE_INFO->extents) { devread (a1[curr_ext].a_start + current_blockpos, 0, 512, (char *) DIRECTORY_BUF); } else { /* errnum =ERR_FILE_NOT_FOUND; */ return NULL; } } return &DIRECTORY_BUF[current_direntry++]; }
int fwormread(Device *d, Off b, void *c) { Iobuf *p; Device *fdev; Devsize l; if(DEBUG) print("fworm read %lld\n", (Wideoff)b); fdev = FDEV(d); l = devsize(fdev); l -= l/(BUFSIZE*8) + 1; if(b >= l) panic("fworm: rbounds %lld", (Wideoff)b); l += b/(BUFSIZE*8); p = getbuf(fdev, l, Brd|Bres); if(!p || checktag(p, Tvirgo, l)) panic("fworm: checktag %lld", (Wideoff)l); l = b % (BUFSIZE*8); if(!(p->iobuf[l/8] & (1<<(l%8)))) { putbuf(p); print("fworm: read %lld\n", (Wideoff)b); return 1; } putbuf(p); return devread(fdev, b, c); }
static int opendir(ino_t inode, struct iob *io) { struct hs_direct hsdep; uint_t i; int retval; /* Set up the saio request */ io->i_offset = 0; io->i_bn = hdbtodb(inode); io->i_cc = ISO_SECTOR_SIZE; if ((retval = devread(&io->i_si)) != ISO_SECTOR_SIZE) return (0); io->i_offset = 0; io->i_bn = hdbtodb(inode); if (inode != root_ino) return (0); if (parse_dir(io, 0, &hsdep) > 0) { register struct inode *ip = &io->i_ino; bzero(io->i_ino, sizeof (struct inode)); ip->i_size = hsdep.hs_dir.ext_size; ip->i_smode = hsdep.hs_dir.mode; ip->i_number = inode; return (0); } return (1); }
/* * get next entry in a directory. */ static struct hs_direct * readdir(struct dirstuff *dirp) { static struct hs_direct hsdep; register struct direct *udp = &hsdep.hs_ufs_dir; struct inode *ip; struct iob *io; daddr_t lbn, d; int off; io = dirp->io; ip = &io->i_ino; for (;;) { if (dirp->loc >= ip->i_size) { return (NULL); } off = dirp->loc & ((1 << ISO_SECTOR_SHIFT) - 1); if (off == 0) { lbn = hdbtodb(dirp->loc >> ISO_SECTOR_SHIFT); io->i_bn = lbn + hdbtodb(ip->i_number); io->i_ma = io->i_buf; io->i_cc = ISO_SECTOR_SIZE; if (devread(&io->i_si) != io->i_cc) { return (NULL); } } dirp->loc += parse_dir(io, off, &hsdep); if (udp->d_reclen == 0 && dirp->loc <= ip->i_size) { dirp->loc = roundup(dirp->loc, ISO_SECTOR_SIZE); continue; } return (&hsdep); }
int devread(Device *d, Off b, void *c) { int e; for (;;) switch(d->type) { case Devcw: return cwread(d, b, c); case Devjuke: d = d->j.m; break; case Devro: return roread(d, b, c); case Devwren: return wrenread(d, b, c); case Devworm: case Devlworm: return wormread(d, b, c); case Devfworm: return fwormread(d, b, c); case Devmcat: return mcatread(d, b, c); case Devmlev: return mlevread(d, b, c); case Devmirr: return mirrread(d, b, c); case Devpart: return partread(d, b, c); case Devswab: e = devread(d->swab.d, b, c); if(e == 0) swab(c, 0); return e; case Devnone: print("read from device none(%lld)\n", (Wideoff)b); return 1; default: panic("illegal device in devread: %Z %lld", d, (Wideoff)b); return 1; } }
static int block_map(int file_block) { int bnum; if (file_block < NDADDR) return(inode.i_db[file_block]); if ((bnum=fsbtodb(fs, inode.i_ib[0])+boff) != mapblock) { devread(mapbuf, bnum, fs->fs_bsize); mapblock = bnum; } return (((int *)mapbuf)[(file_block - NDADDR) % NINDIR(fs)]); }
int etherrxpkt(int ctlrno, Etherpkt *pkt, int timo) { int n; for (;;) { n = devread(ctlrno, (uchar*)pkt, sizeof(*pkt), 0); if (n >= 0) return n; if (timo-- < 0) return -1; } }
int vstafs_mount (void) { int retval = 1; if( (((current_drive & 0x80) || (current_slice != 0)) && current_slice != PC_SLICE_TYPE_VSTAFS) || ! devread (0, 0, BLOCK_SIZE, (char *) FSYS_BUF) || FIRST_SECTOR->fs_magic != 0xDEADFACE) retval = 0; return retval; }
static int getch(int fdesc) { register struct iob *io; struct fs *fs; char *p; int c, lbn, off, size, diff; if ((io = iob_from_fdesc(fdesc)) == 0) { return (-1); } p = io->i_ma; if (io->i_cc <= 0) { if ((io->i_flgs & F_FILE) != 0) { diff = io->i_ino.i_size - io->i_offset; if (diff <= 0) return (-1); fs = io->i_fs; lbn = lblkno(fs, io->i_offset); io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff; off = blkoff(fs, io->i_offset); size = blksize(fs, &io->i_ino, lbn); } else { diff = 0; #ifndef SMALL io->i_bn = io->i_offset / DEV_BSIZE; off = 0; size = DEV_BSIZE; #endif SMALL } io->i_ma = io->i_buf; io->i_cc = size; if (devread(io) < 0) { return (-1); } if ((io->i_flgs & F_FILE) != 0) { if (io->i_offset - off + size >= io->i_ino.i_size) io->i_cc = diff + off; io->i_cc -= off; } p = &io->i_buf[off]; } io->i_cc--; io->i_offset++; c = (unsigned)*p++; io->i_ma = p; return (c); }
int ffs_mount (void) { int retval = 1; if ((((current_drive & 0x80) || (current_slice != 0)) && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_BSDFFS)) || part_length < (SBLOCK + (SBSIZE / DEV_BSIZE)) || !devread (SBLOCK, 0, SBSIZE, (char *) SUPERBLOCK) || SUPERBLOCK->fs_magic != FS_MAGIC) retval = 0; mapblock = -1; mapblock_offset = -1; return retval; }
static void sbread(int fd, daddr_t poffset, struct fs **fs) { int i; daddr_t sboff; for (i = 0; sbtry[i] != -1; i++) { sboff = sbtry[i] / DEV_BSIZE; devread(fd, sblock, poffset + sboff, SBSIZE, "superblock"); *fs = (struct fs *)sblock; if (sbchk(*fs, sbtry[i])) break; } if (sbtry[i] == -1) errx(1, "couldn't find ffs superblock"); }
static grub_int64_t block_map (int file_block) { int bnum, offset, bsize; if (file_block < NDADDR) return (INODE_UFS2->di_db[file_block]); /* If the blockmap loaded does not include FILE_BLOCK, load a new blockmap. */ if ((bnum = fsbtodb (SUPERBLOCK, INODE_UFS2->di_ib[0])) != mapblock || (mapblock_offset <= bnum && bnum <= mapblock_offset + mapblock_bsize)) { if (MAPBUF_LEN < SUPERBLOCK->fs_bsize) { offset = ((file_block - NDADDR) % NINDIR (SUPERBLOCK)); bsize = MAPBUF_LEN; if (offset + MAPBUF_LEN > SUPERBLOCK->fs_bsize) offset = (SUPERBLOCK->fs_bsize - MAPBUF_LEN) / sizeof (int); } else { bsize = SUPERBLOCK->fs_bsize; offset = 0; } if (! devread (bnum, offset * sizeof (int), bsize, (char *) MAPBUF, 0xedde0d90)) { mapblock = -1; mapblock_bsize = -1; mapblock_offset = -1; errnum = ERR_FSYS_CORRUPT; return -1; } mapblock = bnum; mapblock_bsize = bsize; mapblock_offset = offset; } return (((grub_int64_t *) MAPBUF)[((file_block - NDADDR) % NINDIR (SUPERBLOCK)) - mapblock_offset]); }
static struct dir_entry * vstafs_readdir (long sector) { get_file_info (sector); if (FILE_INFO->type != 2) { errnum = ERR_FILE_NOT_FOUND; return 0; } a = FILE_INFO->blocks; curr_ext = 0; devread (a[curr_ext].a_start, 0, 512, (char *) DIRECTORY_BUF); current_direntry = 11; current_blockpos = 0; return &DIRECTORY_BUF[10]; }
static struct dir_entry * vstafs_readdir (long sector) { /* * Get some information from the current directory */ get_file_info (sector); if (FILE_INFO->type != 2) { errnum = ERR_FILE_NOT_FOUND; return NULL; } a1 = FILE_INFO->blocks; curr_ext = 0; devread (a1[curr_ext].a_start, 0, 512, (char *) DIRECTORY_BUF); current_direntry = 11; current_blockpos = 0; return &DIRECTORY_BUF[10]; }
int ufs2_mount (void) { int retval = 0; int i; sblockloc = -1; type = 0; // if (! (((current_drive & 0x80) || (current_slice != 0)) // && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_BSDFFS))) { for (i = 0; sblock_try[i] != -1; ++i) { if (! ((unsigned long)part_length < (sblock_try[i] + (SBLOCKSIZE / DEV_BSIZE)) || ! devread (0, sblock_try[i], SBLOCKSIZE, (char *) SUPERBLOCK, 0xedde0d90))) { if (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC /* && (SUPERBLOCK->fs_sblockloc == sblockloc || (SUPERBLOCK->fs_old_flags & FS_FLAGS_UPDATED) == 0)*/) { type = 2; } else { continue; } retval = 1; sblockloc = sblock_try[i]; break; } } } mapblock = -1; mapblock_offset = -1; return retval; }
int fixmbr(int slice, int dtype) { struct doslabel doslabel; int cc; if (lseek(outfd, (off_t)0, SEEK_SET) < 0) { perror("Could not seek to DOS label"); return 1; } if ((cc = devread(outfd, doslabel.pad2, DOSPARTSIZE)) < 0) { perror("Could not read DOS label"); return 1; } if (cc != DOSPARTSIZE) { fprintf(stderr, "Could not get the entire DOS label\n"); return 1; } if (doslabel.magic != BOOT_MAGIC) { fprintf(stderr, "Wrong magic number in DOS partition table\n"); return 1; } if (doslabel.parts[slice-1].dp_typ != dostype) { doslabel.parts[slice-1].dp_typ = dostype; if (lseek(outfd, (off_t)0, SEEK_SET) < 0) { perror("Could not seek to DOS label"); return 1; } cc = write(outfd, doslabel.pad2, DOSPARTSIZE); if (cc != DOSPARTSIZE) { perror("Could not write DOS label"); return 1; } fprintf(stderr, "Set type of DOS partition %d to %d\n", slice, dostype); } return 0; }
unsigned long ufs2_read (char *buf, unsigned long len, unsigned long write) { unsigned long logno, off, size, ret = 0; grub_int64_t map; while (len && !errnum) { off = blkoff (SUPERBLOCK, filepos); logno = lblkno (SUPERBLOCK, filepos); size = blksize (SUPERBLOCK, INODE_UFS2, logno); if ((map = block_map (logno)) < 0) break; size -= off; if (size > len) size = len; disk_read_func = disk_read_hook; devread (fsbtodb (SUPERBLOCK, map), off, size, buf, write); disk_read_func = NULL; if (buf) buf += size; len -= size; /* len always >= 0 */ filepos += size; ret += size; } if (errnum) ret = 0; return ret; }
int load_prep_partition(int devfd, struct mbr_partition *ppp) { char mbr[512]; struct mbr_partition *mbrp; int i; if (devread(devfd, mbr, MBR_BBSECTOR, DEV_BSIZE, "MBR") != 0) return 1; if (*(u_int16_t *)&mbr[MBR_MAGICOFF] != htole16(MBR_MAGIC)) { warn("no MBR_MAGIC"); return 1; } mbrp = (struct mbr_partition *)&mbr[MBR_PARTOFF]; for (i = 0; i < NMBRPART; i++) { if (mbrp[i].mbrp_typ == MBR_PTYPE_PREP) break; } if (i == NMBRPART) { warn("no PReP partition."); return 1; } if (verbose) { printf("PReP partition: start = %d, size = %d\n", le32toh(mbrp[i].mbrp_start), le32toh(mbrp[i].mbrp_size)); } if (ppp) { *ppp = mbrp[i]; ppp->mbrp_start = le32toh(ppp->mbrp_start); ppp->mbrp_size = le32toh(ppp->mbrp_size); } return 0; }
static int openi(int n, struct iob *io) { struct dinode *dp; int cc; #if ICACHE struct icommon *ip; if (icache == 0) { icache = cacheInit(ICACHE_SIZE, sizeof(struct icommon)); } #endif ICACHE io->i_offset = 0; io->i_bn = fsbtodb(io->i_fs, itod(io->i_fs, n)) + io->i_boff; io->i_cc = io->i_fs->fs_bsize; io->i_ma = io->i_buf; #if ICACHE if (cacheFind(icache, n, 0, (char **)&ip) == 1) { io->i_ino.i_ic = *ip; cc = 0; } else { #endif ICACHE cc = devread(io); dp = (struct dinode *)io->i_buf; #if BIG_ENDIAN_FS byte_swap_inode_in(&dp[itoo(io->i_fs, n)].di_ic, &io->i_ino.i_ic); #else io->i_ino.i_ic = dp[itoo(io->i_fs, n)].di_ic; #endif BIG_ENDIAN_FS #if ICACHE *ip = io->i_ino.i_ic; } #endif ICACHE io->i_ino.i_number = n; return (cc); }
int ufs2_read (char *buf, int len) { int logno, off, size, ret = 0; grub_int64_t map; while (len && !errnum) { off = blkoff (SUPERBLOCK, filepos); logno = lblkno (SUPERBLOCK, filepos); size = blksize (SUPERBLOCK, INODE_UFS2, logno); if ((map = block_map (logno)) < 0) break; size -= off; if (size > len) size = len; disk_read_func = disk_read_hook; devread (fsbtodb (SUPERBLOCK, map), off, size, buf); disk_read_func = NULL; buf += size; len -= size; filepos += size; ret += size; } if (errnum) ret = 0; return ret; }
int read(int fdesc, char *buf, int count) { int i, size; register struct iob *file; struct fs *fs; int lbn, off; if ((file = iob_from_fdesc(fdesc)) == 0) { return (-1); } if ((file->i_flgs&F_READ) == 0) { return (-1); } #ifndef SMALL if ((file->i_flgs & F_FILE) == 0) { file->i_cc = count; file->i_ma = buf; file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); i = devread(file); file->i_offset += count; return (i); } #endif SMALL if (file->i_offset+count > file->i_ino.i_size) count = file->i_ino.i_size - file->i_offset; if ((i = count) <= 0) return (0); /* * While reading full blocks, do I/O into user buffer. * Anything else uses getc(). */ fs = file->i_fs; while (i) { off = blkoff(fs, file->i_offset); lbn = lblkno(fs, file->i_offset); size = blksize(fs, &file->i_ino, lbn); if (off == 0 && size <= i) { file->i_bn = fsbtodb(fs, sbmap(file, lbn)) + file->i_boff; file->i_cc = size; file->i_ma = buf; if (devread(file) < 0) { return (-1); } file->i_offset += size; file->i_cc = 0; buf += size; i -= size; } else { size -= off; if (size > i) size = i; i -= size; do { *buf++ = getch(fdesc); } while (--size); } } return (count); }
int open(char *str, int how) { register char *cp; register struct iob *file; int i, fdesc; #if CHECK_CAREFULLY /* iob[] is in BSS, so it is guaranteed to be zero. */ if (open_init == 0) { for (i = 0; i < NFILES; i++) iob[i].i_flgs = 0; open_init = 1; } #endif for (fdesc = 0; fdesc < NFILES; fdesc++) if (iob[fdesc].i_flgs == 0) goto gotfile; stop("Out of file descriptor slots"); gotfile: (file = &iob[fdesc])->i_flgs |= F_ALLOC; if ((cp = xx(str, file)) == (char *) -1) { close(fdesc); return -1; } if (*cp == '\0') { file->i_flgs |= how+1; file->i_cc = 0; file->i_offset = 0; return (fdesc); } file->i_cc = SBSIZE; file->i_bn = (SBLOCK / DEV_BSIZE) + file->i_boff; file->i_offset = 0; if (file->i_fs == 0) { if (fs_block == 0) { fs_block = (struct fs *)malloc(SBSIZE); } if (fs_block_valid == 0) { file->i_ma = (char *)fs_block; if (devread(file) < 0) { #ifndef SMALL error(SUPERBLOCK_ERROR, 1); #endif close(fdesc); return (-1); } byte_swap_superblock(fs_block); fs_block_valid = 1; } file->i_fs = fs_block; file->i_buf = malloc(MAXBSIZE); } #if BIG_ENDIAN_FS if (file->i_fs->fs_magic != FS_MAGIC) { error(SUPERBLOCK_ERROR, 2); close(fdesc); return (-1); } /* * The following is a gross hack to boot disks that have an actual * blocksize of 512 bytes but were written with a theoretical 1024 * byte blocksize (fsbtodb == 0). * * We can make this assumption because we can only boot disks with * a 512 byte sector size. */ if (file->i_fs->fs_fsize == 0) { error(SUPERBLOCK_ERROR,3); close(fdesc); return (-1); } file->i_fs->fs_fsbtodb = ffs(file->i_fs->fs_fsize / DEV_BSIZE) - 1; #endif BIG_ENDIAN_FS if ((i = find(cp, file)) == 0) { close(fdesc); return (-1); } #if CHECK_CAREFULLY if (how != 0) { error("Can't write files\n"); close(fdesc); return (-1); } #endif CHECK_CAREFULLY if (openi(i, file) < 0) { close(fdesc); return (-1); } file->i_offset = 0; file->i_cc = 0; file->i_flgs |= F_FILE | (how+1); return (fdesc); }
int vstafs_read (char *addr, int len) { struct alloc *a2; int size, ret = 0, offset, curr_len = 0; int curr_ext2; char extent; int ext_size; char *curr_pos; get_file_info (f_sector); size = FILE_INFO->len-VSTAFS_START_DATA; a2 = FILE_INFO->blocks; if (filepos > 0) { if (filepos < a2[0].a_len * 512 - VSTAFS_START_DATA) { offset = filepos + VSTAFS_START_DATA; extent = 0; curr_len = a2[0].a_len * 512 - offset - filepos; } else { ext_size = a2[0].a_len * 512 - VSTAFS_START_DATA; offset = filepos - ext_size; extent = 1; do { curr_len -= ext_size; offset -= ext_size; ext_size = a2[extent+1].a_len * 512; } while (extent < FILE_INFO->extents && offset>ext_size); } } else { offset = VSTAFS_START_DATA; extent = 0; curr_len = a2[0].a_len * 512 - offset; } curr_pos = addr; if (curr_len > len) curr_len = len; for (curr_ext2=extent; curr_ext2 < FILE_INFO->extents; curr_len = a2[curr_ext].a_len * 512, curr_pos += curr_len, curr_ext2++) { ret += curr_len; size -= curr_len; if (size < 0) { ret += size; curr_len += size; } devread (a2[curr_ext2].a_start,offset, curr_len, curr_pos); offset = 0; } return ret; }
/* * get next entry in a directory. */ struct direct * readdir(struct dirstuff *dirp) { struct direct *dp; register struct iob *io; daddr_t lbn, d; int off; #if DCACHE char *bp; int dirblkno; if (dcache == 0) dcache = cacheInit(DCACHE_SIZE, DIRBLKSIZ); #endif DCACHE io = dirp->io; for(;;) { if (dirp->loc >= io->i_ino.i_size) return (NULL); off = blkoff(io->i_fs, dirp->loc); lbn = lblkno(io->i_fs, dirp->loc); #if DCACHE dirblkno = dirp->loc / DIRBLKSIZ; if (cacheFind(dcache, io->i_ino.i_number, dirblkno, &bp)) { dp = (struct direct *)(bp + (dirp->loc % DIRBLKSIZ)); } else #else DCACHE if (io->dirbuf_blkno != lbn) #endif DCACHE { if((d = sbmap(io, lbn)) == 0) return NULL; io->i_bn = fsbtodb(io->i_fs, d) + io->i_boff; io->i_ma = io->i_buf; io->i_cc = blksize(io->i_fs, &io->i_ino, lbn); if (devread(io) < 0) { #if SYS_MESSAGES error("bn %d: directory read error\n", io->i_bn); #endif return (NULL); } #if BIG_ENDIAN_FS byte_swap_dir_block_in(io->i_buf, io->i_cc); #endif BIG_ENDIAN_FS #if DCACHE bcopy(io->i_buf + dirblkno * DIRBLKSIZ, bp, DIRBLKSIZ); dp = (struct direct *)(io->i_buf + off); #endif } #if !DCACHE dp = (struct direct *)(io->i_buf + off); #endif dirp->loc += dp->d_reclen; if (dp->d_ino != 0) return (dp); } }
static daddr_t sbmap(struct iob *io, daddr_t bn) { register struct inode *ip; int i, j, sh; daddr_t nb, *bap; ip = &io->i_ino; if (ip->i_icflags & IC_FASTLINK) { error("fast symlinks unimplemented\n"); return ((daddr_t)0); } if (bn < 0) { #if SYS_MESSAGES error("bn negative\n"); #endif return ((daddr_t)0); } /* * blocks 0..NDADDR are direct blocks */ if(bn < NDADDR) { nb = ip->i_db[bn]; return (nb); } /* * addresses NIADDR have single and double indirect blocks. * the first step is to determine how many levels of indirection. */ sh = 1; bn -= NDADDR; for (j = NIADDR; j > 0; j--) { sh *= NINDIR(io->i_fs); if (bn < sh) break; bn -= sh; } if (j == 0) { #if SYS_MESSAGES error("bn ovf %d\n", bn); #endif return ((daddr_t)0); } /* * fetch the first indirect block address from the inode */ nb = ip->i_ib[NIADDR - j]; if (nb == 0) { #if SYS_MESSAGES error("bn void %d\n",bn); #endif return ((daddr_t)0); } /* * fetch through the indirect blocks */ for (; j <= NIADDR; j++) { if (blknos[j] != nb) { io->i_bn = fsbtodb(io->i_fs, nb) + io->i_boff; if (b[j] == (char *)0) b[j] = malloc(MAXBSIZE); io->i_ma = b[j]; io->i_cc = io->i_fs->fs_bsize; if (devread(io) != io->i_fs->fs_bsize) { #if SYS_MESSAGES error("bn %d: read error\n", io->i_bn); #endif return ((daddr_t)0); } blknos[j] = nb; } bap = (daddr_t *)b[j]; sh /= NINDIR(io->i_fs); i = (bn / sh) % NINDIR(io->i_fs); #if BIG_ENDIAN_FS #if 1 // for now it is little endian FS for intel nb = bap[i]; #else nb = OSSwapBigToHostInt32(bap[i]); #endif 1 #else BIG_ENDIAN_FS nb = bap[i]; #endif BIG_ENDIAN_FS if(nb == 0) { #if SYS_MESSAGES error("bn void %d\n",bn); #endif return ((daddr_t)0); } } return (nb); }
static void get_file_info (int sector) { devread (sector, 0, BLOCK_SIZE, (char *) FILE_INFO); }
int loadblocknums(char *boot, int devfd) { int i, fd; struct stat statbuf; struct statvfs statvfsbuf; struct fs *fs; char *buf; daddr_t blk, *ap; struct ufs1_dinode *ip; int ndb; /* * Open 2nd-level boot program and record the block numbers * it occupies on the filesystem represented by `devfd'. */ /* Make sure the (probably new) boot file is on disk. */ sync(); sleep(1); if ((fd = open(boot, O_RDONLY)) < 0) err(1, "open: %s", boot); if (fstatvfs(fd, &statvfsbuf) != 0) err(1, "statfs: %s", boot); if (strncmp(statvfsbuf.f_fstypename, "ffs", sizeof(statvfsbuf.f_fstypename)) && strncmp(statvfsbuf.f_fstypename, "ufs", sizeof(statvfsbuf.f_fstypename))) { errx(1, "%s: must be on an FFS filesystem", boot); } if (fsync(fd) != 0) err(1, "fsync: %s", boot); if (fstat(fd, &statbuf) != 0) err(1, "fstat: %s", boot); close(fd); /* Read superblock */ devread(devfd, sblock, (daddr_t)(BBSIZE / DEV_BSIZE), SBLOCKSIZE, "superblock"); fs = (struct fs *)sblock; /* Sanity-check super-block. */ if (fs->fs_magic != FS_UFS1_MAGIC) errx(1, "Bad magic number in superblock, must be UFS1"); if (fs->fs_inopb <= 0) err(1, "Bad inopb=%d in superblock", fs->fs_inopb); /* Read inode */ if ((buf = malloc(fs->fs_bsize)) == NULL) errx(1, "No memory for filesystem block"); blk = fsbtodb(fs, ino_to_fsba(fs, statbuf.st_ino)); devread(devfd, buf, blk, fs->fs_bsize, "inode"); ip = (struct ufs1_dinode *)(buf) + ino_to_fsbo(fs, statbuf.st_ino); /* * Have the inode. Figure out how many blocks we need. */ ndb = howmany(ip->di_size, fs->fs_bsize); if (ndb > maxblocknum) errx(1, "Too many blocks"); *block_count_p = ndb; *block_size_p = fs->fs_bsize; if (verbose) printf("Will load %d blocks of size %d each.\n", ndb, fs->fs_bsize); /* * Get the block numbers; we don't handle fragments */ ap = ip->di_db; for (i = 0; i < NDADDR && *ap && ndb; i++, ap++, ndb--) { blk = fsbtodb(fs, *ap); if (verbose) printf("%d: %d\n", i, blk); block_table[i] = blk; } if (ndb == 0) return 0; /* * Just one level of indirections; there isn't much room * for more in the 1st-level bootblocks anyway. */ blk = fsbtodb(fs, ip->di_ib[0]); devread(devfd, buf, blk, fs->fs_bsize, "indirect block"); /* XXX ondisk32 */ ap = (int32_t *)buf; for (; i < NINDIR(fs) && *ap && ndb; i++, ap++, ndb--) { blk = fsbtodb(fs, *ap); if (verbose) printf("%d: %d\n", i, blk); block_table[i] = blk; } return 0; }