mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Add mkinitrd support for multiple roots.
This commit is contained in:
parent
3191e18966
commit
b2aae6094f
1 changed files with 113 additions and 18 deletions
|
@ -39,10 +39,6 @@
|
||||||
|
|
||||||
#include <sortix/initrd.h>
|
#include <sortix/initrd.h>
|
||||||
|
|
||||||
#if !defined(VERSIONSTR)
|
|
||||||
#define VERSIONSTR "unknown version"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DEFAULT_FORMAT "sortix-initrd-2"
|
#define DEFAULT_FORMAT "sortix-initrd-2"
|
||||||
|
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
|
@ -86,6 +82,18 @@ struct DirEntry
|
||||||
Node* node;
|
Node* node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int DirEntryCompare(const DirEntry* a, const DirEntry* b)
|
||||||
|
{
|
||||||
|
return strcmp(a->name, b->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DirEntryCompareIndirect(const void* a_ptr, const void* b_ptr)
|
||||||
|
{
|
||||||
|
const DirEntry* a = (const DirEntry*) a_ptr;
|
||||||
|
const DirEntry* b = (const DirEntry*) b_ptr;
|
||||||
|
return DirEntryCompare(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
struct Node
|
struct Node
|
||||||
{
|
{
|
||||||
char* path;
|
char* path;
|
||||||
|
@ -103,10 +111,14 @@ struct Node
|
||||||
|
|
||||||
void FreeNode(Node* node)
|
void FreeNode(Node* node)
|
||||||
{
|
{
|
||||||
|
if ( !node )
|
||||||
|
return;
|
||||||
if ( 1 < node->nlink ) { node->nlink--; return; }
|
if ( 1 < node->nlink ) { node->nlink--; return; }
|
||||||
for ( size_t i = 0; i < node->direntsused; i++ )
|
for ( size_t i = 0; i < node->direntsused; i++ )
|
||||||
{
|
{
|
||||||
DirEntry* entry = node->dirents + i;
|
DirEntry* entry = node->dirents + i;
|
||||||
|
if ( !entry->name )
|
||||||
|
continue;
|
||||||
if ( strcmp(entry->name, ".") != 0 && strcmp(entry->name, "..") != 0 )
|
if ( strcmp(entry->name, ".") != 0 && strcmp(entry->name, "..") != 0 )
|
||||||
{
|
{
|
||||||
if ( --entry->node->refcount == 0 )
|
if ( --entry->node->refcount == 0 )
|
||||||
|
@ -310,9 +322,92 @@ Node* RecursiveSearch(const char* real_path, const char* virt_path,
|
||||||
FreeNode(node);
|
FreeNode(node);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
qsort(node->dirents, node->direntsused, sizeof(DirEntry),
|
||||||
|
DirEntryCompareIndirect);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node* MergeNodes(Node* a, Node* b)
|
||||||
|
{
|
||||||
|
if ( !S_ISDIR(a->mode) || !S_ISDIR(b->mode) )
|
||||||
|
{
|
||||||
|
FreeNode(b);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
size_t dirents_used = 0;
|
||||||
|
size_t dirents_length = a->direntsused + b->direntsused;
|
||||||
|
DirEntry* dirents = (DirEntry*) malloc(sizeof(DirEntry) * dirents_length);
|
||||||
|
if ( !dirents )
|
||||||
|
{
|
||||||
|
error(0, errno, "malloc");
|
||||||
|
FreeNode(a);
|
||||||
|
FreeNode(b);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bool failure = false;
|
||||||
|
size_t ai = 0;
|
||||||
|
size_t bi = 0;
|
||||||
|
while ( ai != a->direntsused || bi != b->direntsused )
|
||||||
|
{
|
||||||
|
if ( bi == b->direntsused ||
|
||||||
|
(ai != a->direntsused &&
|
||||||
|
bi != b->direntsused &&
|
||||||
|
DirEntryCompare(&a->dirents[ai], &b->dirents[bi]) < 0) )
|
||||||
|
{
|
||||||
|
dirents[dirents_used++] = a->dirents[ai];
|
||||||
|
a->dirents[ai].name = NULL;
|
||||||
|
a->dirents[ai].node = NULL;
|
||||||
|
ai++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( ai == a->direntsused ||
|
||||||
|
(ai != a->direntsused &&
|
||||||
|
bi != b->direntsused &&
|
||||||
|
DirEntryCompare(&a->dirents[ai], &b->dirents[bi]) > 0) )
|
||||||
|
{
|
||||||
|
dirents[dirents_used++] = b->dirents[bi];
|
||||||
|
for ( size_t i = 0; i < b->dirents[bi].node->direntsused; i++ )
|
||||||
|
{
|
||||||
|
if ( strcmp(b->dirents[bi].node->dirents[i].name, "..") != 0 )
|
||||||
|
continue;
|
||||||
|
b->dirents[bi].node->dirents[i].node = a;
|
||||||
|
}
|
||||||
|
b->dirents[bi].name = NULL;
|
||||||
|
b->dirents[bi].node = NULL;
|
||||||
|
bi++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const char* name = a->dirents[ai].name;
|
||||||
|
dirents[dirents_used].name = a->dirents[ai].name;
|
||||||
|
if ( !strcmp(name, ".") || !strcmp(name, "..") )
|
||||||
|
dirents[dirents_used].node = a->dirents[ai].node;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dirents[dirents_used].node =
|
||||||
|
MergeNodes(a->dirents[ai].node, b->dirents[bi].node);
|
||||||
|
if ( !dirents[dirents_used].node )
|
||||||
|
failure = true;
|
||||||
|
}
|
||||||
|
dirents_used++;
|
||||||
|
a->dirents[ai].name = NULL;
|
||||||
|
a->dirents[ai].node = NULL;
|
||||||
|
ai++;
|
||||||
|
free(b->dirents[bi].name);
|
||||||
|
b->dirents[bi].name = NULL;
|
||||||
|
b->dirents[bi].node = NULL;
|
||||||
|
bi++;
|
||||||
|
}
|
||||||
|
free(a->dirents);
|
||||||
|
a->dirents = dirents;
|
||||||
|
a->direntsused = dirents_used;
|
||||||
|
a->direntslength = dirents_length;
|
||||||
|
b->direntsused = 0;
|
||||||
|
FreeNode(b);
|
||||||
|
if ( failure )
|
||||||
|
return FreeNode(b), (Node*) NULL;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
bool WriteNode(struct initrd_superblock* sb, int fd, const char* outputname,
|
bool WriteNode(struct initrd_superblock* sb, int fd, const char* outputname,
|
||||||
Node* node)
|
Node* node)
|
||||||
{
|
{
|
||||||
|
@ -527,7 +622,7 @@ bool get_option_variable(const char* option, char** varptr,
|
||||||
|
|
||||||
static void help(FILE* fp, const char* argv0)
|
static void help(FILE* fp, const char* argv0)
|
||||||
{
|
{
|
||||||
fprintf(fp, "Usage: %s [OPTION]... ROOT -o OUTPUT\n", argv0);
|
fprintf(fp, "Usage: %s [OPTION]... ROOT... -o OUTPUT\n", argv0);
|
||||||
fprintf(fp, "Creates a init ramdisk for the Sortix kernel.\n");
|
fprintf(fp, "Creates a init ramdisk for the Sortix kernel.\n");
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
fprintf(fp, "Mandatory arguments to long options are mandatory for short options too.\n");
|
fprintf(fp, "Mandatory arguments to long options are mandatory for short options too.\n");
|
||||||
|
@ -592,7 +687,6 @@ int main(int argc, char* argv[])
|
||||||
help(stdout, argv0), exit(0);
|
help(stdout, argv0), exit(0);
|
||||||
else if ( !strcmp(arg, "--version") )
|
else if ( !strcmp(arg, "--version") )
|
||||||
version(stdout, argv0), exit(0);
|
version(stdout, argv0), exit(0);
|
||||||
|
|
||||||
else if ( GET_OPTION_VARIABLE("--filter", &arg_filter) )
|
else if ( GET_OPTION_VARIABLE("--filter", &arg_filter) )
|
||||||
{
|
{
|
||||||
FILE* fp = fopen(arg_filter, "r");
|
FILE* fp = fopen(arg_filter, "r");
|
||||||
|
@ -629,13 +723,6 @@ int main(int argc, char* argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( 2 < argc )
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s: Too many roots specified\n", argv0),
|
|
||||||
help(stderr, argv0);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !arg_output )
|
if ( !arg_output )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: No output file specified\n", argv0),
|
fprintf(stderr, "%s: No output file specified\n", argv0),
|
||||||
|
@ -655,12 +742,20 @@ int main(int argc, char* argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* rootstr = argv[1];
|
|
||||||
|
|
||||||
uint32_t inodecount = 1;
|
uint32_t inodecount = 1;
|
||||||
Node* root = RecursiveSearch(rootstr, "/", &inodecount);
|
Node* root = NULL;
|
||||||
if ( !root )
|
for ( int i = 1; i < argc; i++ )
|
||||||
exit(1);
|
{
|
||||||
|
Node* node = RecursiveSearch(argv[i], "/", &inodecount);
|
||||||
|
if ( !node )
|
||||||
|
exit(1);
|
||||||
|
if ( root )
|
||||||
|
root = MergeNodes(root, node);
|
||||||
|
else
|
||||||
|
root = node;
|
||||||
|
if ( !root )
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if ( !Format(arg_output, inodecount, root) )
|
if ( !Format(arg_output, inodecount, root) )
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue