📄 fs-ecos.c
字号:
// 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, "jffs3") == 0 && strcmp(m->devname, mte->devname) == 0) { jffs3_sb = (struct super_block *) m->data; } } if (jffs3_sb == NULL) { jffs3_sb = malloc(sizeof (struct super_block)); if (jffs3_sb == NULL) return ENOMEM; c = JFFS3_SB_INFO(jffs3_sb); memset(jffs3_sb, 0, sizeof (struct super_block)); jffs3_sb->s_dev = t; c->inocache_list = malloc(sizeof(struct jffs3_inode_cache *) * INOCACHE_HASHSIZE); if (!c->inocache_list) { free(jffs3_sb); return ENOMEM; } memset(c->inocache_list, 0, sizeof(struct jffs3_inode_cache *) * INOCACHE_HASHSIZE); if (n_fs_mounted++ == 0) { jffs3_create_slab_caches(); // No error check, cannot fail jffs3_compressors_init(); } err = jffs3_read_super(jffs3_sb); if (err) { if (--n_fs_mounted == 0) { jffs3_destroy_slab_caches(); jffs3_compressors_exit(); } free(jffs3_sb); free(c->inocache_list); return err; } jffs3_sb->s_root->i_parent = jffs3_sb->s_root; // points to itself, no dotdot paths above mountpoint jffs3_sb->s_root->i_cache_prev = NULL; // root inode, so always null jffs3_sb->s_root->i_cache_next = NULL; jffs3_sb->s_root->i_count = 1; // Ensures the root inode is always in ram until umount D2(printf("jffs3_mount erasing pending blocks\n"));#ifdef CYGOPT_FS_JFFS3_WRITE if (!jffs3_is_readonly(c)) jffs3_erase_pending_blocks(c,0);#endif#ifdef CYGOPT_FS_JFFS3_GCTHREAD jffs3_start_garbage_collect_thread(c);#endif } mte->data = (CYG_ADDRWORD) jffs3_sb; jffs3_sb->s_mount_count++; mte->root = (cyg_dir) jffs3_sb->s_root; D2(printf("jffs3_mounted superblock at %x\n", mte->root)); return ENOERR;}extern cyg_dir cyg_cdir_dir;extern cyg_mtab_entry *cyg_cdir_mtab_entry;// -------------------------------------------------------------------------// jffs3_umount()// Unmount the filesystem. static int jffs3_umount(cyg_mtab_entry * mte){ struct _inode *root = (struct _inode *) mte->root; struct super_block *jffs3_sb = root->i_sb; struct jffs3_sb_info *c = JFFS3_SB_INFO(jffs3_sb); struct jffs3_full_dirent *fd, *next; D2(printf("jffs3_umount\n")); // Only really umount if this is the only mount if (jffs3_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; jffs3_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_JFFS3_GCTHREAD jffs3_stop_garbage_collect_thread(c);#endif jffs3_iput(root); // Time to free the root inode // free directory entries for (fd = root->jffs3_i.dents; fd; fd = next) { next=fd->next; jffs3_free_full_dirent(fd); } free(root); //Clear root inode //root_i = NULL; // Clean up the super block and root inode jffs3_free_ino_caches(c); jffs3_free_raw_node_refs(c); free(c->blocks); free(c->inocache_list); free(jffs3_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("jffs3_umount No current mounts\n")); } else { jffs3_sb->s_mount_count--; } if (--n_fs_mounted == 0) { jffs3_destroy_slab_caches(); jffs3_compressors_exit(); } return ENOERR;}// -------------------------------------------------------------------------// jffs3_open()// Open a file for reading or writing.static int jffs3_open(cyg_mtab_entry * mte, cyg_dir dir, const char *name, int mode, cyg_file * file){ jffs3_dirsearch ds; struct _inode *node = NULL; int err; D2(printf("jffs3_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_JFFS3_WRITE if (mode & (O_CREAT|O_TRUNC|O_WRONLY)) return EROFS;#endif init_dirsearch(&ds, (struct _inode *) dir, name); err = jffs3_find(&ds); if (err == ENOENT) {#ifdef CYGOPT_FS_JFFS3_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 = jffs3_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 jffs3_iput(ds.dir); 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)) { jffs3_iput(ds.node); err = EEXIST; } else node = ds.node; } // Finished with the directory now jffs3_iput(ds.dir); if (err != ENOERR) return err; // Check that we actually have a file here if (S_ISDIR(node->i_mode)) { jffs3_iput(node); return EISDIR; }#ifdef CYGOPT_FS_JFFS3_WRITE if (mode & O_TRUNC) { struct jffs3_inode_info *f = JFFS3_INODE_INFO(node); struct jffs3_sb_info *c = JFFS3_SB_INFO(node->i_sb); // If the O_TRUNC bit is set we must clean out the file data. node->i_size = 0; jffs3_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 = &jffs3_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_JFFS3_WRITE// -------------------------------------------------------------------------// jffs3_ops_unlink()// Remove a file link from its directory.static int jffs3_ops_unlink(cyg_mtab_entry * mte, cyg_dir dir, const char *name){ jffs3_dirsearch ds; int err; D2(printf("jffs3_ops_unlink\n")); init_dirsearch(&ds, (struct _inode *) dir, name); err = jffs3_find(&ds); if (err != ENOERR) { jffs3_iput(ds.dir); return err; } // Cannot unlink directories, use rmdir() instead if (S_ISDIR(ds.node->i_mode)) { jffs3_iput(ds.dir); jffs3_iput(ds.node); return EPERM; } // Delete it from its directory err = jffs3_unlink(ds.dir, ds.node, ds.name); jffs3_iput(ds.dir); jffs3_iput(ds.node); return -err;}// -------------------------------------------------------------------------// jffs3_ops_mkdir()// Create a new directory.static int jffs3_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name){ jffs3_dirsearch ds; int err; D2(printf("jffs3_ops_mkdir\n")); init_dirsearch(&ds, (struct _inode *) dir, name); err = jffs3_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 = -jffs3_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. jffs3_iput(ds.node); if (err == ENOERR) err = EEXIST; } jffs3_iput(ds.dir); return err;}// -------------------------------------------------------------------------// jffs3_ops_rmdir()// Remove a directory.static int jffs3_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name){ jffs3_dirsearch ds; int err; D2(printf("jffs3_ops_rmdir\n")); init_dirsearch(&ds, (struct _inode *) dir, name); err = jffs3_find(&ds); if (err != ENOERR) { jffs3_iput(ds.dir); return err; } // Check that this is actually a directory. if (!S_ISDIR(ds.node->i_mode)) { jffs3_iput(ds.dir); jffs3_iput(ds.node); return EPERM; } err = jffs3_rmdir(ds.dir, ds.node, ds.name); jffs3_iput(ds.dir); jffs3_iput(ds.node); return -err;}// -------------------------------------------------------------------------// jffs3_ops_rename()// Rename a file/dir.static int jffs3_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2){ jffs3_dirsearch ds1, ds2; int err; D2(printf("jffs3_ops_rename\n")); init_dirsearch(&ds1, (struct _inode *) dir1, name1); err = jffs3_find(&ds1); if (err != ENOERR) { jffs3_iput(ds1.dir); return err; } init_dirsearch(&ds2, (struct _inode *) dir2, name2); err = jffs3_find(&ds2); // Allow through renames to non-existent objects. if (ds2.last && err == ENOENT) { ds2.node = NULL; err = ENOERR; } if (err != ENOERR) { jffs3_iput(ds1.dir); jffs3_iput(ds1.node); jffs3_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 = -jffs3_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 = -jffs3_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: jffs3_iput(ds1.dir); jffs3_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. */ jffs3_iput(ds1.node->i_parent); ds1.node->i_parent = ds2.dir; /* We effectively increase its use count by not... */ } else { jffs3_iput(ds2.dir); /* ... doing this */ } if (ds2.node) jffs3_iput(ds2.node); return -err;}// -------------------------------------------------------------------------// jffs3_ops_link()// Make a new directory entry for a file.static int jffs3_ops_link(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2, int type){ jffs3_dirsearch ds1, ds2; int err; D2(printf("jffs3_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 = jffs3_find(&ds1); if (err != ENOERR) { jffs3_iput(ds1.dir); return err; } init_dirsearch(&ds2, (struct _inode *) dir2, name2); err = jffs3_find(&ds2); // Don't allow links to existing objects if (err == ENOERR) { jffs3_iput(ds1.dir); jffs3_iput(ds1.node); jffs3_iput(ds2.dir); jffs3_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) { jffs3_iput(ds1.dir); jffs3_iput(ds1.node); jffs3_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 = jffs3_link(ds1.node, ds2.dir, ds2.name); if (err == 0) ds1.node->i_ctime = ds2.dir->i_ctime = ds2.dir->i_mtime = cyg_timestamp(); jffs3_iput(ds1.dir); jffs3_iput(ds1.node); jffs3_iput(ds2.dir); return -err;}#endif /* CYGOPT_FS_JFFS3_WRITE */// -------------------------------------------------------------------------// jffs3_opendir()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -