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

📄 fs-ecos.c

📁 老版本的mtd-snap
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * JFFS3 -- Journalling Flash File System, Version 3. * * Copyright (C) 2001-2003 Red Hat, Inc. * * Created by Dominic Ostrowski <dominic.ostrowski@3glab.com> * Contributors: David Woodhouse, Nick Garnett, Richard Panton. * * For licensing information, see the file 'LICENCE' in this directory. * * JFFS2 Id: fs-ecos.c,v 1.39 2004/11/11 12:46:17 dwmw2  Exp * $Id: fs-ecos.c,v 3.4 2005/01/05 16:19:01 dedekind Exp $ * */#include <linux/types.h>#include <linux/stat.h>#include <linux/kernel.h>#include <linux/pagemap.h>#include <linux/crc32.h>#include "jffs3.h"#include "nodelist.h"#include "compr.h"#include <errno.h>#include <string.h>#include <cyg/io/io.h>#include <cyg/io/config_keys.h>#if (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) && defined (__ARM_ARCH_4__)#error This compiler is known to be broken. Please see:#error http://ecos.sourceware.org/ml/ecos-patches/2003-08/msg00006.html#endif//==========================================================================// Forward definitions// Filesystem operationsstatic int jffs3_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte);static int jffs3_umount(cyg_mtab_entry * mte);static int jffs3_open(cyg_mtab_entry * mte, cyg_dir dir, const char *name,		      int mode, cyg_file * fte);#ifdef CYGOPT_FS_JFFS3_WRITEstatic int jffs3_ops_unlink(cyg_mtab_entry * mte, cyg_dir dir,			    const char *name);static int jffs3_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name);static int jffs3_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name);static int jffs3_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1,			    const char *name1, cyg_dir dir2, const char *name2);static int jffs3_ops_link(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1,			  cyg_dir dir2, const char *name2, int type);#endifstatic int jffs3_opendir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,			 cyg_file * fte);static int jffs3_chdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,		       cyg_dir * dir_out);static int jffs3_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name,		      struct stat *buf);static int jffs3_getinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,			 int key, void *buf, int len);static int jffs3_setinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,			 int key, void *buf, int len);// File operationsstatic int jffs3_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);#ifdef CYGOPT_FS_JFFS3_WRITEstatic int jffs3_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);#endifstatic int jffs3_fo_lseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence);static int jffs3_fo_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,			  CYG_ADDRWORD data);static int jffs3_fo_fsync(struct CYG_FILE_TAG *fp, int mode);static int jffs3_fo_close(struct CYG_FILE_TAG *fp);static int jffs3_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf);static int jffs3_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf,			    int len);static int jffs3_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf,			    int len);// Directory operationsstatic int jffs3_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);static int jffs3_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence);static int jffs3_read_inode (struct _inode *inode);static void jffs3_clear_inode (struct _inode *inode);//==========================================================================// Filesystem table entries// -------------------------------------------------------------------------// Fstab entry.// This defines the entry in the filesystem table.// For simplicity we use _FILESYSTEM synchronization for all accesses since// we should never block in any filesystem operations.#ifdef CYGOPT_FS_JFFS3_WRITEFSTAB_ENTRY(jffs3_fste, "jffs3", 0,	    CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILE,	    jffs3_mount,	    jffs3_umount,	    jffs3_open,	    jffs3_ops_unlink,	    jffs3_ops_mkdir,	    jffs3_ops_rmdir,	    jffs3_ops_rename,	    jffs3_ops_link,	    jffs3_opendir,	    jffs3_chdir, jffs3_stat, jffs3_getinfo, jffs3_setinfo);#elseFSTAB_ENTRY(jffs3_fste, "jffs3", 0,	    CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILE,	    jffs3_mount,	    jffs3_umount,	    jffs3_open,	    (cyg_fsop_unlink *)cyg_fileio_erofs,	    (cyg_fsop_mkdir *)cyg_fileio_erofs,	    (cyg_fsop_rmdir *)cyg_fileio_erofs,	    (cyg_fsop_rename *)cyg_fileio_erofs,	    (cyg_fsop_link *)cyg_fileio_erofs,	    jffs3_opendir,	    jffs3_chdir, jffs3_stat, jffs3_getinfo, jffs3_setinfo);#endif// -------------------------------------------------------------------------// File operations.// This set of file operations are used for normal open files.static cyg_fileops jffs3_fileops = {	jffs3_fo_read,#ifdef CYGOPT_FS_JFFS3_WRITE	jffs3_fo_write,#else	(cyg_fileop_write *) cyg_fileio_erofs,#endif	jffs3_fo_lseek,	jffs3_fo_ioctl,	cyg_fileio_seltrue,	jffs3_fo_fsync,	jffs3_fo_close,	jffs3_fo_fstat,	jffs3_fo_getinfo,	jffs3_fo_setinfo};// -------------------------------------------------------------------------// Directory file operations.// This set of operations are used for open directories. Most entries// point to error-returning stub functions. Only the read, lseek and// close entries are functional.static cyg_fileops jffs3_dirops = {	jffs3_fo_dirread,	(cyg_fileop_write *) cyg_fileio_enosys,	jffs3_fo_dirlseek,	(cyg_fileop_ioctl *) cyg_fileio_enosys,	cyg_fileio_seltrue,	(cyg_fileop_fsync *) cyg_fileio_enosys,	jffs3_fo_close,	(cyg_fileop_fstat *) cyg_fileio_enosys,	(cyg_fileop_getinfo *) cyg_fileio_enosys,	(cyg_fileop_setinfo *) cyg_fileio_enosys};//==========================================================================// STATIC VARIABLES !!!static unsigned char gc_buffer[PAGE_CACHE_SIZE];	//avoids malloc when user may be under memory pressurestatic unsigned char n_fs_mounted = 0;  // a counter to track the number of jffs3 instances mounted//==========================================================================// Directory operationsstruct jffs3_dirsearch {	struct _inode *dir;	// directory to search	const char *path;	// path to follow	struct _inode *node;	// Node found	const char *name;	// last name fragment used	int namelen;		// name fragment length	cyg_bool last;		// last name in path?};typedef struct jffs3_dirsearch jffs3_dirsearch;//==========================================================================// Ref count and nlink management// FIXME: This seems like real cruft. Wouldn't it be better just to do the// right thing?static void icache_evict(struct _inode *root_i, struct _inode *i){	struct _inode *this = root_i, *next; restart:	D2(printf("icache_evict\n"));	// If this is an absolute search path from the root,	// remove all cached inodes with i_count of zero (these are only 	// held where needed for dotdot filepaths)	while (this) {		next = this->i_cache_next;		if (this != i && this->i_count == 0) {			struct _inode *parent = this->i_parent;			if (this->i_cache_next)				this->i_cache_next->i_cache_prev = this->i_cache_prev;			if (this->i_cache_prev)				this->i_cache_prev->i_cache_next = this->i_cache_next;			jffs3_clear_inode(this);			memset(this, 0x5a, sizeof(*this));			free(this);			if (parent && parent != this) {				parent->i_count--;				this = root_i;				goto restart;			}		}		this = next;	}}//==========================================================================// Directory search// -------------------------------------------------------------------------// init_dirsearch()// Initialize a dirsearch object to start a searchstatic void init_dirsearch(jffs3_dirsearch * ds,			   struct _inode *dir, const char *name){	D2(printf("init_dirsearch name = %s\n", name));	D2(printf("init_dirsearch dir = %x\n", dir));	dir->i_count++;	ds->dir = dir;	ds->path = name;	ds->node = dir;	ds->name = name;	ds->namelen = 0;	ds->last = false;}// -------------------------------------------------------------------------// find_entry()// Search a single directory for the next name in a path and update the// dirsearch object appropriately.static int find_entry(jffs3_dirsearch * ds){	struct _inode *dir = ds->dir;	const char *name = ds->path;	const char *n = name;	char namelen = 0;	struct _inode *d;	D2(printf("find_entry\n"));	// check that we really have a directory	if (!S_ISDIR(dir->i_mode))		return ENOTDIR;	// Isolate the next element of the path name. 	while (*n != '\0' && *n != '/')		n++, namelen++;	// Check if this is the last path element.	while( *n == '/') n++;	if (*n == '\0')		ds->last = true;	// update name in dirsearch object	ds->name = name;	ds->namelen = namelen;	if (name[0] == '.')		switch (namelen) {		default:			break;		case 2:			// Dot followed by not Dot, treat as any other name 			if (name[1] != '.')				break;			// Dot Dot 			// Move back up the search path			D2(printf("find_entry found ..\n"));			ds->dir = ds->node;			ds->node = ds->dir->i_parent;			ds->node->i_count++;			return ENOERR;		case 1:			// Dot is consumed			D2(printf("find_entry found .\n"));			ds->node = ds->dir;			ds->dir->i_count++;			return ENOERR;		}	// Here we have the name and its length set up.	// Search the directory for a matching entry	D2(printf("find_entry for name = %s\n", ds->path));	d = jffs3_lookup(dir, name, namelen);	D2(printf("find_entry got dir = %x\n", d));	if (d == NULL)		return ENOENT;	if (IS_ERR(d))		return -PTR_ERR(d);	// If it's a new directory inode, increase refcount on its parent	if (S_ISDIR(d->i_mode) && !d->i_parent) {		d->i_parent = dir;		dir->i_count++;	}	// pass back the node we have found	ds->node = d;	return ENOERR;}// -------------------------------------------------------------------------// jffs3_find()// Main interface to directory search code. This is used in all file// level operations to locate the object named by the pathname.// Returns with use count incremented on both the sought object and // the directory it was found instatic int jffs3_find(jffs3_dirsearch * d){	int err;	D2(printf("jffs3_find for path =%s\n", d->path));	// Short circuit empty paths	if (*(d->path) == '\0') {		d->node->i_count++;		return ENOERR;	}	// iterate down directory tree until we find the object	// we want.	for (;;) {		err = find_entry(d);		if (err != ENOERR)			return err;		if (d->last)			return ENOERR;		/* We're done with it, although it we found a subdir that		   will have caused the refcount to have been increased */		jffs3_iput(d->dir);		// Update dirsearch object to search next directory.		d->dir = d->node;		d->path += d->namelen;		while (*(d->path) == '/')			d->path++;	// skip dirname separators	}}//==========================================================================// Pathconf support// This function provides support for pathconf() and fpathconf().static int jffs3_pathconf(struct _inode *node, struct cyg_pathconf_info *info){	int err = ENOERR;	D2(printf("jffs3_pathconf\n"));	switch (info->name) {	case _PC_LINK_MAX:		info->value = LINK_MAX;		break;	case _PC_MAX_CANON:		info->value = -1;	// not supported		err = EINVAL;		break;	case _PC_MAX_INPUT:		info->value = -1;	// not supported		err = EINVAL;		break;	case _PC_NAME_MAX:		info->value = NAME_MAX;		break;	case _PC_PATH_MAX:		info->value = PATH_MAX;		break;	case _PC_PIPE_BUF:		info->value = -1;	// not supported		err = EINVAL;		break;	case _PC_ASYNC_IO:		info->value = -1;	// not supported		err = EINVAL;		break;	case _PC_CHOWN_RESTRICTED:		info->value = -1;	// not supported		err = EINVAL;		break;	case _PC_NO_TRUNC:		info->value = 0;		break;	case _PC_PRIO_IO:		info->value = 0;		break;	case _PC_SYNC_IO:		info->value = 0;		break;	case _PC_VDISABLE:		info->value = -1;	// not supported		err = EINVAL;		break;	default:		err = EINVAL;		break;	}	return err;}//==========================================================================// Filesystem operations// -------------------------------------------------------------------------// jffs3_mount()// Process a mount request. This mainly creates a root for the// filesystem.static int jffs3_read_super(struct super_block *sb){	struct jffs3_sb_info *c;	Cyg_ErrNo err;	cyg_uint32 len;	cyg_io_flash_getconfig_devsize_t ds;	cyg_io_flash_getconfig_blocksize_t bs;	D1(printk(KERN_DEBUG "jffs3: read_super\n"));	c = JFFS3_SB_INFO(sb);	len = sizeof (ds);	err = cyg_io_get_config(sb->s_dev,				CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &ds, &len);	if (err != ENOERR) {		D1(printf		   ("jffs3: cyg_io_get_config failed to get dev size: %d\n",		    err));		return err;	}	len = sizeof (bs);	bs.offset = 0;	err = cyg_io_get_config(sb->s_dev,				CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE, &bs, &len);	if (err != ENOERR) {		D1(printf		   ("jffs3: cyg_io_get_config failed to get block size: %d\n",		    err));		return err;	}	c->sector_size = bs.block_size;	c->flash_size = ds.dev_size;	c->cleanmarker_size = sizeof(struct jffs3_unknown_node);	err = jffs3_do_mount_fs(c);	if (err)		return -err;	D1(printk(KERN_DEBUG "jffs3_read_super(): Getting root inode\n"));	sb->s_root = jffs3_iget(sb, 1);	if (IS_ERR(sb->s_root)) {		D1(printk(KERN_WARNING "get root inode failed\n"));		err = PTR_ERR(sb->s_root);		sb->s_root = NULL;		goto out_nodes;	}	return 0;      out_nodes:	jffs3_free_ino_caches(c);	jffs3_free_raw_node_refs(c);	free(c->blocks);	return err;}static int jffs3_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte){	extern cyg_mtab_entry cyg_mtab[], cyg_mtab_end;	struct super_block *jffs3_sb = NULL;	struct jffs3_sb_info *c;	cyg_mtab_entry *m;	cyg_io_handle_t t;	Cyg_ErrNo err;	D2(printf("jffs3_mount\n"));	err = cyg_io_lookup(mte->devname, &t);	if (err != ENOERR)		return -err;	// Iterate through the mount table to see if we're mounted	// FIXME: this should be done better - perhaps if the superblock	// can be stored as an inode in the icache.	for (m = &cyg_mtab[0]; m != &cyg_mtab_end; m++) {

⌨️ 快捷键说明

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