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

📄 fs-ecos.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			 cyg_file * file)
{
	jffs2_dirsearch ds;
	int err;

	D2(printf("jffs2_opendir\n"));

	init_dirsearch(&ds, (struct _inode *) dir, name);

	err = jffs2_find(&ds);

	jffs2_iput(ds.dir);

	if (err != ENOERR)
		return err;

	// check it is really a directory.
	if (!S_ISDIR(ds.node->i_mode)) {
		jffs2_iput(ds.node);
		return ENOTDIR;
	}

	// Initialize the file object, setting the f_ops field to a
	// special set of file ops.

	file->f_type = CYG_FILE_TYPE_FILE;
	file->f_ops = &jffs2_dirops;
	file->f_offset = 0;
	file->f_data = (CYG_ADDRWORD) ds.node;
	file->f_xops = 0;

	return ENOERR;

}

// -------------------------------------------------------------------------
// jffs2_chdir()
// Change directory support.

static int jffs2_chdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
		       cyg_dir * dir_out)
{
	D2(printf("jffs2_chdir\n"));

	if (dir_out != NULL) {
		// This is a request to get a new directory pointer in
		// *dir_out.

		jffs2_dirsearch ds;
		int err;

		init_dirsearch(&ds, (struct _inode *) dir, name);

		err = jffs2_find(&ds);
		jffs2_iput(ds.dir);

		if (err != ENOERR)
			return err;

		// check it is a directory
		if (!S_ISDIR(ds.node->i_mode))
			return ENOTDIR;

		// Pass it out
		*dir_out = (cyg_dir) ds.node;
	} else {
		// If no output dir is required, this means that the mte and
		// dir arguments are the current cdir setting and we should
		// forget this fact.

		struct _inode *node = (struct _inode *) dir;

		// Just decrement directory reference count.
		jffs2_iput(node);
	}

	return ENOERR;
}

// -------------------------------------------------------------------------
// jffs2_stat()
// Get struct stat info for named object.

static int jffs2_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
		      struct stat *buf)
{
	jffs2_dirsearch ds;
	int err;

	D2(printf("jffs2_stat\n"));

	init_dirsearch(&ds, (struct _inode *) dir, name);

	err = jffs2_find(&ds);
	jffs2_iput(ds.dir);

	if (err != ENOERR)
		return err;

	// Fill in the status
	buf->st_mode = ds.node->i_mode;
	buf->st_ino = ds.node->i_ino;
	buf->st_dev = 0;
	buf->st_nlink = ds.node->i_nlink;
	buf->st_uid = ds.node->i_uid;
	buf->st_gid = ds.node->i_gid;
	buf->st_size = ds.node->i_size;
	buf->st_atime = ds.node->i_atime;
	buf->st_mtime = ds.node->i_mtime;
	buf->st_ctime = ds.node->i_ctime;

	jffs2_iput(ds.node);

	return ENOERR;
}

// -------------------------------------------------------------------------
// jffs2_getinfo()
// Getinfo. Currently only support pathconf().

static int jffs2_getinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
			 int key, void *buf, int len)
{
	jffs2_dirsearch ds;
	int err;

	D2(printf("jffs2_getinfo\n"));

	init_dirsearch(&ds, (struct _inode *) dir, name);

	err = jffs2_find(&ds);
	jffs2_iput(ds.dir);

	if (err != ENOERR)
		return err;

	switch (key) {
	case FS_INFO_CONF:
		err = jffs2_pathconf(ds.node, (struct cyg_pathconf_info *) buf);
		break;

	default:
		err = EINVAL;
	}

	jffs2_iput(ds.node);
	return err;
}

// -------------------------------------------------------------------------
// jffs2_setinfo()
// Setinfo. Nothing to support here at present.

static int jffs2_setinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
			 int key, void *buf, int len)
{
	// No setinfo keys supported at present

	D2(printf("jffs2_setinfo\n"));

	return EINVAL;
}

