contents.c revision 5446bde9c02f6ae95a30d9c178b13a05bb580fe1
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"
28b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley#include "xattr.h"
29ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
304605b3fb8a00fa37f617a8d0fe3a095d0503a845Raphael Moll#ifdef USE_MINGW
314605b3fb8a00fa37f617a8d0fe3a095d0503a845Raphael Moll#define S_IFLNK 0  /* used by make_link, not needed under mingw */
324605b3fb8a00fa37f617a8d0fe3a095d0503a845Raphael Moll#endif
334605b3fb8a00fa37f617a8d0fe3a095d0503a845Raphael Moll
34ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic u32 dentry_size(u32 entries, struct dentry *dentries)
35ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{
36ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 len = 24;
37ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	unsigned int i;
386bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross	unsigned int dentry_len;
39ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
40ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	for (i = 0; i < entries; i++) {
416bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross		dentry_len = 8 + ALIGN(strlen(dentries[i].filename), 4);
42ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		if (len % info.block_size + dentry_len > info.block_size)
43ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross			len += info.block_size - (len % info.block_size);
44ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		len += dentry_len;
45ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
46ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
47ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	return len;
48ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross}
49ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
50ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossstatic struct ext4_dir_entry_2 *add_dentry(u8 *data, u32 *offset,
51ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		struct ext4_dir_entry_2 *prev, u32 inode, const char *name,
52ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		u8 file_type)
53ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{
54ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u8 name_len = strlen(name);
556bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross	u16 rec_len = 8 + ALIGN(name_len, 4);
56ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	struct ext4_dir_entry_2 *dentry;
57ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
58ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 start_block = *offset / info.block_size;
592ff1c5b6e8c1457dbb65fb8305db92c74e95dd42Colin Cross	u32 end_block = (*offset + rec_len - 1) / info.block_size;
60ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (start_block != end_block) {
61ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		/* Adding this dentry will cross a block boundary, so pad the previous
62ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		   dentry to the block boundary */
63ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		if (!prev)
64ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross			critical_error("no prev");
65ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		prev->rec_len += end_block * info.block_size - *offset;
66ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		*offset = end_block * info.block_size;
67ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
68ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
69ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry = (struct ext4_dir_entry_2 *)(data + *offset);
70ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry->inode = inode;
71ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry->rec_len = rec_len;
72ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry->name_len = name_len;
73ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry->file_type = file_type;
74ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	memcpy(dentry->name, name, name_len);
75ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
76ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	*offset += rec_len;
77ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	return dentry;
78ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross}
79ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
80ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Creates a directory structure for an array of directory entries, dentries,
81ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross   and stores the location of the structure in an inode.  The new inode's
82ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross   .. link is set to dir_inode_num.  Stores the location of the inode number
83ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross   of each directory entry into dentries[i].inode, to be filled in later
84ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross   when the inode for the entry is allocated.  Returns the inode number of the
85ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross   new directory */
86ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossu32 make_directory(u32 dir_inode_num, u32 entries, struct dentry *dentries,
878aef66d2125af8de7672a12895276802fcc1948fColin Cross	u32 dirs)
88ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{
89ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	struct ext4_inode *inode;
906bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross	u32 blocks;
916bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross	u32 len;
92ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 offset = 0;
93ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 inode_num;
94ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u8 *data;
95ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	unsigned int i;
96ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	struct ext4_dir_entry_2 *dentry;
97ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
986bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross	blocks = DIV_ROUND_UP(dentry_size(entries, dentries), info.block_size);
996bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross	len = blocks * info.block_size;
1006bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross
101ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (dir_inode_num) {
102ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		inode_num = allocate_inode(info);
103ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	} else {
104ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		dir_inode_num = EXT4_ROOT_INO;
105ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		inode_num = EXT4_ROOT_INO;
106ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
107ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
108ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (inode_num == EXT4_ALLOCATE_FAILED) {
109ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to allocate inode\n");
110ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
111ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
112ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
113ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	add_directory(inode_num);
114ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
115ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode = get_inode(inode_num);
116ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (inode == NULL) {
117ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to get inode %u", inode_num);
118ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
119ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
120ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
121ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	data = inode_allocate_data_extents(inode, len, len);
122ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (data == NULL) {
1232e905e5f2a3df605c68cb8633580c918e9f4ba71Colin Cross		error("failed to allocate %u extents", len);
124ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
125ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
126ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
127ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_mode = S_IFDIR;
128ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_links_count = dirs + 2;
129ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_flags |= aux_info.default_i_flags;
130ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
131ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry = NULL;
132ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
133ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry = add_dentry(data, &offset, NULL, inode_num, ".", EXT4_FT_DIR);
134ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (!dentry) {
135ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to add . directory");
136ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
137ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
138ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
139ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	dentry = add_dentry(data, &offset, dentry, dir_inode_num, "..", EXT4_FT_DIR);
140ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (!dentry) {
141ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to add .. directory");
142ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
143ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
144ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
145ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	for (i = 0; i < entries; i++) {
1466bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross		dentry = add_dentry(data, &offset, dentry, 0,
1476bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross				dentries[i].filename, dentries[i].file_type);
1486bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross		if (offset > len || (offset == len && i != entries - 1))
1496bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross			critical_error("internal error: dentry for %s ends at %d, past %d\n",
1506bd2b5d80db5630cb73e3e5a4be3b38afa241c5aColin Cross				dentries[i].filename, offset, len);
151ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		dentries[i].inode = &dentry->inode;
152ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		if (!dentry) {
153ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross			error("failed to add directory");
154ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross			return EXT4_ALLOCATE_FAILED;
155ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		}
156ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
157ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
1588748938228acad9e53c4f3cdfa132d2aff7917bfColin Cross	/* pad the last dentry out to the end of the block */
1598748938228acad9e53c4f3cdfa132d2aff7917bfColin Cross	dentry->rec_len += len - offset;
160ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
161ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	return inode_num;
162ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross}
163ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
164ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Creates a file on disk.  Returns the inode number of the new file */
165ec0a2e83dc66d67addeb90e83144187691852a3eColin Crossu32 make_file(const char *filename, u64 len)
166ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{
167ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	struct ext4_inode *inode;
168ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 inode_num;
169ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
170ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode_num = allocate_inode(info);
171ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (inode_num == EXT4_ALLOCATE_FAILED) {
172ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to allocate inode\n");
173ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
174ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
175ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
176ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode = get_inode(inode_num);
177ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (inode == NULL) {
178ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to get inode %u", inode_num);
179ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
180ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
181ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
182cf5c39c1851f8826264822414dbab31c1aeaeec6Colin Cross	if (len > 0)
183cf5c39c1851f8826264822414dbab31c1aeaeec6Colin Cross		inode_allocate_file_extents(inode, len, filename);
184ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
185ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_mode = S_IFREG;
186ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_links_count = 1;
187ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_flags |= aux_info.default_i_flags;
188ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
189ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	return inode_num;
190ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross}
191ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
192ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross/* Creates a file on disk.  Returns the inode number of the new file */
1935446bde9c02f6ae95a30d9c178b13a05bb580fe1Nick Kralevichu32 make_link(const char *link)
194ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{
195ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	struct ext4_inode *inode;
196ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 inode_num;
197ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	u32 len = strlen(link);
198ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
199ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode_num = allocate_inode(info);
200ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (inode_num == EXT4_ALLOCATE_FAILED) {
201ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to allocate inode\n");
202ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
203ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
204ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
205ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode = get_inode(inode_num);
206ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (inode == NULL) {
207ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		error("failed to get inode %u", inode_num);
208ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return EXT4_ALLOCATE_FAILED;
209ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
210ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
211ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_mode = S_IFLNK;
212ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_links_count = 1;
213ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_flags |= aux_info.default_i_flags;
214ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_size_lo = len;
215ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
216ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (len + 1 <= sizeof(inode->i_block)) {
217ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		/* Fast symlink */
218ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		memcpy((char*)inode->i_block, link, len);
219ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	} else {
220ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		u8 *data = inode_allocate_data_indirect(inode, info.block_size, info.block_size);
221ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		memcpy(data, link, len);
222ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		inode->i_blocks_lo = info.block_size / 512;
223ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	}
224ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
225ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	return inode_num;
226ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross}
227ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
228de61f980c7b034eefac6e0ace718b3c1eb3f6252Colin Crossint inode_set_permissions(u32 inode_num, u16 mode, u16 uid, u16 gid, u32 mtime)
229ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross{
230ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	struct ext4_inode *inode = get_inode(inode_num);
231ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
232ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	if (!inode)
233ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross		return -1;
234ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
235ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_mode |= mode;
236ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_uid = uid;
237ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	inode->i_gid = gid;
238de61f980c7b034eefac6e0ace718b3c1eb3f6252Colin Cross	inode->i_mtime = mtime;
239de61f980c7b034eefac6e0ace718b3c1eb3f6252Colin Cross	inode->i_atime = mtime;
240de61f980c7b034eefac6e0ace718b3c1eb3f6252Colin Cross	inode->i_ctime = mtime;
241ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross
242ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross	return 0;
243ec0a2e83dc66d67addeb90e83144187691852a3eColin Cross}
244b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley
245b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley#define XATTR_SELINUX_SUFFIX "selinux"
246b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley
247b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley/* XXX */
248b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley#define cpu_to_le32(x) (x)
249b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley#define cpu_to_le16(x) (x)
250b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley
251b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalleyint inode_set_selinux(u32 inode_num, const char *secon)
252b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley{
253b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	struct ext4_inode *inode = get_inode(inode_num);
254b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	u32 *hdr;
255b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	struct ext4_xattr_entry *entry;
256b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	size_t name_len = strlen(XATTR_SELINUX_SUFFIX);
257c588b0a9db0d27926ad811eca8f32f5e4fc84cbdMatt Finifter	size_t value_len;
258b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	size_t size, min_offs;
259b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	char *val;
260b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley
261b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	if (!secon)
262b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley		return 0;
263b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley
264b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	if (!inode)
265b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley		return -1;
266b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley
267b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	hdr = (u32 *) (inode + 1);
268b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	*hdr = cpu_to_le32(EXT4_XATTR_MAGIC);
269b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	entry = (struct ext4_xattr_entry *) (hdr+1);
270b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	memset(entry, 0, EXT4_XATTR_LEN(name_len));
271b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	entry->e_name_index = EXT4_XATTR_INDEX_SECURITY;
272b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	entry->e_name_len = name_len;
273b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	memcpy(entry->e_name, XATTR_SELINUX_SUFFIX, name_len);
274c588b0a9db0d27926ad811eca8f32f5e4fc84cbdMatt Finifter	value_len = strlen(secon)+1;
275b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	entry->e_value_size = cpu_to_le32(value_len);
276b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	min_offs = (char *)inode + info.inode_size - (char*) entry;
277b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	size = EXT4_XATTR_SIZE(value_len);
278b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	val = (char *)entry + min_offs - size;
279b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	entry->e_value_offs = cpu_to_le16(min_offs - size);
280b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	memset(val + size - EXT4_XATTR_PAD, 0, EXT4_XATTR_PAD);
281b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	memcpy(val, secon, value_len);
282b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	inode->i_extra_isize = cpu_to_le16(sizeof(struct ext4_inode) - EXT4_GOOD_OLD_INODE_SIZE);
283b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley
284b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley	return 0;
285b4eca4b24af9c80ebb2a7fa2ba539a48096b7576Stephen Smalley}
286