Examples¶
FAT and ext partition on GPT¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | import logging import os import simplediskimage logging.basicConfig(level=logging.DEBUG) def main(): image = simplediskimage.DiskImage("foo.img", partition_table='gpt') part_fat = image.new_partition("fat12", partition_flags=["BOOT"], partition_label="EFI System Partition") part_ext = image.new_partition("ext4", filesystem_label="hello") # Allocate some extra data on top of what's taken up by the data on the # ext partition part_ext.set_extra_bytes(16 * simplediskimage.SI.Mi) # Create two directories in the root of each partition part_fat.mkdir("fat1", "fat2") part_ext.mkdir("ext1", "ext2") # Copy the testdata dir into each partition in some interesting ways datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), "testdata")) for part in (part_fat, part_ext): part.copy(os.path.join(datadir, "x"), os.path.join(datadir, "y")) part.mkdir("internet") part.copy(os.path.join(datadir, "internet/z"), destination="internet") part.copy(os.path.join(datadir, "internet/recursive_copy"), destination="internet") image.commit() print("sudo kpartx -av foo.img") print("...") print("sudo kpartx -dv foo.img") if __name__ == '__main__': main() |
Single bootable FAT partition, using sfdisk¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import logging import simplediskimage from common import generate_bb_testdata logging.basicConfig(level=logging.DEBUG) def main(): # Generate test data generate_bb_testdata() # Create image image = simplediskimage.DiskImage("bar.img", partition_table='msdos', partitioner=simplediskimage.Sfdisk) part_fat = image.new_partition("fat16", partition_flags=["BOOT"]) # Copy the files to the root, could also be written: # part_fat.copy("file1", "file2", destination="/"), or without destination part_fat.copy("generated/u-boot.img") part_fat.copy("generated/MLO") # Make sure that the partition is always 48 MiB part_fat.set_fixed_size_bytes(48 * simplediskimage.SI.Mi) image.commit() print("sudo kpartx -av bar.img") print("...") print("sudo kpartx -dv bar.img") if __name__ == '__main__': main() |
Using the NullPartitioner to create a raw image¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import logging import os import simplediskimage logging.basicConfig(level=logging.DEBUG) def main(): image = simplediskimage.DiskImage("null-partitioner.ext4", partition_table='null', partitioner=simplediskimage.NullPartitioner) part = image.new_partition("ext4") # Allocate some extra data on top of what's taken up by the data on the # ext partition part.set_extra_bytes(2 * simplediskimage.SI.Mi) # Create two directories in the root of the partition part.mkdir("ext1", "ext2") # Copy some data from the testdata dir into the image datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), "testdata")) part.copy(os.path.join(datadir, "x"), os.path.join(datadir, "y")) image.commit() print("sudo mount null-partitioner.ext4 /mnt") print("...") print("sudo umount /mnt") if __name__ == '__main__': main() |
Using a raw image as the filesystem for a partition¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | import logging import os import simplediskimage from common import generate_bb_testdata logging.basicConfig(level=logging.DEBUG) def main(): ext4_source = "./null-partitioner.ext4" # Make sure the raw ext4 image has been created by running the # null-partitioner example if not os.path.exists(ext4_source): print("Run the null-partitioner.py example first") # Generate test data generate_bb_testdata() # Create image image = simplediskimage.DiskImage("raw-filesystem-on-p2.img", partition_table='msdos', partitioner=simplediskimage.Sfdisk) part_fat = image.new_partition("fat16", partition_flags=["BOOT"]) part_ext = image.new_partition("ext4", raw_filesystem_image=True) # Copy the files to the root, could also be written: # part_fat.copy("file1", "file2", destination="/"), or without destination part_fat.copy("generated/u-boot.img") part_fat.copy("generated/MLO") # Make sure that the partition is always 48 MiB part_fat.set_fixed_size_bytes(48 * simplediskimage.SI.Mi) # Copy the ext image into the raw partition part_ext.copy(ext4_source) # The partition can be expanded beyond the size of the image, but beware # the warnings in the documentation before doing something like this! #part_ext.set_extra_bytes(16 * simplediskimage.SI.Mi) image.commit() print("sudo kpartx -av raw-filesystem-on-p2.img") print("...") print("sudo kpartx -dv raw-filesystem-on-p2.img") if __name__ == '__main__': main() |
Initialize a file system using a rootfs archive¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | # This example might look a bit convoluted as we create an archive here just to # extract it in the companion python script, but we are simulating a situation # where a separate build system delivers a tar (might as well be a cpio # archive), which the python script will unpack and use as the basis of a # partition. There are multiple variants to this, for example: # # - The rootfs is delivered as a directory. In this case, the image creation # script might be run in the same fakeroot session, or the -s and -i # arguments to fakeroot may be used. # - The rootfs is created using some python scripts under a fakeroot session. # If so, just add some calls to simplediskimage when the rootfs has been # created to turn it into an image. TEMPDIR=./.rootfs-in-p2.tmp EXAMPLE_USER=nobody if ! id nobody &> /dev/null; then EXAMPLE_USER=$USER fi # Create rootfs.tar, this is usually done in a build system rm -rf $TEMPDIR mkdir $TEMPDIR fakeroot <<EOF set -e cd $TEMPDIR mkdir rootfs mkdir -p rootfs/{root,dev,home/nobody} echo data > rootfs/home/nobody/data chown -R nobody:$(id -gn nobody) rootfs/home/nobody mknod rootfs/dev/null c 1 3 dd if=/dev/urandom bs=1M count=16 of=rootfs/large_file ln rootfs/large_file rootfs/large_file_link tar -cf rootfs.tar -C rootfs . EOF rm -rf $TEMPDIR/rootfs set -x ls $TEMPDIR # Invoke the example under fakeroot fakeroot ./_rootfs-in-p2.py $TEMPDIR rm -rf $TEMPDIR |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | import logging import sys import os import tarfile import simplediskimage from common import generate_bb_testdata logging.basicConfig(level=logging.DEBUG) def main(): # Check our surroundings, we should be: # - Getting the tempdir containing rootfs.tar as the sole argument # - Be executed inside a fakeroot environment if len(sys.argv) != 2 or "FAKEROOTKEY" not in os.environ: print("Don't run me directly, use rootfs-in-p2.sh") sys.exit(1) # Generate some testdata for the boot partition generate_bb_testdata() # Create image image = simplediskimage.DiskImage("rootfs-in-p2.img", partition_table='msdos', partitioner=simplediskimage.Sfdisk) part_fat = image.new_partition("fat16", partition_flags=["BOOT"]) part_ext = image.new_partition("ext4", filesystem_label="root") # Copy files to the boot partition and set a fixed size part_fat.copy("generated/u-boot.img") part_fat.copy("generated/MLO") part_fat.set_fixed_size_bytes(48 * simplediskimage.SI.Mi) # Unpack the rootfs.tar file into a temporary directory temp_dir = sys.argv[1] rootfs_tar = os.path.join(temp_dir, "rootfs.tar") rootfs_dir = os.path.join(temp_dir, "p2-rootfs-dir") with tarfile.open(rootfs_tar, 'r:') as tf: def is_within_directory(directory, target): abs_directory = os.path.abspath(directory) abs_target = os.path.abspath(target) prefix = os.path.commonprefix([abs_directory, abs_target]) return prefix == abs_directory def safe_extract(tar, path=".", members=None, *, numeric_owner=False): for member in tar.getmembers(): member_path = os.path.join(path, member.name) if not is_within_directory(path, member_path): raise Exception("Attempted Path Traversal in Tar File") tar.extractall(path, members, numeric_owner=numeric_owner) safe_extract(tf, rootfs_dir) # Use the rootfs directory as the initial data directory for the second # partition (the rootfs) part_ext.set_initial_data_root(rootfs_dir) image.commit() print("sudo kpartx -av rootfs-in-p2.img") print("...") print("sudo kpartx -dv rootfs-in-p2.img") if __name__ == '__main__': main() |