//==========================================================================
// File operations

// -------------------------------------------------------------------------
// jffs2_fo_read()
// Read data from the file.

static int jffs2_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
	struct _inode *inode = (struct _inode *) fp->f_data;
	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
	int i;
	ssize_t resid = uio->uio_resid;
	off_t pos = fp->f_offset;

	down(&f->sem);

	// Loop over the io vectors until there are none left
	for (i = 0; i < uio->uio_iovcnt && pos < inode->i_size; i++) {
		int ret;
		cyg_iovec *iov = &uio->uio_iov[i];
		off_t len = min(iov->iov_len, inode->i_size - pos);

		D2(printf("jffs2_fo_read inode size %d\n", inode->i_size));

		ret =
		    jffs2_read_inode_range(c, f,
					   (unsigned char *) iov->iov_base, pos,
					   len);
		if (ret) {
			D1(printf
			   ("jffs2_fo_read(): read_inode_range failed %d\n",
			    ret));
			uio->uio_resid = resid;
			up(&f->sem);
			return -ret;
		}
		resid -= len;
		pos += len;
	}

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

	inode->i_atime = cyg_timestamp();

	uio->uio_resid = resid;
	fp->f_offset = pos;

	up(&f->sem);

	return ENOERR;
}


#ifdef CYGOPT_FS_JFFS2_WRITE
// -------------------------------------------------------------------------
// jffs2_fo_write()
// Write data to file.
static int jffs2_extend_file (struct _inode *inode, struct jffs2_raw_inode *ri,
		       unsigned long offset)
{
	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
	struct jffs2_full_dnode *fn;
	uint32_t phys_ofs, alloc_len;
	int ret = 0;

	/* Make new hole frag from old EOF to new page */
	D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
		  (unsigned int)inode->i_size, offset));

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

	down(&f->sem);

	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->version = cpu_to_je32(++f->highest_version);
	ri->isize = cpu_to_je32(max((uint32_t)inode->i_size, offset));

	ri->offset = cpu_to_je32(inode->i_size);
	ri->dsize = cpu_to_je32(offset - 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, ALLOC_NORMAL);
	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 = offset;
	up(&f->sem);
	return 0;
}

static int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
	struct _inode *inode = (struct _inode *) fp->f_data;
	off_t pos = fp->f_offset;
	ssize_t resid = uio->uio_resid;
	struct jffs2_raw_inode ri;
	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
	int i;

	// If the APPEND mode bit was supplied, force all writes to
	// the end of the file.
	if (fp->f_flag & CYG_FAPPEND)
		pos = fp->f_offset = inode->i_size;

	if (pos < 0)
		return EINVAL;

	memset(&ri, 0, sizeof(ri));

	ri.ino = cpu_to_je32(f->inocache->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.atime = ri.ctime = ri.mtime = cpu_to_je32(cyg_timestamp());

	if (pos > inode->i_size) {
		int err;
		ri.version = cpu_to_je32(++f->highest_version);
		err = jffs2_extend_file(inode, &ri, pos);
		if (err)
			return -err;
	}
	ri.isize = cpu_to_je32(inode->i_size);

	// 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;

		uint32_t writtenlen;
		int err;

		D2(printf("jffs2_fo_write page_start_pos %d\n", pos));
		D2(printf("jffs2_fo_write transfer size %d\n", l));

		err = jffs2_write_inode_range(c, f, &ri, buf,
					      pos, len, &writtenlen);
		if (err)
			return -err;
		
		if (writtenlen != len)
			return ENOSPC;

		pos += len;
		resid -= len;
	}

	// We wrote some data successfully, update the modified and access
	// times of the inode, increase its size appropriately, and update
	// the file offset and transfer residue.
	inode->i_mtime = inode->i_ctime = je32_to_cpu(ri.mtime);
	if (pos > inode->i_size)
		inode->i_size = pos;

	uio->uio_resid = resid;
	fp->f_offset = pos;

	return ENOERR;
}
#endif /* CYGOPT_FS_JFFS2_WRITE */

