2019-08-29 04:54:12 +03:00
|
|
|
{ stdenvNoCC, lib, writeText }:
|
2019-08-27 21:14:47 +03:00
|
|
|
|
2019-08-29 03:50:28 +03:00
|
|
|
/* */ let scope = { "fileSystem.makeFilesystem" =
|
2019-08-27 21:14:47 +03:00
|
|
|
|
|
|
|
let
|
2019-08-29 03:50:28 +03:00
|
|
|
inherit (lib) optionals optionalString assertMsg;
|
2019-08-27 21:14:47 +03:00
|
|
|
in
|
|
|
|
|
|
|
|
{
|
|
|
|
name
|
2019-09-04 07:48:58 +03:00
|
|
|
# Size (in bytes) the filesystem image will be given.
|
|
|
|
# When size is not given, it is assumed that `populateCommands` will populate
|
|
|
|
# the filesystem, and the size will be derived (see computeMinimalSize).
|
|
|
|
, size ? null
|
|
|
|
|
2019-08-29 03:50:28 +03:00
|
|
|
# The populate commands are executed in a subshell. The CWD at the star is the
|
|
|
|
# public API to know where to add files that will be added to the image.
|
|
|
|
, populateCommands ? null
|
2019-09-04 07:48:58 +03:00
|
|
|
|
|
|
|
# Used with the assumption that files are rounded up to blockSize increments.
|
image-builder: makeFilesystem: reviews minimum size with blockSize
First of all, `du -s` will always combine the sizes into the multiple of
its given --block-size, so 4×1 byte files will show up as 1 block size
(assuming a block size > 4). The expected size would have been at least
one block size per file, so for 512, 512×4 thus 2048.
With this change, we sum the sizes ourselves.
This adds a new requirement to the filesystems, that they pass the block
size to the generic builder, though this is good, as it will increases
reproducibility. In addition, filesystems can present the option to
users, allowing the user to set their block sizes as expected.
2019-09-02 23:29:07 +03:00
|
|
|
, blockSize
|
2019-09-04 07:48:58 +03:00
|
|
|
|
|
|
|
# Additional commands to compute a required increase in size to fit files.
|
|
|
|
, computeMinimalSize ? null
|
|
|
|
|
|
|
|
# When automatic sizing is used, additional amount of bytes to pad the image by.
|
|
|
|
, extraPadding ? 0
|
2019-08-27 21:14:47 +03:00
|
|
|
, ...
|
|
|
|
} @ args:
|
2019-08-29 03:50:28 +03:00
|
|
|
|
|
|
|
assert lib.asserts.assertMsg
|
|
|
|
(size !=null || populateCommands != null)
|
|
|
|
"Either a size or populateCommands needs to be given to build a filesystem.";
|
|
|
|
|
2019-08-27 21:14:47 +03:00
|
|
|
let
|
|
|
|
partName = name;
|
|
|
|
in
|
|
|
|
stdenvNoCC.mkDerivation (args // rec {
|
|
|
|
# Do not inherit `size`; we don't want to accidentally use it. The `size` can
|
|
|
|
# be dynamic depending on the contents.
|
image-builder: makeFilesystem: reviews minimum size with blockSize
First of all, `du -s` will always combine the sizes into the multiple of
its given --block-size, so 4×1 byte files will show up as 1 block size
(assuming a block size > 4). The expected size would have been at least
one block size per file, so for 512, 512×4 thus 2048.
With this change, we sum the sizes ourselves.
This adds a new requirement to the filesystems, that they pass the block
size to the generic builder, though this is good, as it will increases
reproducibility. In addition, filesystems can present the option to
users, allowing the user to set their block sizes as expected.
2019-09-02 23:29:07 +03:00
|
|
|
inherit partName blockSize;
|
2019-08-27 21:14:47 +03:00
|
|
|
|
|
|
|
name = "partition-${partName}";
|
|
|
|
filename = "${partName}.img";
|
|
|
|
img = "${placeholder "out"}/${filename}";
|
|
|
|
|
|
|
|
nativeBuildInputs = [
|
|
|
|
] ++ optionals (args ? nativeBuildInputs) args.nativeBuildInputs;
|
|
|
|
|
|
|
|
buildCommand = ''
|
2019-09-04 07:48:58 +03:00
|
|
|
adjust-minimal-size() {
|
|
|
|
size="$1"
|
|
|
|
|
|
|
|
echo "$size"
|
|
|
|
}
|
|
|
|
|
|
|
|
compute-minimal-size() {
|
|
|
|
local size=0
|
|
|
|
(
|
|
|
|
cd files
|
|
|
|
# Size rounded in blocks. This assumes all files are to be rounded to a
|
|
|
|
# multiple of blockSize.
|
|
|
|
# Use of `--apparent-size` is to ensure we don't get the block size of the underlying FS.
|
|
|
|
# Use of `--block-size` is to get *our* block size.
|
|
|
|
size=$(find . ! -type d -exec 'du' '--apparent-size' '--block-size' "$blockSize" '{}' ';' | cut -f1 | sum-lines)
|
|
|
|
echo "Reserving $size sectors for files..." 1>&2
|
|
|
|
|
|
|
|
# Adds one blockSize per directory, they do take some place, in the end.
|
|
|
|
# FIXME: write test to confirm this assumption
|
|
|
|
local directories=$(find . -type d | wc -l)
|
|
|
|
echo "Reserving $directories sectors for directories..." 1>&2
|
|
|
|
|
|
|
|
size=$(( directories + size ))
|
|
|
|
|
|
|
|
size=$((size * blockSize))
|
|
|
|
|
|
|
|
${if computeMinimalSize == null then "" else computeMinimalSize}
|
|
|
|
|
|
|
|
size=$(( size + ${toString extraPadding} ))
|
|
|
|
|
|
|
|
echo "$size"
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
image-builder: makeFilesystem: reviews minimum size with blockSize
First of all, `du -s` will always combine the sizes into the multiple of
its given --block-size, so 4×1 byte files will show up as 1 block size
(assuming a block size > 4). The expected size would have been at least
one block size per file, so for 512, 512×4 thus 2048.
With this change, we sum the sizes ourselves.
This adds a new requirement to the filesystems, that they pass the block
size to the generic builder, though this is good, as it will increases
reproducibility. In addition, filesystems can present the option to
users, allowing the user to set their block sizes as expected.
2019-09-02 23:29:07 +03:00
|
|
|
sum-lines() {
|
|
|
|
local acc=0
|
|
|
|
while read -r number; do
|
|
|
|
acc=$((acc+number))
|
|
|
|
done
|
|
|
|
|
|
|
|
echo "$acc"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-08-27 21:14:47 +03:00
|
|
|
# The default stdenv/generic clashes with `runHook`.
|
|
|
|
# It doesn't override as expected.
|
|
|
|
unset -f checkPhase
|
|
|
|
|
|
|
|
mkdir -p $out
|
2019-08-29 04:31:33 +03:00
|
|
|
mkdir -p files
|
2019-08-27 21:14:47 +03:00
|
|
|
|
2019-08-29 03:50:28 +03:00
|
|
|
${optionalString (populateCommands != null) ''
|
|
|
|
echo
|
|
|
|
echo "Populating disk image"
|
|
|
|
echo
|
|
|
|
(
|
|
|
|
cd files
|
|
|
|
${populateCommands}
|
|
|
|
)
|
|
|
|
''}
|
2019-08-29 04:31:33 +03:00
|
|
|
${optionalString (size == null) ''
|
2019-09-04 07:48:58 +03:00
|
|
|
size=$(compute-minimal-size)
|
2019-08-29 04:31:33 +03:00
|
|
|
''}
|
|
|
|
|
2019-08-29 04:54:12 +03:00
|
|
|
if (( size < minimumSize )); then
|
|
|
|
size=$minimumSize
|
2019-09-04 07:48:58 +03:00
|
|
|
echo "WARNING: the '$partName' partition was too small, size increased to $minimumSize bytes."
|
2019-08-29 04:31:33 +03:00
|
|
|
fi
|
2019-08-29 03:50:28 +03:00
|
|
|
|
2019-08-27 21:14:47 +03:00
|
|
|
echo
|
|
|
|
echo "Building partition ${partName}"
|
2019-08-29 04:31:33 +03:00
|
|
|
echo "With ${if size == null
|
|
|
|
then "automatic size ($size bytes)"
|
|
|
|
else "$size bytes"
|
|
|
|
}"
|
2019-08-27 21:14:47 +03:00
|
|
|
echo
|
|
|
|
|
|
|
|
echo " -> Allocating space"
|
2019-08-29 04:31:33 +03:00
|
|
|
truncate -s $size "$img"
|
2019-08-27 21:14:47 +03:00
|
|
|
|
|
|
|
echo " -> Making filesystem"
|
|
|
|
runHook filesystemPhase
|
|
|
|
|
|
|
|
echo " -> Copying files"
|
2019-08-29 04:31:33 +03:00
|
|
|
(
|
|
|
|
cd files
|
|
|
|
runHook copyPhase
|
|
|
|
)
|
2019-08-27 21:14:47 +03:00
|
|
|
|
|
|
|
echo " -> Checking filesystem"
|
|
|
|
echo "$checkPhase"
|
|
|
|
runHook checkPhase
|
|
|
|
|
2020-03-31 07:33:16 +03:00
|
|
|
if [ -n "$postProcess" ]; then
|
|
|
|
echo "-> Running post-processing"
|
|
|
|
runHook postProcess
|
|
|
|
fi
|
2019-08-31 05:43:30 +03:00
|
|
|
'';
|
2019-08-28 22:02:32 +03:00
|
|
|
|
2019-08-27 21:14:47 +03:00
|
|
|
})
|
|
|
|
# mkdir -p $out/nix-support
|
|
|
|
# cat ${writeText "${name}-metadata" (builtins.toJSON {
|
|
|
|
# inherit size;
|
|
|
|
# })} > $out/nix-support/partition-metadata.json
|
|
|
|
|
2019-08-29 03:50:28 +03:00
|
|
|
/* */ ;}; in scope."fileSystem.makeFilesystem"
|