* limitations under the License.
*/
-#include "make_ext4fs.h"
#include "ext4_utils.h"
#include "allocate.h"
#include "contents.h"
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
-
-#ifdef USE_MINGW
-
-#include <winsock2.h>
-
-/* These match the Linux definitions of these flags.
- L_xx is defined to avoid conflicting with the win32 versions.
-*/
-#define L_S_IRUSR 00400
-#define L_S_IWUSR 00200
-#define L_S_IXUSR 00100
-#define S_IRWXU (L_S_IRUSR | L_S_IWUSR | L_S_IXUSR)
-#define S_IRGRP 00040
-#define S_IWGRP 00020
-#define S_IXGRP 00010
-#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
-#define S_IROTH 00004
-#define S_IWOTH 00002
-#define S_IXOTH 00001
-#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
-#define S_ISUID 0004000
-#define S_ISGID 0002000
-#define S_ISVTX 0001000
-
-#else
-
-#include <selinux/selinux.h>
-#include <selinux/label.h>
-#include <selinux/android.h>
-
-#define O_BINARY 0
-
-#endif
+#include <locale.h>
/* TODO: Not implemented:
Allocating blocks in the same block group as the file inode
Hash or binary tree directories
- Special files: sockets, devices, fifos
*/
static int filter_dot(const struct dirent *d)
return (strcmp(d->d_name, "..") && strcmp(d->d_name, "."));
}
-static u32 build_default_directory_structure(const char *dir_path,
- struct selabel_handle *sehnd)
+static u32 build_default_directory_structure(time_t fixed_time)
{
u32 inode;
u32 root_inode;
struct dentry dentries = {
- .filename = "lost+found",
- .file_type = EXT4_FT_DIR,
- .mode = S_IRWXU,
- .uid = 0,
- .gid = 0,
- .mtime = 0,
+ .filename = "lost+found",
+ .file_type = EXT4_FT_DIR,
+ .mode = S_IRWXU,
+ .uid = 0,
+ .gid = 0,
+ .mtime = (fixed_time != -1) ? fixed_time : 0,
};
root_inode = make_directory(0, 1, &dentries, 1);
inode = make_directory(root_inode, 0, NULL, 0);
*dentries.inode = inode;
inode_set_permissions(inode, dentries.mode,
- dentries.uid, dentries.gid, dentries.mtime);
-
-#ifndef USE_MINGW
- if (sehnd) {
- char *path = NULL;
- char *secontext = NULL;
-
- asprintf(&path, "%slost+found", dir_path);
- if (selabel_lookup(sehnd, &secontext, path, S_IFDIR) < 0) {
- error("cannot lookup security context for %s", path);
- } else {
- inode_set_selinux(inode, secontext);
- freecon(secontext);
- }
- free(path);
- }
-#endif
+ dentries.uid, dentries.gid, dentries.mtime);
return root_inode;
}
-#ifndef USE_MINGW
/* Read a local directory and create the same tree in the generated filesystem.
Calls itself recursively with each directory in the given directory.
full_path is an absolute or relative path, with a trailing slash, to the
if the image were mounted at the specified mount point */
static u32 build_directory_structure(const char *full_path, const char *dir_path,
u32 dir_inode, fs_config_func_t fs_config_func,
- struct selabel_handle *sehnd, int verbose, time_t fixed_time)
+ int verbose, time_t fixed_time)
{
int entries = 0;
struct dentry *dentries;
u32 dirs = 0;
bool needs_lost_and_found = false;
+ /* alphasort is locale-dependent; let's fix the locale to some sane value */
+ setlocale(LC_COLLATE, "C");
+
if (full_path) {
entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort);
if (entries < 0) {
}
uint64_t capabilities;
if (fs_config_func != NULL) {
-#ifdef ANDROID
unsigned int mode = 0;
unsigned int uid = 0;
unsigned int gid = 0;
int dir = S_ISDIR(stat.st_mode);
- fs_config_func(dentries[i].path, dir, &uid, &gid, &mode, &capabilities);
- dentries[i].mode = mode;
- dentries[i].uid = uid;
- dentries[i].gid = gid;
- dentries[i].capabilities = capabilities;
-#else
- error("can't set android permissions - built without android support");
-#endif
- }
-#ifndef USE_MINGW
- if (sehnd) {
- if (selabel_lookup(sehnd, &dentries[i].secon, dentries[i].path, stat.st_mode) < 0) {
- error("cannot lookup security context for %s", dentries[i].path);
+ if (fs_config_func(dentries[i].path, dir, &uid, &gid, &mode, &capabilities)) {
+ dentries[i].mode = mode;
+ dentries[i].uid = uid;
+ dentries[i].gid = gid;
+ dentries[i].capabilities = capabilities;
}
-
- if (dentries[i].secon && verbose)
- printf("Labeling %s as %s\n", dentries[i].path, dentries[i].secon);
}
-#endif
if (S_ISREG(stat.st_mode)) {
dentries[i].file_type = EXT4_FT_REG_FILE;
dentries[0].file_type = EXT4_FT_DIR;
dentries[0].uid = 0;
dentries[0].gid = 0;
- if (sehnd) {
- if (selabel_lookup(sehnd, &dentries[0].secon, dentries[0].path, dentries[0].mode) < 0)
- error("cannot lookup security context for %s", dentries[0].path);
- }
entries++;
dirs++;
}
if (ret < 0)
critical_error_errno("asprintf");
entry_inode = build_directory_structure(subdir_full_path,
- subdir_dir_path, inode, fs_config_func, sehnd, verbose, fixed_time);
+ subdir_dir_path, inode, fs_config_func, verbose, fixed_time);
free(subdir_full_path);
free(subdir_dir_path);
} else if (dentries[i].file_type == EXT4_FT_SYMLINK) {
entry_inode = make_link(dentries[i].link);
+ } else if (dentries[i].file_type == EXT4_FT_CHRDEV ||
+ dentries[i].file_type == EXT4_FT_BLKDEV ||
+ dentries[i].file_type == EXT4_FT_SOCK ||
+ dentries[i].file_type == EXT4_FT_FIFO) {
+ entry_inode = make_special(dentries[i].full_path);
} else {
error("unknown file type on %s", dentries[i].path);
entry_inode = 0;
if (ret)
error("failed to set permissions on %s\n", dentries[i].path);
- /*
- * It's important to call inode_set_selinux() before
- * inode_set_capabilities(). Extended attributes need to
- * be stored sorted order, and we guarantee this by making
- * the calls in the proper order.
- * Please see xattr_assert_sane() in contents.c
- */
- ret = inode_set_selinux(entry_inode, dentries[i].secon);
- if (ret)
- error("failed to set SELinux context on %s\n", dentries[i].path);
ret = inode_set_capabilities(entry_inode, dentries[i].capabilities);
if (ret)
error("failed to set capability on %s\n", dentries[i].path);
free(dentries[i].full_path);
free(dentries[i].link);
free((void *)dentries[i].filename);
- free(dentries[i].secon);
}
free(dentries);
return inode;
}
-#endif
-static u32 compute_block_size()
+static u32 compute_block_size(void)
{
return 4096;
}
-static u32 compute_journal_blocks()
+static u32 compute_journal_blocks(void)
{
u32 journal_blocks = DIV_ROUND_UP(info.len, info.block_size) / 64;
if (journal_blocks < 1024)
return journal_blocks;
}
-static u32 compute_blocks_per_group()
+static u32 compute_blocks_per_group(void)
{
return info.block_size * 8;
}
-static u32 compute_inodes()
+static u32 compute_inodes(void)
{
return DIV_ROUND_UP(info.len, info.block_size) / 4;
}
-static u32 compute_inodes_per_group()
+static u32 compute_inodes_per_group(void)
{
u32 blocks = DIV_ROUND_UP(info.len, info.block_size);
u32 block_groups = DIV_ROUND_UP(blocks, info.blocks_per_group);
return inodes;
}
-static u32 compute_bg_desc_reserve_blocks()
+static u32 compute_bg_desc_reserve_blocks(void)
{
u32 blocks = DIV_ROUND_UP(info.len, info.block_size);
u32 block_groups = DIV_ROUND_UP(blocks, info.blocks_per_group);
return bg_desc_reserve_blocks;
}
-void reset_ext4fs_info() {
- // Reset all the global data structures used by make_ext4fs so it
- // can be called again.
- memset(&info, 0, sizeof(info));
- memset(&aux_info, 0, sizeof(aux_info));
-
- if (ext4_sparse_file) {
- sparse_file_destroy(ext4_sparse_file);
- ext4_sparse_file = NULL;
- }
-}
-
-int make_ext4fs_sparse_fd(int fd, long long len,
- const char *mountpoint, struct selabel_handle *sehnd)
-{
- reset_ext4fs_info();
- info.len = len;
-
- return make_ext4fs_internal(fd, NULL, mountpoint, NULL, 0, 1, 0, 0, sehnd, 0, -1, NULL);
-}
-
-int make_ext4fs(const char *filename, long long len,
- const char *mountpoint, struct selabel_handle *sehnd)
-{
- int fd;
- int status;
-
- reset_ext4fs_info();
- info.len = len;
-
- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
- if (fd < 0) {
- error_errno("open");
- return EXIT_FAILURE;
- }
-
- status = make_ext4fs_internal(fd, NULL, mountpoint, NULL, 0, 0, 0, 1, sehnd, 0, -1, NULL);
- close(fd);
-
- return status;
-}
-
/* return a newly-malloc'd string that is a copy of str. The new string
is guaranteed to have a trailing slash. If absolute is true, the new string
is also guaranteed to have a leading slash.
}
int make_ext4fs_internal(int fd, const char *_directory,
- const char *_mountpoint, fs_config_func_t fs_config_func, int gzip,
+ fs_config_func_t fs_config_func, int gzip,
int sparse, int crc, int wipe,
- struct selabel_handle *sehnd, int verbose, time_t fixed_time,
+ int verbose, time_t fixed_time,
FILE* block_list_file)
{
u32 root_inode_num;
u16 root_mode;
- char *mountpoint;
char *directory = NULL;
if (setjmp(setjmp_env))
return EXIT_FAILURE; /* Handle a call to longjmp() */
- if (_mountpoint == NULL) {
- mountpoint = strdup("");
- } else {
- mountpoint = canonicalize_abs_slashes(_mountpoint);
- }
-
- if (_directory) {
+ if (_directory)
directory = canonicalize_rel_slashes(_directory);
- }
if (info.len <= 0)
info.len = get_file_size(fd);
printf(" Blocks: %"PRIu64"\n", aux_info.len_blocks);
printf(" Block groups: %d\n", aux_info.groups);
+ printf(" Reserved blocks: %"PRIu64"\n", (aux_info.len_blocks / 100) * info.reserve_pcnt);
printf(" Reserved block group size: %d\n", info.bg_desc_reserve_blocks);
ext4_sparse_file = sparse_file_new(info.block_size, info.len);
if (info.feat_compat & EXT4_FEATURE_COMPAT_RESIZE_INODE)
ext4_create_resize_inode();
-#ifdef USE_MINGW
- // Windows needs only 'create an empty fs image' functionality
- assert(!directory);
- root_inode_num = build_default_directory_structure(mountpoint, sehnd);
-#else
if (directory)
- root_inode_num = build_directory_structure(directory, mountpoint, 0,
- fs_config_func, sehnd, verbose, fixed_time);
+ root_inode_num = build_directory_structure(directory, "", 0,
+ fs_config_func, verbose, fixed_time);
else
- root_inode_num = build_default_directory_structure(mountpoint, sehnd);
-#endif
+ root_inode_num = build_default_directory_structure(fixed_time);
root_mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
- inode_set_permissions(root_inode_num, root_mode, 0, 0, 0);
-
-#ifndef USE_MINGW
- if (sehnd) {
- char *secontext = NULL;
-
- if (selabel_lookup(sehnd, &secontext, mountpoint, S_IFDIR) < 0) {
- error("cannot lookup security context for %s", mountpoint);
- }
- if (secontext) {
- if (verbose) {
- printf("Labeling %s as %s\n", mountpoint, secontext);
- }
- inode_set_selinux(root_inode_num, secontext);
- }
- freecon(secontext);
- }
-#endif
+ inode_set_permissions(root_inode_num, root_mode, 0, 0,
+ (fixed_time != 1) ? fixed_time : 0);
ext4_update_free();
ext4_queue_sb();
if (block_list_file) {
- size_t dirlen = directory ? strlen(directory) : 0;
+ size_t dirlen = strlen(directory);
struct block_allocation* p = get_saved_allocation_chain();
while (p) {
- if (directory && strncmp(p->filename, directory, dirlen) == 0) {
- // substitute mountpoint for the leading directory in the filename, in the output file
- fprintf(block_list_file, "%s%s", mountpoint, p->filename + dirlen);
+ if (strncmp(p->filename, directory, dirlen) == 0) {
+ fprintf(block_list_file, "%s", p->filename + dirlen);
} else {
fprintf(block_list_file, "%s", p->filename);
}
sparse_file_destroy(ext4_sparse_file);
ext4_sparse_file = NULL;
- free(mountpoint);
free(directory);
return 0;