示例#1
0
static int
read_next_dir_buffer (FatTraverseInfo* trav_info)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (trav_info->fs);

	PED_ASSERT (!trav_info->is_legacy_root_dir);

	trav_info->this_buffer = trav_info->next_buffer;

	if (trav_info->this_buffer < 2
	    || trav_info->this_buffer >= fs_info->cluster_count + 2) {
		ped_exception_throw (
			PED_EXCEPTION_ERROR,
			PED_EXCEPTION_CANCEL,
			"Cluster %ld in directory %s is outside file system!",
			(long) trav_info->this_buffer,
			trav_info->dir_name);
		return 0;
	}

	trav_info->next_buffer
		= fat_table_get (fs_info->fat, trav_info->this_buffer);

	return fat_read_cluster (trav_info->fs, (void *) trav_info->dir_entries,
				 trav_info->this_buffer);
}
示例#2
0
文件: vfsfat.c 项目: pagxir/deadshot
static int fatfs_lookup(void *priv, const char *name, struct vfs_node *dir)
{
    struct fatfs_dirent *dirent = (struct fatfs_dirent *)priv;
    struct fatfs_priv   *fsop   = dirent->fs;

    size_t bytes_per_cluster = (fsop->bytes_per_sector * fsop->sectors_per_cluster);
    char *cluster_buffer = (char *)malloc(bytes_per_cluster);

    if (dirent->flag & 0xFF00) {
        return fatfs_root(fsop, name, dir);
    }else if (!IS_DIR(dirent->flag)) {
        return -1;
    }

    size_t valid_cluster = dirent->entry;
    size_t dpcnt = bytes_per_cluster / 32;
    struct fat_entry *dirents, entry;
    dirents = (struct fat_entry *)cluster_buffer;
    
    struct fat_opvector *opv = fsop->opvector;
    while (valid_cluster < opv->fat_max_cluster) {
        size_t cluster;
        if (-1 == fat_read_cluster(fsop, valid_cluster, cluster_buffer)) {
            free(cluster_buffer);
            return -1;
        }

        if (0 == fat_dirent_lookup(dirents, dpcnt, name, &entry)) {
            VFS_MALLOC(struct fatfs_dirent, dirent);
            dirent->length = entry.length;
            dirent->entry  = entry.cluster_entry| (entry.cluster_high << 16);
            dirent->entry &= opv->fat_cluster_mask;
            printf("found: %d\n", dirent->entry);
            dirent->flag   = entry.attribute;
            dirent->fs = fsop;
            dir->vops = &fatfs_vops;
            dir->priv = dirent;
            free(cluster_buffer);
            return 0;
        }
        
        if (-1 == (*opv->fat_next_cluster)(fsop, valid_cluster, &cluster)) {
            free(cluster_buffer);
            return -1;
        }
        valid_cluster = cluster;
    }

    free(cluster_buffer);
    return -1;
}
示例#3
0
文件: vfsfat.c 项目: pagxir/deadshot
int fatfs_pread(struct fatfs_dirent *file, void *buf, size_t count, size_t off)
{
    if (!IS_DIR(file->flag)) {
        if (off > file->length)
            return -1;
        if (off + count > file->length)
            count = file->length - off;
    }

    if (count == 0)
        return 0;

    if (off < file->offset) {
        file->cluster = file->entry;
        file->offset = 0;
    }

    size_t i;
    struct fatfs_priv *fs = (struct fatfs_priv *)file->fs;
    size_t bytes_per_cluster = (fs->bytes_per_sector * fs->sectors_per_cluster);
    size_t cluster_count = (offset - file->offset) / bytes_per_cluster;

    struct fat_opvector *opv = fs->opvector;
    while (cluster_count > 0) {
        size_t cluster;
        if ((*opv->fat_next_cluster)(fs, file->cluster, &cluster) == -1) {
            return -1;
        }
        if (cluster >= opv->fat_max_cluster) {
            return 0;
        }
        file->offset += bytes_per_cluster;
        file->cluster = cluster;
        cluster_count--;
    }

    char *cluster_buffer = (char *)malloc(bytes_per_cluster);
    assert(cluster_buffer);

    if (fat_read_cluster(fs, file->cluster, cluster_buffer)) {
        free(cluster_buffer);
        return -1;
    }

    size_t cluster_offset = off - file->offset;
    size_t cpcnt = bytes_per_cluster > cluster_offset + count?
        count: bytes_per_cluster - cluster_offset;
    memcpy(buf, cluster_buffer + cluster_offset, cpcnt);
    free(cluster_buffer);
    off += cpcnt;
    count -= cpcnt;

    int hr = 0;

    while (off < file->length && count > 0) {
        if ((hr = fatfs_pread(file, (char*)buf + cpcnt, count, off)) == -1) {
            return -1;
        }
        if (hr == 0) {
            break;
        }
        off += hr;
        count -= hr;
        cpcnt += hr;
    }

    return cpcnt;
}
示例#4
0
文件: fat_file.c 项目: BarryChen/RDA
INT32 fat_file_read(struct inode *inode, 
                    struct file * filp, INT8 * buf, INT32 len)
{
    FAT_DIR_ENTRY d_entry = {0,};
    FAT_SB_INFO* sb = NULL;
    UINT32 fpos = 0;
    UINT32 fsize = 0;
    UINT32 secperclu = 0;
    
