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

📄 fs-ecos.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	for (m = &cyg_mtab[0]; m != &cyg_mtab_end; m++) {
		// stop if there are more than the configured maximum
		if (m - &cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX) {
			m = &cyg_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);
                if (n_fs_mounted++ == 0)
                        jffs2_create_slab_caches(); // No error check, cannot fail

		err = jffs2_read_super(jffs2_sb);

		if (err) {
                        if (--n_fs_mounted == 0)
                                jffs2_destroy_slab_caches();
                        
			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"));
#ifdef CYGOPT_FS_JFFS2_WRITE
		if (!jffs2_is_readonly(c))
		    jffs2_erase_pending_blocks(c,0);
#endif
#ifdef CYGOPT_FS_JFFS2_GCTHREAD
		jffs2_start_garbage_collect_thread(c);
#endif
	}
	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;
}

extern cyg_dir cyg_cdir_dir;
extern cyg_mtab_entry *cyg_cdir_mtab_entry;

// -------------------------------------------------------------------------
// 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);
        struct jffs2_full_dirent *fd, *next;

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

	// Only really umount if this is the only mount
	if (jffs2_sb->s_mount_count == 1) {
		icache_evict(root, NULL);
		if (root->i_cache_next != NULL)	{
			struct _inode *inode = root;
			printf("Refuse to unmount.\n");
			while (inode) {
				printf("Ino #%u has use count %d\n",
				       inode->i_ino, inode->i_count);
				inode = inode->i_cache_next;
			}
			// root icount was set to 1 on mount
			return EBUSY;
                }
		if (root->i_count == 2 &&
		    cyg_cdir_mtab_entry == mte &&
		    cyg_cdir_dir == (cyg_dir)root &&
		    !strcmp(mte->name, "/")) {
			/* If we were mounted on root, there's no
			   way for the cwd to change out and free 
			   the file system for unmounting. So we hack
			   it -- if cwd is '/' we unset it. Perhaps
			   we should allow chdir(NULL) to unset
			   cyg_cdir_dir? */
			cyg_cdir_dir = CYG_DIR_NULL;
			jffs2_iput(root);
		}
		/* Argh. The fileio code sets this; never clears it */
		if (cyg_cdir_mtab_entry == mte)
			cyg_cdir_mtab_entry = NULL;

		if (root->i_count != 1) {
			printf("Ino #1 has use count %d\n",
			       root->i_count);
			return EBUSY;
		}
#ifdef CYGOPT_FS_JFFS2_GCTHREAD
		jffs2_stop_garbage_collect_thread(c);
#endif
		jffs2_iput(root);	// Time to free the root inode

		// free directory entries
		for (fd = root->jffs2_i.dents; fd; fd = next) {
		  next=fd->next;
		  free(fd);
		}

		free(root);
		//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 superblock & root pointer
		mte->root = CYG_DIR_NULL;
                mte->data = 0;
		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"));
	} else {
		jffs2_sb->s_mount_count--;
        }
        if (--n_fs_mounted == 0)
                jffs2_destroy_slab_caches();        
	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"));

	/* If no chdir has been called and we were the first file system
	   mounted, we get called with dir == NULL. Deal with it */
	if (!dir)
		dir = mte->root;

#ifndef CYGOPT_FS_JFFS2_WRITE
	if (mode & (O_CREAT|O_TRUNC|O_WRONLY))
		return EROFS;
#endif
	init_dirsearch(&ds, (struct _inode *) dir, name);

	err = jffs2_find(&ds);

	if (err == ENOENT) {
#ifdef CYGOPT_FS_JFFS2_WRITE
		if (ds.last && (mode & O_CREAT)) {

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

			err = jffs2_create(ds.dir, ds.name, 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;
		}
#endif
	} 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)) {
			jffs2_iput(ds.node);
			err = EEXIST;
		} else
			node = ds.node;
	}

	// Finished with the directory now 
	jffs2_iput(ds.dir);

	if (err != ENOERR)
		return err;

	// Check that we actually have a file here
	if (S_ISDIR(node->i_mode)) {
		jffs2_iput(node);
		return EISDIR;
	}

#ifdef CYGOPT_FS_JFFS2_WRITE
	if (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();
	}
#endif
	// Initialise 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;
}

