Пример #1
0
static int filldir(struct ubifs_info *c, const char *name, int namlen,
		   u64 ino, unsigned int d_type)
{
	struct inode *inode;
	char filetime[32];

	switch (d_type) {
	case UBIFS_ITYPE_REG:
		printf("\t");
		break;
	case UBIFS_ITYPE_DIR:
		printf("<DIR>\t");
		break;
	case UBIFS_ITYPE_LNK:
		printf("<LNK>\t");
		break;
	default:
		printf("other\t");
		break;
	}

	inode = ubifs_iget(c->vfs_sb, ino);
	if (IS_ERR(inode)) {
		printf("%s: Error in ubifs_iget(), ino=%lld ret=%p!\n",
		       __func__, ino, inode);
		return -1;
	}
	ctime_r((time_t *)&inode->i_mtime, filetime);
	printf("%9lld  %24.24s  ", inode->i_size, filetime);
	ubifs_iput(inode);

	printf("%s\n", name);

	return 0;
}
Пример #2
0
static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
				   unsigned int flags)
{
	int err;
	union ubifs_key key;
	struct inode *inode = NULL;
	struct ubifs_dent_node *dent;
	struct ubifs_info *c = dir->i_sb->s_fs_info;

	dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino);

	if (dentry->d_name.len > UBIFS_MAX_NLEN)
		return ERR_PTR(-ENAMETOOLONG);

	dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
	if (!dent)
		return ERR_PTR(-ENOMEM);

	dent_key_init(c, &key, dir->i_ino, &dentry->d_name);

	err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name);
	if (err) {
		if (err == -ENOENT) {
			dbg_gen("not found");
			goto done;
		}
		goto out;
	}

	if (dbg_check_name(c, dent, &dentry->d_name)) {
		err = -EINVAL;
		goto out;
	}

	inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum));
	if (IS_ERR(inode)) {
		/*
		 * This should not happen. Probably the file-system needs
		 * checking.
		 */
		err = PTR_ERR(inode);
		ubifs_err(c, "dead directory entry '%pd', error %d",
			  dentry, err);
		ubifs_ro_mode(c, err);
		goto out;
	}

done:
	kfree(dent);
	/*
	 * Note, d_splice_alias() would be required instead if we supported
	 * NFS.
	 */
	d_add(dentry, inode);
	return NULL;

out:
	kfree(dent);
	return ERR_PTR(err);
}
Пример #3
0
int ubifs_size(const char *filename, loff_t *size)
{
	struct ubifs_info *c = ubifs_sb->s_fs_info;
	unsigned long inum;
	struct inode *inode;
	int err = 0;

	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);

	inum = ubifs_findfile(ubifs_sb, (char *)filename);
	if (!inum) {
		err = -1;
		goto out;
	}

	inode = ubifs_iget(ubifs_sb, inum);
	if (IS_ERR(inode)) {
		printf("%s: Error reading inode %ld!\n", __func__, inum);
		err = PTR_ERR(inode);
		goto out;
	}

	*size = inode->i_size;

	ubifs_iput(inode);
