From 7e0f021a9aec35fd8e6725e87e3313b101d26f5e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sun, 27 Jan 2008 11:37:44 +0100 Subject: Initial import (2.0.2-6) --- reference/C/CONTRIB/OR_USING_C/13.3.c | 118 ++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 reference/C/CONTRIB/OR_USING_C/13.3.c (limited to 'reference/C/CONTRIB/OR_USING_C/13.3.c') diff --git a/reference/C/CONTRIB/OR_USING_C/13.3.c b/reference/C/CONTRIB/OR_USING_C/13.3.c new file mode 100644 index 0000000..a0dc4b1 --- /dev/null +++ b/reference/C/CONTRIB/OR_USING_C/13.3.c @@ -0,0 +1,118 @@ + +#include +#include +#include +#include +#include + +#define sblock sb_un.u_sblock + +/* + * The super block. We allow enough room for + * a complete disk block. + */ +union { + struct fs u_sblock; + char dummy[SBSIZE]; +} sb_un; + +read_blocks(dp) +struct dinode *dp; +{ + int count; + register int i, n; + char dblock[MAXBSIZE]; + + count = dp->di_size; + + /* + * For each direct block in the file (NDADDR indicates + * the number of direct addresses stored)... + */ + for (i = 0; (i < NDADDR) && (count > 0); i++) { + /* + * Read in the block from disk. Read in count + * bytes or a disk block, whichever is less. + */ + bread(fsbtodb(&sblock, dp->di_db[i]), dblock, + n = min(count, sblock.fs_bsize)); + count -= n; + + /* process data block ... */ + + } + + /* + * Now start reading the indirect blocks. NIADDR is + * the number of indirect addresses. Recall that + * the first indirect address is singly indirect, + * the second is doubly indirect, an so on. + */ + for (i = 0; (i < NIADDR) && (count > 0); i++) + read_indirect (dp->di_ib[i], i, &count); +} + +/* + * read_indirect--read the indirect blocks of the file. The + * level argument indicates our level of indirection; 0 is + * singly indirect, 1 is doubly indirect, and so on. + */ +read_indirect (blkno, level, count) +ino_t blkno; +int *count; +int level; +{ + register int i, n; + char dblock[MAXBSIZE]; + daddr_t idblk[MAXBSIZE / sizeof(daddr_t)]; + + /* + * Read in the block from disk. + */ + if (blkno) + bread(fsbtodb(&sblock, blkno), idblk, sblock.fs_bsize); + else + bzero(idblk, sblock.fs_bsize); + + /* + * If level is zero, then this block contains disk block + * addresses, since blkno was a singly indirect address. + * If level is non-zero, then this block contains addresses + * of more indirect blocks. + */ + if (level <= 0) { + /* + * For each disk block (the NINDIR macro returns + * the number of indirect addresses in a block)... + */ + for (i = 0; (i < NINDIR(&sblock)) && (*count > 0); i++) { + /* + * Read in the block from disk. + */ + bread(fsbtodb(&sblock, idblk[i]), dblock, + n = min(*count, sblock.fs_bsize)); + *count -= n; + + /* process data block ... */ + } + + /* + * Done processing. + */ + return; + } + + /* + * Decrement the level we're at. + */ + level--; + + /* + * Handle the next level of indirection by calling + * ourselves recursively with each address in this + * block. + */ + for (i = 0; i < NINDIR(&sblock); i++) + read_indirect(idblk[i], level, count); +} + -- cgit v1.2.3-54-g00ecf