示例#1
0
struct fsw_posix_volume * fsw_posix_mount(const char *path, struct fsw_fstype_table *fstype_table)
{
    fsw_status_t        status;
    struct fsw_posix_volume *pvol;
    
    // allocate volume structure
    status = fsw_alloc_zero(sizeof(struct fsw_posix_volume), (void **)&pvol);
    if (status)
        return NULL;
    pvol->fd = -1;
    
    // open underlying file/device
    pvol->fd = open(path, O_RDONLY, 0);
    if (pvol->fd < 0) {
        fprintf(stderr, "fsw_posix_mount: %s: %s\n", path, strerror(errno));
        fsw_free(pvol);
        return NULL;
    }
    
    // mount the filesystem
    if (fstype_table == NULL)
        fstype_table = &FSW_FSTYPE_TABLE_NAME(FSTYPE);
    status = fsw_mount(pvol, &fsw_posix_host_table, fstype_table, &pvol->vol);
    if (status) {
        fprintf(stderr, "fsw_posix_mount: fsw_mount returned %d\n", status);
        fsw_free(pvol);
        return NULL;
    }
    
    return pvol;
}
示例#2
0
static void fsw_ext2_volume_free(struct fsw_ext2_volume *vol)
{
    if (vol->sb)
        fsw_free(vol->sb);
    if (vol->inotab_bno)
        fsw_free(vol->inotab_bno);
}
static void fsw_blockcache_free(struct fsw_volume *vol)
{
    fsw_u32 i;

    for (i = 0; i < vol->bcache_size; i++) {
        if (vol->bcache[i].data != NULL)
            fsw_free(vol->bcache[i].data);
    }
    if (vol->bcache != NULL) {
        fsw_free(vol->bcache);
        vol->bcache = NULL;
    }
    vol->bcache_size = 0;
}
示例#4
0
int fsw_posix_unmount(struct fsw_posix_volume *pvol)
{
    if (pvol->vol != NULL)
        fsw_unmount(pvol->vol);
    fsw_free(pvol);
    return 0;
}
void fsw_dnode_release(struct fsw_dnode *dno)
{
    struct fsw_volume *vol = dno->vol;
    struct fsw_dnode *parent_dno;

    dno->refcount--;

    if (dno->refcount == 0) {
        parent_dno = dno->parent;

        // de-register from volume's list
        if (dno->next)
            dno->next->prev = dno->prev;
        if (dno->prev)
            dno->prev->next = dno->next;
        if (vol->dnode_head == dno)
            vol->dnode_head = dno->next;

        // run fstype-specific cleanup
        vol->fstype_table->dnode_free(vol, dno);

        fsw_strfree(&dno->name);
        fsw_free(dno);

        // release our pointer to the parent, possibly deallocating it, too
        if (parent_dno)
            fsw_dnode_release(parent_dno);
    }
}
void fsw_unmount(struct fsw_volume *vol)
{
    if (vol->root)
        fsw_dnode_release(vol->root);
    /// @todo check that no other dnodes are still around

    vol->fstype_table->volume_free(vol);

    fsw_blockcache_free(vol);
    fsw_strfree(&vol->label);
    fsw_free(vol);
}
示例#7
0
struct fsw_posix_dir * fsw_posix_opendir(struct fsw_posix_volume *pvol, const char *path)
{
    fsw_status_t        status;
    struct fsw_posix_dir *dir;
    
    // allocate file structure
    status = fsw_alloc(sizeof(struct fsw_posix_dir), &dir);
    if (status)
        return NULL;
    dir->pvol = pvol;
    
    // open the directory
    status = fsw_posix_open_dno(pvol, path, FSW_DNODE_TYPE_DIR, &dir->shand);
    if (status) {
        fprintf(stderr, "fsw_posix_opendir: open_dno returned %d\n", status);
        fsw_free(dir);
        return NULL;
    }
    
    return dir;
}
示例#8
0
fsw_status_t fsw_dnode_create_with_tree(struct fsw_dnode *parent_dno, fsw_u64 tree_id, fsw_u64 dnode_id, int type,
                              struct fsw_string *name, struct fsw_dnode **dno_out)
{
    fsw_status_t    status;
    struct fsw_volume *vol = parent_dno->vol;
    struct fsw_dnode *dno;

    // check if we already have a dnode with the same id
    for (dno = vol->dnode_head; dno; dno = dno->next) {
        if (dno->dnode_id == dnode_id && dno->tree_id == tree_id) {
            fsw_dnode_retain(dno);
            *dno_out = dno;
            return FSW_SUCCESS;
        }
    }

