📄 inode.c
字号:
r = -ENOENT; } } else { D3(printk("jffs_lookup(): Couldn't find the file. " "f = 0x%p, name = \"%s\", d = 0x%p, d->ino = %u\n", f, name, d, d->ino)); r = -ENOENT; }jffs_lookup_end: iput(dir); return r;} /* jffs_lookup() *//* Try to read a page of data from a file. */static intjffs_readpage(struct inode *inode, struct page *page){ unsigned long buf; unsigned long read_len; int result = -EIO; struct jffs_file *f = (struct jffs_file *)inode->u.generic_ip; int r; D2(printk("***jffs_readpage(): file = \"%s\", page->offset = %lu\n", (f->name ? f->name : ""), page->offset)); page->count++; set_bit(PG_locked, &page->flags); buf = page_address(page); clear_bit(PG_uptodate, &page->flags); clear_bit(PG_error, &page->flags); if (page->offset < inode->i_size) { read_len = jffs_min(inode->i_size - page->offset, PAGE_SIZE); r = jffs_read_data(f, (char *)buf, page->offset, read_len); if (r == read_len) { if (read_len < PAGE_SIZE) { memset((void *)(buf + read_len), 0, PAGE_SIZE - read_len); } set_bit(PG_uptodate, &page->flags); result = 0; } D(else { printk("***jffs_readpage(): Read error! " "Wanted to read %lu bytes but only " "read %d bytes.\n", read_len, r); }); } if (result) { set_bit(PG_error, &page->flags); memset((void *)buf, 0, PAGE_SIZE); } clear_bit(PG_locked, &page->flags); wake_up(&page->wait); free_page(buf); D3(printk("jffs_readpage(): Leaving...\n")); return result;} /* jffs_readpage() *//* Create a new directory. */static intjffs_mkdir(struct inode *dir, const char *name, int len, int mode){ struct jffs_raw_inode raw_inode; struct jffs_control *c; struct jffs_node *node; struct jffs_file *dir_f; int dir_mode; int result = 0; D1({ char *_name = (char *) kmalloc(len + 1, GFP_KERNEL); memcpy(_name, name, len); _name[len] = '\0'; printk("***jffs_mkdir(): dir = 0x%p, name = \"%s\", " "len = %d, mode = 0x%08x\n", dir, _name, len, mode); kfree(_name); }); if (!dir) { return -ENOENT; } if (len > JFFS_MAX_NAME_LEN) { result = -ENAMETOOLONG; goto jffs_mkdir_end; } dir_f = (struct jffs_file *)dir->u.generic_ip; ASSERT(if (!dir_f) { printk(KERN_ERR "jffs_mkdir(): No reference to a " "jffs_file struct in inode.\n"); result = -1; goto jffs_mkdir_end; }); c = dir_f->c; if (!JFFS_ENOUGH_SPACE(c->fmc)) { D1(printk("jffs_mkdir(): Free size = %u\n", jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc))); D(printk(KERN_NOTICE "JFFS: No space left on device\n")); result = -ENOSPC; goto jffs_mkdir_end; } /* If there already exists a file or directory with the same name, then this operation should fail. I originally thought that VFS should take care of this issue. */ if (jffs_find_child(dir_f, name, len)) { D(printk("jffs_mkdir(): There already exists a file or " "directory with the same name!\n")); result = -EEXIST; goto jffs_mkdir_end; } dir_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask); if (dir->i_mode & S_ISGID) { dir_mode |= S_ISGID; } /* Create a node and initialize it as much as needed. */ if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) { D(printk("jffs_mkdir(): Allocation failed: node == 0\n")); result = -ENOMEM; goto jffs_mkdir_end; } DJM(no_jffs_node++); node->data_offset = 0; node->removed_size = 0; /* Initialize the raw inode. */ raw_inode.magic = JFFS_MAGIC_BITMASK; raw_inode.ino = c->next_ino++; raw_inode.pino = dir_f->ino; raw_inode.version = 1; raw_inode.mode = dir_mode; raw_inode.uid = current->fsuid; raw_inode.gid = current->fsgid; raw_inode.atime = CURRENT_TIME; raw_inode.mtime = raw_inode.atime; raw_inode.ctime = raw_inode.atime; raw_inode.offset = 0; raw_inode.dsize = 0; raw_inode.rsize = 0; raw_inode.nsize = len; raw_inode.nlink = 1; raw_inode.spare = 0; raw_inode.rename = 0; raw_inode.deleted = 0; /* Write the new node to the flash. */ if (jffs_write_node(c, node, &raw_inode, name, 0) < 0) { D(printk("jffs_mkdir(): jffs_write_node() failed.\n")); kfree(node); DJM(no_jffs_node--); result = -1; goto jffs_mkdir_end; } /* Insert the new node into the file system. */ result = jffs_insert_node(c, 0, &raw_inode, name, node);jffs_mkdir_end: iput(dir); return result;} /* jffs_mkdir() *//* Remove a directory. */static intjffs_rmdir(struct inode *dir, const char *name, int len){ D3(printk("***jffs_rmdir()\n")); return jffs_remove(dir, name, len, S_IFDIR, 1);}/* Remove any kind of file except for directories. */static intjffs_unlink(struct inode *dir, const char *name, int len){ D3(printk("***jffs_unlink()\n")); return jffs_remove(dir, name, len, 0, 1);}/* Remove a JFFS entry, i.e. plain files, directories, etc. Here we shouldn't test for free space on the device. */static intjffs_remove(struct inode *dir, const char *name, int len, int type, int must_iput){ struct jffs_raw_inode raw_inode; struct jffs_control *c; struct jffs_file *dir_f; /* The file-to-remove's parent. */ struct jffs_file *del_f; /* The file to remove. */ struct jffs_node *del_node; struct inode *inode = 0; int result = 0; D1({ char *_name = (char *) kmalloc(len + 1, GFP_KERNEL); memcpy(_name, name, len); _name[len] = '\0'; printk("***jffs_remove(): file = \"%s\"\n", _name); kfree(_name); }); if (!dir) { return -ENOENT; } if (len > JFFS_MAX_NAME_LEN) { result = -ENAMETOOLONG; goto jffs_remove_end; } dir_f = (struct jffs_file *) dir->u.generic_ip; c = dir_f->c; if (!(del_f = jffs_find_child(dir_f, name, len))) { D(printk("jffs_remove(): jffs_find_child() failed.\n")); result = -ENOENT; goto jffs_remove_end; } if (S_ISDIR(type)) { if (!S_ISDIR(del_f->mode)) { result = -ENOTDIR; goto jffs_remove_end; } if (del_f->children) { result = -ENOTEMPTY; goto jffs_remove_end; } } else if (S_ISDIR(del_f->mode)) { D(printk("jffs_remove(): node is a directory " "but it shouldn't be.\n")); result = -EPERM; goto jffs_remove_end; } if (!(inode = iget(dir->i_sb, del_f->ino))) { printk(KERN_ERR "JFFS: Unlink failed.\n"); result = -ENOENT; goto jffs_remove_end; } /* Create a node for the deletion. */ if (!(del_node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) { D(printk("jffs_remove(): Allocation failed!\n")); result = -ENOMEM; goto jffs_remove_end; } DJM(no_jffs_node++); del_node->data_offset = 0; del_node->removed_size = 0; /* Initialize the raw inode. */ raw_inode.magic = JFFS_MAGIC_BITMASK; raw_inode.ino = del_f->ino; raw_inode.pino = del_f->pino; raw_inode.version = del_f->highest_version + 1; raw_inode.mode = del_f->mode; raw_inode.uid = current->fsuid; raw_inode.gid = current->fsgid; raw_inode.atime = CURRENT_TIME; raw_inode.mtime = del_f->mtime; raw_inode.ctime = raw_inode.atime; raw_inode.offset = 0; raw_inode.dsize = 0; raw_inode.rsize = 0; raw_inode.nsize = 0; raw_inode.nlink = del_f->nlink; raw_inode.spare = 0; raw_inode.rename = 0; raw_inode.deleted = 1; /* Write the new node to the flash memory. */ if (jffs_write_node(c, del_node, &raw_inode, 0, 0) < 0) { kfree(del_node); DJM(no_jffs_node--); result = -1; goto jffs_remove_end; } /* Update the file. This operation will make the file disappear from the in-memory file system structures. */ jffs_insert_node(c, del_f, &raw_inode, 0, del_node); dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_dirt = 1; inode->i_nlink = inode->i_nlink ? inode->i_nlink - 1 : 0; if (inode->i_nlink == 0) { inode->u.generic_ip = 0; } inode->i_dirt = 1; inode->i_ctime = dir->i_ctime;jffs_remove_end: if (must_iput) { iput(dir); } if (inode) { iput(inode); } return result;} /* jffs_remove() */static intjffs_mknod(struct inode *dir, const char *name, int len, int mode, int rdev){ struct jffs_raw_inode raw_inode; struct jffs_file *dir_f; struct jffs_node *node = 0; struct jffs_control *c; int result = 0; kdev_t dev = to_kdev_t(rdev); D1(printk("***jffs_mknod()\n")); if (!dir) { return -ENOENT; } if (len > JFFS_MAX_NAME_LEN) { result = -ENAMETOOLONG; goto jffs_mknod_end; } dir_f = (struct jffs_file *)dir->u.generic_ip; c = dir_f->c; if (!JFFS_ENOUGH_SPACE(c->fmc)) { D1(printk("jffs_mknod(): Free size = %u\n", jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc))); D(printk(KERN_NOTICE "JFFS: No space left on device\n")); result = -ENOSPC; goto jffs_mknod_end; } /* Check and see if the file exists already. */ if (jffs_find_child(dir_f, name, len)) { D(printk("jffs_mknod(): There already exists a file or " "directory with the same name!\n")); result = -EEXIST; goto jffs_mknod_end; } /* Create and initialize a new node. */ if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) { D(printk("jffs_mknod(): Allocation failed!\n")); result = -ENOMEM; goto jffs_mknod_err; } DJM(no_jffs_node++); node->data_offset = 0; node->removed_size = 0; /* Initialize the raw inode. */ raw_inode.magic = JFFS_MAGIC_BITMASK; raw_inode.ino = c->next_ino++; raw_inode.pino = dir_f->ino; raw_inode.version = 1; raw_inode.mode = mode; raw_inode.uid = current->fsuid; raw_inode.gid = current->fsgid; raw_inode.atime = CURRENT_TIME; raw_inode.mtime = raw_inode.atime; raw_inode.ctime = raw_inode.atime; raw_inode.offset = 0; raw_inode.dsize = sizeof(kdev_t); raw_inode.rsize = 0; raw_inode.nsize = len; raw_inode.nlink = 1; raw_inode.spare = 0; raw_inode.rename = 0; raw_inode.deleted = 0; /* Write the new node to the flash. */ if (jffs_write_node(c, node, &raw_inode, name, (unsigned char *)&dev) < 0) { D(printk("jffs_mknod(): jffs_write_node() failed.\n")); result = -1; goto jffs_mknod_err; } /* Insert the new node into the file system. */ if (jffs_insert_node(c, 0, &raw_inode, name, node) < 0) { result = -1; goto jffs_mknod_end; } goto jffs_mknod_end;jffs_mknod_err: if (node) { kfree(node); DJM(no_jffs_node--); }jffs_mknod_end: iput(dir); return result;} /* jffs_mknod() */static intjffs_symlink(struct inode *dir, const char *name, int len, const char *symname){ struct jffs_raw_inode raw_inode; struct jffs_control *c; struct jffs_file *dir_f; struct jffs_node *node; int symname_len = strlen(symname); D1({ char *_name = (char *)kmalloc(len + 1, GFP_KERNEL); char *_symname = (char *)kmalloc(symname_len + 1, GFP_KERNEL); memcpy(_name, name, len); _name[len] = '\0'; memcpy(_symname, symname, symname_len); _symname[symname_len] = '\0'; printk("***jffs_symlink(): dir = 0x%p, name = \"%s\", " "symname = \"%s\"\n", dir, _name, _symname); kfree(_name); kfree(_symname); }); if (!dir) { return -ENOENT; } if (len > JFFS_MAX_NAME_LEN) { iput(dir); return -ENAMETOOLONG; } dir_f = (struct jffs_file *)dir->u.generic_ip; ASSERT(if (!dir_f) { printk(KERN_ERR "jffs_symlink(): No reference to a " "jffs_file struct in inode.\n"); iput(dir); return -1; }); c = dir_f->c; if (!JFFS_ENOUGH_SPACE(c->fmc)) { D1(printk("jffs_symlink(): Free size = %u\n", jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc))); D(printk(KERN_NOTICE "JFFS: No space left on device\n")); iput(dir); return -ENOSPC; } /* Check so there isn't an already existing file with the specified name. */ if (jffs_find_child(dir_f, name, len)) { iput(dir); return -EEXIST; } /* Create a node and initialize it as much as needed. */ if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) { D(printk("jffs_symlink(): Allocation failed: node == NULL\n")); iput(dir); return -ENOMEM; } DJM(no_jffs_node++); node->data_offset = 0; node->removed_size = 0; /* Initialize the raw inode. */ raw_inode.magic = JFFS_MAGIC_BITMASK; raw_inode.ino = c->next_ino++; raw_inode.pino = dir_f->ino; raw_inode.version = 1; raw_inode.mode = S_IFLNK | S_IRWXUGO; raw_inode.uid = current->fsuid; raw_inode.gid = current->fsgid; raw_inode.atime = CURRENT_TIME; raw_inode.mtime = raw_inode.atime; raw_inode.ctime = raw_inode.atime; raw_inode.offset = 0; raw_inode.dsize = symname_len; raw_inode.rsize = 0; raw_inode.nsize = len; raw_inode.nlink = 1; raw_inode.spare = 0; raw_inode.rename = 0; raw_inode.deleted = 0; /* Write the new node to the flash. */ if (jffs_write_node(c, node, &raw_inode, name, (const unsigned char *)symname) < 0) { D(printk("jffs_symlink(): jffs_write_node() failed.\n")); kfree(node); DJM(no_jffs_node--); iput(dir); return -1; } /* Insert the new node into the file system. */ if (jffs_insert_node(c, 0, &raw_inode, name, node) < 0) { iput(dir); return -1; } iput(dir); return 0;} /* jffs_symlink() *//* Read the path that a symbolic link is referring to. */static intjffs_readlink(struct inode *inode, char *buffer, int buflen){ struct jffs_file *f; int i; char *link; int result; D2(printk("***jffs_readlink()\n")); /* Continue only if the file is a symbolic link. */ if (!S_ISLNK(inode->i_mode)) { result = -EINVAL; goto jffs_readlink_end1; } f = (struct jffs_file *)inode->u.generic_ip; ASSERT(if (!f) { printk(KERN_ERR "jffs_readlink(): No reference to a " "jffs_file struct in inode.\n"); result = -1; goto jffs_readlink_end1; }); if (!(link = (char *)kmalloc(f->size + 1, GFP_KERNEL))) { result = -ENOMEM; goto jffs_readlink_end1; } if ((result = jffs_read_data(f, link, 0, f->size)) < 0) { goto jffs_readlink_end2; } link[result] = '\0'; for (i = 0; (i < buflen) && (i < result); i++) { put_user(link[i], buffer++); } UPDATE_ATIME(inode);jffs_readlink_end2: kfree(link);jffs_readlink_end1: iput(inode); return result;} /* jffs_readlink() */static intjffs_follow_link(struct inode *dir, struct inode *inode, int flag, int mode, struct inode **res_inode){ struct jffs_file *f; char *link; int r; D3(printk("jffs_follow_link(): dir = 0x%p, " "inode = 0x%p, flag = 0x%08x, mode = 0x%08x\n", dir, inode, flag, mode));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -