contents.c revision 4605b3fb8a00fa37f617a8d0fe3a095d0503a845
1ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/*
2ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * Copyright (C) 2010 The Android Open Source Project
3ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross *
4ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * Licensed under the Apache License, Version 2.0 (the "License");
5ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * you may not use this file except in compliance with the License.
6ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * You may obtain a copy of the License at
7ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross *
8ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross *      http://www.apache.org/licenses/LICENSE-2.0
9ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross *
10ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * Unless required by applicable law or agreed to in writing, software
11ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * distributed under the License is distributed on an "AS IS" BASIS,
12ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * See the License for the specific language governing permissions and
14ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross * limitations under the License.
15ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross */
16ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
17ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <sys/stat.h>
18ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <string.h>
19ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include <stdio.h>
20ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
21ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "ext4_utils.h"
22ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "ext4.h"
23ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "make_ext4fs.h"
24ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "allocate.h"
25ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "contents.h"
26ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "extent.h"
27ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross#include "indirect.h"
28ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
294605b3fb8a00fa37f617a8d0fe3a095d0503a845Raphael Moll#ifdef USE_MINGW
304605b3fb8a00fa37f617a8d0fe3a095d0503a845Raphael Moll#define S_IFLNK 0  /* used by make_link, not needed under mingw */
314605b3fb8a00fa37f617a8d0fe3a095d0503a845Raphael Moll#endif
324605b3fb8a00fa37f617a8d0fe3a095d0503a845Raphael Moll
33ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u32 dentry_size(u32 entries, struct dentry *dentries)
34ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{
35ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 len = 24;
36ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	unsigned int i;
376bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross	unsigned int dentry_len;
38ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
39ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	for (i = 0; i < entries; i++) {
406bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross		dentry_len = 8 + ALIGN(strlen(dentries[i].filename), 4);
41ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		if (len % info.block_size + dentry_len > info.block_size)
42ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross			len += info.block_size - (len % info.block_size);
43ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		len += dentry_len;
44ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
45ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
467c81ec40f5f466b23c2ebacabe1e4e9ac6932bd5Ken Sumrall	/* include size of the dentry used to pad until the end of the block */
477c81ec40f5f466b23c2ebacabe1e4e9ac6932bd5Ken Sumrall	if (len % info.block_size + 8 > info.block_size)
487c81ec40f5f466b23c2ebacabe1e4e9ac6932bd5Ken Sumrall		len += info.block_size - (len % info.block_size);
497c81ec40f5f466b23c2ebacabe1e4e9ac6932bd5Ken Sumrall	len += 8;
507c81ec40f5f466b23c2ebacabe1e4e9ac6932bd5Ken Sumrall
51ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	return len;
52ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross}
53ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
54ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic struct ext4_dir_entry_2 *add_dentry(u8 *data, u32 *offset,
55ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		struct ext4_dir_entry_2 *prev, u32 inode, const char *name,
56ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		u8 file_type)
57ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{
58ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u8 name_len = strlen(name);
596bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross	u16 rec_len = 8 + ALIGN(name_len, 4);
60ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	struct ext4_dir_entry_2 *dentry;
61ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
62ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 start_block = *offset / info.block_size;
632ff1c5b6e8c1457dbb65fb8305db92c74e95dd42Colin Cross	u32 end_block = (*offset + rec_len - 1) / info.block_size;
64ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (start_block != end_block) {
65ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		/* Adding this dentry will cross a block boundary, so pad the previous
66ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		   dentry to the block boundary */
67ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		if (!prev)
68ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross			critical_error("no prev");
69ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		prev->rec_len += end_block * info.block_size - *offset;
70ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		*offset = end_block * info.block_size;
71ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
72ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
73ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry = (struct ext4_dir_entry_2 *)(data + *offset);
74ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry->inode = inode;
75ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry->rec_len = rec_len;
76ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry->name_len = name_len;
77ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry->file_type = file_type;
78ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	memcpy(dentry->name, name, name_len);
79ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
80ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	*offset += rec_len;
81ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	return dentry;
82ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross}
83ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
84ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Creates a directory structure for an array of directory entries, dentries,
85ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross   and stores the location of the structure in an inode.  The new inode's
86ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross   .. link is set to dir_inode_num.  Stores the location of the inode number
87ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross   of each directory entry into dentries[i].inode, to be filled in later
88ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross   when the inode for the entry is allocated.  Returns the inode number of the
89ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross   new directory */
90ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossu32 make_directory(u32 dir_inode_num, u32 entries, struct dentry *dentries,
918aef66d2125af8de7672a12895276802fcc1948fColin Cross	u32 dirs)
92ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{
93ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	struct ext4_inode *inode;
946bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross	u32 blocks;
956bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross	u32 len;
96ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 offset = 0;
97ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 inode_num;
98ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u8 *data;
99ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	unsigned int i;
100ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	struct ext4_dir_entry_2 *dentry;
101ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
1026bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross	blocks = DIV_ROUND_UP(dentry_size(entries, dentries), info.block_size);
1036bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross	len = blocks * info.block_size;
1046bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross
105ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (dir_inode_num) {
106ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		inode_num = allocate_inode(info);
107ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	} else {
108ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		dir_inode_num = EXT4_ROOT_INO;
109ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		inode_num = EXT4_ROOT_INO;
110ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
111ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
112ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (inode_num == EXT4_ALLOCATE_FAILED) {
113ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to allocate inode\n");
114ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
115ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
116ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
117ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	add_directory(inode_num);
118ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
119ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode = get_inode(inode_num);
120ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (inode == NULL) {
121ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to get inode %u", inode_num);
122ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
123ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
124ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
125ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	data = inode_allocate_data_extents(inode, len, len);
126ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (data == NULL) {
1272e905e5f2a3df605c68cb8633580c918e9f4ba71Colin Cross		error("failed to allocate %u extents", len);
128ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
129ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
130ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
131ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_mode = S_IFDIR;
132ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_links_count = dirs + 2;
133ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_flags |= aux_info.default_i_flags;
134ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
135ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry = NULL;
136ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
137ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry = add_dentry(data, &offset, NULL, inode_num, ".", EXT4_FT_DIR);
138ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (!dentry) {
139ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to add . directory");
140ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
141ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
142ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
143ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry = add_dentry(data, &offset, dentry, dir_inode_num, "..", EXT4_FT_DIR);
144ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (!dentry) {
145ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to add .. directory");
146ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
147ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
148ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
149ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	for (i = 0; i < entries; i++) {
1506bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross		dentry = add_dentry(data, &offset, dentry, 0,
1516bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross				dentries[i].filename, dentries[i].file_type);
1526bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross		if (offset > len || (offset == len && i != entries - 1))
1536bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross			critical_error("internal error: dentry for %s ends at %d, past %d\n",
1546bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross				dentries[i].filename, offset, len);
155ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		dentries[i].inode = &dentry->inode;
156ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		if (!dentry) {
157ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross			error("failed to add directory");
158ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross			return EXT4_ALLOCATE_FAILED;
159ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		}
160ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
161ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
162ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry = (struct ext4_dir_entry_2 *)(data + offset);
163ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry->inode = 0;
164ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry->rec_len = len - offset;
165ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry->name_len = 0;
166ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry->file_type = EXT4_FT_UNKNOWN;
167ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
168ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	return inode_num;
169ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross}
170ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
171ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Creates a file on disk.  Returns the inode number of the new file */
172ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossu32 make_file(const char *filename, u64 len)
173ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{
174ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	struct ext4_inode *inode;
175ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 inode_num;
176ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
177ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode_num = allocate_inode(info);
178ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (inode_num == EXT4_ALLOCATE_FAILED) {
179ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to allocate inode\n");
180ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
181ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
182ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
183ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode = get_inode(inode_num);
184ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (inode == NULL) {
185ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to get inode %u", inode_num);
186ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
187ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
188ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
189cf5c39c1851f8826264822414dbab31c1aeaeec6Colin Cross	if (len > 0)
190cf5c39c1851f8826264822414dbab31c1aeaeec6Colin Cross		inode_allocate_file_extents(inode, len, filename);
191ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
192ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_mode = S_IFREG;
193ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_links_count = 1;
194ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_flags |= aux_info.default_i_flags;
195ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
196ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	return inode_num;
197ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross}
198ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
199ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Creates a file on disk.  Returns the inode number of the new file */
200ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossu32 make_link(const char *filename, const char *link)
201ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{
202ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	struct ext4_inode *inode;
203ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 inode_num;
204ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 len = strlen(link);
205ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
206ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode_num = allocate_inode(info);
207ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (inode_num == EXT4_ALLOCATE_FAILED) {
208ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to allocate inode\n");
209ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
210ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
211ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
212ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode = get_inode(inode_num);
213ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (inode == NULL) {
214ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to get inode %u", inode_num);
215ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
216ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
217ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
218ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_mode = S_IFLNK;
219ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_links_count = 1;
220ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_flags |= aux_info.default_i_flags;
221ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_size_lo = len;
222ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
223ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (len + 1 <= sizeof(inode->i_block)) {
224ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		/* Fast symlink */
225ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		memcpy((char*)inode->i_block, link, len);
226ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	} else {
227ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		u8 *data = inode_allocate_data_indirect(inode, info.block_size, info.block_size);
228ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		memcpy(data, link, len);
229ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		inode->i_blocks_lo = info.block_size / 512;
230ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
231ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
232ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	return inode_num;
233ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross}
234ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
235de61f980c7b034eefac6e0ace718b3c1eb3f6252Colin Crossint inode_set_permissions(u32 inode_num, u16 mode, u16 uid, u16 gid, u32 mtime)
236ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{
237ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	struct ext4_inode *inode = get_inode(inode_num);
238ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
239ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (!inode)
240ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return -1;
241ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
242ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_mode |= mode;
243ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_uid = uid;
244ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_gid = gid;
245de61f980c7b034eefac6e0ace718b3c1eb3f6252Colin Cross	inode->i_mtime = mtime;
246de61f980c7b034eefac6e0ace718b3c1eb3f6252Colin Cross	inode->i_atime = mtime;
247de61f980c7b034eefac6e0ace718b3c1eb3f6252Colin Cross	inode->i_ctime = mtime;
248ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
249ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	return 0;
250ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross}
251