📄 fs-ecos.c
字号:
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 + -