about summary refs log tree commit diff
path: root/pkgs/games/build-support/setup-hooks/make-sandbox.sh
blob: 7779234f5b3ce5a4475c1fe770d110c5c99807a4 (plain) (blame)
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
sandbox_params_include="$(mktemp --suffix=.c)"
trap "rm -f '$sandbox_params_include'" EXIT
sandbox_references=""

hasReference() {
    local ref
    for ref in $sandbox_references; do
        if [ "$1" = "$ref" ]; then return 0; fi
    done

    return 1
}

addReference() {
    local toAdd="$1"

    sandbox_references="$sandbox_references $toAdd"

    echo 'if (!bind_mount("'"$toAdd"'", true)) return false;' \
        >> "$sandbox_params_include"
}

gatherReferencesRecursive() {
    local path="$1"

    if hasReference "$path"; then return; fi
    addReference "$path"

    local valid_hash='[0-9a-df-np-sv-z]\{32\}'
    local valid_name='[A-Za-z0-9+_?=-][A-Za-z0-9+._?=-]*'
    local valid_path="$NIX_STORE/$valid_hash-$valid_name"

    local hashpaths="$(
        find "$path" -type f -exec grep -hao "$valid_path" {} +
        find "$path" -type l -exec readlink {} +
    )"

    local hashpath
    for hashpath in $hashpaths; do
        local realsp
        for realsp in "$NIX_STORE"/*; do
            if echo "$hashpath" | grep -q -m 1 "^${realsp//./\\.}"; then
                gatherReferencesRecursive "$realsp"
                break
            fi
        done
    done
}

gatherReferences() {
    [ -z "$sandbox_references" ] || return 0

    echo 'static bool setup_app_paths(void) {' > "$sandbox_params_include"

    for output in $outputs; do
        [ -e "${!output}" ] || continue
        gatherReferencesRecursive "${!output}"
    done

    if [ -n "$extraSandboxPaths" ]; then
        local oldIfs="$IFS"
        IFS=':!*!:'
        local extra
        for extra in $extraSandboxPaths; do
            local extraC="$(echo "$extra" | sed -e 's/"\\/\\&/g')"
            echo 'if (!extra_mount("'"$extraC"'")) return false;' \
                >> "$sandbox_params_include"
        done
        IFS="$oldIfs"
    fi

    echo 'return true; }' >> "$sandbox_params_include"
    cat "$sandbox_params_include"
}

wrapSandbox() {
    local progname="$1"
    local wrapped="$2"
    local output="$3"

    @gcc@/bin/gcc -g -std=gnu11 -Wall \
        -DWRAPPED_PATH=\""$wrapped"\" \
        -DWRAPPED_PROGNAME=\""$progname"\" \
        -DPARAMS_FILE=\""$sandbox_params_include"\" \
        -o "$output" @sandbox_main@
}

makeSandbox() {
    gatherReferences

    for output in $outputs; do
        [ -e "${!output}" ] || continue
        local bin
        for bin in "${!output}"/bin/*; do
            local binbase="$(basename "$bin")"
            local newdest="$(dirname "$bin")/.$binbase-wrapped"
            mv "$bin" "$newdest"
            wrapSandbox "$binbase" "$newdest" "$bin"
        done
    done
}

postFixupHooks+=(makeSandbox)