contents.c revision 8aef66d2125af8de7672a12895276802fcc1948f
179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn/*
279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn * Copyright (C) 2010 The Android Open Source Project
379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn *
479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn * you may not use this file except in compliance with the License.
679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn * You may obtain a copy of the License at
779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn *
879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn *
1079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
1179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
1279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn * See the License for the specific language governing permissions and
1479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn * limitations under the License.
1579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn */
1679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
1779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn#include <sys/stat.h>
1879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn#include <string.h>
1979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn#include <stdio.h>
2079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
2179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn#include "ext4_utils.h"
2279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn#include "ext4.h"
2379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn#include "make_ext4fs.h"
2479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn#include "allocate.h"
2579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn#include "contents.h"
2679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn#include "extent.h"
2779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn#include "indirect.h"
2879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
2979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackbornstatic u32 dentry_size(u32 entries, struct dentry *dentries)
3079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn{
3179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u32 len = 24;
3279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	unsigned int i;
3379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
3479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	for (i = 0; i < entries; i++) {
3579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		unsigned int dentry_len = 8 + 4 *
3679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn			DIV_ROUND_UP(strlen(dentries[i].filename), 4);
3779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		if (len % info.block_size + dentry_len > info.block_size)
3879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn			len += info.block_size - (len % info.block_size);
3979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		len += dentry_len;
4079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
4179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
4279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	return len;
4379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn}
4479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
4579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn#define PAD_TO(x, y) (x + (y - (x % y)))
4679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
4779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackbornstatic struct ext4_dir_entry_2 *add_dentry(u8 *data, u32 *offset,
4879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		struct ext4_dir_entry_2 *prev, u32 inode, const char *name,
4979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		u8 file_type)
5079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn{
5179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u8 name_len = strlen(name);
5279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u16 rec_len = 8 + PAD_TO(name_len, 4);
5379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	struct ext4_dir_entry_2 *dentry;
5479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
5579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u32 start_block = *offset / info.block_size;
5679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u32 end_block = (*offset + rec_len) / info.block_size;
5779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (start_block != end_block) {
5879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		/* Adding this dentry will cross a block boundary, so pad the previous
5979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		   dentry to the block boundary */
6079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		if (!prev)
6179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn			critical_error("no prev");
6279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		prev->rec_len += end_block * info.block_size - *offset;
6379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		*offset = end_block * info.block_size;
6479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
6579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
6679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry = (struct ext4_dir_entry_2 *)(data + *offset);
6779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry->inode = inode;
6879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry->rec_len = rec_len;
6979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry->name_len = name_len;
7079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry->file_type = file_type;
7179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	memcpy(dentry->name, name, name_len);
7279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
7379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	*offset += rec_len;
7479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	return dentry;
7579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn}
7679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
7779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn/* Creates a directory structure for an array of directory entries, dentries,
7879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn   and stores the location of the structure in an inode.  The new inode's
7979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn   .. link is set to dir_inode_num.  Stores the location of the inode number
8079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn   of each directory entry into dentries[i].inode, to be filled in later
8179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn   when the inode for the entry is allocated.  Returns the inode number of the
8279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn   new directory */
8379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackbornu32 make_directory(u32 dir_inode_num, u32 entries, struct dentry *dentries,
8479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u32 dirs)
8579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn{
8679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	struct ext4_inode *inode;
8779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u32 blocks = DIV_ROUND_UP(dentry_size(entries, dentries), info.block_size);
8879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u64 len = (u64)blocks * info.block_size;
8979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u32 offset = 0;
9079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u32 inode_num;
9179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u8 *data;
9279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	unsigned int i;
9379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	struct ext4_dir_entry_2 *dentry;
9479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
9579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (dir_inode_num) {
9679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		inode_num = allocate_inode(info);
9779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	} else {
9879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		dir_inode_num = EXT4_ROOT_INO;
9979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		inode_num = EXT4_ROOT_INO;
10079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
10179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
10279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (inode_num == EXT4_ALLOCATE_FAILED) {
10379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		error("failed to allocate inode\n");
10479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		return EXT4_ALLOCATE_FAILED;
10579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
10679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
10779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	add_directory(inode_num);
10879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
10979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode = get_inode(inode_num);
11079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (inode == NULL) {
11179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		error("failed to get inode %u", inode_num);
11279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		return EXT4_ALLOCATE_FAILED;
11379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
11479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
11579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	data = inode_allocate_data_extents(inode, len, len);
11679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (data == NULL) {
11779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		error("failed to allocate %llu extents", len);
11879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		return EXT4_ALLOCATE_FAILED;
11979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
12079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
12179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode->i_mode = S_IFDIR;
12279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode->i_links_count = dirs + 2;
12379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode->i_flags |= aux_info.default_i_flags;
12479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
12579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry = NULL;
12679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
12779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry = add_dentry(data, &offset, NULL, inode_num, ".", EXT4_FT_DIR);
12879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (!dentry) {
12979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		error("failed to add . directory");
13079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		return EXT4_ALLOCATE_FAILED;
13179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
13279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
13379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry = add_dentry(data, &offset, dentry, dir_inode_num, "..", EXT4_FT_DIR);
13479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (!dentry) {
13579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		error("failed to add .. directory");
13679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		return EXT4_ALLOCATE_FAILED;
13779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
13879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
13979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	for (i = 0; i < entries; i++) {
14079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		dentry = add_dentry(data, &offset, dentry, 0, dentries[i].filename,
14179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn				dentries[i].file_type);
14279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		dentries[i].inode = &dentry->inode;
143f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi		if (!dentry) {
144f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi			error("failed to add directory");
145f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi			return EXT4_ALLOCATE_FAILED;
146f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi		}
147f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi	}
14879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
14979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry = (struct ext4_dir_entry_2 *)(data + offset);
15079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry->inode = 0;
15179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry->rec_len = len - offset;
15279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry->name_len = 0;
15379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	dentry->file_type = EXT4_FT_UNKNOWN;
15479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
15579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	return inode_num;
15679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn}
15779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
15879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn/* Creates a file on disk.  Returns the inode number of the new file */
15979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackbornu32 make_file(const char *filename, u64 len)
16079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn{
16179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	struct ext4_inode *inode;
16279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u32 inode_num;
16379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
16479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode_num = allocate_inode(info);
16579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (inode_num == EXT4_ALLOCATE_FAILED) {
16679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		error("failed to allocate inode\n");
16779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		return EXT4_ALLOCATE_FAILED;
16879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
16979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
17079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode = get_inode(inode_num);
17179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (inode == NULL) {
17279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		error("failed to get inode %u", inode_num);
17379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		return EXT4_ALLOCATE_FAILED;
17479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
17579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
17679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode_allocate_file_extents(inode, len, filename);
17779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
17879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode->i_mode = S_IFREG;
17979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode->i_links_count = 1;
18079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode->i_flags |= aux_info.default_i_flags;
18179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
18279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	return inode_num;
18379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn}
18479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
18579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn/* Creates a file on disk.  Returns the inode number of the new file */
18679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackbornu32 make_link(const char *filename, const char *link)
18779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn{
18879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	struct ext4_inode *inode;
18979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u32 inode_num;
19079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	u32 len = strlen(link);
19179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
19279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode_num = allocate_inode(info);
19379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (inode_num == EXT4_ALLOCATE_FAILED) {
19479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		error("failed to allocate inode\n");
19579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		return EXT4_ALLOCATE_FAILED;
19679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
19779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
19879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode = get_inode(inode_num);
19979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (inode == NULL) {
20079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		error("failed to get inode %u", inode_num);
20179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		return EXT4_ALLOCATE_FAILED;
20279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
20379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
20479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode->i_mode = S_IFLNK;
20579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode->i_links_count = 1;
20679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode->i_flags |= aux_info.default_i_flags;
20779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	inode->i_size_lo = len;
20879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
20979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (len + 1 <= sizeof(inode->i_block)) {
21079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		/* Fast symlink */
21179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		memcpy((char*)inode->i_block, link, len);
21279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	} else {
21379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		u8 *data = inode_allocate_data_indirect(inode, info.block_size, info.block_size);
21479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		memcpy(data, link, len);
21579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn		inode->i_blocks_lo = info.block_size / 512;
21679f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	}
21779f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
21879f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	return inode_num;
21979f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn}
22079f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
22179f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackbornint inode_set_permissions(u32 inode_num, u16 mode, u16 uid, u16 gid)
22279f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn{
22379f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	struct ext4_inode *inode = get_inode(inode_num);
22479f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn
22579f7ec70ebd5758ce54fd5b6fcd60fd27457cba6Dianne Hackborn	if (!inode)
226		return -1;
227
228	inode->i_mode |= mode;
229	inode->i_uid = uid;
230	inode->i_gid = gid;
231
232	return 0;
233}
234