/* Inspired by generic filldir in fs/readir.c */ static int ecryptfs_filldir(void *dirent, const char *name, int namelen, loff_t offset, u64 ino, unsigned int d_type) { struct ecryptfs_crypt_stat *crypt_stat; struct ecryptfs_getdents_callback *buf = (struct ecryptfs_getdents_callback *)dirent; int rc; int decoded_length; char *decoded_name; crypt_stat = ecryptfs_dentry_to_private(buf->dentry)->crypt_stat; buf->filldir_called++; decoded_length = ecryptfs_decode_filename(crypt_stat, name, namelen, &decoded_name); if (decoded_length < 0) { rc = decoded_length; goto out; } rc = buf->filldir(buf->dirent, decoded_name, decoded_length, offset, ino, d_type); kfree(decoded_name); if (rc >= 0) buf->entries_written++; out: return rc; }
static int ecryptfs_readlink(struct dentry *dentry, char __user * buf, int bufsiz) { int rc; struct dentry *lower_dentry; char *decoded_name; char *lower_buf; mm_segment_t old_fs; struct ecryptfs_crypt_stat *crypt_stat; lower_dentry = ecryptfs_dentry_to_lower(dentry); if (!lower_dentry->d_inode->i_op || !lower_dentry->d_inode->i_op->readlink) { rc = -EINVAL; goto out; } /* Released in this function */ lower_buf = kmalloc(bufsiz, GFP_KERNEL); if (lower_buf == NULL) { ecryptfs_printk(KERN_ERR, "Out of memory\n"); rc = -ENOMEM; goto out; } old_fs = get_fs(); set_fs(get_ds()); ecryptfs_printk(KERN_DEBUG, "Calling readlink w/ " "lower_dentry->d_name.name = [%s]\n", lower_dentry->d_name.name); rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, (char __user *)lower_buf, bufsiz); set_fs(old_fs); if (rc >= 0) { crypt_stat = NULL; rc = ecryptfs_decode_filename(crypt_stat, lower_buf, rc, &decoded_name); if (rc == -ENOMEM) goto out_free_lower_buf; if (rc > 0) { ecryptfs_printk(KERN_DEBUG, "Copying [%d] bytes " "to userspace: [%*s]\n", rc, decoded_name); if (copy_to_user(buf, decoded_name, rc)) rc = -EFAULT; } kfree(decoded_name); fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); } out_free_lower_buf: kfree(lower_buf); out: return rc; }