    // allocate memory for the structure
    status = fsw_alloc_zero(vol->fstype_table->dnode_struct_size, (void **)&dno);
    if (status)
        return status;

    // fill the structure
    dno->vol = vol;
    dno->parent = parent_dno;
    fsw_dnode_retain(dno->parent);
    dno->tree_id = tree_id;
    dno->dnode_id = dnode_id;
    dno->type = type;
    dno->refcount = 1;
    status = fsw_strdup_coerce(&dno->name, vol->host_table->native_string_type, name);
    if (status) {
        fsw_free(dno);
        return status;
    }

    fsw_dnode_register(vol, dno);

    *dno_out = dno;
    return FSW_SUCCESS;
}
示例#9
0
struct fsw_posix_file * fsw_posix_open(struct fsw_posix_volume *pvol, const char *path, int flags, mode_t mode)
{
    fsw_status_t        status;
    struct fsw_posix_file *file;
    
    // TODO: check flags for unwanted values
    
    // allocate file structure
    status = fsw_alloc(sizeof(struct fsw_posix_file), &file);
    if (status)
        return NULL;
    file->pvol = pvol;
    
    // open the file
    status = fsw_posix_open_dno(pvol, path, FSW_DNODE_TYPE_FILE, &file->shand);
    if (status) {
        fprintf(stderr, "fsw_posix_open: open_dno returned %d\n", status);
        fsw_free(file);
        return NULL;
    }
    
    return file;
}
示例#10
0
static struct fsw_volume *create_dummy_volume(EFI_DISK_IO *diskio, UINT32 mediaid)
{
    fsw_status_t err;
    struct fsw_volume *vol;
    FSW_VOLUME_DATA *Volume;

    err = fsw_alloc_zero(sizeof(struct fsw_volume), (void **)&vol);
    if(err)
        return NULL;
    err = fsw_alloc_zero(sizeof(FSW_VOLUME_DATA), (void **)&Volume);
    if(err) {
        fsw_free(vol);
        return NULL;
    }
    /* fstype_table->volume_free for fsw_unmount */
    vol->fstype_table = &dummy_fstype;
    /* host_data needded to fsw_block_get()/fsw_efi_read_block() */
    Volume->DiskIo = diskio;
    Volume->MediaId = mediaid;