out:
	ubi_close_volume(c->ubi);
	return err;
}
Пример #4
0
int ubifs_filesize(char *filename, u32* size)
{
    struct ubifs_info *c = ubifs_sb->s_fs_info;
    unsigned long inum=0;
    struct inode *inode=NULL;
    int err = 0;

    c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
    if (IS_ERR(c->ubi)) {
        err = PTR_ERR(c->ubi);
    	goto out_no_close;
    }
    inum = ubifs_findfile(ubifs_sb, filename);
    if (!inum) {
        err = -1;
        goto out;
    }

    /*
     * Read file inode
     */
    inode = ubifs_iget(ubifs_sb, inum);
    if (IS_ERR(inode)) {
        printf("%s: Error reading inode %ld!\n", __func__, inum);
        err = PTR_ERR(inode);
        goto out;
    }

    /*
     * If no size was specified or if size bigger than filesize
     * set size to filesize
     */
    //if ((size == 0) || (size > inode->i_size))
     *size = inode->i_size;
     printf("ubifs_filesize  %08x \n", *size);

    //return 0;
out:
    ubi_close_volume(c->ubi);
out_no_close:
    return err;

}
Пример #5
0
int ubifs_load(char *filename, u32 addr, u32 size)
{
	struct ubifs_info *c = ubifs_sb->s_fs_info;
	unsigned long inum;
	struct inode *inode;
	struct page page;
	int err = 0;
	int i;
	int count;
	int last_block_size = 0;

	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
	/* ubifs_findfile will resolve symlinks, so we know that we get
	 * the real file here */
	inum = ubifs_findfile(ubifs_sb, filename);
	if (!inum) {
		err = -1;
		goto out;
	}

	/*
	 * Read file inode
	 */
	inode = ubifs_iget(ubifs_sb, inum);
	if (IS_ERR(inode)) {
		printf("%s: Error reading inode %ld!\n", __func__, inum);
		err = PTR_ERR(inode);
		goto out;
	}

	/*
	 * If no size was specified or if size bigger than filesize
	 * set size to filesize
	 */
	if ((size == 0) || (size > inode->i_size))
		size = inode->i_size;

	count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
	printf("Loading file '%s' to addr 0x%08x with size %d (0x%08x)...\n",
	       filename, addr, size, size);

	page.addr = (void *)addr;
	page.index = 0;
	page.inode = inode;
	for (i = 0; i < count; i++) {
		/*
		 * Make sure to not read beyond the requested size
		 */
		if ((i + 1) == count)
			last_block_size = size - (i * PAGE_SIZE);

		err = do_readpage(c, inode, &page, last_block_size);
		if (err)
			break;

		page.addr += PAGE_SIZE;
		page.index++;
	}

	if (err)
		printf("Error reading file '%s'\n", filename);
	else
		printf("Done\n");

	ubifs_iput(inode);

out:
	ubi_close_volume(c->ubi);
	return err;
}
Пример #6
0
static unsigned long ubifs_findfile(struct super_block *sb, char *filename)
{
	int ret;
	char *next;
	char fpath[128];
	char symlinkpath[128];
	char *name = fpath;
	unsigned long root_inum = 1;
	unsigned long inum;
	int symlink_count = 0; /* Don't allow symlink recursion */
	char link_name[64];

	strcpy(fpath, filename);

	/* Remove all leading slashes */
	while (*name == '/')
		name++;

	/*
	 * Handle root-direcoty ('/')
	 */
	inum = root_inum;
	if (!name || *name == '\0')
		return inum;

	for (;;) {
		struct inode *inode;
		struct ubifs_inode *ui;

		/* Extract the actual part from the pathname.  */
		next = strchr(name, '/');
		if (next) {
			/* Remove all leading slashes.  */
			while (*next == '/')
				*(next++) = '\0';
		}

		ret = ubifs_finddir(sb, name, root_inum, &inum);
		if (!ret)
			return 0;
		inode = ubifs_iget(sb, inum);

		if (!inode)
			return 0;
		ui = ubifs_inode(inode);

		if ((inode->i_mode & S_IFMT) == S_IFLNK) {
			char buf[128];

			/* We have some sort of symlink recursion, bail out */
			if (symlink_count++ > 8) {
				printf("Symlink recursion, aborting\n");
				return 0;
			}
			memcpy(link_name, ui->data, ui->data_len);
			link_name[ui->data_len] = '\0';

			if (link_name[0] == '/') {
				/* Absolute path, redo everything without
				 * the leading slash */
				next = name = link_name + 1;
				root_inum = 1;
				continue;
			}
			/* Relative to cur dir */
			sprintf(buf, "%s/%s",
					link_name, next == NULL ? "" : next);
			memcpy(symlinkpath, buf, sizeof(buf));
			next = name = symlinkpath;
			continue;
		}

		/*
		 * Check if directory with this name exists
		 */

		/* Found the node!  */
		if (!next || *next == '\0')
			return inum;

		root_inum = inum;
		name = next;
	}

	return 0;
}
Пример #7
0
int ubifs_load(char *filename, u32 addr, u32 size)
{
	struct ubifs_info *c = ubifs_sb->s_fs_info;
	unsigned long inum;
	struct inode *inode;
	struct page page;
	int err = 0;
	int i;
	int count;
	char link_name[64];
	struct ubifs_inode *ui;

	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
	inum = ubifs_findfile(ubifs_sb, filename);
	if (!inum) {
		err = -1;
		goto out;
	}

	/*
	 * Read file inode
	 */
	inode = ubifs_iget(ubifs_sb, inum);
	if (IS_ERR(inode)) {
		printf("%s: Error reading inode %ld!\n", __func__, inum);
		err = PTR_ERR(inode);
		goto out;
	}

	/*
	 * Check for symbolic link
	 */
	ui = ubifs_inode(inode);
	if (((inode->i_mode & S_IFMT) == S_IFLNK) && ui->data_len) {
		memcpy(link_name, ui->data, ui->data_len);
		printf("%s is linked to %s!\n", filename, link_name);
		ubifs_iput(inode);

		/*
		 * Now we have the "real" filename, call ubifs_load()
		 * again (recursive call) to load this file instead
		 */
		return ubifs_load(link_name, addr, size);
	}

	/*
	 * If no size was specified or if size bigger than filesize
	 * set size to filesize
	 */
	if ((size == 0) || (size > inode->i_size))
		size = inode->i_size;

	count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
	printf("Loading file '%s' to addr 0x%08x with size %d (0x%08x)...\n",
	       filename, addr, size, size);

	page.addr = (void *)addr;
	page.index = 0;
	page.inode = inode;
	for (i = 0; i < count; i++) {
		err = do_readpage(c, inode, &page);
		if (err)
			break;

		page.addr += PAGE_SIZE;
		page.index++;
	}

	if (err)
		printf("Error reading file '%s'\n", filename);
	else
		printf("Done\n");

	ubifs_iput(inode);

out:
	ubi_close_volume(c->ubi);
	return err;
}
Пример #8
0
static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
{
	struct ubi_volume_desc *ubi = sb->s_fs_info;
	struct ubifs_info *c;
	struct inode *root;
	int err;

	c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL);
	if (!c)
		return -ENOMEM;

	spin_lock_init(&c->cnt_lock);
	spin_lock_init(&c->cs_lock);
	spin_lock_init(&c->buds_lock);
	spin_lock_init(&c->space_lock);
	spin_lock_init(&c->orphan_lock);
	init_rwsem(&c->commit_sem);
	mutex_init(&c->lp_mutex);
	mutex_init(&c->tnc_mutex);
	mutex_init(&c->log_mutex);
	mutex_init(&c->mst_mutex);
	mutex_init(&c->umount_mutex);
	init_waitqueue_head(&c->cmt_wq);
	c->buds = RB_ROOT;
	c->old_idx = RB_ROOT;
	c->size_tree = RB_ROOT;
	c->orph_tree = RB_ROOT;
	INIT_LIST_HEAD(&c->infos_list);
	INIT_LIST_HEAD(&c->idx_gc);
	INIT_LIST_HEAD(&c->replay_list);
	INIT_LIST_HEAD(&c->replay_buds);
	INIT_LIST_HEAD(&c->uncat_list);
	INIT_LIST_HEAD(&c->empty_list);
	INIT_LIST_HEAD(&c->freeable_list);
	INIT_LIST_HEAD(&c->frdi_idx_list);
	INIT_LIST_HEAD(&c->unclean_leb_list);
	INIT_LIST_HEAD(&c->old_buds);
	INIT_LIST_HEAD(&c->orph_list);
	INIT_LIST_HEAD(&c->orph_new);

	c->highest_inum = UBIFS_FIRST_INO;
	c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM;

	ubi_get_volume_info(ubi, &c->vi);
	ubi_get_device_info(c->vi.ubi_num, &c->di);

	/* Re-open the UBI device in read-write mode */
	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
	if (IS_ERR(c->ubi)) {
		err = PTR_ERR(c->ubi);
		goto out_free;
	}

	c->vfs_sb = sb;

	sb->s_fs_info = c;
	sb->s_magic = UBIFS_SUPER_MAGIC;
	sb->s_blocksize = UBIFS_BLOCK_SIZE;
	sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT;
	sb->s_dev = c->vi.cdev;
	sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c);
	if (c->max_inode_sz > MAX_LFS_FILESIZE)
		sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE;

	if (c->rw_incompat) {
		ubifs_err("the file-system is not R/W-compatible");
		ubifs_msg("on-flash format version is w%d/r%d, but software "
			  "only supports up to version w%d/r%d", c->fmt_version,
			  c->ro_compat_version, UBIFS_FORMAT_VERSION,
			  UBIFS_RO_COMPAT_VERSION);
		return -EROFS;
	}

	mutex_lock(&c->umount_mutex);
	err = mount_ubifs(c);
	if (err) {
		ubifs_assert(err < 0);
		goto out_unlock;
	}

	/* Read the root inode */
	root = ubifs_iget(sb, UBIFS_ROOT_INO);
	if (IS_ERR(root)) {
		err = PTR_ERR(root);
		goto out_umount;
	}

	sb->s_root = NULL;

	mutex_unlock(&c->umount_mutex);
	return 0;

