Skip to content

Commit 4ed69c0

Browse files
authored
Merge pull request #35 from ValShaped/dev
Rwfus v0.4.2
2 parents 1839898 + be6bb4a commit 4ed69c0

File tree

12 files changed

+214
-71
lines changed

12 files changed

+214
-71
lines changed

.shellcheckrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
source-path=SCRIPTDIR/
22
source-path=SCRIPTDIR/rwfus_include
3+
# Disable unassigned variable lint
4+
disable=2154

documentation/naming-conventions.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ There are three kinds of variable used in this project:
66
- `local_variables`
77
- These are used to store temporary information, and are used as if they're scoped. They're not scoped. Bash isn't a programming language.
88
- When possible, use these with the local keyword.
9+
- `cf_Global`
10+
- These are variables *set by config.sh* for use in other scripts. Please do not set them outside config.sh.
911
- `Global_Configuration_Variables`
10-
- These are used to store information that needs to be easily accessible by everything. Generally related to the config file.
12+
- These are used to store information that needs to be easily accessible by everything. Generally set by info.sh
13+
1114
- `GLOBAL_STATE_FLAGS`
12-
- These are used when a variable needs to persist between runs of a single function, and carry information about the so-called-program state
15+
- These are used when a variable needs to persist between runs of a non-reentrant function, and carry information about the so-called-program state

documentation/rwfus.conf.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# /etc/opt/rwfus.conf
2+
3+
### Common
4+
| Field | Explanation | Default |
5+
|---------------------|------------------|------------------------------------------------------|
6+
| `Directories` | Overlay paths | /usr /etc/pacman.d /var/lib/pacman /var/cache/pacman |
7+
| `Base_Directory` | Install path | /opt/rwfus |
8+
### Service
9+
| Field | Explanation | Default |
10+
|---------------------|------------------|------------------------------------------------------|
11+
| `Stop_Units` | Units to stop | var-cache-pacman.mount |
12+
| `Mask_Units` | Units to mask | pacman-cleanup.service |
13+
| `Restart_Units` | Units to restart | usr-local.mount polkit.service |
14+
### Overlay
15+
| Field | Explanation | Default |
16+
|---------------------|----------------------------------------------|--------------------------|
17+
| `Upper_Directory` | Source for overlay's files | /opt/rwfus/mount/upper |
18+
| `Work_Directory` | OverlayFS requires space for temporary files | /opt/rwfus/mount/work |
19+
### Disk
20+
| Field | Explanation | Default |
21+
|---------------------|------------------------------|------------------------------------------|
22+
| `Mount_Options` | Btrfs mount options | loop,compress |
23+
| `Mount_Directory` | Path to mount disk into | /opt/rwfus/mount |
24+
| `Disk_Image_Path` | Path to disk image | /opt/rwfus/rwfus.btrfs |
25+
| `Disk_Image_Size` | Maximum size of image | 8G |
26+
### Configurator
27+
| Field | Explanation | Default |
28+
|---------------------|------------------------------|------------------------------------------|
29+
| `Systemd_Directory` | Systemd units go here | /etc/systemd/system |
30+
| `Service_Directory` | `rwfusd` script goes here | /opt/rwfus/service |
31+
| `Install_Directory` | Where `rwfus -I` installs to | /home/.steamos/offload/usr/local/bin |
32+
| `Logfile` | Log file path | /var/log/rwfus.log |
33+
34+
# Additional Configuration
35+
| Field | Type | Default | Reason not included in config file |
36+
|---------------|-------------|---------------------|---------------------------------------------------|
37+
| `Config_File` | Config path | /etc/opt/rwfus.conf | Can't find config file if this option is changed. |
38+
39+
40+
# Examples
41+
```conf
42+
# Generated by Rwfus v0.4.1
43+
44+
[Common]
45+
# All other paths, if left unspecified, derive from this one
46+
Base_Directory /opt/rwfus
47+
Directories /usr /etc/pacman.d /var/lib/pacman /var/cache/pacman
48+
49+
[Service]
50+
# Units to [Stop|Mask|Restart] while Rwfus is running
51+
Stop_Units var-cache-pacman.mount
52+
Mask_Units pacman-cleanup.service
53+
Restart_Units usr-local.mount
54+
55+
[Overlay]
56+
# Where the overlayfs upperdirs and lowerdirs go
57+
Upper_Directory /opt/rwfus/mount/upper
58+
Work_Directory /opt/rwfus/mount/work
59+
60+
[Disk]
61+
# Btrfs mount options. Make sure you keep `loop`
62+
Mount_Options loop,compress
63+
Mount_Directory /opt/rwfus/mount
64+
# Path to the disk image
65+
Disk_Image_Path /opt/rwfus/rwfus.btrfs
66+
Disk_Image_Size 8G
67+
68+
[Configurator]
69+
# Where systemd expects units to be
70+
Systemd_Directory /etc/systemd/system
71+
# Storage directory for the daemon script and service-unit
72+
Service_Directory /opt/rwfus/service
73+
Install_Directory /home/.steamos/offload/usr/local/bin
74+
# The path to the logfile
75+
Logfile /var/log/rwfus.log
76+
```

