Search code examples
fuseappimageunionfsappimage-builder

Using unionfs from inside an appimage


I'm creating an overlay FS (using unionfs-fuse) from a script in an AppImage (created with appimage-builder v0.9.2).
The overlay is mounted successfully, but at the end of the script, it fails to unmount properly with 'Operation not permitted'.
After the AppImage has ended though, fusermount -u works fine.

Here is the script script.sh:

#!/bin/sh

ROOT_DIR=$(mktemp -d -t test-XXXXXX)
myUID=$(id -u)
myGID=$(id -g)
USER_DIR=/tmp/a
mkdir -p ${USER_DIR}

echo "Hello world!" > ${USER_DIR}/hello.txt

# create an overlay of $USER_DIR (rw) over $APPDIR (ro) into $ROOT_DIR
UNIONFS="unionfs -o cow,uid=${myUID},gid=${myGID} ${USER_DIR}=RW:${APPDIR} ${ROOT_DIR}"
if ! $( ${UNIONFS} ); then
    echo "mount failed!"
    exit 1
fi
echo "overlay created in ${ROOT_DIR}"

# files in $USER_DIR may be read/written from the overlay
cat ${ROOT_DIR}/hello.txt

# unmount overlay before closing the AppImage
fusermount -zu ${ROOT_DIR}
rmdir ${ROOT_DIR}

Here is the AppImage recipe AppImageBuilder.yml:

version: 1

AppDir:
  path: /home/user/bugreport

  app_info:
    id: org.appimage.test
    name: AppimageTest
    icon: terminal
    version: 0.0.1
    exec: bin/dash
    exec_args: "script.sh"

  apt:
    arch: amd64
    sources:
      - sourceline: 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ bionic main restricted universe multiverse'
        key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3b4fe6acc0b21f32'
      - sourceline: 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ bionic-updates main restricted universe multiverse'
      - sourceline: 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ bionic-backports main restricted universe multiverse'

    include: [unionfs-fuse, dash, coreutils]
    exclude: []

AppImage:
  arch: x86_64
  update-information: None
  sign-key: None

(a random icon file is also required in terminal.png to build the AppImage).

The AppImage was built using:

$ appimage-builder --recipe ./AppImageBuilder.yml

Any help would be appreciated!


Solution

  • A workaround is:

    • start unionfs with option auto_unmount
    • instead of fusermount -u, kill the last unionfs process with pkill -nf ${ROOT_DIR}
      (kills the most recent process that has ${ROOT_DIR} in its arguments)

    The resulting script:

    #!/bin/sh
    
    ROOT_DIR=$(mktemp -d -t test-XXXXXX)
    myUID=$(id -u)
    myGID=$(id -g)
    USER_DIR=/tmp/a
    mkdir -p ${USER_DIR}
    
    echo "Hello world!" > ${USER_DIR}/hello.txt
    
    # create an overlay of $USER_DIR (rw) over $APPDIR (ro) into $ROOT_DIR
    UNIONFS="unionfs -o cow,auto_unmount,uid=${myUID},gid=${myGID} ${USER_DIR}=RW:${APPDIR} ${ROOT_DIR}"
    if ! $( ${UNIONFS} ); then
        echo "mount failed!"
        exit 1
    fi
    echo "overlay created in ${ROOT_DIR}"
    
    # files in $USER_DIR may be read/written from the overlay
    cat ${ROOT_DIR}/hello.txt
    
    # killing unionfs will unmount the overlay
    pkill -nf ${ROOT_DIR}
    sleep 0.1
    rmdir ${ROOT_DIR}