NAME
Sys::Export - Export a subset of an OS file tree, for chroot/initrd
SYNOPSIS
use Sys::Export -src => '/', -dst => [ CPIO => "initrd.cpio" ];
rewrite_path '/sbin' => '/bin';
rewrite_path '/usr/sbin' => '/bin';
rewrite_path '/usr/bin' => '/bin';
# Add files and their dependencies
add '/bin/busybox';
add qw( bin/sh bin/date bin/cat bin/mount );
# tell 'add' to ignore specific files
skip 'usr/share/zoneinfo/tzdata.zi';
# recurse and filter directories with 'find'
add find 'usr/share/zoneinfo', sub { ! /(leapseconds|\.tab|\.list)$/ };
# Inject dynamically generated files
add [ file400 => "/etc/some-service.conf", <<~END ];
# Some config file
secret = $secret
END
# Inject files that come from a different name, or outside the 'src' tree
add [ file644 => "/opt/some-app/data", filedata("/path/to/some/data") ];
# For Linux, generate minimal /etc/passwd /etc/group /etc/shadow according
# to UID/GID which were exported so far.
exporter->add_passwd;
finish;
DESCRIPTION
This module is designed to export a subset of an operating system to a new directory, automatically detecting and including any libraries or interpreters required by the requested subset, and optionally rewriting paths and users/groups and updating the copied files to refer to the rewritten paths, when possible.
The actual export implementation is handled by a OS-specific module, like Sys::Export::Linux. This top-level module just exports methods. You can configure a global exporter instance on the use line, and then call its methods via exported functions. For instance,
use Sys::Export \%options;
is roughly equivalent to:
BEGIN {
if ($^O eq 'linux') {
require Sys::Export::Linux;
$Sys::Export::exporter= Sys::Export::Linux->new(\%options);
} else {
...
}
sub exporter { $Sys::Export::exporter }
sub add { $Sys::Export::exporter->add(@_) }
sub rewrite_path { $Sys::Export::exporter->rewrite_path(@_) }
sub rewrite_user { $Sys::Export::exporter->rewrite_user(@_) }
sub rewrite_group { $Sys::Export::exporter->rewrite_group(@_) }
sub finish { $Sys::Export::exporter->finish }
}
In other words, just a convenience for creating an exporter instance and giving you access to most of its important methods without needing to reference the object. You can skip this module entirely and just directly use a Sys::Export::Linux object, if you prefer.
Currently, only Linux is fully supported.
CONFIGURATION
The following can be passed on the use line to configure a global exporter object:
- A Hashref
-
use Sys::Export { ... };The keys of the hashref will be passed to the exporter constructor (aside from the key
'type'which is used to override the default class) - -type
-
Specify a class of exporter, like
'Linux'or'Sys::Export::Linux'. Names without colons imply a prefix ofSys::Export::. - -src
-
Source directory; see "src" in Sys::Export::Unix.
- -dst
-
Destination directory or CPIO instance; see "dst" in Sys::Export::Unix.
- -src_userdb
-
Defines UID/GID of source filesystem; see "src_userdb" in Sys::Export::Unix.
- -dst_userdb
-
Defines UID/GID of destination; see "dst_userdb" in Sys::Export::Unix.
- -rewrite_path
-
Hashref of rewrites; see "rewrite_path" in Sys::Export::Unix.
- -rewrite_user
-
Hashref of rewrites; see "rewrite_user" in Sys::Export::Unix.
- -rewrite_group
-
Hashref of rewrites; see "rewrite_group" in Sys::Export::Unix.
EXPORTS
exporter
A function to access $Sys::Exporter::exporter
init_global_exporter
init_global_exporter(\%config);
A function to initialize $Sys::Exporter::exporter, which also handles autoselecting the type of the exporter.
:basic_methods bundle
You get this bundle by default if you configured a global exporter. The following methods of the global exporter object get exported as functions:
:isa bundle
use Sys::Export ":isa";
These boolean functions are useful for type inspection.
- isa_exporter
-
Is it an object and an instance of
Sys::Export::Exporter? - isa_export_dst
-
Is it an object which can receive exported files? (
addandfinishmethods) - isa_userdb
-
Is it an instance of
Sys::Export::Unix::UserDB? - isa_user
-
Is it an instance of
Sys::Export::Unix::UserDB::User? - isa_group
-
Is it an instance of
Sys::Export::Unix::UserDB::Group? - isa_hash
-
Is it a hashref?
- isa_array
-
Is it an arrayref?
- isa_data_ref
-
Is it a scalar ref or an object with method
as_scalarref? - isa_handle
-
Is it a GLOB ref or IO::Handle?
- isa_int
-
Is it an integer?
- isa_pow2
-
Is it a power of 2?
:stat_modes bundle
S_IFREG S_IFDIR S_IFLNK S_IFBLK S_IFCHR S_IFIFO S_IFSOCK S_IFWHT S_IFMT
These are like the exports from Fcntl, but return 0 if the macro is not defined on this platform.
:stat_tests bundle
S_ISREG S_ISDIR S_ISLNK S_ISBLK S_ISCHR S_ISFIFO S_ISSOCK S_ISWHT
These are like the exports from Fcntl, but return false if the macro is not defined on this platform.
expand_stat_shorthand
@kv_list= expand_stat_shorthand($arrayref);
@kv_list= expand_stat_shorthand($mode, $name);
@kv_list= expand_stat_shorthand($mode, $name, $mode_specific_data);
@kv_list= expand_stat_shorthand($mode, $name, \%other_attrs);
@kv_list= expand_stat_shorthand($mode, $name, $mode_specific_data, \%other_attrs);
This is a utility function that takes a shorthand array notation for a directory entry, and expands it to the file attribute names as used in "add" in Sys::Export::Unix or "add" in Sys::Export::CPIO.
The $mode can either be a numeric Unix mode like use Fcntl 'S_IFDIR'; (S_IFDIR|0755) or a name like 'dir' (with default permissions) or a name with a permission suffix like 'dir755'.
For example:
[ file644 => "foo", $literal_data ],
[ file644 => "foo", { data_path => $filename } ],
[ dir700 => "root/.ssh" ],
[ dir1777 => "tmp" ],
[ sym => "bar" => "foo" ],
[ chr777 => "dev/null" => [1,3] ],
[ blk660 => "dev/sda" => [8,0], { group => "disk" } ],
[ fifo => "run/queue" ],
[ sock => "run/mysqld/mysql.sock", { user => "mysql", group => "mysql" } ],
The default permissions are 0777 & ~umask for a directory, 0777 for symlinks, and 0666 & ~umask for others.
round_up_to_pow2
$pow2= round_up_to_pow2($number);
Return a number rounded up to the next power of 2, or itself if it was already a power of 2. Dies if the number is less than 0. Returns 1 when $number is 0.
round_up_to_multiple
$aligned= round_up_to_multiple($n, $pow2);
Return a number rounded up to the next multiple of a power of 2. Dies if the number is less than 0.
map_or_load_file
$scalar_ref= map_or_load_file($path);
$scalar_ref= map_or_load_file($path, $offset);
$scalar_ref= map_or_load_file($path, $offset, $length);
If File::Map is available, this creates a read-only memory map of the file (from the specified offset) and rreturns a scalar ref to it. If not, it simply loads the file into a scalar and returns a ref to that. You should assume the data in the scalar is read-only.
filedata
$filedata= filedata($path);
$filedata= filedata($path, $offset);
$filedata= filedata(\$scalar_ref, $offset, $length);
This is a shortcut for creating Sys::Export::LazyFileData objects. These objects delay the memory-mapping of a file (or substr operation on a large scalar) until it is needed. This is a convenient way to pass file data to various methods such as "add".
write_file_extent
write_file_extent($fh, $file_addr, $size, $data_ref, $data_ofs, $description=undef);
This utility method writes a full extent of a file, padding the supplied data with NUL bytes if needed. It first seeks to $file_addr, then writes a full $size bytes from $$data_ref from offset $data_ofs if possible. If the length of the scalar in $$data_ref is too short, this pads the write with NUL bytes. If $$data_ref is especially large (>1MiB) it first performs a syswrite of as many whole pages of the data as possible, then pads the final page with NUL bytes on a second syswrite.
You can skip the seek operation with an undefined $file_addr, in which case it just syswrites from the current position of the file.
$description is for debug-logging purposes and can be undef.
If any syscall fails, or can't write the full size, this croaks.
VERSION
version 0.004
AUTHOR
Michael Conrad <mike@nrdvana.net>
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Michael Conrad.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.