readme.md

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
11
## Rwfus: Read-Write OverlayFS for your Steam Deck!
22
---
33

4-
Like a vinyl couch cover for your filesystem, Rwfus covers your Deck's /usr/ directory (and some others) allowing you to initialize and use pacman (the Arch Linux package manager) on the Steam Deck without losing packages when the next update comes out.
4+
Like a vinyl couch cover for your filesystem, Rwfus covers your Deck's /usr/ directory (and some others) allowing you to initialize and use* pacman (the Arch Linux package manager) on the Steam Deck without losing packages when the next update comes out.
55

66
Directories covered in a default installation:
7-
Directory | Contents
8-
--- | ---
9-
/etc/pacman.d | `pacman` configuration
10-
/usr | Programs and libraries
11-
/var/cache/pacman | Package cache
12-
/var/lib/pacman | Package metadata
7+
| Directory | Contents |
8+
| ----------------- | ---------------------- |
9+
| /etc/pacman.d | `pacman` configuration |
10+
| /usr | Programs and libraries |
11+
| /var/cache/pacman | Package cache |
12+
| /var/lib/pacman | Package metadata |
1313

14+
### * Jank warning
15+
16+
Due to the way Valve's firmware updates work, doing `pacman -S[y[y]]u` at any time will lead to complications when the next firmware update is installed. I highly advise avoiding `-Su`, `-Syu`, and `-Syyu` altogether on a Steam Deck with read-only rootfs. It may lead to bad behavior.
17+
18+
Rwfus is, right now, a proof of concept (hence the 0.x version number, and being written in Bash.)
19+
I made it to install a couple user-mode packages (nano-syntax-highlighting and yakuake specifically.)
20+
It is not production-ready software, and in using Rwfus, you accept that I am not liable if your Deck catches fire.
21+
22+
Rwfus will allow you to install *any* package, but not everything will let your Deck survive an update. In particular, `glibc` will crash your Deck after an update, requiring the SteamOS recovery image and some knowledge of Linux and/or Rwfus' internals to fix.
1423

1524
### Installation:
1625

@@ -20,15 +29,14 @@ Directory | Contents
2029

2130
Then you're all set! Remember to periodically run `pacman -Sy` to update your repos
2231

23-
### Jank warning
24-
25-
Due to the way Valve's firmware updates work, doing `pacman -S[y[y]]u` at any time will lead to complications when the next firmware update is installed. I highly advise avoiding `-Su`, `-Syu`, and `-Syyu` altogether on a Steam Deck with read-only rootfs. It may lead to bad behavior.
26-
2732
### Usage:
2833

