NAME

Sys::Export::Unix::WriteFS - An export target that writes files to a directory in the host filesystem

SYNOPSIS

This is used automatically when you specify a path string as the 'dst' parameter of the Unix exporter.

use Sys::Export::Unix;
my $exporter= Sys::Export::Unix->new(
  src => '/', dst => '/initrd'
);

DESCRIPTION

This module simply writes all exported files to the host's filesystem. This is more-or-less the default that people use when building system images, but the downside is that it reqrires the build script to be run as root. You can avoid this by using Sys::Export::CPIO as an export target, which is able to write directory entries directly to the cpio archive, skipping any local filesystem writes.

Note that this module tracks device and inode in order to preserve hard-links, though only entries with nlink greater than 1 are considered. To generate a hard link, specify a distinct dev and ino combination (and nlink greater than 1) and then repeat those parameters later in order to link to the previous file.

CONSTRUCTORS

new

Sys::Export::Unix::WriteFS->new(\%attributes); # hashref
Sys::Export::Unix::WriteFS->new(%attributes);  # key/value list

Required attributes:

dst

The root of the exported system. This directory must exist, and should be empty unless you specify 'on_collision'.

Options:

tmp

A temporary directory in the same filesystem as "dst" where this module can prepare temporary files, then rename them into place. This prevents any partially-prepared files from ending up in the destination tree. If you specify this, it is your responsibility to clean it up, such as by passing an instance of File::Temp->newdir.

By default, this module uses the normaal File::Temp location, unless that path is not on the same volume as the destination, in which case it will create a temp directory within $dst.

on_collision

Specifies what to do if there is a name collision in the destination. The default 'ignore_if_same' causes an exception unless the existing file is identical to the one that would be written.

Setting this to 'overwrite' will unconditionally replace files as it runs. Setting it to 'ignore' will silently ignore collisions and leave the existing file in place. Setting it to a coderef will provide you with the path and content thata was about to be written to it:

on_collision => sub ($dst_abs, $fileinfo) {
  # dst_abs is the absolute path about to be written
  # fileinfo is the hash of file attributes passed to ->add
  # _ will be set to an lstat of $dst_abs
  return $action; # 'ignore' or 'overwrite' or 'ignore_if_same'
}

ATTRIBUTES

dst

The root of the destination filesystem. This is the logical root of your destination filesystem. The directory must exist, cannot be the actual "/" root directory, and probably ought to be empty to avoid collisions.

dst_abs

The abs_path of the root of the destination filesystem, always ending with '/'. This is only defined if dst is not a coderef.

tmp

The abs_path of a directory to use for temporary staging before renaming into "dst". This must be in the same volume as dst so that rename() can be used to move temporary files into their dst location. A default will be chosen within /dst_abs if that isn't the same device as the natural. It will be cleaned up automatically or when you call "finish".

METHODS

add

$exporter->add(\%file_attrs);

Add content to a destination path. File attributes are:

name            # destination path relative to destination root
data            # literal data content of file (must be bytes, not unicode)
data_path       # absolute path of file to load 'data' from
dev             # device, from stat
dev_major       # major(dev), if you know it and don't know 'dev'
dev_minor       # minor(dev), if you know it and don't know 'dev'
ino             # inode, from stat
mode            # permissions and type, as per stat
nlink           # number of hard links
uid             # user id
gid             # group id
rdev            # referenced device, for device nodes
rdev_major      # major(rdev), if you know it and don't know 'rdev'
rdev_minor      # minor(rdev), if you know it and don't know 'rdev'
size            # size, in bytes.  Can be ommitted if 'data' is present
mtime           # modification time, as per stat

Returns a true value if the file/dirent was written to the filesystem, or false otherwise. Errors writing to the filesystem will generate exceptions rather than a false return value, but a false return may occur if you set on_collision => 'ignore'.

finish

Apply any postponed changes to the destination filesystem. For instance, this applies mtimes to directories since writing the contents of the directory would have changed the mtime.

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.