# [SCRIPT] Generate file list for gen_init_cpio

## AaylaSecura

I decided to properly understand the initramfs, so created my first "mock" initramfs from scratch (have no need for it and it does nothing really; but hey, why not?!). Following this guide I found out about gen_init_cpio, which I ended up using. Because it's a pain to have to manually write the file containing the list of files to be included (and it the correct order: first directories in the order they are to be created), I wrote a script to do just that given a list of existing files on my system. Two useful features: it finds all libraries needed by an executable and adds those as well, and it adds all directories needed, so only need to specify files. It also uses the current permissions of the file. Usage:

```
<you name the script> [options] [<file>]

If <file> is missing, print list to stdout.

Options:

  --dyn-bin   | -b <binary>   Add a dynamically linked binary and all of its

                              dependencies.

  --file      | -f <file>     Add a file, automatically detecting the type

                              (file, dir, nod, slink, pipe or sock) and mode..

  --overwrite | -o            Do not append to file.

  --generate  | -g [<name>]   Generate the initramfs after creating/updating

                              the file list. A default name is generated from

                              the currently SELECTED kernel.

  --compress  | -c [<level>]  Compress the initramfs. Default <level> is 4.

  --quiet     | -q            Do not write file list to stdout.

```

[list][*]When writing a 'file' (regular file) entry, the <location> within the initramfs will be the same as the current path of the file.

[*]When adding an 'slink' (symbolic link), the <target> is the target of the link (relative links stay relative)

Example: to generate initramfs-<selected kernel>.cpio including busybox, findfs (and all of its libraries), do:

```
<you name the script> -f /bin/busybox -b findfs -f /init -g -q
```

LINK (Updated 19/08/16) to the script.

Bugs: probably lots  :Very Happy:  Please report here.Last edited by AaylaSecura on Fri Aug 19, 2016 11:59 am; edited 1 time in total

----------

## Hu

```
    30   find_bin() {

    31       local dir BIN

    32       BIN=$1

    33       for dir in ${PATH//:/ } ; do

    34           [[ -f ${dir}/${BIN} ]] && echo ${dir}/${BIN} && break

    35       done

    36   }

```

I think this could be rewritten to use the bash intrinsic type with option -p instead of open-coding the search.  That would also handle users with embedded whitespace in their $PATH.

```
    46   add_file() {

    47       echo "file $1 $1 $(get_mode $1) 0 0" >> ${TMPFILE}

    48   }

```

The add_* family could be simplified by passing the entire string to stat -c instead.  For example:

```
add_file() {

   stat -c "file $1 $1 %a 0 0" "$1" >> $TMPFILE

}

```

If you want to handle filenames with a literal % in their name, you would need to double the %:

```
add_file() {

   local f="${1//%/%%}"

   stat -c "file $f $f %a 0 0" "$1" >> $TMPFILE

}

```

```
    85   add_dyn_bin() {

    86       local BIN LIB TRUELIB

    87       BIN=$1

    88       [[ ${BIN} = /* ]] || BIN=$(find_bin $1)

    92       add_obj ${BIN}

```

I think you should quote expansions of $BIN.  Users with an embedded space in the filename could cause strange results otherwise.

```
    94       ldd ${BIN} | egrep -v ' *not a dynamic executable' \

    95           | sed -r -n -e '/linux-vdso.so/b' -e 's/^\t*(.*+> )?([^ ]+) .*/\2/p' \

```

I think you could use sed to implement that egrep expression, which would let you remove the use of egrep from the pipeline.

```
   207   if [[ -n ${INITRAMFS} ]] ; then

   208       GEN_INIT_CPIO=$(readlink -e /usr/src/linux/usr/gen_init_cpio)

   209       if [[ -n ${GEN_INIT_CPIO} ]] ; then

   210           eval ${GEN_INIT_CPIO} "${FILE}" > "${INITRAMFS}"

```

Why do you need eval here?  It looks like you could remove the eval keyword and get the same result.

----------

## AaylaSecura

Thanks for the feedback, Hu! I will incorporate those changes soon, though I'm not sure about those two:

 *Hu wrote:*   

> If you want to handle filenames with a literal % in their name...
> 
> I think you should quote expansions of $BIN.  Users with an embedded space in the filename could cause strange results otherwise.

 

I thought about the whitespace, special characters, etc and quoting, but I decided to leave it like that since I don't expect anyone to be including files in the initramfs with funny names. I'm probably wrong about it, but wouldn't only system files go in there, and I haven't encountered a single one that has whitespace, let alone % or other symbols. Of course it's not a problem to put quotes where needed, but I'm not sure what should be fed to gen_init_cpio: the filenames printed to the file that gen_init_cpio takes should also include quotes, right? so double quoting needed...

----------

## Hu

Yes, nobody should put weird characters in their filenames.  However, assuming that nobody ever will use such characters can lead to annoying problems later when someone does it and the failure is not clear.  If you do not want to handle special characters (and that seems reasonable in this script), I suggest including just enough handling to recognize that the user has done something weird and bail out with an error message, such as "File paths can only contain alphanumerics, dashes, dots, and slashes.  Bad file $file".  That saves you from writing and testing full support, and saves you and your users from confusing problem reports caused by strange filenames being mangled due to improper quoting.

----------

## AaylaSecura

 *Hu wrote:*   

> Yes, nobody should put weird characters in their filenames.  However, assuming that nobody ever will use such characters can lead to annoying problems later when someone does it and the failure is not clear.  If you do not want to handle special characters (and that seems reasonable in this script), I suggest including just enough handling to recognize that the user has done something weird and bail out with an error message, such as "File paths can only contain alphanumerics, dashes, dots, and slashes.  Bad file $file".  That saves you from writing and testing full support, and saves you and your users from confusing problem reports caused by strange filenames being mangled due to improper quoting.

 

Good point! I should have done that indeed, thanks for your feedback.

----------

## AaylaSecura

I added support for % (and presumably other special characters) but spaces do not work and I don't think there is a way to make them work: gen_init_cpio uses sscanf with %s format modifier which stops scanning at the first whitespace. There is a way to accept spaces but that would require a modification to gen_init_cpio. I'd be glad to hear I can work around it and "fool" scanf to somehow absorb spaces with the %s modifier.

----------

## frostschutz

 *AaylaSecura wrote:*   

> There is a way to accept spaces but that would require a modification to gen_init_cpio.

 

Well, it's not like they don't accept patches.

But I don't think it's necessary either.

Not even sure how well the crazier things (files with Unicode characters and such) would work within Initramfs...

----------

## AaylaSecura

 *frostschutz wrote:*   

> Well, it's not like they don't accept patches.
> 
> But I don't think it's necessary either.
> 
> Not even sure how well the crazier things (files with Unicode characters and such) would work within Initramfs...

 

True, I think patching gen_init_cpio to accept funny names may actually be for the worse, since full support for unicode names would require thorough testing and probably more modifications (some of which may not be trivial).

----------

