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

📄 fs-ecos.c

📁 带SD卡的LINUX根文件系统. 在ARM上应用
💻 C
📖 第 1 页 / 共 4 页
字号:
	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 = &mtab[0]; m != &mtab_end; m++) {		// stop if there are more than the configured maximum		if (m - &mtab[0] >= CYGNUM_FILEIO_MTAB_MAX) {			m = &mtab_end;			break;		}		if (m->valid && strcmp(m->fsname, "jffs2") == 0 &&		    strcmp(m->devname, mte->devname) == 0) {			jffs2_sb = (struct super_block *) m->data;		}	}	if (jffs2_sb == NULL) {		jffs2_sb = malloc(sizeof (struct super_block));		if (jffs2_sb == NULL)			return ENOMEM;		c = JFFS2_SB_INFO(jffs2_sb);		memset(jffs2_sb, 0, sizeof (struct super_block));		jffs2_sb->s_dev = t;		c->inocache_list = malloc(sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE);		if (!c->inocache_list) {			free(jffs2_sb);			return ENOMEM;		}		memset(c->inocache_list, 0, sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE);		err = jffs2_read_super(jffs2_sb);		if (err) {			free(jffs2_sb);			free(c->inocache_list);			return err;		}		jffs2_sb->s_root->i_parent = jffs2_sb->s_root;	// points to itself, no dotdot paths above mountpoint		jffs2_sb->s_root->i_cache_prev = NULL;	// root inode, so always null		jffs2_sb->s_root->i_cache_next = NULL;		jffs2_sb->s_root->i_count = 1;	// Ensures the root inode is always in ram until umount		D2(printf("jffs2_mount erasing pending blocks\n"));		jffs2_erase_pending_blocks(c);	}	mte->data = (CYG_ADDRWORD) jffs2_sb;	jffs2_sb->s_mount_count++;	mte->root = (cyg_dir) jffs2_sb->s_root;	D2(printf("jffs2_mounted superblock at %x\n", mte->root));	return ENOERR;}// -------------------------------------------------------------------------// jffs2_umount()// Unmount the filesystem. static int jffs2_umount(cyg_mtab_entry * mte){	struct inode *root = (struct inode *) mte->root;	struct super_block *jffs2_sb = root->i_sb;	struct jffs2_sb_info *c = JFFS2_SB_INFO(jffs2_sb);	D2(printf("jffs2_umount\n"));	// Decrement the mount count	jffs2_sb->s_mount_count--;	// Only really umount if this is the only mount	if (jffs2_sb->s_mount_count == 0) {		// Check for open/inuse root or any cached inodes//if( root->i_count != 1 || root->i_cache_next != NULL) // root icount was set to 1 on mount		if (root->i_cache_next != NULL)	// root icount was set to 1 on mount			return EBUSY;		dec_refcnt(root);	// Time to free the root inode		//Clear root inode		//root_i = NULL;		// Clean up the super block and root inode		jffs2_free_ino_caches(c);		jffs2_free_raw_node_refs(c);		free(c->blocks);		free(c->inocache_list);		free(jffs2_sb);		// Clear root pointer		mte->root = CYG_DIR_NULL;		mte->fs->data = 0;	// fstab entry, visible to all mounts. No current mount		// That's all folks.		D2(printf("jffs2_umount No current mounts\n"));	}	return ENOERR;}// -------------------------------------------------------------------------// jffs2_open()// Open a file for reading or writing.static int jffs2_open(cyg_mtab_entry * mte, cyg_dir dir, const char *name,		      int mode, cyg_file * file){	jffs2_dirsearch ds;	struct inode *node = NULL;	int err;	D2(printf("jffs2_open\n"));	icache_evict((struct inode *) mte->root, (struct inode *) dir);	init_dirsearch(&ds, (struct inode *) dir, name);	err = jffs2_find(&ds);	if (err == ENOENT) {		if (ds.last && (mode & O_CREAT)) {			unsigned long hash;			struct qstr this;			unsigned int c;			const char *hashname;			// 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.			hashname = ds.name;			this.name = hashname;			c = *(const unsigned char *) hashname;			hash = init_name_hash();			do {				hashname++;				hash = partial_name_hash(c, hash);				c = *(const unsigned char *) hashname;			} while (c && (c != '/'));			this.len = hashname - (const char *) this.name;			this.hash = end_name_hash(hash);			err = jffs2_create(ds.dir, &this, S_IRUGO|S_IXUGO|S_IWUSR|S_IFREG, &node);			if (err != 0) {				//Possible orphaned inode on the flash - but will be gc'd				return err;			}			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)) {		struct jffs2_inode_info *f = JFFS2_INODE_INFO(node);		struct jffs2_sb_info *c = JFFS2_SB_INFO(node->i_sb);		// If the O_TRUNC bit is set we must clean out the file data.		node->i_size = 0;		jffs2_truncate_fraglist(c, &f->fragtree, 0);		// Update file times		node->i_ctime = node->i_mtime = cyg_timestamp();	}	if (err != ENOERR)		return err;	// Check that we actually have a file here	if (S_ISDIR(node->i_mode))		return EISDIR;	node->i_count++;	// Count successful open	// Initialize the file object	file->f_flag |= mode & CYG_FILE_MODE_MASK;	file->f_type = CYG_FILE_TYPE_FILE;	file->f_ops = &jffs2_fileops;	file->f_offset = (mode & O_APPEND) ? node->i_size : 0;	file->f_data = (CYG_ADDRWORD) node;	file->f_xops = 0;	return ENOERR;}// -------------------------------------------------------------------------// jffs2_ops_unlink()// Remove a file link from its directory.static int jffs2_ops_unlink(cyg_mtab_entry * mte, cyg_dir dir, const char *name){	unsigned long hash;	struct qstr this;	unsigned int c;	const char *hashname;	jffs2_dirsearch ds;	int err;	D2(printf("jffs2_ops_unlink\n"));	icache_evict((struct inode *) mte->root, (struct inode *) dir);	init_dirsearch(&ds, (struct inode *) dir, name);	err = jffs2_find(&ds);	if (err != ENOERR)		return err;	// Cannot unlink directories, use rmdir() instead	if (S_ISDIR(ds.node->i_mode))		return EPERM;	// Delete it from its directory	hashname = ds.name;	this.name = hashname;	c = *(const unsigned char *) hashname;	hash = init_name_hash();	do {		hashname++;		hash = partial_name_hash(c, hash);		c = *(const unsigned char *) hashname;	} while (c && (c != '/'));	this.len = hashname - (const char *) this.name;	this.hash = end_name_hash(hash);	err = jffs2_unlink(ds.dir, ds.node, &this);	return err;}// -------------------------------------------------------------------------// jffs2_ops_mkdir()// Create a new directory.static int jffs2_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name){	jffs2_dirsearch ds;	struct inode *node = NULL;	int err;	D2(printf("jffs2_ops_mkdir\n"));	icache_evict((struct inode *) mte->root, (struct inode *) dir);	init_dirsearch(&ds, (struct inode *) dir, name);	err = jffs2_find(&ds);	if (err == ENOENT) {		if (ds.last) {			unsigned long hash;			struct qstr this;			unsigned int c;			const char *hashname;			// The entry does not exist, and it is the last element in			// the pathname, so we can create it here.			hashname = ds.name;			this.name = hashname;			c = *(const unsigned char *) hashname;			hash = init_name_hash();			do {				hashname++;				hash = partial_name_hash(c, hash);				c = *(const unsigned char *) hashname;			} while (c && (c != '/'));			this.len = hashname - (const char *) this.name;			this.hash = end_name_hash(hash);			err = jffs2_mkdir(ds.dir, &this, 0, &node);			if (err != 0)				return ENOSPC;		}		// If this was not the last element, then and intermediate		// directory does not exist.	} else {		// If there we no error, something already exists with that		// name, so we cannot create another one.		if (err == ENOERR)			err = EEXIST;	}	return err;}// -------------------------------------------------------------------------// jffs2_ops_rmdir()// Remove a directory.static int jffs2_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name){	unsigned long hash;	struct qstr this;	unsigned int c;	const char *hashname;	jffs2_dirsearch ds;	int err;	D2(printf("jffs2_ops_rmdir\n"));	icache_evict((struct inode *) mte->root, (struct inode *) dir);	init_dirsearch(&ds, (struct inode *) dir, name);	err = jffs2_find(&ds);	if (err != ENOERR)		return err;	// Check that this is actually a directory.	if (!S_ISDIR(ds.node->i_mode))		return EPERM;	// Delete the entry. 	hashname = ds.name;	this.name = hashname;	c = *(const unsigned char *) hashname;	hash = init_name_hash();	do {		hashname++;		hash = partial_name_hash(c, hash);		c = *(const unsigned char *) hashname;	} while (c && (c != '/'));	this.len = hashname - (const char *) this.name;	this.hash = end_name_hash(hash);	err = jffs2_rmdir(ds.dir, ds.node, &this);	return err;	return ENOERR;}// -------------------------------------------------------------------------// jffs2_ops_rename()// Rename a file/dir.static int jffs2_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1,			    const char *name1, cyg_dir dir2, const char *name2){	unsigned long hash;	struct qstr this1, this2;	unsigned int c;	const char *hashname;	jffs2_dirsearch ds1, ds2;	int err;	D2(printf("jffs2_ops_rename\n"));	init_dirsearch(&ds1, (struct inode *) dir1, name1);	err = jffs2_find(&ds1);	if (err != ENOERR)		return err;	init_dirsearch(&ds2, (struct inode *) dir2, name2);	err = jffs2_find(&ds2);	// Allow through renames to non-existent objects.	if (ds2.last && err == ENOENT)		ds2.node = NULL, err = ENOERR;	if (err != ENOERR)		return err;	// Null rename, just return	if (ds1.node == ds2.node)		return ENOERR;	hashname = ds1.name;	this1.name = hashname;	c = *(const unsigned char *) hashname;	hash = init_name_hash();	do {		hashname++;		hash = partial_name_hash(c, hash);		c = *(const unsigned char *) hashname;	} while (c && (c != '/'));	this1.len = hashname - (const char *) this1.name;	this1.hash = end_name_hash(hash);	hashname = ds2.name;	this2.name = hashname;	c = *(const unsigned char *) hashname;	hash = init_name_hash();	do {		hashname++;		hash = partial_name_hash(c, hash);		c = *(const unsigned char *) hashname;	} while (c && (c != '/'));	this2.len = hashname - (const char *) this2.name;	this2.hash = end_name_hash(hash);	// First deal with any entry that is at the destination	if (ds2.node) {		// Check that we are renaming like-for-like		if (!S_ISDIR(ds1.node->i_mode) && S_ISDIR(ds2.node->i_mode))			return EISDIR;		if (S_ISDIR(ds1.node->i_mode) && !S_ISDIR(ds2.node->i_mode))			return ENOTDIR;		// Now delete the destination directory entry		err = jffs2_unlink(ds2.dir, ds2.node, &this2);		if (err != 0)			return err;	}	// Now we know that there is no clashing node at the destination,	// make a new direntry at the destination and delete the old entry	// at the source.	err = jffs2_rename(ds1.dir, ds1.node, &this1, ds2.dir, &this2);	// Update directory times	if (err == 0)		ds1.dir->i_ctime =		    ds1.dir->i_mtime =		    ds2.dir->i_ctime = ds2.dir->i_mtime = cyg_timestamp();	return err;}// -------------------------------------------------------------------------// jffs2_ops_link()// Make a new directory entry for a file.static int jffs2_ops_link(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1,			  cyg_dir dir2, const char *name2, int type){	unsigned long hash;	struct qstr this;	unsigned int c;	const char *hashname;	jffs2_dirsearch ds1, ds2;	int err;	D2(printf("jffs2_ops_link\n"));	// Only do hard links for now in this filesystem	if (type != CYG_FSLINK_HARD)		return EINVAL;	init_dirsearch(&ds1, (struct inode *) dir1, name1);	err = jffs2_find(&ds1);	if (err != ENOERR)		return err;	init_dirsearch(&ds2, (struct inode *) dir2, name2);	err = jffs2_find(&ds2);	// Don't allow links to existing objects	if (err == ENOERR)		return EEXIST;	// Allow through links to non-existing terminal objects	if (ds2.last && err == ENOENT)		ds2.node = NULL, err = ENOERR;	if (err != ENOERR)		return err;	// Now we know that there is no existing node at the destination,	// make a new direntry at the destination.	hashname = ds2.name;	this.name = hashname;	c = *(const unsigned char *) hashname;	hash = init_name_hash();	do {		hashname++;		hash = partial_name_hash(c, hash);		c = *(const unsigned char *) hashname;	} while (c && (c != '/'));	this.len = hashname - (const char *) this.name;	this.hash = end_name_hash(hash);	err = jffs2_link(ds2.dir, ds1.node, &this);

⌨️ 快捷键说明

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