Ejemplo n.º 1
0
Inode *Ext2Inode::Mknod(const std::string name, mode_t mode)
{
    anvil_syslog(0, "Ext2Inode::Mknod %o\n", mode);

    // Call the Filesystem to find an unused inode in the inode bitmap
    Ext2filesystem *pfs = static_cast<Ext2filesystem *>(m_fs);
    ino_t inum = pfs->AllocInode(true);

    struct ext2_inode *ext2inode = pfs->inodeGet(inum);
    ext2inode->i_links_count = 1;
    ext2inode->i_mode = mode;
    ext2inode->i_ctime =
    ext2inode->i_atime =
    ext2inode->i_mtime = time(NULL);

    //pfs->inodePut(inum);

    if (S_ISDIR(mode))
    {
        // We're creating a directory
        anvil_syslog(0, "We're creating a directory\n");

        Ext2Inode *child = new Ext2Inode((Ext2filesystem *)m_fs, inum);
        child->Read();

        // If we are creating a directory, increase the link count on 'this'
        // inode because the .. entry we are about to make actually points to
        // 'this' inode
        struct ext2_inode *thisext2inode = pfs->inodeGet(m_ino);
        ++thisext2inode->i_links_count;
        pfs->inodePut(m_ino);

        // And the . entry will point to itself so increase that by one as well
        ++ext2inode->i_links_count;

        uint32_t blk_no = pfs->AllocBlock();
        anvil_syslog(0, "Block %u allocated\n", blk_no);
        //ext2inode = pfs->inodeGet(inum);
        ext2inode->i_block[0] = blk_no;
        ext2inode->i_size = pfs->m_block_size;
        ext2inode->i_blocks = pfs->m_block_size / 512;
        //pfs->inodePut(inum);
//        struct ext2_direntry *d = (struct ext2_direntry *)pfs->GetBlock(blk_no);
        Page *p = child->GetPage(0);
        struct ext2_direntry *d = (struct ext2_direntry *)p->GetAddr();

        d->d_inode = inum;
        d->d_reclen = 12;
        d->d_namelen = 1;
        d->d_type = 0;
        memcpy(d + 1, ".\0\0\0", 4);

        d = (ext2_direntry *)((char *)d + d->d_reclen);

        d->d_inode = m_ino;
        d->d_reclen = 1024 - 12;
        d->d_namelen = 2;
        d->d_type = 0;
        memcpy(d + 1, "..\0\0", 4);

        p->set_dirty(0xff);
        p->flush();
    }
    else
    {
    }

    pfs->inodePut(inum);

    anvil_syslog(0, "Inode %d allocated\n", inum);


    // Now we search the directory to see if we can find it
    Inode *new_child = (Ext2Inode *)SearchDirAndAct(name.c_str(), Inode::action::create, inum);

    return new_child;
}
Ejemplo n.º 2
0
Inode *Ext2Inode::SearchDirAndAct(const char *lookup_name, enum Inode::action action, ino_t inum)
{
    //anvil_syslog(0, "Ext2Inode::SearchDir %s dirsize=%d\n", lookup_name, m_size);

    Ext2Inode *inode = nullptr;

    // Now search the pages that hold the directory
    off_t offset_of_page = 0;
    off_t offset_of_space = 0;
    off_t offs = 0;
    uint32_t remains = m_size;

    // If we are creating work out how much space we need
    off_t needed_space;

    if (action == Inode::action::create)
    {
        needed_space = (8 + strlen(lookup_name) + 3) & ~0x3;
        anvil_syslog(0, "Ext2Inode::SearchDir space needed = %d\n", needed_space);
    }

    while (1)
    {
        Page *p = GetPage(offs);
        char *addr = p->GetAddr();
        struct ext2_direntry *item = (struct ext2_direntry *)addr;

        // Figure out how much of this page is used
        struct ext2_direntry *end = (struct ext2_direntry *)(addr + (remains > __PAGESIZE ? __PAGESIZE : remains));
        while (item < end)
        {
            char found_name[1024];
            memcpy(found_name, item+1, item->d_namelen);
            found_name[item->d_namelen] = 0;
            //anvil_syslog(0, "found_name: %.20s - ", found_name);
            int space = item->d_reclen - item->d_namelen - 8;
            if (action == Inode::action::create && offset_of_page == 0 && needed_space <= space)
            {
                offset_of_page = offs;
                offset_of_space = (char *)item - addr;
            }
            //anvil_syslog(0, "inode=%d reclen=%d namelen=%d type=%d SPACE=%d\n", item->d_inode, item->d_reclen, item->d_namelen, item->d_type, space);
            if (!namecmp(found_name, lookup_name))
            {
                // It's a match
                inode = new Ext2Inode((Ext2filesystem *)m_fs, item->d_inode);
                inode->Read();
                //anvil_syslog(0, "Returning inode %016lx\n", inode);
                return inode;
            }
            item = (ext2_direntry *)((char *)item + item->d_reclen);
            //anvil_syslog(0, "item=%016lx end=%016lx\n", item, end);
        }
        offs += __PAGESIZE;
        if (offs > m_size)
            break;
    }

    if (action == Inode::action::create)
    {
        if (offset_of_page == 0)
        {
            // Todo: create a new page



        }
        Page *p = GetPage(offset_of_page);
        char *addr = p->GetAddr();
        struct ext2_direntry *item = (struct ext2_direntry *)addr;
        item = (ext2_direntry *)((char *)item + offset_of_space);
        off_t space = item->d_reclen - item->d_namelen - 8;
        off_t actual_space_needed = (8 + item->d_namelen + 3) & ~0x3;
        anvil_syslog(0, "CREATING: space_needed=%d\n", needed_space);
        anvil_syslog(0, "CREATING: inode=%d reclen=%d namelen=%d type=%d SPACE=%d\n",
                item->d_inode, item->d_reclen, item->d_namelen, item->d_type, space);

        anvil_syslog(0, "inode=%d reclen=%d namelen=%d type=%d\n", item->d_inode, item->d_reclen, item->d_namelen, item->d_type);

        struct ext2_direntry *new_item = (struct ext2_direntry *)((char *)item + actual_space_needed);
        new_item->d_inode = inum;
        new_item->d_namelen = strlen(lookup_name);
        memcpy(new_item+1, lookup_name, new_item->d_namelen);
        new_item->d_reclen = item->d_reclen - actual_space_needed;
        new_item->d_type = 0;

        // change it
        item->d_reclen = actual_space_needed;

        anvil_syslog(0, "inode=%d reclen=%d namelen=%d type=%d\n", item->d_inode, item->d_reclen, item->d_namelen, item->d_type);
        anvil_syslog(0, "inode=%d reclen=%d namelen=%d type=%d\n", new_item->d_inode, new_item->d_reclen, new_item->d_namelen, new_item->d_type);

        p->set_dirty(0xff);
        p->flush();

        inode = new Ext2Inode((Ext2filesystem *)m_fs, new_item->d_inode);
        inode->Read();
        anvil_syslog(0, "Returning inode %016lx\n", inode);
        return inode;
    }

    //anvil_syslog(0, "Returning null\n");
    return NULL;
}