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)$/ };

# 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 of Sys::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:

add
skip
find
finish
rewrite_path
rewrite_user
rewrite_group

: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? (add and finish methods)

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_int

Is it an integer?

: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.

VERSION

version 0.003

AUTHOR

Michael Conrad <mike@nrdvana.net>

COPYRIGHT AND LICENSE

This software is copyright (c) 2025 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.