    INT32 rcount = 0;
    UINT32 rsize = 0;
    UINT32  cursec, secnum;
    UINT32 clunum, secoff;
    UINT8* secbuf;
    INT8* bufp = NULL;
    
    INT32 iResult = _ERR_FAT_SUCCESS;


     d_entry = inode->u.fat_i.entry;
     sb = &(inode->i_sb->u.fat_sb);
     fpos = filp->f_pos;
     fsize = d_entry.DIR_FileSize;
     secperclu = (UINT32)sb->iSecPerClus;
     bufp = buf;

    
    // set the rsize.
    if(fpos > fsize)
    {
        D( ( DL_FATERROR, "in fat_file_read. fpos(%d) >  fsize(%d).\n",fpos,fsize) );
        return _ERR_FAT_READ_EXCEED;
    }
    else if(fpos+len > fsize)
    {
        rsize = fsize - fpos;
    }
    else
    {
        rsize = len;
    }
    
    // malloc the secbuf for read sector.
    secbuf = FAT_SECT_BUF_ALLOC();
    if(NULL == secbuf)
    {        
        D(( DL_FATERROR,"in fat_file_read,1.FAT_SECT_BUF_ALLOC() failed.")); 
        DSM_ASSERT(0,"in fat_file_read,1.FAT_SECT_BUF_ALLOC() failed.");
        return _ERR_FAT_MALLOC_FAILED;
    }  
    
    // get the wcluser number.
    iResult = fat_fpos2CSO(filp->f_inode, fpos, &clunum, &secnum, &secoff, (UINT32*)NULL);
    if (iResult != _ERR_FAT_SUCCESS)
    {
        // Out of file size,error.
        D( ( DL_FATERROR, "fat_file_read: fat_fpos2CSO error!!!\n") );
        g_TstFsErrCode = 1019;
        iResult = _ERR_FAT_ERROR;
        goto end;
    }
    
    cursec = secnum; 
    
    while(!fat_is_last_cluster(sb, clunum))
    {
        for(cursec = secnum; cursec < secperclu; cursec++)
        {
            // DSM_MemSet(secbuf, 0x00, DEFAULT_SECSIZE);
            iResult = fat_read_cluster(sb, clunum, cursec, secbuf);
            if(_ERR_FAT_SUCCESS != iResult)
            {
                D( ( DL_FATERROR, "Call fat_read_cluster() failed. Local error code:%d. clunum = 0x%x, secnum = 0x%x.\n",iResult, clunum, cursec) );
                iResult = _ERR_FAT_READ_SEC_FAILED;
                goto end;
            }
            
            if(0 == secoff)
            {
                if(rsize > DEFAULT_SECSIZE)
                {
                    DSM_MemCpy(bufp, secbuf, DEFAULT_SECSIZE);
                    
                    filp->f_pos += DEFAULT_SECSIZE;
                    bufp += DEFAULT_SECSIZE;
                    rsize -= DEFAULT_SECSIZE;
                    rcount += DEFAULT_SECSIZE;
                    secoff = 0;
                }
                else if (rsize == DEFAULT_SECSIZE)
                {
                    DSM_MemCpy(bufp, secbuf, DEFAULT_SECSIZE);
                    
                    filp->f_pos += DEFAULT_SECSIZE;
                    bufp += DEFAULT_SECSIZE;
                    rsize -= DEFAULT_SECSIZE;
                    rcount += DEFAULT_SECSIZE;
                    secoff = 0;

                    goto end;
                }
                else //secoff + rsize <= DEFAULT_SECSIZE (1)
                {
                    DSM_MemCpy(bufp, secbuf, rsize);
                    
                    filp->f_pos += rsize;
                    bufp += rsize;
                    secoff = secoff + rsize;
                    rcount += rsize;
                    rsize = 0;

                    goto end;
                }
            }
            else // secoff > 0
            {
                if(secoff + rsize > DEFAULT_SECSIZE)
                {
                    DSM_MemCpy(bufp, secbuf+secoff, DEFAULT_SECSIZE-secoff);
                    
                    filp->f_pos += (DEFAULT_SECSIZE-secoff);
                    bufp += (DEFAULT_SECSIZE-secoff);
                    rsize -= (DEFAULT_SECSIZE-secoff);
                    rcount += (DEFAULT_SECSIZE-secoff);
                    secoff = 0;
                }
                else //secoff + rsize <= DEFAULT_SECSIZE (1)
                {
                    DSM_MemCpy(bufp, secbuf+secoff, rsize);
                    
                    filp->f_pos += rsize;
                    bufp += rsize;
                    secoff = secoff + rsize;
                    rcount += rsize;
                    rsize = 0;
                    goto end;
                }
            }
            
        }

        // Get next cluster, secnum, secoff
        iResult = fat_fpos2CSO(filp->f_inode, filp->f_pos, &clunum, &secnum, &secoff, (UINT32*)NULL);
        if (iResult != _ERR_FAT_SUCCESS)
        {
           // Out of file size,error.
            D( ( DL_FATERROR, "fat_file_read: fat_fpos2CSO error2 !!!\n") );
            iResult = _ERR_FAT_ERROR;
            g_TstFsErrCode = 1020;
            goto end;
        }                
        DSM_ASSERT((BOOL)(clunum >= 2),"clunum = %d.",clunum);    
            
    }
    
end:

