-
Notifications
You must be signed in to change notification settings - Fork 1
/
pelf-dwfs
executable file
·369 lines (319 loc) · 14.5 KB
/
pelf-dwfs
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
#!/bin/sh
# Create a temporary directory for bundling the files
_VAR_WORKDIR="/tmp/pelf_$(date '+%s%M%S')"
_VAR_TO_BE_BUNDLED="$_VAR_WORKDIR/blob"
mkdir -p "$_VAR_TO_BE_BUNDLED" || exit 1
# Trap all termination signals
trap 'rm -rf "$_VAR_WORKDIR"' INT TERM HUP QUIT EXIT
#
# Exit with error message
error() {
printf >&2 "ERROR: %s\n" "$*"
exit 1
}
# Check if the required arguments are provided
if [ "$#" -lt 3 ]; then
error "Usage: $0 [--add-appdir [AppDir] EXE_NAME]|[--output-to OUTPUT.AppBundle]|<--embed-static-tools>]"
fi
# Throw an error if any of these are missing
for cmd in mkdwarfs dwarfs fusermount; do
if ! command -v "$cmd" >/dev/null 2>&1; then
error "$cmd could not be found. Please install it and try again"
fi
done
# Function to handle file/directory existence checks and operations
check_and_process() {
FPATH="$1"
ACTION="$2"
if [ -e "$FPATH" ]; then
eval "$ACTION" "$FPATH"
else
echo "$FPATH does not exist." >&2
exit 1
fi
}
# Process arguments
while [ "$#" -gt 0 ]; do
case "$1" in
--output-to)
_VAR_OUT_FILE="$2"
shift 2
;;
--compression)
_VAR_COMPRESS_ARG="$2"
shift 2
;;
--add-appdir)
if [ "$_VAR_APPDIR_MODE" = "true" ]; then
echo "--add-appdir cannot be used more than 1 time" >&2
exit 1
fi
__APPDIR="${2:-}"
if [ -d "$__APPDIR" ]; then
_VAR_MAIN_BINARY="$3"
if [ -z "$_VAR_MAIN_BINARY" ]; then
error "You must specify an ID for this binary (usually, the name of the main program is just fine)"
elif [ "$_VAR_MAIN_BINARY" = "AppRun" ]; then
error "The ID of this binary cannot be named 'AppRun'."
fi
if [ ! -f "$__APPDIR/AppRun" ]; then
echo "This AppDir does not contain an AppRun" >&2
if [ -f "./AppRun.generic" ]; then
echo "Copying a generic AppRun" >&2
cp ./AppRun.generic "$__APPDIR/AppRun"
else
echo "Downloading a generic AppRun..." >&2
wget -q -O "$__APPDIR/AppRun" "https://raw.githubusercontent.com/Samueru-sama/deploy/main/AppRun" || {
error "Failed to download AppRun."
}
fi
chmod +x "$__APPDIR/AppRun"
fi
_VAR_APPDIR_MODE="true"
check_and_process "$__APPDIR" "true" && \
find "$__APPDIR" -mindepth 1 -maxdepth 1 | while IFS= read -r item; do
cp -a "$item" "${_VAR_TO_BE_BUNDLED}/"
done
shift 3
else
error "[$__APPDIR] is not an existing directory"
fi
;;
--embed-static-tools)
EMBED_STATIC_TOOLS="1"
shift 1
;;
*)
echo "Unrecognized argument: $1" >&2
exit 1
;;
esac
done
# Create a DWFS archive of the executable, libraries and additional files
[ -n "$_VAR_COMPRESS_ARG" ] || _VAR_COMPRESS_ARG="--max-lookback-blocks=5 --no-history --compression zstd:level=22" #_VAR_COMPRESS_ARG="--max-lookback-blocks=5 --categorize=pcmaudio --compression pcmaudio/waveform::flac:level=8"
# shellcheck disable=SC2086
if ! mkdwarfs --input "$_VAR_TO_BE_BUNDLED" --output "$_VAR_WORKDIR/archive.dwfs" --progress=ascii $_VAR_COMPRESS_ARG; then
error "Compression failed"
fi
# Create a self-extracting archive
_VAR_HOST_INFO="$(uname -mrspv)"
CONST_VERSION="1.8_dwfs_raw" # (vanilla)
# Generate the loader script with conditional LD_LIBRARY_PATH replacements
LOADER_SCRIPT=$(sed -e "s|__ENTRY_POINT__|${_VAR_MAIN_BINARY##*/}|g" \
-e "s|__PELF_VERSION__|${CONST_VERSION}|g" \
-e "s|__PELF_HOST__|${_VAR_HOST_INFO}|g" <<'_END_OF_LOADER_SCRIPT'
#!/bin/sh
# This file was automatically generated by PELF. Find out more about it here: https://github.com/xplshn/pelf
# Please DO NOT EDIT this file, unless you are testing for changes/fixes. If you found the need to modify
# PELF's behavior, submit a PR of your "PELF EDITION" if you think it is appropiate. -
# NOTE: The only way to make changes to this file is by using a `vi` implementation like Busybox's, which respects non-visible characters
# Get the binary's name
[ -n "$EXE_NAME" ] || EXE_NAME="__ENTRY_POINT__"
# rEXE_NAME can be used as a variable name :)
rEXE_NAME="$(echo "$EXE_NAME" | tr -dc '[:alnum:]_' | tr '[:upper:]' '[:lower:]')"
# Important variables
_VAR_BUNDLE_DIR="${TMPDIR:-/tmp}/.pelfbundles" # Temporary pool directory
_VAR_BWORK_DIR="${_VAR_BUNDLE_DIR}/pbundle_${rEXE_NAME}$(date '+%s%M%S')_${RANDOM}" # Temporary work directory
_VAR_MOUNT_DIR="$_VAR_BWORK_DIR/mounted" # Temporary directory for mounting
_VAR_ARCHIVE="$_VAR_BWORK_DIR/archive.dwfs" # The DwarFS archive in case we do base64 thingies
_VAR_EXEC_FILE="${_VAR_MOUNT_DIR}/AppRun" # The file to execute
mkdir -p "$_VAR_BWORK_DIR"
# Log messages to stderr
log() {
echo >&2 "$*"
}
# Exit with error message
error() {
printf >&2 "ERROR: %s\n" "$*"
exit 1
}
# Check if dwarfs is available
check_fuse() {
# Check if dwarfs AND fusermount is available in the system PATH
if command -v dwarfs >/dev/null && command -v fusermount >/dev/null; then
return
fi
# If either dwarfs or fusermount is not available, check if they are bundled in the script
__STATIC_TOOLS_ARCHIVE_MARKER=$(awk '/^__STATIC_TOOLS__/ { print NR + 1; exit }' "$0") || error "Failed to locate static tools marker in the script."
if [ -z "$__STATIC_TOOLS_ARCHIVE_MARKER" ]; then
error "Failed to locate static tools marker in the script. No static tools where bundled and your system lacks dwarfs"
fi
_VAR_STATIC_TOOLS_DIR="$_VAR_BWORK_DIR/static/$(uname -om | tr ' ' '_')"
# Ensure the directory for extracted tools exists
mkdir -p "$_VAR_STATIC_TOOLS_DIR" || error "Failed to create directory $_VAR_STATIC_TOOLS_DIR"
# Extract the bundled tar archive
tail -n +"$__STATIC_TOOLS_ARCHIVE_MARKER" "$0" | base64 -d 2>/dev/null | tar -xzf - -C "$_VAR_STATIC_TOOLS_DIR" || error "Failed to extract tar archive."
# Add the extracted tools to PATH
PATH="$PATH:$_VAR_STATIC_TOOLS_DIR" || error "Failed to update PATH with the extracted tools."
# Check again if either dwarfs or fusermount is available
if command -v dwarfs >/dev/null || command -v fusermount >/dev/null; then
return
fi
error "Neither dwarfs nor fusermount are available in the system and were not found in the bundled archive."
}
# Mount the DwarFS archive from an offset in the script
mount_dwarfs() {
check_fuse
# Mount the embedded DwarFS archive using the offset
mkdir -p "$_VAR_MOUNT_DIR" && \
dwarfs -o offset="auto",ro "$0" "$_VAR_MOUNT_DIR" >/dev/null 2>&1 || error "Failed to mount DwarFS archive."
}
# Main function to handle the logic
main() {
# Check if we need to mount the dwarfs archive
# if [ "$_VAR_FOUND_RUNNING_INSTANCE" != "1" ] && [ "$PELF_REUSE_INSTANCES" != "1" ]; then
mount_dwarfs && touch "${_VAR_BWORK_DIR}/.$$"
# fi
cleanup() {
count() {
[ -e "$1" ] \
&& printf '%s\n' "$#" \
|| printf '%s\n' 0
}
## If the process that created & mounted the "$_VAR_MOUNT_DIR" is not this one (us), refuse to clean up
#_OWNER_OF_MOUNT_DIR="$(basename ""$(dirname "$_VAR_MOUNT_DIR")"/.$$")" # PID OF THE OWNER OF THE MOUNT_DIR
#if [ "$_OWNER_OF_MOUNT_DIR" = "$$" ]; then
fusermount -uz "$_VAR_MOUNT_DIR" 2>/dev/null
rm -rf "$_VAR_BWORK_DIR" 2>/dev/null || true
# Check if .pelfbundles is empty and remove it if so
if [ -d "$_VAR_BUNDLE_DIR" ] && [ "$(count "$_VAR_BUNDLE_DIR")" -eq 0 ]; then
rmdir "$_VAR_BUNDLE_DIR"
fi
#fi
}
# Set up cleanup trap
trap 'cleanup' INT TERM HUP QUIT EXIT
_BIN_DIRs="$_VAR_MOUNT_DIR/bin:$_VAR_MOUNT_DIR/usr/bin"
_LIB_DIRs="$_VAR_MOUNT_DIR/lib:$_VAR_MOUNT_DIR/usr/lib:$_VAR_MOUNT_DIR/lib64:$_VAR_MOUNT_DIR/usr/lib64:$_VAR_MOUNT_DIR/lib32:$_VAR_MOUNT_DIR/usr/lib32:$_VAR_MOUNT_DIR/libx32:$_VAR_MOUNT_DIR/usr/libx32"
# Add extra binaries to the PATH if they exist
if [ "$_VAR_FOUND_RUNNING_INSTANCE" != "1" ]; then
# Export directories with transformed variable names
export "${rEXE_NAME}_binDir=$_BIN_DIRs"
export "${rEXE_NAME}_libDir=$_LIB_DIRs"
export "${rEXE_NAME}_mountDir=$_VAR_MOUNT_DIR"
fi
# Figure out what we do
case "$1" in
--pbundle_help)
printf "This bundle was generated automatically by PELF __PELF_VERSION__, the machine on which it was created has the following \"uname -mrspv\":\n %s \n" "__PELF_HOST__"
printf "Usage:\n <|--pbundle_help|--pbundle_list|--pbundle_link <binary>|--pbundle_pngIcon|--pbundle_svgIcon|--pbundle_desktop|--pbundle_genThumbnail|--pbundle_mount|> <args...>\n"
exit 1
;;
--pbundle_list)
ls -FAl "$_VAR_MOUNT_DIR" && \
ls -FAl "$_BIN_DIRs" && \
test -d "$_LIB_DIRs" && ls -FAl "$_LIB_DIRs"
exit 1
;;
--pbundle_link)
# NOTE: This would be under execute_file, except LD_LIBRARY_PATH MUSTN'T be set when using an AppRun, but we do need this var in order to run a binary manually
if [ "$PELF_NO_LD_VAR" != "1" ]; then
if [ -z "$LD_LIBRARY_PATH" ] ; then
LD_LIBRARY_PATH="$_LIB_DIRs"
else
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$_LIB_DIRs"
fi
export LD_LIBRARY_PATH
fi
_VAR_EXEC_FILE="$2"
shift 2
;;
--pbundle_pngIcon)
if [ -f "$_VAR_MOUNT_DIR/.DirIcon" ]; then
base64 "$_VAR_MOUNT_DIR/.DirIcon"
exit 0
else
exit 1
fi
;;
--pbundle_svgIcon)
if [ -f "$_VAR_MOUNT_DIR/.DirIcon.svg" ]; then
base64 "$_VAR_MOUNT_DIR/.DirIcon.svg"
exit 0
else
exit 1
fi
;;
--pbundle_desktop)
desktop_found=false
for file in "$_VAR_MOUNT_DIR"/*.desktop; do
if [ -e "$file" ]; then
desktop_found=true
base64 "$file"
exit 0
fi
done
exit 1
;;
--pbundle_genThumbnail)
if [ -f "$_BIN_DIRs/.pelf_thumbgen" ]; then
if [ -f "$_VAR_MOUNT_DIR/.DirIcon" ]; then
"$_BIN_DIRs/.pelf_thumbgen" "$0" "$_VAR_MOUNT_DIR/.DirIcon"
exit 0
else
echo "$_VAR_MOUNT_DIR/.DirIcon does not exist"
fi
else
echo "Sorry, this bundle does not contain .pelf_thumbgen, add that binary if you wish to enable this functionality. (github.com/xplshn/pelf/tree/master/cmd/misc/thumbgen)"
fi
exit 1
;;
esac
# Execute the specified file from the mounted directory
execute_file() {
# Add directories to that do exists to the xPATH
[ -d "$_VAR_MOUNT_DIR/bin" ] && xPATH="${xPATH:+$xPATH:}$_VAR_MOUNT_DIR/bin"
[ -d "$_VAR_MOUNT_DIR/usr/bin" ] && xPATH="$_VAR_MOUNT_DIR/usr/bin"
# Update PATH based on PBUNDLE_OVERTAKE_PATH
if [ "$PBUNDLE_OVERTAKE_PATH" = 1 ]; then
PATH="$xPATH${PATH:+:$PATH}"
else
PATH="${PATH:+$PATH:}$xPATH"
fi
export PATH
# Append to XDG_DATA_DIRS if it exists and we have ./share || ./usr/share directories
if [ -n "$XDG_DATA_DIRS" ]; then
[ -d "$_VAR_MOUNT_DIR/share" ] && XDG_DATA_DIRS="$XDG_DATA_DIRS:$_VAR_MOUNT_DIR/share"
[ -d "$_VAR_MOUNT_DIR/usr/share" ] && XDG_DATA_DIRS="$XDG_DATA_DIRS:$_VAR_MOUNT_DIR/usr/share"
fi
export XDG_DATA_DIRS
# Utility variables for scripting/AppRuns/wrappers
export SELF_TEMPDIR="$_VAR_MOUNT_DIR"
export SELF="$0" # Like ARGV0 in AppImages
if ! command -v "$_VAR_EXEC_FILE" >/dev/null 2>&1; then
error "[$2] does NOT exist. It is not contained here nor is it available in the user's PATH"
fi
# Proceed to execute the packed ENTRY POINT binary
"$_VAR_EXEC_FILE" "$@"
EXE_NAME_PID="$!"
}
execute_file "$@"
}
main "$@"
exit $?
_END_OF_LOADER_SCRIPT
)
# Create RUNTIME
echo "$LOADER_SCRIPT" > "$_VAR_OUT_FILE"
embed_static_tools() {
_VAR_STATIC_TOOLS_DIR="$_VAR_WORKDIR/static/$(uname -om | tr ' ' '_')"
# Create the static tools directory
mkdir -p "$_VAR_STATIC_TOOLS_DIR" || error "Failed to create directory $_VAR_WORKDIR/static"
# Copy static tools to the directory
if ! cp "$(which fusermount)" "$(which dwarfs)" "$_VAR_STATIC_TOOLS_DIR"; then
error "Failed to copy static tools"
fi
# Create the tar archive
if ! tar -C "$_VAR_STATIC_TOOLS_DIR" -czf "$_VAR_WORKDIR/static.tgz" .; then
error "Compression of static tools failed"
fi
# Append the marker and the tar archive to the output file
printf "\n__STATIC_TOOLS__\n" >> "$_VAR_OUT_FILE" || error "Failed to write marker (TAR) to output file"
base64 <"$_VAR_WORKDIR/static.tgz" >> "$_VAR_OUT_FILE" || error "Failed to append TAR archive to output file"
}
[ -n "$EMBED_STATIC_TOOLS" ] && embed_static_tools
# Append the DWFS archive to the self-extracting script
printf "\n__ARCHIVE_MARKER__\n" >> "$_VAR_OUT_FILE" || error "Failed to write marker (DWFS) to output file"
cat <"$_VAR_WORKDIR/archive.dwfs" >> "$_VAR_OUT_FILE" || error "Failed to append DWFS archive to output file"
# Make the self-extracting script executable
chmod +x "$_VAR_OUT_FILE" || error "Could not mark output file as executable"