2934
```
35+
Rwfus v0.4.1
36+
Carry Pacman across SteamOS updates!
37+
3038
USAGE:
31-
rwfus [FLAGS] [OPTIONS] [--] [DIRECTORY]...
39+
./rwfus [FLAGS] [OPTIONS]
3240
3341
FLAGS:
3442
-h, --help Show this help text, then exit
@@ -45,7 +53,7 @@ FLAGS:
4553
--mount* Mount Rwfus's disk image
4654
--umount* Unmount Rwfus's disk image
4755
48-
-I, --install-bin* Put /usr/local/bin/rwfus into a [...]/usr/local/bin folder
56+
-I, --install-bin* Put ./rwfus into a [...]/usr/local/bin folder
4957
-R, --remove-bin* Remove Rwfus from a [...]/usr/local/bin folder
5058
5159
-t, --test Use fake directory targets when performing operations
@@ -55,17 +63,13 @@ FLAGS:
5563
5664
OPTIONS:
5765
-l, --logfile <path> Specify the location of Rwfus's log file
58-
Default: /tmp/rwfus.XXXX.log (where X is random)
66+
Default: /var/log/rwfus.log (where X is random)
5967
-c, --config <path> Specify a configuration file to use
6068
Default: /opt/rwfus/
6169
--backup <dest>* Backup Rwfus's disk image to (file path) <dest>
6270
--restore <src>* Restore Rwfus's disk image from (file path) <src>
6371
6472
* options marked with a star require root, unless the --test flag is set.
65-
66-
ARGS:
67-
<DIRECTORY>... List of directories to create overlays for
68-
Defaults: /usr /etc/pacman.d /var/lib/pacman /var/cache/pacman
6973
```
7074

7175
#### Examples:

rwfus

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ $Name v$Version
4949
$Description
5050
5151
USAGE:
52-
$0 [FLAGS] [OPTIONS] [--] [DIRECTORY]...
52+
$0 [FLAGS] [OPTIONS]
5353
5454
FLAGS:
5555
-h, --help Show this help text, then exit
@@ -83,10 +83,6 @@ FLAGS:
8383
--restore <src>* Restore $Name's disk image from (file path) <src>
8484
8585
* options marked with a star require root, unless the --test flag is set.
86-
87-
ARGS:
88-
<DIRECTORY>... List of directories to create overlays for
89-
Defaults: $cf_Directories
9086
EOF
9187
}
9288

@@ -236,10 +232,14 @@ for operation in ${Operation:=$Default_Operation}; do
236232
config --load
237233
state=$(service_state)
238234
echo "$state"
239-
if [[ "$state" =~ "active" ]]; then
240-
disable_service
235+
if [[ "$state" == "active"* ]]; then
236+
service disable
241237
$operation "$disk_path"
242-
enable_service
238+
case "$operation" in
239+
"backup_disk"|"restore_disk")
240+
service enable
241+
;;
242+
esac
243243
else
244244
$operation "$disk_path"
245245
fi

rwfus_include/config.sh

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# shellcheck shell=bash
33
: <<LICENSE
44
config.sh: Rwfus
5-
Copyright (C) 2022 ValShaped ([email protected])
5+
Copyright (C) 2022-2023 ValShaped ([email protected])
66
77
This library is free software; you can redistribute it and/or
88
modify it under the terms of the GNU Lesser General Public
@@ -46,23 +46,38 @@ CF_DEFAULT=(
4646
# /etc/pacman.d /var/lib/pacman /var/cache/pacman : store pacman state
4747
[cf_Directories]="/usr /etc/pacman.d /var/lib/pacman /var/cache/pacman"
4848
# Default directories (These can be changed in the config file. Run `rwfus --gen-config` to generate an example file.)
49-
[cf_Base_Directory]="/opt/${Name@L}" # Where all the files will go
50-
[cf_Service_Directory]="" # Where generated service will go
51-
[cf_Disk_Image_Path]="" # Where the disk image will go
52-
[cf_Mount_Directory]="" # Where the disk image will be mounted
53-
[cf_Upper_Directory]="" # Where the overlayfs upper dirs will go
54-
[cf_Work_Directory]="" # Where the overlayfs work dirs will go
55-
[cf_Disk_Image_Size]="8G" # Size to make the disk image, when resizing
49+
# Note: Items have been intentionally left blank.
50+
# See function change_base below.
51+
# Where all the files will go
52+
[cf_Base_Directory]="/opt/${Name@L}"
53+
# Where generated service will go
54+
[cf_Service_Directory]=""
55+
# Where the disk image will go
56+
[cf_Disk_Image_Path]=""
57+
# Where the disk image will be mounted
58+
[cf_Mount_Directory]=""
59+
# Where the overlayfs upper dirs will go
60+
[cf_Upper_Directory]=""
61+
# Where the overlayfs work dirs will go
62+
[cf_Work_Directory]=""
5663
# Systemd-related things
57-
[cf_Systemd_Directory]="/etc/systemd/system" # Where systemd expects units to be
58-
[cf_Restart_Units]="usr-local.mount" # Units to restart when daemon starts
59-
[cf_Stop_Units]="var-cache-pacman.mount" # Units to stop when daemon starts and restart when daemon stops
60-
[cf_Mask_Units]="pacman-cleanup.service" # Units to mask when daemon starts and unmask when daemon stops.
61-
62-
[cf_Mount_Options]="loop,compress" # Make sure you keep 'loop', so it creates a loop device
64+
# Where systemd expects units to be
65+
[cf_Systemd_Directory]="/etc/systemd/system"
66+
# Units to restart when daemon starts
67+
[cf_Restart_Units]="usr-local.mount polkit.service"
68+
# Units to stop when daemon starts and restart when daemon stops
69+
[cf_Stop_Units]="var-cache-pacman.mount"
70+
# Units to mask when daemon starts and unmask when daemon stops.
71+
[cf_Mask_Units]="pacman-cleanup.service"
72+
# Disk-related things
73+
# Make sure you keep 'loop', so it creates a loop device
74+
[cf_Mount_Options]="loop,compress"
75+
# Size to make the disk image, when resizing
76+
[cf_Disk_Image_Size]="8G"
77+
78+
# SteamOS Offload offloads /usr/local to /home/.steamos/offload/usr/local
79+
# Beware! This will be considered read-only to overlayfs, so adding stuff while rwfus is enabled is not recommended.
6380

64-
# # SteamOS Offload offloads /usr/local to /home/.steamos/offload/usr/local
65-
# # Beware! This will be considered read-only to overlayfs, so adding stuff while rwfus is enabled is not recommended.
6681
[cf_Install_Directory]="/home/.steamos/offload/usr/local/bin"
6782
)
6883

@@ -108,6 +123,9 @@ CF_TESTPATHS="cf_Base_Directory cf_Service_Directory cf_Mount_Directory
108123
cf_Upper_Directory cf_Work_Directory cf_Install_Directory
109124
cf_Systemd_Directory cf_Disk_Image_Path cf_Config_File cf_Logfile"
110125

126+
# shellcheck disable=SC2034
127+
CF_CONFIGURATIOR=true
128+
111129
# This function loads the default config. Run `rwfus --gen-config` to generate an example file.
112130
function load_defaults {
113131
for cf_option in "${!CF_DEFAULT[@]}"; do
@@ -119,12 +137,12 @@ function load_defaults {
119137
# Derive subdirs of the cf_Base_Directory
120138
function change_base {
121139
# Subdirs of cf_Base_Directory
122-
export cf_Service_Directory="$cf_Base_Directory/service" # Where service will go
140+
export cf_Service_Directory="$cf_Base_Directory/service" # Where service will go
123141
export cf_Disk_Image_Path="$cf_Base_Directory/${Name@L}.btrfs" # Where the disk image will go
124-
export cf_Mount_Directory="$cf_Base_Directory/mount" # Where the disk image will be mounted
142+
export cf_Mount_Directory="$cf_Base_Directory/mount" # Where the disk image will be mounted
125143
# Subdirs of cf_Mount_Directory
126-
export cf_Upper_Directory="$cf_Mount_Directory/upper" # Where the overlayfs upper dirs will go
127-
export cf_Work_Directory="$cf_Mount_Directory/work" # Where the overlayfs work dirs will go
144+
export cf_Upper_Directory="$cf_Mount_Directory/upper" # Where the overlayfs upper dirs will go
145+
export cf_Work_Directory="$cf_Mount_Directory/work" # Where the overlayfs work dirs will go
128146
}
129147

130148
function enable_testmode {
@@ -157,7 +175,7 @@ function construct_config {
157175
for cf_option in ${CF_SECTION[$section]}; do
158176
# Comment line
159177
#Variable Value
160-
printf "%b%-18s %-24s\n" \
178+
printf "%b%-18s %-1s\n" \
161179
"${CF_COMMENT[$cf_option]}" \
162180
"${CF_REQUIRE[$cf_option]-"#"}${cf_option:3}" \
163181
"${!cf_option}"
@@ -190,10 +208,11 @@ function load_config {
190208
# also filter lines which don't contain any non-space characters.
191209
local expression='^[[:space:]]*[^\[\#[:space:]]+'
192210
if [[ "$var" =~ $expression ]]; then
193-
CF_REQUIRE["$var"]=true # Save the loaded option
194-
val="$(echo "$val" | cut -f1 -d# | xargs)" # chop off inline comments
195211
local cf_var="cf_$var"
196-
CF_REQUIRE["$cf_var"]="" # Mark option loaded
212+
if [ "$CF_CONFIGURATOR" ]; then
213+
CF_REQUIRE["$cf_var"]="" # Save the loaded option
214+
fi
215+
val="$(echo "$val" | cut -f1 -d# | xargs)" # chop off inline comments
197216
export "$cf_var"="${val}"
198217
printf "> %s: \"%s\"\n" "$var" "${!cf_var}"
199218
if [[ "$cf_var" = "cf_Base_Directory" ]]; then
@@ -206,7 +225,6 @@ function load_config {
206225
done < "$config_file"
207226
CONFIG_LOADED=true
208227
if [ "$TESTMODE" ]; then enable_testmode ./test; fi
209-
echo
210228
}
211229

212230
function config {

rwfus_include/disk.sh

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
#!/bin/false
12
# shellcheck shell=bash
23
: <<LICENSE
34
disk.sh: Rwfus
4-
Copyright (C) 2022 ValShaped ([email protected])
5+
Copyright (C) 2022-2023 ValShaped ([email protected])
56
67
This library is free software; you can redistribute it and/or
78
modify it under the terms of the GNU Lesser General Public
@@ -22,6 +23,13 @@ LICENSE
2223
source "$IncludeDir/testlog.sh"
2324

2425
function mount_disk {
26+
# Wait up to 3 seconds!!? for disk to become available
27+
for _i in {1..3}; do
28+
if [ ! -f "$cf_Disk_Image_Path" ]
29+
then sleep 1
30+
else break
31+
fi
32+
done
2533
# Set mount options, if none are specified
2634
mount -vo "${cf_Mount_Options:=loop}" -- "$cf_Disk_Image_Path" "$cf_Mount_Directory" && \
2735
btrfs filesystem resize max "$cf_Mount_Directory"
@@ -98,6 +106,19 @@ function mount_all {
98106
printf "Could not mount disk.\n"
99107
return 255;
100108
fi
109+
# Check for the presence of glibc
110+
# Glibc will cause the Deck to fail boot.
111+
# FIXME: instead of looking for glibc, dynamically detect a failed boot
112+
if [ -f "${cf_Upper_Directory}/usr/include/gnu/libc-version.h" ]; then
113+
printf "GLibC has been installed inside %s's overlay.\
114+
\nYour Deck will likely not survive a SteamOS update.\
115+
\nIn an attempt to preserve your Deck, %s has not mounted any overlays.\
116+
\n\033[1mThis is not a bug. It is an intentional safety measure.\033[0m\
117+
\nThe disk, however, has remained mounted, in case you want to remedy this.\
118+
\nYou may unmount it with \033[1m%s --umount\033[0m\n"\
119+
"${Name}" "${Name}" "${Name@L}"
120+
return 254;
121+
fi
101122
for target in $cf_Directories; do
102123
local escaped; escaped=$(systemd-escape -p -- "$target")
103124
local lower="$target"

rwfus_include/info.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
export Name="Rwfus"
44
export Description="Carry Pacman across SteamOS updates!"
55
export Repository="https://github.com/ValShaped/rwfus"
6-
export Version="0.4.1"
6+
export Version="0.4.2"

0 commit comments

Comments
 (0)