/* * Initialize an ext2 partition starting at offset P_OFFSET; this is * sort-of the same idea as "mounting" it. Read in the relevant * control structures and make them available to the user. Returns 0 * if successful, -1 on failure. */ static int ext2_mount(long cons_dev, long p_offset, long quiet) { long sb_block = 1; long sb_offset; int i; dev = cons_dev; partition_offset = p_offset; /* initialize the inode table */ for (i = 0; i < MAX_OPEN_FILES; i++) { inode_table[i].free = 1; inode_table[i].inumber = 0; } /* clear the root inode pointer (very important!) */ root_inode = NULL; /* read in the first superblock */ sb_offset = sb_block * EXT2_MIN_BLOCK_SIZE; if (cons_read(dev, &sb, sizeof(sb), partition_offset + sb_offset) != sizeof(sb)) { printf("ext2 sb read failed\n"); return -1; } if (sb.s_magic != EXT2_SUPER_MAGIC) { if (!quiet) { printf("ext2_init: bad magic 0x%x\n", sb.s_magic); } return -1; } ngroups = (sb.s_blocks_count - sb.s_first_data_block + EXT2_BLOCKS_PER_GROUP(&sb) - 1) / EXT2_BLOCKS_PER_GROUP(&sb); gds = (struct ext2_group_desc *) malloc((size_t)(ngroups * sizeof(struct ext2_group_desc))); ext2fs.blocksize = EXT2_BLOCK_SIZE(&sb); /* read in the group descriptors (immediately follows superblock) */ cons_read(dev, gds, ngroups * sizeof(struct ext2_group_desc), partition_offset + ext2fs.blocksize * (EXT2_MIN_BLOCK_SIZE/ext2fs.blocksize + 1)); /* * Calculate direct/indirect block limits for this file system * (blocksize dependent): */ ext2fs.blocksize = EXT2_BLOCK_SIZE(&sb); directlim = EXT2_NDIR_BLOCKS - 1; ptrs_per_blk = ext2fs.blocksize/sizeof(unsigned int); ind1lim = ptrs_per_blk + directlim; ind2lim = (ptrs_per_blk * ptrs_per_blk) + directlim; return 0; }
int main(void *arg) { int fid = (int)arg; int c = cons_read(); assert(psend(fid, 1) == 0); printf(" %d (%c)", 134 - getprio(getpid()), c); return 0; }
/* * Read the specified inode from the disk and return it to the user. * Returns NULL if the inode can't be read... */ static struct ext2_inode *ext2_iget(int ino) { int i; struct ext2_inode *ip; struct inode_table_entry *itp = 0; int group; long offset; ip = 0; for (i = 0; i < MAX_OPEN_FILES; i++) { #ifdef DEBUG_EXT2 printf("ext2_iget: looping, entry %d inode %d free %d\n", i, inode_table[i].inumber, inode_table[i].free); #endif if (inode_table[i].free) { itp = &inode_table[i]; ip = &itp->inode; break; } } if (!ip) { printf("ext2_iget: no free inodes\n"); return NULL; } group = (ino-1) / sb.s_inodes_per_group; #ifdef DEBUG_EXT2 printf("group is %d\n", group); #endif offset = partition_offset + ((long) gds[group].bg_inode_table * (long)ext2fs.blocksize) + (((ino - 1) % EXT2_INODES_PER_GROUP(&sb)) * EXT2_INODE_SIZE(&sb)); #ifdef DEBUG_EXT2 printf("ext2_iget: reading %ld bytes at offset %ld " "(%ld + (%d * %d) + ((%d) %% %d) * %d) " "(inode %d -> table %d)\n", sizeof(struct ext2_inode), offset, partition_offset, gds[group].bg_inode_table, ext2fs.blocksize, ino - 1, EXT2_INODES_PER_GROUP(&sb), EXT2_INODE_SIZE(&sb), ino, (int) (itp - inode_table)); #endif if (cons_read(dev, ip, sizeof(struct ext2_inode), offset) != sizeof(struct ext2_inode)) { printf("ext2_iget: read error\n"); return NULL; } itp->free = 0; itp->inumber = ino; itp->old_mode = ip->i_mode; return ip; }
static int ext2_breadi(struct ext2_inode *ip, long blkno, long nblks, char *buffer) { long dev_blkno, ncontig, offset, nbytes, tot_bytes; tot_bytes = 0; if ((blkno+nblks)*ext2fs.blocksize > ip->i_size) nblks = (ip->i_size + ext2fs.blocksize) / ext2fs.blocksize - blkno; while (nblks) { /* * Contiguous reads are a lot faster, so we try to group * as many blocks as possible: */ ncontig = 0; nbytes = 0; dev_blkno = ext2_blkno(ip, blkno); do { ++blkno; ++ncontig; --nblks; nbytes += ext2fs.blocksize; } while (nblks && ext2_blkno(ip, blkno) == dev_blkno + ncontig); if (dev_blkno == 0) { /* This is a "hole" */ memset(buffer, 0, nbytes); } else { /* Read it for real */ offset = partition_offset + (long) dev_blkno* (long) ext2fs.blocksize; #ifdef DEBUG_EXT2 printf("ext2_bread: reading %ld bytes at offset %ld\n", nbytes, offset); #endif if (cons_read(dev, buffer, nbytes, offset) != nbytes) { printf("ext2_bread: read error\n"); return -1; } } buffer += nbytes; tot_bytes += nbytes; } return tot_bytes; }
/* * Map a block offset into a file into an absolute block number. * (traverse the indirect blocks if necessary). Note: Double-indirect * blocks allow us to map over 64Mb on a 1k file system. Therefore, for * our purposes, we will NOT bother with triple indirect blocks. * * The "allocate" argument is set if we want to *allocate* a block * and we don't already have one allocated. */ static int ext2_blkno(struct ext2_inode *ip, int blkoff) { unsigned int *lp; unsigned int *ilp; unsigned int *dlp; int blkno; int iblkno; int diblkno; unsigned long offset; ilp = (unsigned int *)iblkbuf; dlp = (unsigned int *)diblkbuf; lp = (unsigned int *)blkbuf; /* If it's a direct block, it's easy! */ if (blkoff <= directlim) { return ip->i_block[blkoff]; } /* Is it a single-indirect? */ if (blkoff <= ind1lim) { iblkno = ip->i_block[EXT2_IND_BLOCK]; if (iblkno == 0) { return 0; } /* Read the indirect block */ if (cached_iblkno != iblkno) { offset = partition_offset + (long)iblkno * (long)ext2fs.blocksize; if (cons_read(dev, iblkbuf, ext2fs.blocksize, offset) != ext2fs.blocksize) { printf("ext2_blkno: error on iblk read\n"); return 0; } cached_iblkno = iblkno; } blkno = ilp[blkoff-(directlim+1)]; return blkno; } /* Is it a double-indirect? */ if (blkoff <= ind2lim) { /* Find the double-indirect block */ diblkno = ip->i_block[EXT2_DIND_BLOCK]; if (diblkno == 0) { return 0; } /* Read in the double-indirect block */ if (cached_diblkno != diblkno) { offset = partition_offset + (long) diblkno * (long) ext2fs.blocksize; if (cons_read(dev, diblkbuf, ext2fs.blocksize, offset) != ext2fs.blocksize) { printf("ext2_blkno: err reading dindr blk\n"); return 0; } cached_diblkno = diblkno; } /* Find the single-indirect block pointer ... */ iblkno = dlp[(blkoff - (ind1lim+1)) / ptrs_per_blk]; if (iblkno == 0) { return 0; } /* Read the indirect block */ if (cached_iblkno != iblkno) { offset = partition_offset + (long) iblkno * (long) ext2fs.blocksize; if (cons_read(dev, iblkbuf, ext2fs.blocksize, offset) != ext2fs.blocksize) { printf("ext2_blkno: err on iblk read\n"); return 0; } cached_iblkno = iblkno; } /* Find the block itself. */ blkno = ilp[(blkoff-(ind1lim+1)) % ptrs_per_blk]; return blkno; } if (blkoff > ind2lim) { printf("ext2_blkno: block number too large: %d\n", blkoff); return 0; } return -1; }