Architecture

This document explains exactly how pafl works. This has been a process I've been thinking about and revising many times over the past few months, and it still most definitely needs improvement, speed increases, security improvements, anything! So if you have any ideas, please post in the forums, I'd love to hear them!

Directory Structure

First of all, let's review the directory structure of a pafl application. We'll take abiword as an example:

AbiWord-Portable/
  blobs/
    abiword-2.8.2.img
    userdata.img
  utils/
    lib/
    mountlo
    fakechroot
    libfakechroot.so
    unionfs-fuse
  app.conf
  abiword

Not too complicated. Let's review what each file is for.

blobs

The blobs directory contains the 'blobs' necessary for pafl to run.

abiword-2.8.2.img is the application blob. This is a squashfs compressed image of the application, containing LSB-like directories (/usr, /lib, /etc and so on).

userdata.img is simply an ext3 filesystem containing the home directory (/home/default), where all the user settings will be stored. When the application is started, the launcher fakes to the application that the user actually logged in is the user default, which means that no matter which computer you put the application in, the settings will remain.

utils

This is the directory where all the utilities necessary to make pafl work are located. We make use of a few filesystem-based utilities to make pafl possible.

mountlo is an interesting project which, with the help of FUSE (Filesystem in Userspace) and UML(User-mode Linux), allows you to mount any filesystem the Linux kernel supports into a directory, without the need for root privileges.

fakechroot (along with libfakechroot.so) is a utility that allows you to chroot into a directory without the need of root privileges.

unionfs-fuse is a utility which allows you to mount multiple directories into a combined directory, known as a union. This is, again, accomplished with FUSE, and does not require root privileges.

lib/ is a directory with a few Perl modules the launcher needs to run.

Launcher

The pieces should be in place by now, but I'll still explain exactly what the launcher does.

app.conf

Before it does anything, it reads the app.conf file. The file should look like this:

[app]
full_name      = OpenOffice.org
unix_name      = openoffice-org
version        = 3.0.1
userdata_space = 3MB

[exe]
executable     = oowriter
Required configuration parameters
  • [app] full_name is what the application is actually called (Abiword, GIMP, OpenOffice.org)
  • [app] unix_name should be what it's referenced to by in Linux: (abiword, gimp, openoffice-org)
  • [app] version is the version of the software
  • [exe] executable is the name of the executable that should run once everything is mounted and ready (it can be a full path, if you wish. abiword or /usr/bin/abiword work fine).
  • [app] userdata_space is a bit more complicated. Set it to however much space the application will need to store user info (/home/default/.something). You might need to do some test runs to figure this out. (The format is xMB, where x can be a multiple of 0.5). Don't worry about being too precise, if the user runs out of space, the launcher will resize userdata. However, try to make sure this doesn't happen. Don't overshoot either. ;-)
Optional configuration parameters
  • [app] beta = true will signal to the launcher to force verbose mode. Use if the application is still in beta.
  • [exe] env_param will set the enviornmental variables specified before running the application. Specify in one string (i.e. ABC=def PATH=/)

Process

After it reads the configuration, it looks for a suitable place on the host computer where it can set itself up. More specifically, it looks for a ext2/3/4 filesystem that it has read-write access to. In 99% of cases, this will be /home/user/.pafl, but if that doesn't work, it'll try /tmp, if that doesn't work, it'll fail. (Anyone have any other ideas for places the launcher should look?) For the purpose of the explanation, we'll assume it has chosen /home/user/.pafl (this is the only option in the current version of the launcher).

Next, it creates a directory for the application (for example, /home/user/.pafl/abiword-2.8.2/). It then creates subdirectories for the mountpoints: abiword/application, abiword/userdata, abiword/union for the application blob, the userdata blob, and the unionfs union, respectively.

Then, it mounts (using mountlo) the userdata blob into the userdata directory, then the application blob into the application directory. The last mount happens with unionfs-fuse. The exact command line we use is:

utils/unionfs-fuse -o cow $mnt_dir/userdata=RW:$mnt_dir/application=RO:/=RW $mnt_dir/union

Dissecting that, we mount (with Copy-on-write mode enabled) the userdata on top, because that's where we want the profile writes to occur. Underneath, we mount the application read-only, because we're not gonna be modifying the application files. Then, we mount / read-write. We need to mount / to have the system libraries, utilities, executables, and so on. We're mounting it read-write so that the application can write to your home directory (save files, copy files from USB drives, etc.) In effect, this creates an identical copy of your Linux install, but with the application “installed” on top.

Next, the launcher creates two files in the union: /etc/passwd and /etc/group. To create them, we take the system's /etc/passwd and /etc/group files and simply replace your username with 'default'. We need to do this so that the application's settings always get saved to the same place, on all computers, in userdata.img.

Once we've mounted, we need to chroot to the union and launch the application. Here's what we do:

export FAKECHROOT_EXCLUDE_PATH=/dev:/proc:/tmp:/var/run:/sys
export USER=default
export HOME=/home/default
utils/fakechroot -l`pwd`/utils/libfakechroot.so chroot $mnt_dir/union bash -c "abiword"

A lot to process there. Let's take it apart. The first line tells fakechroot to not fakechroot the /dev/, /tmp, /var/run, /sys, and /proc directories, to leave them directly as they are, to avoid union problems. The second and third lines set the USER and HOME environment variables to fool the system into thinking we're user default, and our home directory is at /home/default. We then tell fakechroot where the union is, and tell it to run abiword (via bash) once it's chrooted.

That's it! At this point, the application will start. The application should work fine, save it's profile information to userdata.img (/home/default), and allow you to save information to your host system, if necessary.

Once you close the application, the launcher quickly unmounts everything (first union, then application, then userdata) and cleans up the folders it created on the host system. That's all! The userdata stays in userdata.img, ready for you to put the application on another computer, and have all your settings still there.

Additional Info

That's pretty much it. If you have any suggestions on how to speed up, improve, optimize the process, please let us know in the forums, it would be greatly appreciated. Thanks!

Also, if you want to figure out what else the launcher does (a lot of sanity checks, cleanups, etc.) check out the source (written in Perl). It also has a cool resizing algorithm (detects when you're using too much or too little of your userdata space, and resizes the image file accordingly.) Yeah, it's not very well commented right now, but I'll work on that in future versions.

 
architecture.txt · Last modified: 2010/05/30 14:44 by dkulchenko
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki