diff --git a/mkinitrd/mkinitrd.8 b/mkinitrd/mkinitrd.8 index fc9ffbcd..a49b4950 100644 --- a/mkinitrd/mkinitrd.8 +++ b/mkinitrd/mkinitrd.8 @@ -8,6 +8,7 @@ .Nm mkinitrd .Op Fl \-filter Ns "=" Ns Ar rules-file .Op Fl \-format Ns "=" Ns Ar format +.Op Fl \-manifest Ns "=" Ns Ar manifest-file .Fl o Ar destination .Ar directory ... .Sh DESCRIPTION @@ -61,6 +62,10 @@ is an alias for the newest format will default to a newer format when one is introduced and this allows .Nm to support old callers during the transitional period. +.It Fl \-manifest Ns "=" Ns Ar manifest-file +Include only files and directories during the recursive search whose path +exactly matches a line in the +.Ar manifest-file . .It Fl o , Fl \-output Ns "=" Ns Ar destination Store the produced .Xr initrd 7 diff --git a/mkinitrd/mkinitrd.cpp b/mkinitrd/mkinitrd.cpp index f6e895c9..dc796e27 100644 --- a/mkinitrd/mkinitrd.cpp +++ b/mkinitrd/mkinitrd.cpp @@ -658,6 +658,7 @@ int main(int argc, char* argv[]) { char* arg_filter = NULL; char* arg_format = strdup(DEFAULT_FORMAT); + char* arg_manifest = NULL; char* arg_output = NULL; const char* argv0 = argv[0]; @@ -711,6 +712,17 @@ int main(int argc, char* argv[]) free(arg_filter); arg_filter = NULL; } + else if ( GET_OPTION_VARIABLE("--manifest", &arg_manifest) ) + { + FILE* fp = fopen(arg_manifest, "r"); + if ( !fp ) + error(1, errno, "%s", arg_manifest); + if ( !path_filter.AddManifestFromFile(fp, stderr, arg_manifest) ) + exit(1); + fclose(fp); + free(arg_manifest); + arg_manifest = NULL; + } else if ( GET_OPTION_VARIABLE("--format", &arg_format) ) { } else if ( GET_OPTION_VARIABLE("--output", &arg_output) ) { } else diff --git a/mkinitrd/rules.cpp b/mkinitrd/rules.cpp index 3a5919e2..9ef749b4 100644 --- a/mkinitrd/rules.cpp +++ b/mkinitrd/rules.cpp @@ -113,6 +113,13 @@ InclusionRules::~InclusionRules() delete[] rules; } +static int search_path(const void* a_ptr, const void* b_ptr) +{ + const char* key = (const char*) a_ptr; + char* path = *(char**) b_ptr; + return strcmp(key, path); +} + bool InclusionRules::IncludesPath(const char* path) const { bool determined = false; @@ -136,7 +143,12 @@ bool InclusionRules::IncludesPath(const char* path) const } if ( !determined ) included = default_inclusion; - return included; + if ( !included ) + return false; + if ( manifest_used && + !bsearch(path, manifest, manifest_used, sizeof(char*), search_path) ) + return false; + return true; } bool InclusionRules::ChangeRulesAmount(size_t new_length) @@ -265,3 +277,49 @@ bool InclusionRules::AddRulesFromFile(FILE* fp, FILE* err, const char* fpname) } return true; } + +int compare_path(const void* a_ptr, const void* b_ptr) +{ + const char* a = *(const char* const*) a_ptr; + const char* b = *(const char* const*) b_ptr; + return strcmp(a, b); +} + +bool InclusionRules::AddManifestFromFile(FILE* fp, FILE* err, const char* fpname) +{ + char* line = NULL; + size_t line_size = 0; + ssize_t line_len; + while ( 0 <= (line_len = getline(&line, &line_size, fp)) ) + { + if ( line_len && line[line_len-1] == '\n' ) + line[line_len-1] = '\0'; + if ( manifest_used == manifest_length ) + { + size_t new_length = 2 * manifest_length; + if ( new_length == 0 ) + new_length = 64; + size_t new_size = new_length * sizeof(char*); + char** new_manifest = (char**) realloc(manifest, new_size); + if ( !new_manifest ) + { + free(line); + error_fp(err, 0, errno, "malloc"); + return false; + } + manifest = new_manifest; + manifest_length = new_length; + } + manifest[manifest_used++] = line; + line = NULL; + line_size = 0; + } + free(line); + if ( ferror(fp) ) + { + error_fp(err, 0, errno, "%s", fpname); + return false; + } + qsort(manifest, manifest_used, sizeof(char*), compare_path); + return true; +} diff --git a/mkinitrd/rules.h b/mkinitrd/rules.h index 39812435..0b95e9e5 100644 --- a/mkinitrd/rules.h +++ b/mkinitrd/rules.h @@ -52,6 +52,7 @@ public: bool IncludesPath(const char* path) const; bool AddRule(InclusionRule* rule); bool AddRulesFromFile(FILE* fp, FILE* err, const char* fpname); + bool AddManifestFromFile(FILE* fp, FILE* err, const char* fpname); bool ChangeRulesAmount(size_t newnum); public: @@ -60,6 +61,9 @@ public: size_t num_rules_allocated; bool default_inclusion; bool default_inclusion_determined; + char** manifest; + size_t manifest_used; + size_t manifest_length; };