    if(NULL != secbuf) 
    {
        FAT_SECT_BUF_FREE((SECT_BUF*)secbuf);
    }

    rcount = _ERR_FAT_SUCCESS == iResult ? rcount: iResult;
    return rcount;
}
示例#5
0
static int
fatfs_rename(vnode_t dvp1, vnode_t vp1, char *name1,
             vnode_t dvp2, vnode_t vp2, char *name2)
{
    struct fatfsmount *fmp;
    struct fatfs_node np1;
    struct fat_dirent *de1, *de2;
    int error;

    fmp = dvp1->v_mount->m_data;
    mutex_lock(&fmp->lock);

    error = fatfs_lookup_node(dvp1, name1, &np1);
    if (error)
        goto out;
    de1 = &np1.dirent;

    if (IS_FILE(de1)) {
        /* Remove destination file, first */
        error = fatfs_remove(dvp2, vp1, name2);
        if (error == EIO)
            goto out;

        /* Change file name of directory entry */
        fat_convert_name(name2, (char *)de1->name);

        /* Same directory ? */
        if (dvp1 == dvp2) {
            /* Change the name of existing file */
            error = fatfs_put_node(fmp, &np1);
            if (error)
                goto out;
        } else {
            /* Create new directory entry */
            error = fatfs_add_node(dvp2, &np1);
            if (error)
                goto out;

            /* Remove souce file */
            error = fatfs_remove(dvp1, vp2, name1);
            if (error)
                goto out;
        }
    } else {

        /* remove destination directory */
        error = fatfs_rmdir(dvp2, NULL, name2);
        if (error == EIO)
            goto out;

        /* Change file name of directory entry */
        fat_convert_name(name2, (char *)de1->name);

        /* Same directory ? */
        if (dvp1 == dvp2) {
            /* Change the name of existing directory */
            error = fatfs_put_node(fmp, &np1);
            if (error)
                goto out;
        } else {
            /* Create new directory entry */
            error = fatfs_add_node(dvp2, &np1);
            if (error)
                goto out;

            /* Update "." and ".." for renamed directory */
            if (fat_read_cluster(fmp,(de1->cluster_hi << 16) |  de1->cluster)) {
                error = EIO;
                goto out;
            }

            de2 = (struct fat_dirent *)fmp->io_buf;
            de2->cluster_hi = de1->cluster_hi;
            de2->cluster = de1->cluster;
            de2->time = TEMP_TIME;
            de2->date = TEMP_DATE;
            de2++;
            de2->cluster_hi = (dvp2->v_blkno & 0xFFFF0000) >> 16;
            de2->cluster = dvp2->v_blkno & 0x0000FFFF;
            de2->time = TEMP_TIME;
            de2->date = TEMP_DATE;

            if (fat_write_cluster(fmp,(de1->cluster_hi << 16) |  de1->cluster)) {
                error = EIO;
                goto out;
            }

            /* Remove souce directory */
            error = fatfs_rmdir(dvp1, NULL, name1);
            if (error)
                goto out;
        }
    }
out:
    mutex_unlock(&fmp->lock);
    return error;
}
示例#6
0
static int
fatfs_write(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
{
    struct fatfsmount *fmp;
    struct fatfs_node *np;
    struct fat_dirent *de;
    int nr_copy, nr_write, buf_pos, i, cl_size, error;
    u_long file_pos, end_pos;
    u_long cl;

    DPRINTF(("fatfs_write: vp=%x size=%d\n", vp, size));

    *result = 0;
    fmp = vp->v_mount->m_data;

    if (vp->v_type == VDIR)
        return EISDIR;
    if (vp->v_type != VREG)
        return EINVAL;

    mutex_lock(&fmp->lock);

    /* Check if file position exceeds the end of file. */
    end_pos = vp->v_size;
    file_pos = (fp->f_flags & O_APPEND) ? end_pos : fp->f_offset;
    if (file_pos + size > end_pos) {
        /* Expand the file size before writing to it */
        end_pos = file_pos + size;
        error = fat_expand_file(fmp, vp->v_blkno, end_pos);
        if (error) {
            error = EIO;
            goto out;
        }

        /* Update directory entry */
        np = vp->v_data;
        de = &np->dirent;
        de->size = end_pos;
        error = fatfs_put_node(fmp, np);
        if (error)
            goto out;
        vp->v_size = end_pos;
    }

    /* Seek to the cluster for the file offset */
    error = fat_seek_cluster(fmp, vp->v_blkno, file_pos, &cl);
    if (error)
        goto out;

    buf_pos = file_pos % fmp->cluster_size;
    cl_size = size / fmp->cluster_size + 1;
    nr_write = 0;
    i = 0;
    do {
        /* First and last cluster must be read before write */
        if (i == 0 || i == cl_size) {
            if (fat_read_cluster(fmp, cl)) {
                error = EIO;
                goto out;
            }
        }
        nr_copy = fmp->cluster_size;
        if (buf_pos > 0)
            nr_copy -= buf_pos;
        if (buf_pos + size < fmp->cluster_size)
            nr_copy = size;
        memcpy(fmp->io_buf + buf_pos, buf, nr_copy);

        if (fat_write_cluster(fmp, cl)) {
            error = EIO;
            goto out;
        }
        file_pos += nr_copy;
        nr_write += nr_copy;
        size -= nr_copy;
        if (size <= 0)
            break;

        error = fat_next_cluster(fmp, cl, &cl);
        if (error)
            goto out;

        buf = (void *)((u_long)buf + nr_copy);
        buf_pos = 0;
        i++;
    } while (!IS_EOFCL(fmp, cl));

    fp->f_offset = file_pos;

    /*
     * XXX: Todo!
     *    de.time = ?
     *    de.date = ?
     *    if (dirent_set(fp, &de))
     *        return EIO;
     */
    *result = nr_write;
    error = 0;
out:
    mutex_unlock(&fmp->lock);
    return error;
}
示例#7
0
static int
fatfs_read(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
{
    struct fatfsmount *fmp;
    int nr_read, nr_copy, buf_pos, error;
    u_long cl, file_pos;

    DPRINTF(("fatfs_read: vp=%x\n", vp));

    *result = 0;
    fmp = vp->v_mount->m_data;

    if (vp->v_type == VDIR)
        return EISDIR;
    if (vp->v_type != VREG)
        return EINVAL;

    /* Check if current file position is already end of file. */
    file_pos = fp->f_offset;
    if (file_pos >= vp->v_size)
        return 0;

    mutex_lock(&fmp->lock);

    /* Get the actual read size. */
    if (vp->v_size - file_pos < size)
        size = vp->v_size - file_pos;

    /* Seek to the cluster for the file offset */
    error = fat_seek_cluster(fmp, vp->v_blkno, file_pos, &cl);
    if (error)
        goto out;

    /* Read and copy data */
    nr_read = 0;
    buf_pos = file_pos % fmp->cluster_size;
    do {
        if (fat_read_cluster(fmp, cl)) {
            error = EIO;
            goto out;
        }

        nr_copy = fmp->cluster_size;
        if (buf_pos > 0)
            nr_copy -= buf_pos;
        if (buf_pos + size < fmp->cluster_size)
            nr_copy = size;
        memcpy(buf, fmp->io_buf + buf_pos, nr_copy);

        file_pos += nr_copy;
        nr_read += nr_copy;
        size -= nr_copy;
        if (size <= 0)
            break;

        error = fat_next_cluster(fmp, cl, &cl);
        if (error)
            goto out;

        buf = (void *)((u_long)buf + nr_copy);
        buf_pos = 0;
    } while (!IS_EOFCL(fmp, cl));

    fp->f_offset = file_pos;
    *result = nr_read;
    error = 0;
out:
    mutex_unlock(&fmp->lock);
    return error;
}