2 * Copyright (C) 2010 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #ifdef HAVE_ANDROID_OS
22 #include <linux/capability.h>
24 #include <private/android_filesystem_capability.h>
27 #define XATTR_SELINUX_SUFFIX "selinux"
28 #define XATTR_CAPS_SUFFIX "capability"
30 #include "ext4_utils.h"
31 #include "make_ext4fs.h"
38 #define S_IFLNK 0 /* used by make_link, not needed under mingw */
41 static struct block_allocation
* saved_allocation_head
= NULL
;
43 struct block_allocation
* get_saved_allocation_chain() {
44 return saved_allocation_head
;
47 static u32
dentry_size(u32 entries
, struct dentry
*dentries
)
51 unsigned int dentry_len
;
53 for (i
= 0; i
< entries
; i
++) {
54 dentry_len
= 8 + EXT4_ALIGN(strlen(dentries
[i
].filename
), 4);
55 if (len
% info
.block_size
+ dentry_len
> info
.block_size
)
56 len
+= info
.block_size
- (len
% info
.block_size
);
63 static struct ext4_dir_entry_2
*add_dentry(u8
*data
, u32
*offset
,
64 struct ext4_dir_entry_2
*prev
, u32 inode
, const char *name
,
67 u8 name_len
= strlen(name
);
68 u16 rec_len
= 8 + EXT4_ALIGN(name_len
, 4);
69 struct ext4_dir_entry_2
*dentry
;
71 u32 start_block
= *offset
/ info
.block_size
;
72 u32 end_block
= (*offset
+ rec_len
- 1) / info
.block_size
;
73 if (start_block
!= end_block
) {
74 /* Adding this dentry will cross a block boundary, so pad the previous
75 dentry to the block boundary */
77 critical_error("no prev");
78 prev
->rec_len
+= end_block
* info
.block_size
- *offset
;
79 *offset
= end_block
* info
.block_size
;
82 dentry
= (struct ext4_dir_entry_2
*)(data
+ *offset
);
83 dentry
->inode
= inode
;
84 dentry
->rec_len
= rec_len
;
85 dentry
->name_len
= name_len
;
86 dentry
->file_type
= file_type
;
87 memcpy(dentry
->name
, name
, name_len
);
93 /* Creates a directory structure for an array of directory entries, dentries,
94 and stores the location of the structure in an inode. The new inode's
95 .. link is set to dir_inode_num. Stores the location of the inode number
96 of each directory entry into dentries[i].inode, to be filled in later
97 when the inode for the entry is allocated. Returns the inode number of the
99 u32
make_directory(u32 dir_inode_num
, u32 entries
, struct dentry
*dentries
,
102 struct ext4_inode
*inode
;
109 struct ext4_dir_entry_2
*dentry
;
111 blocks
= DIV_ROUND_UP(dentry_size(entries
, dentries
), info
.block_size
);
112 len
= blocks
* info
.block_size
;
115 inode_num
= allocate_inode(info
);
117 dir_inode_num
= EXT4_ROOT_INO
;
118 inode_num
= EXT4_ROOT_INO
;
121 if (inode_num
== EXT4_ALLOCATE_FAILED
) {
122 error("failed to allocate inode\n");
123 return EXT4_ALLOCATE_FAILED
;
126 add_directory(inode_num
);
128 inode
= get_inode(inode_num
);
130 error("failed to get inode %u", inode_num
);
131 return EXT4_ALLOCATE_FAILED
;
134 data
= inode_allocate_data_extents(inode
, len
, len
);
136 error("failed to allocate %u extents", len
);
137 return EXT4_ALLOCATE_FAILED
;
140 inode
->i_mode
= S_IFDIR
;
141 inode
->i_links_count
= dirs
+ 2;
142 inode
->i_flags
|= aux_info
.default_i_flags
;
146 dentry
= add_dentry(data
, &offset
, NULL
, inode_num
, ".", EXT4_FT_DIR
);
148 error("failed to add . directory");
149 return EXT4_ALLOCATE_FAILED
;
152 dentry
= add_dentry(data
, &offset
, dentry
, dir_inode_num
, "..", EXT4_FT_DIR
);
154 error("failed to add .. directory");
155 return EXT4_ALLOCATE_FAILED
;
158 for (i
= 0; i
< entries
; i
++) {
159 dentry
= add_dentry(data
, &offset
, dentry
, 0,
160 dentries
[i
].filename
, dentries
[i
].file_type
);
161 if (offset
> len
|| (offset
== len
&& i
!= entries
- 1))
162 critical_error("internal error: dentry for %s ends at %d, past %d\n",
163 dentries
[i
].filename
, offset
, len
);
164 dentries
[i
].inode
= &dentry
->inode
;
166 error("failed to add directory");
167 return EXT4_ALLOCATE_FAILED
;
171 /* pad the last dentry out to the end of the block */
172 dentry
->rec_len
+= len
- offset
;
177 /* Creates a file on disk. Returns the inode number of the new file */
178 u32
make_file(const char *filename
, u64 len
)
180 struct ext4_inode
*inode
;
183 inode_num
= allocate_inode(info
);
184 if (inode_num
== EXT4_ALLOCATE_FAILED
) {
185 error("failed to allocate inode\n");
186 return EXT4_ALLOCATE_FAILED
;
189 inode
= get_inode(inode_num
);
191 error("failed to get inode %u", inode_num
);
192 return EXT4_ALLOCATE_FAILED
;
196 struct block_allocation
* alloc
= inode_allocate_file_extents(inode
, len
, filename
);
198 alloc
->filename
= strdup(filename
);
199 alloc
->next
= saved_allocation_head
;
200 saved_allocation_head
= alloc
;
204 inode
->i_mode
= S_IFREG
;
205 inode
->i_links_count
= 1;
206 inode
->i_flags
|= aux_info
.default_i_flags
;
211 /* Creates a file on disk. Returns the inode number of the new file */
212 u32
make_link(const char *link
)
214 struct ext4_inode
*inode
;
216 u32 len
= strlen(link
);
218 inode_num
= allocate_inode(info
);
219 if (inode_num
== EXT4_ALLOCATE_FAILED
) {
220 error("failed to allocate inode\n");
221 return EXT4_ALLOCATE_FAILED
;
224 inode
= get_inode(inode_num
);
226 error("failed to get inode %u", inode_num
);
227 return EXT4_ALLOCATE_FAILED
;
230 inode
->i_mode
= S_IFLNK
;
231 inode
->i_links_count
= 1;
232 inode
->i_flags
|= aux_info
.default_i_flags
;
233 inode
->i_size_lo
= len
;
235 if (len
+ 1 <= sizeof(inode
->i_block
)) {
237 memcpy((char*)inode
->i_block
, link
, len
);
239 u8
*data
= inode_allocate_data_indirect(inode
, info
.block_size
, info
.block_size
);
240 memcpy(data
, link
, len
);
241 inode
->i_blocks_lo
= info
.block_size
/ 512;
247 int inode_set_permissions(u32 inode_num
, u16 mode
, u16 uid
, u16 gid
, u32 mtime
)
249 struct ext4_inode
*inode
= get_inode(inode_num
);
254 inode
->i_mode
|= mode
;
257 inode
->i_mtime
= mtime
;
258 inode
->i_atime
= mtime
;
259 inode
->i_ctime
= mtime
;
265 * Returns the amount of free space available in the specified
268 static size_t xattr_free_space(struct ext4_xattr_entry
*entry
, char *end
)
270 while(!IS_LAST_ENTRY(entry
) && (((char *) entry
) < end
)) {
271 end
-= EXT4_XATTR_SIZE(le32_to_cpu(entry
->e_value_size
));
272 entry
= EXT4_XATTR_NEXT(entry
);
275 if (((char *) entry
) > end
) {
276 error("unexpected read beyond end of xattr space");
280 return end
- ((char *) entry
);
284 * Returns a pointer to the free space immediately after the
287 static struct ext4_xattr_entry
* xattr_get_last(struct ext4_xattr_entry
*entry
)
289 for (; !IS_LAST_ENTRY(entry
); entry
= EXT4_XATTR_NEXT(entry
)) {
296 * assert that the elements in the ext4 xattr section are in sorted order
298 * The ext4 filesystem requires extended attributes to be sorted when
299 * they're not stored in the inode. The kernel ext4 code uses the following
302 * 1) First sort extended attributes by their name_index. For example,
303 * EXT4_XATTR_INDEX_USER (1) comes before EXT4_XATTR_INDEX_SECURITY (6).
304 * 2) If the name_indexes are equal, then sorting is based on the length
305 * of the name. For example, XATTR_SELINUX_SUFFIX ("selinux") comes before
306 * XATTR_CAPS_SUFFIX ("capability") because "selinux" is shorter than "capability"
307 * 3) If the name_index and name_length are equal, then memcmp() is used to determine
308 * which name comes first. For example, "selinux" would come before "yelinux".
310 * This method is intended to implement the sorting function defined in
311 * the Linux kernel file fs/ext4/xattr.c function ext4_xattr_find_entry().
313 static void xattr_assert_sane(struct ext4_xattr_entry
*entry
)
315 for( ; !IS_LAST_ENTRY(entry
); entry
= EXT4_XATTR_NEXT(entry
)) {
316 struct ext4_xattr_entry
*next
= EXT4_XATTR_NEXT(entry
);
317 if (IS_LAST_ENTRY(next
)) {
321 int cmp
= next
->e_name_index
- entry
->e_name_index
;
323 cmp
= next
->e_name_len
- entry
->e_name_len
;
325 cmp
= memcmp(next
->e_name
, entry
->e_name
, next
->e_name_len
);
327 error("BUG: extended attributes are not sorted\n");
331 error("BUG: duplicate extended attributes detected\n");
337 #define NAME_HASH_SHIFT 5
338 #define VALUE_HASH_SHIFT 16
340 static void ext4_xattr_hash_entry(struct ext4_xattr_header
*header
,
341 struct ext4_xattr_entry
*entry
)
344 char *name
= entry
->e_name
;
347 for (n
= 0; n
< entry
->e_name_len
; n
++) {
348 hash
= (hash
<< NAME_HASH_SHIFT
) ^
349 (hash
>> (8*sizeof(hash
) - NAME_HASH_SHIFT
)) ^
353 if (entry
->e_value_block
== 0 && entry
->e_value_size
!= 0) {
354 u32
*value
= (u32
*)((char *)header
+
355 le16_to_cpu(entry
->e_value_offs
));
356 for (n
= (le32_to_cpu(entry
->e_value_size
) +
357 EXT4_XATTR_ROUND
) >> EXT4_XATTR_PAD_BITS
; n
; n
--) {
358 hash
= (hash
<< VALUE_HASH_SHIFT
) ^
359 (hash
>> (8*sizeof(hash
) - VALUE_HASH_SHIFT
)) ^
360 le32_to_cpu(*value
++);
363 entry
->e_hash
= cpu_to_le32(hash
);
366 #undef NAME_HASH_SHIFT
367 #undef VALUE_HASH_SHIFT
369 static struct ext4_xattr_entry
* xattr_addto_range(
372 struct ext4_xattr_entry
*first
,
378 size_t name_len
= strlen(name
);
382 size_t available_size
= xattr_free_space(first
, block_end
);
383 size_t needed_size
= EXT4_XATTR_LEN(name_len
) + EXT4_XATTR_SIZE(value_len
);
385 if (needed_size
> available_size
)
388 struct ext4_xattr_entry
*new_entry
= xattr_get_last(first
);
389 memset(new_entry
, 0, EXT4_XATTR_LEN(name_len
));
391 new_entry
->e_name_len
= name_len
;
392 new_entry
->e_name_index
= name_index
;
393 memcpy(new_entry
->e_name
, name
, name_len
);
394 new_entry
->e_value_block
= 0;
395 new_entry
->e_value_size
= cpu_to_le32(value_len
);
397 char *val
= (char *) new_entry
+ available_size
- EXT4_XATTR_SIZE(value_len
);
398 size_t e_value_offs
= val
- (char *) block_start
;
400 new_entry
->e_value_offs
= cpu_to_le16(e_value_offs
);
401 memset(val
, 0, EXT4_XATTR_SIZE(value_len
));
402 memcpy(val
, value
, value_len
);
404 xattr_assert_sane(first
);
408 static int xattr_addto_inode(struct ext4_inode
*inode
, int name_index
,
409 const char *name
, const void *value
, size_t value_len
)
411 struct ext4_xattr_ibody_header
*hdr
= (struct ext4_xattr_ibody_header
*) (inode
+ 1);
412 struct ext4_xattr_entry
*first
= (struct ext4_xattr_entry
*) (hdr
+ 1);
413 char *block_end
= ((char *) inode
) + info
.inode_size
;
415 struct ext4_xattr_entry
*result
=
416 xattr_addto_range(first
, block_end
, first
, name_index
, name
, value
, value_len
);
421 hdr
->h_magic
= cpu_to_le32(EXT4_XATTR_MAGIC
);
422 inode
->i_extra_isize
= cpu_to_le16(sizeof(struct ext4_inode
) - EXT4_GOOD_OLD_INODE_SIZE
);
427 static int xattr_addto_block(struct ext4_inode
*inode
, int name_index
,
428 const char *name
, const void *value
, size_t value_len
)
430 struct ext4_xattr_header
*header
= get_xattr_block_for_inode(inode
);
434 struct ext4_xattr_entry
*first
= (struct ext4_xattr_entry
*) (header
+ 1);
435 char *block_end
= ((char *) header
) + info
.block_size
;
437 struct ext4_xattr_entry
*result
=
438 xattr_addto_range(header
, block_end
, first
, name_index
, name
, value
, value_len
);
443 ext4_xattr_hash_entry(header
, result
);
448 static int xattr_add(u32 inode_num
, int name_index
, const char *name
,
449 const void *value
, size_t value_len
)
454 struct ext4_inode
*inode
= get_inode(inode_num
);
459 int result
= xattr_addto_inode(inode
, name_index
, name
, value
, value_len
);
461 result
= xattr_addto_block(inode
, name_index
, name
, value
, value_len
);
466 int inode_set_selinux(u32 inode_num
, const char *secon
)
471 return xattr_add(inode_num
, EXT4_XATTR_INDEX_SECURITY
,
472 XATTR_SELINUX_SUFFIX
, secon
, strlen(secon
) + 1);
475 int inode_set_capabilities(u32 inode_num
, uint64_t capabilities
) {
476 if (capabilities
== 0)
479 struct vfs_cap_data cap_data
;
480 memset(&cap_data
, 0, sizeof(cap_data
));
482 cap_data
.magic_etc
= VFS_CAP_REVISION
| VFS_CAP_FLAGS_EFFECTIVE
;
483 cap_data
.data
[0].permitted
= (uint32_t) (capabilities
& 0xffffffff);
484 cap_data
.data
[0].inheritable
= 0;
485 cap_data
.data
[1].permitted
= (uint32_t) (capabilities
>> 32);
486 cap_data
.data
[1].inheritable
= 0;
488 return xattr_add(inode_num
, EXT4_XATTR_INDEX_SECURITY
,
489 XATTR_CAPS_SUFFIX
, &cap_data
, sizeof(cap_data
));