cpio: add support for --renumber-inodes like GNU cpio

The --renumber-inodes option renumbers the inodes starting from 1,
so that the sequence of inodes is always stable.  This helps with
reproducibility.

function                                             old     new   delta
cpio_o                                               961    1045     +84
.rodata                                            78422   78440     +18
bbconfig_config_bz2                                 6168    6164      -4
packed_usage                                       25764   25756      -8
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/2 up/down: 102/-12)            Total: 90 bytes

Signed-off-by: Ariadne Conill <ariadne@dereferenced.org>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Ariadne Conill 2021-06-28 08:31:23 -06:00 committed by Denys Vlasenko
parent 8aa5585ff4
commit 836b79211d

View File

@ -45,6 +45,13 @@
//config: depends on FEATURE_CPIO_O && LONG_OPTS //config: depends on FEATURE_CPIO_O && LONG_OPTS
//config: help //config: help
//config: Optionally ignore device numbers when creating archives. //config: Optionally ignore device numbers when creating archives.
//config:
//config:config FEATURE_CPIO_RENUMBER_INODES
//config: bool "Support --renumber-inodes like GNU cpio"
//config: default y
//config: depends on FEATURE_CPIO_O && LONG_OPTS
//config: help
//config: Optionally renumber inodes when creating archives.
//applet:IF_CPIO(APPLET(cpio, BB_DIR_BIN, BB_SUID_DROP)) //applet:IF_CPIO(APPLET(cpio, BB_DIR_BIN, BB_SUID_DROP))
@ -85,6 +92,9 @@
//usage: IF_FEATURE_CPIO_IGNORE_DEVNO( //usage: IF_FEATURE_CPIO_IGNORE_DEVNO(
//usage: "\n --ignore-devno" //usage: "\n --ignore-devno"
//usage: ) //usage: )
//usage: IF_FEATURE_CPIO_RENUMBER_INODES(
//usage: "\n --renumber-inodes"
//usage: )
/* GNU cpio 2.9 --help (abridged): /* GNU cpio 2.9 --help (abridged):
@ -173,18 +183,21 @@ enum {
IF_LONG_OPTS( OPTBIT_QUIET ,) IF_LONG_OPTS( OPTBIT_QUIET ,)
IF_LONG_OPTS( OPTBIT_2STDOUT ,) IF_LONG_OPTS( OPTBIT_2STDOUT ,)
IF_FEATURE_CPIO_IGNORE_DEVNO(OPTBIT_IGNORE_DEVNO,) IF_FEATURE_CPIO_IGNORE_DEVNO(OPTBIT_IGNORE_DEVNO,)
IF_FEATURE_CPIO_RENUMBER_INODES(OPTBIT_RENUMBER_INODES,)
OPT_CREATE = IF_FEATURE_CPIO_O((1 << OPTBIT_CREATE )) + 0, OPT_CREATE = IF_FEATURE_CPIO_O((1 << OPTBIT_CREATE )) + 0,
OPT_FORMAT = IF_FEATURE_CPIO_O((1 << OPTBIT_FORMAT )) + 0, OPT_FORMAT = IF_FEATURE_CPIO_O((1 << OPTBIT_FORMAT )) + 0,
OPT_PASSTHROUGH = IF_FEATURE_CPIO_P((1 << OPTBIT_PASSTHROUGH)) + 0, OPT_PASSTHROUGH = IF_FEATURE_CPIO_P((1 << OPTBIT_PASSTHROUGH)) + 0,
OPT_QUIET = IF_LONG_OPTS( (1 << OPTBIT_QUIET )) + 0, OPT_QUIET = IF_LONG_OPTS( (1 << OPTBIT_QUIET )) + 0,
OPT_2STDOUT = IF_LONG_OPTS( (1 << OPTBIT_2STDOUT )) + 0, OPT_2STDOUT = IF_LONG_OPTS( (1 << OPTBIT_2STDOUT )) + 0,
OPT_IGNORE_DEVNO = IF_FEATURE_CPIO_IGNORE_DEVNO((1 << OPTBIT_IGNORE_DEVNO)) + 0, OPT_IGNORE_DEVNO = IF_FEATURE_CPIO_IGNORE_DEVNO((1 << OPTBIT_IGNORE_DEVNO)) + 0,
OPT_RENUMBER_INODES = IF_FEATURE_CPIO_RENUMBER_INODES((1 << OPTBIT_RENUMBER_INODES)) + 0,
}; };
#define OPTION_STR "it0uvdmLF:R:" #define OPTION_STR "it0uvdmLF:R:"
struct globals { struct globals {
struct bb_uidgid_t owner_ugid; struct bb_uidgid_t owner_ugid;
ino_t next_inode;
} FIX_ALIASING; } FIX_ALIASING;
#define G (*(struct globals*)bb_common_bufsiz1) #define G (*(struct globals*)bb_common_bufsiz1)
void BUG_cpio_globals_too_big(void); void BUG_cpio_globals_too_big(void);
@ -218,6 +231,9 @@ static NOINLINE int cpio_o(void)
struct inodes_s *next; struct inodes_s *next;
struct name_s *names; struct name_s *names;
struct stat st; struct stat st;
#if ENABLE_FEATURE_CPIO_RENUMBER_INODES
ino_t mapped_inode;
#endif
}; };
struct inodes_s *links = NULL; struct inodes_s *links = NULL;
@ -272,6 +288,10 @@ static NOINLINE int cpio_o(void)
l = xzalloc(sizeof(*l)); l = xzalloc(sizeof(*l));
l->st = st; l->st = st;
l->next = links; l->next = links;
#if ENABLE_FEATURE_CPIO_RENUMBER_INODES
if (option_mask32 & OPT_RENUMBER_INODES)
l->mapped_inode = ++G.next_inode;
#endif
links = l; links = l;
break; break;
} }
@ -290,6 +310,11 @@ static NOINLINE int cpio_o(void)
free(line); free(line);
continue; continue;
} }
#if ENABLE_FEATURE_CPIO_RENUMBER_INODES
else if (option_mask32 & OPT_RENUMBER_INODES) {
st.st_ino = ++G.next_inode;
}
#endif
} else { /* line == NULL: EOF */ } else { /* line == NULL: EOF */
next_link: next_link:
if (links) { if (links) {
@ -297,6 +322,10 @@ static NOINLINE int cpio_o(void)
st = links->st; st = links->st;
name = links->names->name; name = links->names->name;
links->names = links->names->next; links->names = links->names->next;
#if ENABLE_FEATURE_CPIO_RENUMBER_INODES
if (links->mapped_inode)
st.st_ino = links->mapped_inode;
#endif
/* GNU cpio is reported to emit file data /* GNU cpio is reported to emit file data
* only for the last instance. Mimic that. */ * only for the last instance. Mimic that. */
if (links->names == NULL) if (links->names == NULL)
@ -398,6 +427,9 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
"to-stdout\0" No_argument "\xfe" "to-stdout\0" No_argument "\xfe"
#if ENABLE_FEATURE_CPIO_IGNORE_DEVNO #if ENABLE_FEATURE_CPIO_IGNORE_DEVNO
"ignore-devno\0" No_argument "\xfd" "ignore-devno\0" No_argument "\xfd"
#endif
#if ENABLE_FEATURE_CPIO_RENUMBER_INODES
"renumber-inodes\0" No_argument "\xfc"
#endif #endif
; ;
#endif #endif