    vol->host_data = Volume;
    vol->host_table = &fsw_efi_host_table;
    return vol;
}
示例#11
0
int fsw_posix_close(struct fsw_posix_file *file)
{
    fsw_shandle_close(&file->shand);
    fsw_free(file);
    return 0;
}
示例#12
0
static void fsw_ext2_dnode_free(struct fsw_ext2_volume *vol, struct fsw_ext2_dnode *dno)
{
    if (dno->raw)
        fsw_free(dno->raw);
}
示例#13
0
int fsw_posix_closedir(struct fsw_posix_dir *dir)
{
    fsw_shandle_close(&dir->shand);
    fsw_free(dir);
    return 0;
}
fsw_status_t fsw_block_get(struct VOLSTRUCTNAME *vol, fsw_u32 phys_bno, fsw_u32 cache_level, void **buffer_out)
{
    fsw_status_t    status;
    fsw_u32         i, discard_level, new_bcache_size;
    struct fsw_blockcache *new_bcache;

    /// @todo allow the host driver to do its own caching; just call through if
    //  the appropriate function pointers are set

    if (cache_level > MAX_CACHE_LEVEL)
        cache_level = MAX_CACHE_LEVEL;

    // check block cache
    for (i = 0; i < vol->bcache_size; i++) {
        if (vol->bcache[i].phys_bno == phys_bno) {
            // cache hit!
            if (vol->bcache[i].cache_level < cache_level)
                vol->bcache[i].cache_level = cache_level;  // promote the entry
            vol->bcache[i].refcount++;
            *buffer_out = vol->bcache[i].data;
            return FSW_SUCCESS;
        }
    }

    // find a free entry in the cache table
    for (i = 0; i < vol->bcache_size; i++) {
        if (vol->bcache[i].phys_bno == FSW_INVALID_BNO)
            break;
    }
    if (i >= vol->bcache_size) {
        for (discard_level = 0; discard_level <= MAX_CACHE_LEVEL; discard_level++) {
            for (i = 0; i < vol->bcache_size; i++) {
                if (vol->bcache[i].refcount == 0 && vol->bcache[i].cache_level <= discard_level)
                    break;
            }
            if (i < vol->bcache_size)
                break;
        }
    }
    if (i >= vol->bcache_size) {
        // enlarge / create the cache
        if (vol->bcache_size < 16)
            new_bcache_size = 16;
        else
            new_bcache_size = vol->bcache_size << 1;
        status = fsw_alloc(new_bcache_size * sizeof(struct fsw_blockcache), &new_bcache);
        if (status)
            return status;
        if (vol->bcache_size > 0)
            fsw_memcpy(new_bcache, vol->bcache, vol->bcache_size * sizeof(struct fsw_blockcache));
        for (i = vol->bcache_size; i < new_bcache_size; i++) {
            new_bcache[i].refcount = 0;
            new_bcache[i].cache_level = 0;
            new_bcache[i].phys_bno = FSW_INVALID_BNO;
            new_bcache[i].data = NULL;
        }
        i = vol->bcache_size;

        // switch caches
        if (vol->bcache != NULL)
            fsw_free(vol->bcache);
        vol->bcache = new_bcache;
        vol->bcache_size = new_bcache_size;
    }
    vol->bcache[i].phys_bno = FSW_INVALID_BNO;

    // read the data
    if (vol->bcache[i].data == NULL) {
        status = fsw_alloc(vol->phys_blocksize, &vol->bcache[i].data);
        if (status)
            return status;
    }
    status = vol->host_table->read_block(vol, phys_bno, vol->bcache[i].data);
    if (status)
        return status;

    vol->bcache[i].phys_bno = phys_bno;
    vol->bcache[i].cache_level = cache_level;
    vol->bcache[i].refcount = 1;
    *buffer_out = vol->bcache[i].data;
    return FSW_SUCCESS;
}
void fsw_shandle_close(struct fsw_shandle *shand)
{
    if (shand->extent.type == FSW_EXTENT_TYPE_BUFFER)
        fsw_free(shand->extent.buffer);
    fsw_dnode_release(shand->dnode);
}
示例#16
0
static void fsw_iso9660_volume_free(struct fsw_iso9660_volume *vol)
{
    if (vol->primary_voldesc)
        fsw_free(vol->primary_voldesc);
}
示例#17
0
static fsw_status_t fsw_iso9660_volume_mount(struct fsw_iso9660_volume *vol)
{
    fsw_status_t    status;
    void            *buffer;
    fsw_u32         blockno;
    struct iso9660_volume_descriptor *voldesc;
    struct iso9660_primary_volume_descriptor *pvoldesc;
    fsw_u32         voldesc_type;
    int             i;
    struct fsw_string s;
    struct iso9660_dirrec rootdir;
    int sua_pos;
    char *sig;
    int skip;
    struct fsw_rock_ridge_susp_entry *entry;

    // read through the Volume Descriptor Set
    fsw_set_blocksize(vol, ISO9660_BLOCKSIZE, ISO9660_BLOCKSIZE);
    blockno = ISO9660_SUPERBLOCK_BLOCKNO;

    do {
        status = fsw_block_get(vol, blockno, 0, &buffer);
        if (status)
            return status;

        voldesc = (struct iso9660_volume_descriptor *)buffer;
        voldesc_type = voldesc->volume_descriptor_type;
        if (fsw_memeq(voldesc->standard_identifier, "CD001", 5)) {
            // descriptor follows ISO 9660 standard
            if (voldesc_type == 1 && voldesc->volume_descriptor_version == 1) {
                // suitable Primary Volume Descriptor found
                if (vol->primary_voldesc) {
                    fsw_free(vol->primary_voldesc);
                    vol->primary_voldesc = NULL;
                }
                status = fsw_memdup((void **)&vol->primary_voldesc, voldesc, ISO9660_BLOCKSIZE);
            }
        } else if (!fsw_memeq(voldesc->standard_identifier, "CD", 2)) {
            // completely alien standard identifier, stop reading
            voldesc_type = 255;
        }

        fsw_block_release(vol, blockno, buffer);
        blockno++;
    } while (!status && voldesc_type != 255);
    if (status)
        return status;

    // get information from Primary Volume Descriptor
    if (vol->primary_voldesc == NULL)
        return FSW_UNSUPPORTED;
    pvoldesc = vol->primary_voldesc;
    if (ISOINT(pvoldesc->logical_block_size) != 2048)
        return FSW_UNSUPPORTED;

    // get volume name
    for (i = 32; i > 0; i--)
        if (pvoldesc->volume_identifier[i-1] != ' ')
            break;
    s.type = FSW_STRING_TYPE_ISO88591;
    s.size = s.len = i;
    s.data = pvoldesc->volume_identifier;
    status = fsw_strdup_coerce(&vol->g.label, vol->g.host_string_type, &s);
    if (status)
        return status;

    // setup the root dnode
    status = fsw_dnode_create_root(vol, ISO9660_SUPERBLOCK_BLOCKNO << ISO9660_BLOCKSIZE_BITS, &vol->g.root);
    if (status)
        return status;
    fsw_memcpy(&vol->g.root->dirrec, &pvoldesc->root_directory, sizeof(struct iso9660_dirrec));

    if (   pvoldesc->escape[0] == 0x25
        && pvoldesc->escape[1] == 0x2f
        && (   pvoldesc->escape[2] == 0x40
            || pvoldesc->escape[2] == 0x43
            || pvoldesc->escape[2] == 0x45))
    {
        FSW_MSG_DEBUG((FSW_MSGSTR("fsw_iso9660_volume_mount: success (joliet!!!)\n")));
        vol->fJoliet = 1;
    }


    fsw_memcpy(&rootdir, &pvoldesc->root_directory, sizeof(rootdir));
    sua_pos = (sizeof(struct iso9660_dirrec)) + rootdir.file_identifier_length + (rootdir.file_identifier_length % 2) - 2;
    //int sua_size = rootdir.dirrec_length - rootdir.file_identifier_length;
    //FSW_MSG_DEBUG((FSW_MSGSTR("fsw_iso9660_volume_mount: success (SUA(pos:%x, sz:%d)!!!)\n"), sua_pos, sua_size));

#if 1
    status = fsw_block_get(vol, ISOINT(rootdir.extent_location), 0, &buffer);
    sig = (char *)buffer + sua_pos;
    skip = 0;
    entry = (struct fsw_rock_ridge_susp_entry *)sig;
    if (   entry->sig[0] == 'S'
        && entry->sig[1] == 'P')
    {
        struct fsw_rock_ridge_susp_sp *sp = (struct fsw_rock_ridge_susp_sp *)entry;
        if (sp->magic[0] == 0xbe && sp->magic[1] == 0xef)
        {
            vol->fRockRidge = 1;
        } else {
            FSW_MSG_DEBUG((FSW_MSGSTR("fsw_iso9660_volume_mount: SP magic isn't valid\n")));
        }
        skip = sp->skip;
    }
#endif
    // release volume descriptors
    fsw_free(vol->primary_voldesc);
    vol->primary_voldesc = NULL;


    FSW_MSG_DEBUG((FSW_MSGSTR("fsw_iso9660_volume_mount: success\n")));

    return FSW_SUCCESS;
}
示例#18
0
static fsw_status_t rr_find_nm(struct fsw_iso9660_volume *vol, struct iso9660_dirrec *dirrec, int off, struct fsw_string *str)
{
    fsw_u8 *r, *begin;
    int fCe = 0;
    struct fsw_rock_ridge_susp_nm *nm;
    int limit = dirrec->dirrec_length;
    begin = (fsw_u8 *)dirrec;
    r = (fsw_u8 *)dirrec + off;
    str->data = NULL;
    str->len = 0;
    str->size = 0;
    str->type = 0;
    while(off < limit)
    {
        if (r[0] == 'C' && r[1] == 'E' && r[2] == 28)
        {
            int rc;
            int ce_off;
            union fsw_rock_ridge_susp_ce *ce;
            if (fCe == 0)
                fsw_alloc_zero(ISO9660_BLOCKSIZE, (void *)&begin);
            fCe = 1;
            DEBUG((DEBUG_WARN, "%a:%d we found CE before NM or its continuation\n", __FILE__, __LINE__));
            ce = (union fsw_rock_ridge_susp_ce *)r;
            limit = ISOINT(ce->X.len);
            ce_off = ISOINT(ce->X.offset);
            rc = rr_read_ce(vol, ce, begin);
            if (rc != FSW_SUCCESS)
            {
                fsw_free(begin);
                return rc;
            }
            begin += ce_off;
            r = begin;
        }
        if (r[0] == 'N' && r[1] == 'M')
        {
            nm = (struct fsw_rock_ridge_susp_nm *)r;
            if(    nm->e.sig[0] == 'N'
                && nm->e.sig[1] == 'M')
            {
                int len = 0;
                fsw_u8 *tmp = NULL;
                if (nm->flags & RR_NM_CURR)
                {
                     fsw_memdup(str->data, ".", 1);
                     str->len = 1;
                     goto done;
                }
                if (nm->flags & RR_NM_PARE)
                {
                     fsw_memdup(str->data, "..", 2);
                     str->len = 2;
                     goto done;
                }
                len = nm->e.len - sizeof(struct fsw_rock_ridge_susp_nm) + 1;
                fsw_alloc_zero(str->len + len, (void **)&tmp);
                if (str->data != NULL)
                {
                    fsw_memcpy(tmp, str->data, str->len);
                    fsw_free(str->data);
                }
                DEBUG((DEBUG_INFO, "dst:%p src:%p len:%d\n", tmp + str->len, &nm->name[0], len));
                fsw_memcpy(tmp + str->len, &nm->name[0], len);
                str->data = tmp;
                str->len += len;

                if ((nm->flags & RR_NM_CONT) == 0)
                    goto done;
            }
        }
        r++;
        off = (int)(r - (fsw_u8 *)begin);
    }
    if(fCe == 1)
        fsw_free(begin);
    return FSW_NOT_FOUND;
done:
    str->type = FSW_STRING_TYPE_ISO88591;
    str->size = str->len;
    if(fCe == 1)
        fsw_free(begin);
    return FSW_SUCCESS;
}
示例#19
0
static void free_dummy_volume(struct fsw_volume *vol)
{
    fsw_free(vol->host_data);
    fsw_unmount(vol);
}
fsw_status_t fsw_shandle_read(struct fsw_shandle *shand, fsw_u32 *buffer_size_inout, void *buffer_in)
{
    fsw_status_t    status;
    struct fsw_dnode *dno = shand->dnode;
    struct fsw_volume *vol = dno->vol;
    fsw_u8          *buffer, *block_buffer;
    fsw_u32         buflen, copylen, pos;
    fsw_u32         log_bno, pos_in_extent, phys_bno, pos_in_physblock;
    fsw_u32         cache_level;

    if (shand->pos >= dno->size) {   // already at EOF
        *buffer_size_inout = 0;
        return FSW_SUCCESS;
    }

    // initialize vars
    buffer = buffer_in;
    buflen = *buffer_size_inout;
    pos = (fsw_u32)shand->pos;
    cache_level = (dno->type != FSW_DNODE_TYPE_FILE) ? 1 : 0;
    // restrict read to file size
    if (buflen > dno->size - pos)
        buflen = (fsw_u32)(dno->size - pos);

    while (buflen > 0) {
        // get extent for the current logical block
        log_bno = pos / vol->log_blocksize;
        if (shand->extent.type == FSW_EXTENT_TYPE_INVALID ||
            log_bno < shand->extent.log_start ||
            log_bno >= shand->extent.log_start + shand->extent.log_count) {

            if (shand->extent.type == FSW_EXTENT_TYPE_BUFFER)
                fsw_free(shand->extent.buffer);

            // ask the file system for the proper extent
            shand->extent.log_start = log_bno;
            status = vol->fstype_table->get_extent(vol, dno, &shand->extent);
            if (status) {
                shand->extent.type = FSW_EXTENT_TYPE_INVALID;
                return status;
            }
        }

        pos_in_extent = pos - shand->extent.log_start * vol->log_blocksize;

        // dispatch by extent type
        if (shand->extent.type == FSW_EXTENT_TYPE_PHYSBLOCK) {
            // convert to physical block number and offset
            phys_bno = shand->extent.phys_start + pos_in_extent / vol->phys_blocksize;
            pos_in_physblock = pos_in_extent & (vol->phys_blocksize - 1);
            copylen = vol->phys_blocksize - pos_in_physblock;
            if (copylen > buflen)
                copylen = buflen;

            // get one physical block
            status = fsw_block_get(vol, phys_bno, cache_level, (void **)&block_buffer);
            if (status)
                return status;

            // copy data from it
            fsw_memcpy(buffer, block_buffer + pos_in_physblock, copylen);
            fsw_block_release(vol, phys_bno, block_buffer);

        } else if (shand->extent.type == FSW_EXTENT_TYPE_BUFFER) {
            copylen = shand->extent.log_count * vol->log_blocksize - pos_in_extent;
            if (copylen > buflen)
                copylen = buflen;
            fsw_memcpy(buffer, (fsw_u8 *)shand->extent.buffer + pos_in_extent, copylen);

        } else {   // _SPARSE or _INVALID
            copylen = shand->extent.log_count * vol->log_blocksize - pos_in_extent;
            if (copylen > buflen)
                copylen = buflen;
            fsw_memzero(buffer, copylen);

        }

        buffer += copylen;
        buflen -= copylen;
        pos    += copylen;
    }

    *buffer_size_inout = (fsw_u32)(pos - shand->pos);
    shand->pos = pos;

    return FSW_SUCCESS;
}
示例#21
0
文件: fsw_lib.c 项目: jeppeter/vbox
void fsw_strfree(struct fsw_string *s)
{
    if (s->type != FSW_STRING_TYPE_EMPTY && s->data)
        fsw_free(s->data);
    s->type = FSW_STRING_TYPE_EMPTY;
}