예제 #1
0
파일: fatfs.c 프로젝트: KarenHung/ecosgit
static int 
fatfs_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
    fatfs_disk_t      *disk    = (fatfs_disk_t *)  fp->f_mte->data;
    fatfs_fd_t        *fd      = (fatfs_fd_t *)    fp->f_data;
    struct dirent     *ent     = (struct dirent *) uio->uio_iov[0].iov_base;
    char              *nbuf    = ent->d_name;
    off_t              len     = uio->uio_iov[0].iov_len;
    fatfs_dir_entry_t  dentry;
    int                err;
    
    CYG_TRACE3(TFO, "dirread fp=%p uio=%p pos=%d", fp, uio, fp->f_offset);

    if (len < sizeof(struct dirent))
        return EINVAL;

    err = fatfs_read_dir_entry(disk, &fd->node->dentry, &fd->pos, &dentry);

    if (err != ENOERR)
        return (err == EEOF ? ENOERR : err);

    strcpy(nbuf, dentry.filename);
#ifdef CYGPKG_FS_FAT_RET_DIRENT_DTYPE
    ent->d_type = dentry.mode;
#endif
    fd->node->dentry.atime  = cyg_timestamp();
    uio->uio_resid         -= sizeof(struct dirent);
    fp->f_offset++;
    
    return ENOERR;
}
예제 #2
0
파일: file-ecos.c 프로젝트: LucidOne/Rovio
//int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsigned end)
int jffs2_commit_write (struct inode *d_inode, struct page *pg, unsigned start, unsigned end)
{
	/* Actually commit the write from the page cache page we're looking at.
	 * For now, we write the full page out each time. It sucks, but it's simple
	 */
	struct inode *inode = d_inode;
	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
	struct jffs2_raw_inode *ri;
	int ret = 0;
	uint32_t writtenlen = 0;

	D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d\n",
		  inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end));


	ri = jffs2_alloc_raw_inode();
	if (!ri) {
		D1(printk(KERN_DEBUG "jffs2_commit_write(): Allocation of raw inode failed\n"));
		return -ENOMEM;
	}

	/* Set the fields that the generic jffs2_write_inode_range() code can't find */
	ri->ino = cpu_to_je32(inode->i_ino);
	ri->mode = cpu_to_jemode(inode->i_mode);
	ri->uid = cpu_to_je16(inode->i_uid);
	ri->gid = cpu_to_je16(inode->i_gid);
	ri->isize = cpu_to_je32((uint32_t)inode->i_size);
	ri->atime = ri->ctime = ri->mtime = cpu_to_je32(cyg_timestamp());

	ret = jffs2_write_inode_range(c, f, ri, page_address(pg) + start,
				      (pg->index << PAGE_CACHE_SHIFT) + start,
				      end - start, &writtenlen);

	if (ret) {
		/* There was an error writing. */
		SetPageError(pg);
	}

	if (writtenlen) {
		if (inode->i_size < (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen) {
			inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen;
			inode->i_ctime = inode->i_mtime = je32_to_cpu(ri->ctime);
		}
	}

	jffs2_free_raw_inode(ri);

	if (start+writtenlen < end) {
		/* generic_file_write has written more to the page cache than we've
		   actually written to the medium. Mark the page !Uptodate so that 
		   it gets reread */
		D1(printk(KERN_DEBUG "jffs2_commit_write(): Not all bytes written. Marking page !uptodate\n"));
		SetPageError(pg);
		ClearPageUptodate(pg);
	}

	D1(printk(KERN_DEBUG "jffs2_commit_write() returning %d\n",writtenlen?writtenlen:ret));
	return writtenlen?writtenlen:ret;
}
예제 #3
0
파일: fatfs.c 프로젝트: KarenHung/ecosgit
static int 
fatfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
    fatfs_disk_t  *disk   = (fatfs_disk_t *) fp->f_mte->data;
    fatfs_fd_t    *fd     = (fatfs_fd_t *)   fp->f_data;
    fatfs_node_t  *node   = fd->node;
    cyg_uint32     pos    = fp->f_offset;
    ssize_t        resid  = uio->uio_resid;
    int            i;

    CYG_TRACE3(TFO, "read fp=%p uio=%p pos=%d", fp, uio, pos);

    // Loop over the io vectors until there are none left

    for (i = 0; i < uio->uio_iovcnt; i++)
    {
        cyg_iovec  *iov  = &uio->uio_iov[i];
        char       *buf  = (char *) iov->iov_base;
        off_t       len  = iov->iov_len;

        // Loop over each vector filling it with data from the file
        
        while (len > 0 && pos < node->dentry.size)
        {
            cyg_uint32 l = len;
            int        err;

            // Adjust size to end of file if necessary
            if (l > node->dentry.size-pos)
                l = node->dentry.size-pos;

            err = fatfs_read_data(disk, &node->dentry, &fd->pos, buf, &l);
            if (err != ENOERR)
                return err;

            // Update working vars

            len   -= l;
            buf   += l;
            pos   += l;
            resid -= l;
        }
    }

    // We successfully read some data, update the access time, 
    // file offset and transfer residue

    node->dentry.atime = cyg_timestamp(); 
    uio->uio_resid     = resid;
    fp->f_offset       = (off_t) pos;

    return ENOERR;
}
예제 #4
0
파일: file-ecos.c 프로젝트: LucidOne/Rovio
//int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, unsigned end)
int jffs2_prepare_write (struct inode *d_inode, struct page *pg, unsigned start, unsigned end)
{
	struct inode *inode = d_inode;
	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
	uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT;
	int ret = 0;

	D1(printk(KERN_DEBUG "jffs2_prepare_write()\n"));

	if (pageofs > inode->i_size) {
		/* Make new hole frag from old EOF to new page */
		struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
		struct jffs2_raw_inode ri;
		struct jffs2_full_dnode *fn;
		uint32_t phys_ofs, alloc_len;
		
		D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
			  (unsigned int)inode->i_size, pageofs));

		ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, ALLOC_NORMAL);
		if (ret)
			return ret;

		down(&f->sem);
		memset(&ri, 0, sizeof(ri));

		ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
		ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
		ri.totlen = cpu_to_je32(sizeof(ri));
		ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4));

		ri.ino = cpu_to_je32(f->inocache->ino);
		ri.version = cpu_to_je32(++f->highest_version);
		ri.mode = cpu_to_jemode(inode->i_mode);
		ri.uid = cpu_to_je16(inode->i_uid);
		ri.gid = cpu_to_je16(inode->i_gid);

		ri.isize = cpu_to_je32(max((uint32_t)inode->i_size, pageofs));
		ri.atime = ri.ctime = ri.mtime = cpu_to_je32(cyg_timestamp());
		ri.offset = cpu_to_je32(inode->i_size);
		ri.dsize = cpu_to_je32(pageofs - inode->i_size);
		ri.csize = cpu_to_je32(0);
		ri.compr = JFFS2_COMPR_ZERO;
		ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
		ri.data_crc = cpu_to_je32(0);
		
		fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, NULL);
		jffs2_complete_reservation(c);
		if (IS_ERR(fn)) {
			ret = PTR_ERR(fn);
			up(&f->sem);
			return ret;
		}
		ret = jffs2_add_full_dnode_to_inode(c, f, fn);
		if (f->metadata) {
			jffs2_mark_node_obsolete(c, f->metadata->raw);
			jffs2_free_full_dnode(f->metadata);
			f->metadata = NULL;
		}
		if (ret) {
			D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in prepare_write, returned %d\n", ret));
			jffs2_mark_node_obsolete(c, fn->raw);
			jffs2_free_full_dnode(fn);
			up(&f->sem);
			return ret;
		}
		inode->i_size = pageofs;
		up(&f->sem);
	}
	

	/* Read in the page if it wasn't already present, unless it's a whole page */
        // eCos has no concept of uptodate and by default always reads pages afresh
	if (!Page_Uptodate(pg) && (start || end < PAGE_CACHE_SIZE)) {
		down(&f->sem);
		ret = jffs2_do_readpage_nolock(inode, pg);
		up(&f->sem);
	}
	D1(printk(KERN_DEBUG "end prepare_write()\n"));
	return ret;
}
예제 #5
0
int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode)
{
	struct jffs2_inode_info *f, *dir_f;
	struct jffs2_sb_info *c;
	struct _inode *inode;
	struct jffs2_raw_inode *ri;
	struct jffs2_raw_dirent *rd;
	struct jffs2_full_dnode *fn;
	struct jffs2_full_dirent *fd;
	int namelen;
	uint32_t alloclen, phys_ofs;
	int ret;

	mode |= S_IFDIR;

	ri = jffs2_alloc_raw_inode();
	if (!ri)
		return -ENOMEM;
	
	c = JFFS2_SB_INFO(dir_i->i_sb);

	/* Try to reserve enough space for both node and dirent. 
	 * Just the node will do for now, though 
	 */
	namelen = strlen(d_name);
	ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);

	if (ret) {
		jffs2_free_raw_inode(ri);
		return ret;
	}

	inode = jffs2_new_inode(dir_i, mode, ri);

	if (IS_ERR(inode)) {
		jffs2_free_raw_inode(ri);
		jffs2_complete_reservation(c);
		return PTR_ERR(inode);
	}

	f = JFFS2_INODE_INFO(inode);

	ri->data_crc = cpu_to_je32(0);
	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
	
	fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);

	jffs2_free_raw_inode(ri);

	if (IS_ERR(fn)) {
		/* Eeek. Wave bye bye */
		up(&f->sem);
		jffs2_complete_reservation(c);
		inode->i_nlink = 0;
		jffs2_iput(inode);
		return PTR_ERR(fn);
	}
	/* No data here. Only a metadata node, which will be 
	   obsoleted by the first data write
	*/
	f->metadata = fn;
	up(&f->sem);

	jffs2_complete_reservation(c);
	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
	if (ret) {
		/* Eep. */
		inode->i_nlink = 0;
		jffs2_iput(inode);
		return ret;
	}
	
	rd = jffs2_alloc_raw_dirent();
	if (!rd) {
		/* Argh. Now we treat it like a normal delete */
		jffs2_complete_reservation(c);
		inode->i_nlink = 0;
		jffs2_iput(inode);
		return -ENOMEM;
	}

	dir_f = JFFS2_INODE_INFO(dir_i);
	down(&dir_f->sem);

	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));

	rd->pino = cpu_to_je32(dir_i->i_ino);
	rd->version = cpu_to_je32(++dir_f->highest_version);
	rd->ino = cpu_to_je32(inode->i_ino);
	rd->mctime = cpu_to_je32(cyg_timestamp());
	rd->nsize = namelen;
	rd->type = DT_DIR;
	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
	rd->name_crc = cpu_to_je32(crc32(0, d_name, namelen));

	fd = jffs2_write_dirent(c, dir_f, rd, d_name, namelen, phys_ofs, ALLOC_NORMAL);
	
	jffs2_complete_reservation(c);
	jffs2_free_raw_dirent(rd);
	
	if (IS_ERR(fd)) {
		/* dirent failed to write. Delete the inode normally 
		   as if it were the final unlink() */
		up(&dir_f->sem);
		inode->i_nlink = 0;
		jffs2_iput(inode);
		return PTR_ERR(fd);
	}

	/* Link the fd into the inode's list, obsoleting an old
	   one if necessary. */
	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
	up(&dir_f->sem);

	jffs2_iput(inode);
	return 0;
}
예제 #6
0
파일: fatfs.c 프로젝트: KarenHung/ecosgit
static int 
fatfs_rename(cyg_mtab_entry *mte, 
             cyg_dir         dir1, 
             const char     *name1,
             cyg_dir         dir2, 
             const char     *name2)
{
    fatfs_disk_t       *disk = (fatfs_disk_t *) mte->data;
    fatfs_dirsearch_t   ds1, ds2;
    int                 err;
 
    CYG_TRACE5(TFS, "rename mte=%p dir1=%p name1='%s' dir2=%p name2='%s'", 
                    mte, dir1, name1, dir2, name2);

    init_dirsearch(&ds1, disk, (fatfs_node_t *)dir1, name1);

    err = fatfs_find(&ds1);
    if (err != ENOERR)
        return err;

#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
    // if the file is read only fail with permission error
    if (S_FATFS_ISRDONLY(ds1.node->dentry.attrib))
        return EPERM;
#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES

    // Protect the found nodes from being reused 
    // by the search for the ds2 dir/node pair 
    fatfs_node_ref(disk, ds1.dir);
    fatfs_node_ref(disk, ds1.node);
    
    init_dirsearch(&ds2, disk, (fatfs_node_t *) dir2, name2);
   
    err = fatfs_find(&ds2);

    // Check if the target name already exists
    if (err == ENOERR && ds2.last)
    {
        err = EEXIST;  
        goto out;  
    }
    
    // Check if the target dir doesn't exist
    if (err == ENOENT && !ds2.last)
        goto out;
    
    // Check if the target and the source are the same
    if (ds1.node == ds2.node)
    {
        err = ENOERR;
        goto out;
    }
    
    err = fatfs_rename_file(disk, 
                            &ds1.dir->dentry, 
                            &ds1.node->dentry, 
                            &ds2.dir->dentry, 
                            ds2.name, 
                            ds2.namelen);  

    fatfs_node_rehash(disk, ds1.node);

out:
    // Unreference previousely protected nodes
    fatfs_node_unref(disk, ds1.dir);
    fatfs_node_unref(disk, ds1.node);
   
    if (err == ENOERR)
    {
        ds1.dir->dentry.atime =
        ds1.dir->dentry.mtime = 
        ds2.dir->dentry.atime = 
        ds2.dir->dentry.mtime = cyg_timestamp();    
    } 
    return err;
}
예제 #7
0
파일: fatfs.c 프로젝트: KarenHung/ecosgit
static int 
fatfs_open(cyg_mtab_entry *mte,
           cyg_dir         dir, 
           const char     *name,
           int             mode,  
           cyg_file       *file)
{
    fatfs_disk_t       *disk = (fatfs_disk_t *) mte->data;
    fatfs_node_t       *node = NULL;
    fatfs_fd_t         *fd;
    fatfs_dirsearch_t   ds;
    int                 err;

    CYG_TRACE5(TFS, "open mte=%p dir=%p name='%s' mode=%d file=%p", 
                    mte, dir, name, mode, file);

    init_dirsearch(&ds, disk, (fatfs_node_t *) dir, name);

    err = fatfs_find(&ds);

    if (err == ENOENT)
    {
        if (ds.last && (mode & O_CREAT))
        {
            fatfs_dir_entry_t new_file_dentry;
            
            // No node there, if the O_CREAT bit is set then we must
            // create a new one. The dir and name fields of the dirsearch
            // object will have been updated so we know where to put it.

            CYG_TRACE1(TFS, "creating new file '%s'", name); 

            err = fatfs_create_file(disk, 
                                    &ds.dir->dentry, 
                                    ds.name, 
                                    ds.namelen, 
                                    &new_file_dentry);
            if (err != ENOERR)
                return err;

            node = fatfs_node_alloc(disk, &new_file_dentry);
            if (NULL == node)
                return EMFILE;
           
            // Update directory times
            ds.dir->dentry.atime =
            ds.dir->dentry.mtime = cyg_timestamp();
            
            err = ENOERR;
        }
    }
    else if (err == ENOERR)
    {
        // The node exists. If the O_CREAT and O_EXCL bits are set, we
        // must fail the open

        if ((mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
            err = EEXIST;
        else
            node = ds.node;
    }

    if (err == ENOERR && (mode & O_TRUNC))
    {
        // If the O_TRUNC bit is set we must clean out the file data
        CYG_TRACE0(TFS, "truncating file"); 
        fatfs_trunc_file(disk, &node->dentry);
    }

    if (err != ENOERR)
        return err;
    
    if (S_ISDIR(node->dentry.mode))
        return EISDIR;

#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
    // if the file is read only and is opened for writing
    // fail with permission error
    if (S_FATFS_ISRDONLY(node->dentry.attrib) && (mode & O_WRONLY))
        return EACCES;
#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES

    // Allocate file object private data and
    // make a reference to this file node

    fd = alloc_fatfs_fd(disk, node);
    if (NULL == fd)
        return EMFILE;

    fatfs_node_ref(disk, node);

    // Initialize the file object

    if (mode & O_APPEND)
        fatfs_setpos(disk, &node->dentry, &fd->pos, node->dentry.size);  
    
    file->f_flag   |= mode & CYG_FILE_MODE_MASK;
    file->f_type    = CYG_FILE_TYPE_FILE;
    file->f_ops     = &fatfs_fileops;
    file->f_offset  = (mode & O_APPEND) ? node->dentry.size : 0;
    file->f_data    = (CYG_ADDRWORD) fd;
    file->f_xops    = 0;

    return ENOERR;
}
예제 #8
0
파일: fatfs.c 프로젝트: KarenHung/ecosgit
static int 
fatfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
    fatfs_disk_t  *disk   = (fatfs_disk_t *) fp->f_mte->data;
    fatfs_fd_t    *fd     = (fatfs_fd_t *)   fp->f_data;
    fatfs_node_t  *node   = fd->node;
    cyg_uint32     pos    = fp->f_offset;
    ssize_t        resid  = uio->uio_resid;
    int            err    = ENOERR;
    int            i;

    CYG_TRACE3(TFO, "write fp=%p uio=%p pos=%d", fp, uio, pos);
    
    // If the APPEND mode bit was supplied, force all writes to
    // the end of the file
    if (fp->f_flag & CYG_FAPPEND)
    {
        fatfs_setpos(disk, &node->dentry, &fd->pos, node->dentry.size);
        pos = fp->f_offset = node->dentry.size;
    }
    
    // Check that pos is within current file size, or at the very end
    if (pos < 0 || pos > node->dentry.size)
        return EINVAL;
   
    // Now loop over the iovecs until they are all done, or we get an error
    
    for (i = 0; i < uio->uio_iovcnt; i++)
    {
        cyg_iovec  *iov  = &uio->uio_iov[i];
        char       *buf  = (char *) iov->iov_base;
        off_t       len  = iov->iov_len;
 
        // Loop over the vector writing it to the file 
        // until it has all been done

        while (len > 0)
        {
            cyg_uint32 l = len;

            err = fatfs_write_data(disk, &node->dentry, &fd->pos, buf, &l);

            // Update working vars

            len   -= l;
            buf   += l;
            pos   += l;
            resid -= l;

            // Stop writing if there is no more space in the file
            if (err == ENOSPC)
                break;
            
            if (err != ENOERR)
                return err;
        }
    }        

    // We wrote some data successfully, update the modified and access
    // times of the node, increase its size appropriately, and update
    // the file offset and transfer residue.

    node->dentry.mtime = 
    node->dentry.atime = cyg_timestamp();

    if (pos > node->dentry.size)
        node->dentry.size = pos;

    uio->uio_resid = resid;
    fp->f_offset   = (off_t) pos;

    return err;
}