out_umount:
	ubifs_umount(c);
out_unlock:
	mutex_unlock(&c->umount_mutex);
	ubi_close_volume(c->ubi);
out_free:
	kfree(c);
	return err;
}
Пример #9
0
static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
				   unsigned int flags)
{
	int err;
	union ubifs_key key;
	struct inode *inode = NULL;
	struct ubifs_dent_node *dent;
	struct ubifs_info *c = dir->i_sb->s_fs_info;
	struct fscrypt_name nm;

	dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino);

	if (ubifs_crypt_is_encrypted(dir)) {
		err = fscrypt_get_encryption_info(dir);

		/*
		 * DCACHE_ENCRYPTED_WITH_KEY is set if the dentry is
		 * created while the directory was encrypted and we
		 * have access to the key.
		 */
		if (fscrypt_has_encryption_key(dir))
			fscrypt_set_encrypted_dentry(dentry);
		fscrypt_set_d_op(dentry);
		if (err && err != -ENOKEY)
			return ERR_PTR(err);
	}

	err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm);
	if (err)
		return ERR_PTR(err);

	if (fname_len(&nm) > UBIFS_MAX_NLEN) {
		err = -ENAMETOOLONG;
		goto out_fname;
	}

	dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
	if (!dent) {
		err = -ENOMEM;
		goto out_fname;
	}

	if (nm.hash) {
		ubifs_assert(fname_len(&nm) == 0);
		ubifs_assert(fname_name(&nm) == NULL);
		dent_key_init_hash(c, &key, dir->i_ino, nm.hash);
		err = ubifs_tnc_lookup_dh(c, &key, dent, nm.minor_hash);
	} else {
		dent_key_init(c, &key, dir->i_ino, &nm);
		err = ubifs_tnc_lookup_nm(c, &key, dent, &nm);
	}

	if (err) {
		if (err == -ENOENT) {
			dbg_gen("not found");
			goto done;
		}
		goto out_dent;
	}

	if (dbg_check_name(c, dent, &nm)) {
		err = -EINVAL;
		goto out_dent;
	}

	inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum));
	if (IS_ERR(inode)) {
		/*
		 * This should not happen. Probably the file-system needs
		 * checking.
		 */
		err = PTR_ERR(inode);
		ubifs_err(c, "dead directory entry '%pd', error %d",
			  dentry, err);
		ubifs_ro_mode(c, err);
		goto out_dent;
	}

	if (ubifs_crypt_is_encrypted(dir) &&
	    (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
	    !fscrypt_has_permitted_context(dir, inode)) {
		ubifs_warn(c, "Inconsistent encryption contexts: %lu/%lu",
			   dir->i_ino, inode->i_ino);
		err = -EPERM;
		goto out_inode;
	}

done:
	kfree(dent);
	fscrypt_free_filename(&nm);
	/*
	 * Note, d_splice_alias() would be required instead if we supported
	 * NFS.
	 */
	d_add(dentry, inode);
	return NULL;

out_inode:
	iput(inode);
out_dent:
	kfree(dent);
out_fname:
	fscrypt_free_filename(&nm);
	return ERR_PTR(err);
}
Пример #10
0
int ubifs_read(const char *filename, void *buf, loff_t offset,
	       loff_t size, loff_t *actread)
{
	struct ubifs_info *c = ubifs_sb->s_fs_info;
	unsigned long inum;
	struct inode *inode;
	struct page page;
	int err = 0;
	int i;
	int count;
	int last_block_size = 0;

	*actread = 0;

	if (offset & (PAGE_SIZE - 1)) {
		printf("ubifs: Error offset must be a multple of %d\n",
		       PAGE_SIZE);
		return -1;
	}

	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
	/* ubifs_findfile will resolve symlinks, so we know that we get
	 * the real file here */
	inum = ubifs_findfile(ubifs_sb, (char *)filename);
	if (!inum) {
		err = -1;
		goto out;
	}

	/*
	 * Read file inode
	 */
	inode = ubifs_iget(ubifs_sb, inum);
	if (IS_ERR(inode)) {
		printf("%s: Error reading inode %ld!\n", __func__, inum);
		err = PTR_ERR(inode);
		goto out;
	}

	if (offset > inode->i_size) {
		printf("ubifs: Error offset (%lld) > file-size (%lld)\n",
		       offset, size);
		err = -1;
		goto put_inode;
	}

	/*
	 * If no size was specified or if size bigger than filesize
	 * set size to filesize
	 */
	if ((size == 0) || (size > (inode->i_size - offset)))
		size = inode->i_size - offset;

	count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;

	page.addr = buf;
	page.index = offset / PAGE_SIZE;
	page.inode = inode;
	for (i = 0; i < count; i++) {
		/*
		 * Make sure to not read beyond the requested size
		 */
		if (((i + 1) == count) && (size < inode->i_size))
			last_block_size = size - (i * PAGE_SIZE);

		err = do_readpage(c, inode, &page, last_block_size);
		if (err)
			break;

		page.addr += PAGE_SIZE;
		page.index++;
	}

	if (err) {
		printf("Error reading file '%s'\n", filename);
		*actread = i * PAGE_SIZE;
	} else {
		*actread = size;
	}

put_inode:
	ubifs_iput(inode);

out:
	ubi_close_volume(c->ubi);
	return err;
}
Пример #11
0
int ubifs_part_load(char *filename, u32 addr, u32 offset, u32 size)
{
    struct ubifs_info *c = ubifs_sb->s_fs_info;
    unsigned long inum=0;
    struct inode *inode=NULL;
    struct page page;
    int err = 0;
    int i=0;
    int count=0;
	int last_block_size = 0;
    char link_name[64];
    struct ubifs_inode *ui=NULL;
    
    if(offset % PAGE_SIZE != 0)
    {
        printf("%s: offset(0x%x) should align to page size(0x%x), at %d\n", __func__, offset, PAGE_SIZE, __LINE__);
        return 1;
    }

    c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
    if (IS_ERR(c->ubi)) {
        err = PTR_ERR(c->ubi);
        goto out_no_close;
    }
    inum = ubifs_findfile(ubifs_sb, filename);
    if (!inum) {
        err = -1;
        goto out;
    }

    /*
    * Read file inode
    */
    inode = ubifs_iget(ubifs_sb, inum);
    if (IS_ERR(inode)) {
        printf("%s: Error reading inode %ld!\n", __func__, inum);
        err = PTR_ERR(inode);
        goto out;
    }

    /*
    * Check for symbolic link
    */
    ui = ubifs_inode(inode);
    if (((inode->i_mode & S_IFMT) == S_IFLNK) && ui->data_len) {
        memcpy(link_name, ui->data, ui->data_len);
        link_name[ui->data_len] = '\0';
        printf("%s is linked to %s!\n", filename, link_name);
        ubifs_iput(inode);

        /*
         * Now we have the "real" filename, call ubifs_load()
         * again (recursive call) to load this file instead
         */
        return ubifs_part_load(link_name, addr, offset, size);
    }

    /*
    * If no size was specified or if size bigger than filesize
    * set size to filesize
    */
    if ((size == 0) || (size > inode->i_size))
        size = inode->i_size;

    count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
    printf("Loading file '%s' to addr 0x%08x with size %d (0x%08x)...\n",
        filename, addr, size, size);

    page.addr = (void *)addr;
    page.index = (offset / PAGE_SIZE);
    page.inode = inode;
    //offset
    for (i = 0; i < count; i++) {
		/*
		 * Make sure to not read beyond the requested size
		 */
		if (((i + 1) == count) && (size < inode->i_size))
			last_block_size = size - (i * PAGE_SIZE);

        err = do_readpage(c, inode, &page, last_block_size);
        if (err)
            break;

        page.addr += PAGE_SIZE;
        page.index++;
    }

    if (err)
        printf("Error reading file '%s'\n", filename);
    else
        printf("Done\n");

    ubifs_iput(inode);

out:
    ubi_close_volume(c->ubi);
out_no_close:
	return err;
}