1# SPDX-License-Identifier:      GPL-2.0+
2#
3# Copyright (c) 2018, Linaro Limited
4# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
5
6"""Helper functions for dealing with filesystems"""
7
8import re
9import os
10from subprocess import call, check_call, check_output, CalledProcessError
11
12def mk_fs(config, fs_type, size, prefix, use_src_dir=False):
13    """Create a file system volume
14
15    Args:
16        config (u_boot_config): U-Boot configuration
17        fs_type (str): File system type, e.g. 'ext4'
18        size (int): Size of file system in bytes
19        prefix (str): Prefix string of volume's file name
20        use_src_dir (bool): true to put the file in the source directory
21
22    Raises:
23        CalledProcessError: if any error occurs when creating the filesystem
24    """
25    fs_img = f'{prefix}.{fs_type}.img'
26    fs_img = os.path.join(config.source_dir if use_src_dir
27                          else config.persistent_data_dir, fs_img)
28
29    if fs_type == 'fat16':
30        mkfs_opt = '-F 16'
31    elif fs_type == 'fat32':
32        mkfs_opt = '-F 32'
33    else:
34        mkfs_opt = ''
35
36    if re.match('fat', fs_type):
37        fs_lnxtype = 'vfat'
38    else:
39        fs_lnxtype = fs_type
40
41    count = (size + 0x100000 - 1) // 0x100000
42
43    # Some distributions do not add /sbin to the default PATH, where mkfs lives
44    if '/sbin' not in os.environ["PATH"].split(os.pathsep):
45        os.environ["PATH"] += os.pathsep + '/sbin'
46
47    try:
48        check_call(f'rm -f {fs_img}', shell=True)
49        check_call(f'dd if=/dev/zero of={fs_img} bs=1M count={count}',
50                   shell=True)
51        check_call(f'mkfs.{fs_lnxtype} {mkfs_opt} {fs_img}', shell=True)
52        if fs_type == 'ext4':
53            sb_content = check_output(f'tune2fs -l {fs_img}',
54                                      shell=True).decode()
55            if 'metadata_csum' in sb_content:
56                check_call(f'tune2fs -O ^metadata_csum {fs_img}', shell=True)
57        return fs_img
58    except CalledProcessError:
59        call(f'rm -f {fs_img}', shell=True)
60        raise
61
62# Just for trying out
63if __name__ == "__main__":
64    import collections
65
66    CNF= collections.namedtuple('config', 'persistent_data_dir')
67
68    mk_fs(CNF('.'), 'ext4', 0x1000000, 'pref')
69