#ifdef CYGOPT_FS_JFFS2_WRITE
// -------------------------------------------------------------------------
// 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)
{
	jffs2_dirsearch ds;
	int err;

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

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

	err = jffs2_find(&ds);

	if (err != ENOERR) {
		jffs2_iput(ds.dir);
		return err;
	}

	// Cannot unlink directories, use rmdir() instead
	if (S_ISDIR(ds.node->i_mode)) {
		jffs2_iput(ds.dir);
		jffs2_iput(ds.node);
		return EPERM;
	}

	// Delete it from its directory

	err = jffs2_unlink(ds.dir, ds.node, ds.name);
	jffs2_iput(ds.dir);
	jffs2_iput(ds.node);

	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;
	int err;

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

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

	err = jffs2_find(&ds);

	if (err == ENOENT) {
		if (ds.last) {
			// The entry does not exist, and it is the last element in
			// the pathname, so we can create it here.

			err = -jffs2_mkdir(ds.dir, ds.name, S_IRUGO|S_IXUGO|S_IWUSR);
		}
		// If this was not the last element, then an intermediate
		// directory does not exist.
	} else {
		// If there we no error, something already exists with that
		// name, so we cannot create another one.
		jffs2_iput(ds.node);
		if (err == ENOERR)
			err = EEXIST;
	}
	jffs2_iput(ds.dir);
	return err;
}

// -------------------------------------------------------------------------
// jffs2_ops_rmdir()
// Remove a directory.

static int jffs2_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name)
{
	jffs2_dirsearch ds;
	int err;

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

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

	err = jffs2_find(&ds);

	if (err != ENOERR) {
		jffs2_iput(ds.dir);
		return err;
	}

	// Check that this is actually a directory.
	if (!S_ISDIR(ds.node->i_mode)) {
		jffs2_iput(ds.dir);
		jffs2_iput(ds.node);
		return EPERM;
	}

	err = jffs2_rmdir(ds.dir, ds.node, ds.name);

	jffs2_iput(ds.dir);
	jffs2_iput(ds.node);
	return -err;
}

// -------------------------------------------------------------------------
// 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)
{
	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) {
		jffs2_iput(ds1.dir);
		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) {
		jffs2_iput(ds1.dir);
		jffs2_iput(ds1.node);
		jffs2_iput(ds2.dir);
		return err;
	}

	// Null rename, just return
	if (ds1.node == ds2.node) {
		err = ENOERR;
		goto out;
	}

	// 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)) {
			err = EISDIR;
			goto out;
		}

		if (S_ISDIR(ds1.node->i_mode) && !S_ISDIR(ds2.node->i_mode)) {
			err = ENOTDIR;
			goto out;
		}

		// Now delete the destination directory entry
		/* Er, what happened to atomicity of rename()? */
		err = -jffs2_unlink(ds2.dir, ds2.node, ds2.name);

		if (err != 0)
			goto out;

	}
	// 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, ds1.name, ds2.dir, ds2.name);

	// Update directory times
	if (!err)
		ds1.dir->i_ctime =
		    ds1.dir->i_mtime =
		    ds2.dir->i_ctime = ds2.dir->i_mtime = cyg_timestamp();
 out:
	jffs2_iput(ds1.dir);
	jffs2_iput(ds1.node);
	if (S_ISDIR(ds1.node->i_mode)) {
		/* Renamed a directory to elsewhere... so fix up its
		   i_parent pointer and the i_counts of its old and
		   new parents. */
		jffs2_iput(ds1.node->i_parent);
		ds1.node->i_parent = ds2.dir;
		/* We effectively increase its use count by not... */
	} else {
		jffs2_iput(ds2.dir); /* ... doing this */
	}
	if (ds2.node)
		jffs2_iput(ds2.node);
 
	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)
{
	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) {
		jffs2_iput(ds1.dir);
		return err;
	}

	init_dirsearch(&ds2, (struct _inode *) dir2, name2);

	err = jffs2_find(&ds2);

	// Don't allow links to existing objects
	if (err == ENOERR) {
		jffs2_iput(ds1.dir);
		jffs2_iput(ds1.node);
		jffs2_iput(ds2.dir);
		jffs2_iput(ds2.node);
		return EEXIST;
	}

	// Allow through links to non-existing terminal objects
	if (ds2.last && err == ENOENT) {
		ds2.node = NULL;
		err = ENOERR;
	}

	if (err != ENOERR) {
		jffs2_iput(ds1.dir);
		jffs2_iput(ds1.node);
		jffs2_iput(ds2.dir);
		return err;
	}

	// Now we know that there is no existing node at the destination,
	// make a new direntry at the destination.

	err = jffs2_link(ds1.node, ds2.dir, ds2.name);

	if (err == 0)
		ds1.node->i_ctime =
		    ds2.dir->i_ctime = ds2.dir->i_mtime = cyg_timestamp();

	jffs2_iput(ds1.dir);
	jffs2_iput(ds1.node);
	jffs2_iput(ds2.dir);

	return -err;
}
#endif /* CYGOPT_FS_JFFS2_WRITE */
// -------------------------------------------------------------------------
// jffs2_opendir()
// Open a directory for reading.

static int jffs2_opendir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,

⌨️ 快捷键说明

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