static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode) { struct inode * inode = new_inode(sb); if (inode) { inode->i_mode = cramfs_inode->mode; inode->i_uid = cramfs_inode->uid; inode->i_size = cramfs_inode->size; inode->i_gid = cramfs_inode->gid; inode->i_ino = CRAMINO(cramfs_inode); /* inode->i_nlink is left 1 - arguably wrong for directories, but it's the best we can do without reading the directory contents. 1 yields the right result in GNU find, even without -noleaf option. */ insert_inode_hash(inode); if (S_ISREG(inode->i_mode)) { inode->i_fop = &generic_ro_fops; inode->i_data.a_ops = &cramfs_aops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &cramfs_dir_inode_operations; inode->i_fop = &cramfs_directory_operations; } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &page_symlink_inode_operations; inode->i_data.a_ops = &cramfs_aops; } else { inode->i_size = 0; init_special_inode(inode, inode->i_mode, cramfs_inode->size); } } return inode; }
static int cramfs_iget5_set(struct inode *inode, void *opaque) { static struct timespec zerotime; struct cramfs_inode *cramfs_inode = opaque; inode->i_mode = cramfs_inode->mode; inode->i_uid = cramfs_inode->uid; inode->i_size = cramfs_inode->size; inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; inode->i_gid = cramfs_inode->gid; /* Struct copy intentional */ inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; inode->i_ino = CRAMINO(cramfs_inode); /* inode->i_nlink is left 1 - arguably wrong for directories, but it's the best we can do without reading the directory contents. 1 yields the right result in GNU find, even without -noleaf option. */ if (S_ISREG(inode->i_mode)) { inode->i_fop = &generic_ro_fops; inode->i_data.a_ops = &cramfs_aops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &cramfs_dir_inode_operations; inode->i_fop = &cramfs_directory_operations; } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &page_symlink_inode_operations; inode->i_data.a_ops = &cramfs_aops; } else { inode->i_size = 0; inode->i_blocks = 0; init_special_inode(inode, inode->i_mode, old_decode_dev(cramfs_inode->size)); } return 0; }
static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode) { struct inode *inode; if (CRAMINO(cramfs_inode) == 1) { inode = new_inode(sb); if (inode) { inode->i_ino = 1; setup_inode(inode, cramfs_inode); } } else { inode = iget_locked(sb, CRAMINO(cramfs_inode)); if (inode) { setup_inode(inode, cramfs_inode); unlock_new_inode(inode); } } return inode; }
static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode) { struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode), cramfs_iget5_test, cramfs_iget5_set, cramfs_inode); if (inode && (inode->i_state & I_NEW)) { unlock_new_inode(inode); } return inode; }
static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode) { struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode), cramfs_iget5_test, cramfs_iget5_set, cramfs_inode); static struct timespec zerotime; if (inode && (inode->i_state & I_NEW)) { inode->i_mode = cramfs_inode->mode; inode->i_uid = cramfs_inode->uid; inode->i_size = cramfs_inode->size; inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_gid = cramfs_inode->gid; /* Struct copy intentional */ inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; inode->i_ino = CRAMINO(cramfs_inode); /* inode->i_nlink is left 1 - arguably wrong for directories, but it's the best we can do without reading the directory contents. 1 yields the right result in GNU find, even without -noleaf option. */ if (S_ISREG(inode->i_mode)) { inode->i_fop = &generic_ro_fops; inode->i_data.a_ops = &cramfs_aops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &cramfs_dir_inode_operations; inode->i_fop = &cramfs_directory_operations; } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &page_symlink_inode_operations; inode->i_data.a_ops = &cramfs_aops; } else { inode->i_size = 0; inode->i_blocks = 0; init_special_inode(inode, inode->i_mode, old_decode_dev(cramfs_inode->size)); } unlock_new_inode(inode); } return inode; }
/* * Read a cramfs directory entry. */ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; struct super_block *sb = inode->i_sb; unsigned int offset; int copied; /* Offset within the thing. */ offset = filp->f_pos; if (offset >= inode->i_size) return 0; /* Directory entries are always 4-byte aligned */ if (offset & 3) return -EINVAL; copied = 0; while (offset < inode->i_size) { struct cramfs_inode *de; unsigned long nextoffset; char *name; int namelen, error; down(&read_mutex); de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+256); up(&read_mutex); name = (char *)(de+1); /* * Namelengths on disk are shifted by two * and the name padded out to 4-byte boundaries * with zeroes. */ namelen = de->namelen << 2; nextoffset = offset + sizeof(*de) + namelen; for (;;) { if (!namelen) return -EIO; if (name[namelen-1]) break; namelen--; } error = filldir(dirent, name, namelen, offset, CRAMINO(de), de->mode >> 12); if (error) break; offset = nextoffset; filp->f_pos = offset; copied++; } return 0; }
static int cramfs_iget5_test(struct inode *inode, void *opaque) { struct cramfs_inode *cramfs_inode = opaque; if (inode->i_ino != CRAMINO(cramfs_inode)) return 0; /* does not match */ if (inode->i_ino != 1) return 1; /* all empty directories, char, block, pipe, and sock, share inode #1 */ if ((inode->i_mode != cramfs_inode->mode) || (inode->i_gid != cramfs_inode->gid) || (inode->i_uid != cramfs_inode->uid)) return 0; /* does not match */ if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) && (inode->i_rdev != old_decode_dev(cramfs_inode->size))) return 0; /* does not match */ return 1; /* matches */ }
static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode) { struct inode * inode = new_inode(sb); if (inode) { inode->i_mode = cramfs_inode->mode; inode->i_uid = cramfs_inode->uid; inode->i_size = cramfs_inode->size; inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_gid = cramfs_inode->gid; inode->i_ino = CRAMINO(cramfs_inode); /* inode->i_nlink is left 1 - arguably wrong for directories, but it's the best we can do without reading the directory contents. 1 yields the right result in GNU find, even without -noleaf option. */ insert_inode_hash(inode); if (S_ISREG(inode->i_mode)) { #ifdef CONFIG_CRAMFS_LINEAR_XIP inode->i_fop = CRAMFS_INODE_IS_XIP(inode) ? &cramfs_linear_xip_fops : &generic_ro_fops; #else inode->i_fop = &generic_ro_fops; #endif inode->i_data.a_ops = &cramfs_aops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &cramfs_dir_inode_operations; inode->i_fop = &cramfs_directory_operations; } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &page_symlink_inode_operations; inode->i_data.a_ops = &cramfs_aops; } else { inode->i_size = 0; init_special_inode(inode, inode->i_mode, cramfs_inode->size); } } return inode; }
/* * Read a cramfs directory entry. */ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct inode *inode = filp->f_path.dentry->d_inode; struct super_block *sb = inode->i_sb; char *buf; unsigned int offset; int copied; /* Offset within the thing. */ offset = filp->f_pos; if (offset >= inode->i_size) return 0; /* Directory entries are always 4-byte aligned */ if (offset & 3) return -EINVAL; buf = kmalloc(CRAMFS_MAXPATHLEN, GFP_KERNEL); if (!buf) return -ENOMEM; copied = 0; while (offset < inode->i_size) { struct cramfs_inode *de; unsigned long nextoffset; char *name; ino_t ino; mode_t mode; int namelen, error; mutex_lock(&read_mutex); de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN); name = (char *)(de+1); /* * Namelengths on disk are shifted by two * and the name padded out to 4-byte boundaries * with zeroes. */ namelen = de->namelen << 2; memcpy(buf, name, namelen); ino = CRAMINO(de); mode = de->mode; mutex_unlock(&read_mutex); nextoffset = offset + sizeof(*de) + namelen; for (;;) { if (!namelen) { kfree(buf); return -EIO; } if (buf[namelen-1]) break; namelen--; } error = filldir(dirent, buf, namelen, offset, ino, mode >> 12); if (error) break; offset = nextoffset; filp->f_pos = offset; copied++; } kfree(buf); return 0; }
static int cramfs_iget5_set(struct inode *inode, void *opaque) { struct cramfs_inode *cramfs_inode = opaque; inode->i_ino = CRAMINO(cramfs_inode); return 0; }
static int cramfs_iget5_test(struct inode *inode, void *opaque) { struct cramfs_inode *cramfs_inode = opaque; return inode->i_ino == CRAMINO(cramfs_inode) && inode->i_ino != 1; }