// -------------------------------------------------------------------------
// jffs2_fo_lseek()
// Seek to a new file position.

static int jffs2_fo_lseek(struct CYG_FILE_TAG *fp, off_t * apos, int whence)
{
	struct _inode *node = (struct _inode *) fp->f_data;
	off_t pos = *apos;

	D2(printf("jffs2_fo_lseek\n"));

	switch (whence) {
	case SEEK_SET:
		// Pos is already where we want to be.
		break;

	case SEEK_CUR:
		// Add pos to current offset.
		pos += fp->f_offset;
		break;

	case SEEK_END:
		// Add pos to file size.
		pos += node->i_size;
		break;

	default:
		return EINVAL;
	}

        // Check that pos is still within current file size, or at the
        // very end.
        if (pos < 0 || pos > node->i_size)
                return EINVAL;

	// All OK, set fp offset and return new position.
	*apos = fp->f_offset = pos;

	return ENOERR;
}

// -------------------------------------------------------------------------
// jffs2_fo_ioctl()
// Handle ioctls. Currently none are defined.

static int jffs2_fo_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
			  CYG_ADDRWORD data)
{
	// No Ioctls currenly defined.

	D2(printf("jffs2_fo_ioctl\n"));

	return EINVAL;
}

// -------------------------------------------------------------------------
// jffs2_fo_fsync().
// Force the file out to data storage.

static int jffs2_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
{
	// Data is always permanently where it belongs, nothing to do
	// here.

	D2(printf("jffs2_fo_fsync\n"));

	return ENOERR;
}

// -------------------------------------------------------------------------
// jffs2_fo_close()
// Close a file. We just decrement the refcnt and let it go away if
// that is all that is keeping it here.

static int jffs2_fo_close(struct CYG_FILE_TAG *fp)
{
	struct _inode *node = (struct _inode *) fp->f_data;

	D2(printf("jffs2_fo_close\n"));

	jffs2_iput(node);

	fp->f_data = 0;		// zero data pointer

	return ENOERR;
}

// -------------------------------------------------------------------------
//jffs2_fo_fstat()
// Get file status.

static int jffs2_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf)
{
	struct _inode *node = (struct _inode *) fp->f_data;

	D2(printf("jffs2_fo_fstat\n"));

	// Fill in the status
	buf->st_mode = node->i_mode;
	buf->st_ino = node->i_ino;
	buf->st_dev = 0;
	buf->st_nlink = node->i_nlink;
	buf->st_uid = node->i_uid;
	buf->st_gid = node->i_gid;
	buf->st_size = node->i_size;
	buf->st_atime = node->i_atime;
	buf->st_mtime = node->i_mtime;
	buf->st_ctime = node->i_ctime;

	return ENOERR;
}

// -------------------------------------------------------------------------
// jffs2_fo_getinfo()
// Get info. Currently only supports fpathconf().

static int jffs2_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf,
			    int len)
{
	struct _inode *node = (struct _inode *) fp->f_data;
	int err;

	D2(printf("jffs2_fo_getinfo\n"));

	switch (key) {
	case FS_INFO_CONF:
		err = jffs2_pathconf(node, (struct cyg_pathconf_info *) buf);
		break;

	default:
		err = EINVAL;
	}
	return err;

	return ENOERR;
}

// -------------------------------------------------------------------------
// jffs2_fo_setinfo()
// Set info. Nothing supported here.

static int jffs2_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf,
			    int len)
{
	// No setinfo key supported at present

	D2(printf("jffs2_fo_setinfo\n"));

	return ENOERR;
}

//==========================================================================
// Directory operations

// -------------------------------------------------------------------------
// jffs2_fo_dirread()
// Read a single directory entry from a file.

static __inline void filldir(char *nbuf, int nlen, const char *name, int namlen)
{
	int len = nlen < namlen ? nlen : namlen;

⌨️ 快捷键说明

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