⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dstream.c

📁 be文件系统实现的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  This file contains the code to read and write the data stream of a file.    THIS CODE COPYRIGHT DOMINIC GIAMPAOLO.  NO WARRANTY IS EXPRESSED   OR IMPLIED.  YOU MAY USE THIS CODE AND FREELY DISTRIBUTE IT FOR  NON-COMMERCIAL USE AS LONG AS THIS NOTICE REMAINS ATTACHED.  FOR COMMERCIAL USE, CONTACT DOMINIC GIAMPAOLO (dbg@be.com).  Dominic Giampaolo  dbg@be.com*/#include "myfs.h"intmyfs_init_data_stream(myfs_info *myfs, myfs_inode *mi){    /* nothing to do for this simple implementation */    return 0;}#define MAX_DIRECT_RANGE          (NUM_DIRECT_BLOCKS * bsize)#define MAX_INDIRECT_RANGE        (((bsize / sizeof(fs_off_t)) * bsize) +   \                                   MAX_DIRECT_RANGE)#define MAX_DOUBLE_INDIRECT_RANGE (((bsize / sizeof(fs_off_t)) *            \                                    ((bsize / sizeof(fs_off_t)) * bsize)) + \                                   MAX_INDIRECT_RANGE)/* this is the amount of data mapped by each set of blocks */#define DIRECT_SIZE               (NUM_DIRECT_BLOCKS * bsize)#define INDIRECT_SIZE             ((bsize / sizeof(fs_off_t)) * bsize)#define DOUBLE_INDIRECT_SIZE      ((bsize / sizeof(fs_off_t)) *            \                                   ((bsize / sizeof(fs_off_t)) * bsize))static fs_off_tfile_pos_to_disk_addr(myfs_info *myfs, myfs_inode *mi, fs_off_t pos){    int       bsize = myfs->dsb.block_size;    int       index;    fs_off_t  addr, offset, tmp;    fs_off_t *block, *block2;        if (pos < NUM_DIRECT_BLOCKS*bsize) {        index = pos / bsize;        addr = mi->data.direct[index];                if (addr < 0 || addr > myfs->dsb.num_blocks) {            myfs_die("file_pos:1: addr 0x%lx is out of range (max %ld)\n",                     addr, myfs->dsb.num_blocks);        }        return addr;    } else if (pos < MAX_INDIRECT_RANGE) {        block = get_block(myfs->fd, mi->data.indirect, bsize);        addr = block[(pos - MAX_DIRECT_RANGE) / bsize];        release_block(myfs->fd, mi->data.indirect);        if (addr < 0 || addr > myfs->dsb.num_blocks) {            myfs_die("file_pos:1: addr 0x%lx is out of range (max %ld)\n",                     addr, myfs->dsb.num_blocks);        }                return addr;    } else if (pos < MAX_DOUBLE_INDIRECT_RANGE) {        index = (int)((pos - MAX_INDIRECT_RANGE) / INDIRECT_SIZE);        block = get_block(myfs->fd, mi->data.double_indirect, bsize);        addr = block[index];        release_block(myfs->fd, mi->data.double_indirect);        tmp = addr;        block = get_block(myfs->fd, tmp, bsize);        addr = block[(((pos - MAX_INDIRECT_RANGE) % INDIRECT_SIZE) / bsize)];        release_block(myfs->fd, tmp);        if (addr < 0 || addr > myfs->dsb.num_blocks) {            myfs_die("file_pos:1: addr 0x%lx is out of range (max %ld)\n",                     addr, myfs->dsb.num_blocks);        }            } else {        printf("heidy-ho... looks like it's time to implement triple "               "indirect blocks.  have fun!\n");        return -1;    }        return -1;}intmyfs_read_data_stream(myfs_info *myfs, myfs_inode *mi,                           fs_off_t pos, char *buf, size_t *_len){    int       i, offset, bsize = myfs->dsb.block_size;    size_t    len = *_len, amt;    fs_off_t  addr;    char     *block;        if (len == 0)    /* just a quick check */        return 0;    if (pos < 0)        pos = 0;        if (pos > mi->data.size) {        *_len = 0;        return 0;    }    *_len = 0;    /* this will now count up */        if (pos + len > mi->data.size)        len = mi->data.size - pos;    addr = file_pos_to_disk_addr(myfs, mi, pos);    if (addr < 0)        return EINVAL;    if ((pos % bsize) != 0) { /* then we have to work up to a block boundary */        block = get_block(myfs->fd, addr, bsize);        if (block == NULL)            return EINVAL;        offset = (pos % bsize);        if (len < (bsize - offset))            amt = len;        else            amt = (bsize - offset);        memcpy(buf, &block[offset], amt);        buf   += amt;        pos   += amt;        *_len += amt;        release_block(myfs->fd, addr);    }    /* this is the main data reading loop */    for(; *_len < len; *_len+=amt) {        addr = file_pos_to_disk_addr(myfs, mi, pos);        if (addr < 0)            return EINVAL;        block = get_block(myfs->fd, addr, bsize);        if (block == NULL)            return EINVAL;        if ((len - *_len) < bsize)            amt = len - *_len;        else            amt = bsize;        memcpy(buf, block, amt);        buf   += amt;        pos   += amt;        release_block(myfs->fd, addr);    }    return 0;}static intgrow_dstream(myfs_info *myfs, myfs_inode *mi, fs_off_t new_size){    int       bsize = myfs->dsb.block_size;    int       index, err;    fs_off_t  i, max_index = bsize / sizeof(fs_off_t);    fs_off_t  addr, offset;    fs_off_t  cur_size_rounded, new_size_rounded, num_blocks_needed;    fs_off_t  nblocks;    fs_off_t *block, *block2;        if (new_size > MAX_DOUBLE_INDIRECT_RANGE)        return E2BIG;    /* round up the current file size to the next block boundary */    cur_size_rounded = (mi->data.size + bsize - 1) & ~(bsize - 1);    /* round up the new file size to the next block boundary */    new_size_rounded = (new_size + bsize - 1) & ~(bsize - 1);    if (cur_size_rounded == new_size_rounded) {  /* can grow in-place */        mi->data.size = new_size;                return 0;    }    num_blocks_needed = ((new_size_rounded - cur_size_rounded) / bsize);    i = 0;    mi->data.size = cur_size_rounded;    if (cur_size_rounded < DIRECT_SIZE) {   /* grow the direct blocks first */        /* use the rounded size to calculate the index to start growing at */        index = cur_size_rounded / bsize;        if (mi->data.direct[index] != 0) {            myfs_die("grow_dstream: mi (inum %ld): direct[%d] == %ld, not "                     "zero!\n", mi->inode_num, index, mi->data.direct[index]);        }        for(; i < num_blocks_needed && index < NUM_DIRECT_BLOCKS; i++,index++){            nblocks = 1;            err = myfs_allocate_blocks(myfs, mi->inode_num, &nblocks, &addr,                                       EXACT_ALLOCATION);            if (err != 0)                return err;                        if (addr < 0)                return ENOSPC;            mi->data.direct[index]  = addr;            mi->data.size          += bsize;        }        if (mi->data.size >= new_size) {   /* all done! */            mi->data.size = new_size;            return 0;        }    }    /* now see if we have to grow the indirect range */    if (mi->data.size >= MAX_DIRECT_RANGE &&        mi->data.size < MAX_INDIRECT_RANGE) {                if (mi->data.indirect == 0) {            nblocks = 1;            err = myfs_allocate_blocks(myfs, mi->inode_num, &nblocks, &addr,                                       EXACT_ALLOCATION);            if (err != 0)                return err;                        if (addr < 0)                return ENOSPC;            mi->data.indirect = addr;            block = get_empty_block(myfs->fd, addr, bsize);        } else {            block = get_block(myfs->fd, mi->data.indirect, bsize);        }        index = (mi->data.size - MAX_DIRECT_RANGE) / bsize;        for(; i < num_blocks_needed && index < max_index; i++, index++) {            nblocks = 1;            err = myfs_allocate_blocks(myfs, mi->inode_num, &nblocks, &addr,                                       EXACT_ALLOCATION);            if (err != 0)                return err;                        if (addr < 0)                return ENOSPC;                        block[index]   = addr;            mi->data.size += bsize;        }        mark_blocks_dirty(myfs->fd, mi->data.indirect, 1);        release_block(myfs->fd, mi->data.indirect);        if (mi->data.size >= new_size) {   /* all done! */            mi->data.size = new_size;            return 0;        }    }    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -