The traditional Unix filesystem hierarchy is a bit complicated.
As it was explained in the first section of my post on it, /opt
is
used for software to be contained in a single tree rather having their
files spread through the system. This concept of each program gets its
own directory tree is taken to extreme by GoboLinux distro. More
generally it reorganizes root to a new, hopefully more logical way.
Hierarchy
The root structure in GoboLinux is the following.
/Data | System and program resources |
/Mount | Mount points |
/Programs | Every program; no exceptions |
/System | System files |
/Users | User home directories |
First of all, there’s a common misconception that
descriptive directory names are for user friendliness. The actual reason
is to not conflict with Unix namespace. The capitalized descriptive
names originated from NeXT that also had to make its own directories
coexist with Unix ones. Using the regular directory tree with different
semantics can be confusing. This happens in AtheOS, where /usr
behaves like /opt
. The influencial Unix-derived Plan 9 also does
this, or better say Unix itself did it. In Plan 9 /usr
behaves like
/home
. This is actually similar to early Unix versions, where
/usr
was holding user home directories.
Having every program in /Programs
means that someone can explore what
is installed in their system just by doing ls /Programs
. This can be
thought as a database-less package management system with the directory
structure itself organizing the system. As a consequence of this system,
package management can take place using common Unix file tools.
Specifically it’s simpler to create and share binary packages. Having
this structure means that packages can be created just by compressing
its directory. They can removed just by removing the directory.
Each entry in /Programs
contains all files for that program, stored in
a versioned subdirectory. The subdirectory mirrors /usr
hierarchy of
traditional systems for the specific program. The versioned tree makes
it simple to maintain simultaneously multiple versions for each program.
For each file category, there is a directory under /System/Index
grouping files from each application as links. Those directories are
the traditional Unix ones found in /usr
and specifically bin, include,
lib, lib64 -> lib, libexec, sbin -> bin, and share. It can kinda be
though as /usr/local
.
In its initial presentation the directory was /System/Links
, and
the directories were Executables, Libraries, Headers, Shared and
Manuals. The migration to the new hierarchy happened in version 015.
The reason was issues with packaging.
Legacy applications continue to work thanks to symlink mapping of
traditional paths into their GoboLinux counterparts. Those paths are
hidden when listing root but application can still read and write to
them. This is made possible by using GoboHide an icotls-based
interface, actually a kernel extension meaning no kernel modifications
are required. The gobohide
is the userspace tool that talks with
kernel. To show all hidden directories gobohide -l
can be used.
The mapping can then be seen with
$ gobohide -l / | while read dir; do ls -l $dir; done
For reference in latest (v017) version this is
/bin -> /System/Index/bin |
/boot -> /System/Kernel/Boot |
/config -> /System/Kernel/Config |
/dev -> /System/Kernel/Devices |
/etc -> /System/Settings |
/lib -> /System/Index/lib |
/lib64 -> /System/Index/lib64 |
/media -> /Mount/Media |
/mnt -> /Mount |
/proc -> /System/Kernel/Status |
/root -> /Users/root |
/run -> /Data/Variable/run |
/sbin -> /System/Index/sbin |
/srv -> /Data |
/sys -> /System/Kernel/Objects |
/tmp -> /Data/Variable/tmp |
/var -> /Data/Variable |
There’s also /usr
with the following directories and files in it.
./bin -> /System/Index/bin |
./include -> /System/Index/include |
./lib -> /System/Index/lib |
./lib64 -> /System/Index/lib64 |
./libexec |
./local -> /usr |
./man -> /System/Index/share/man |
./plugins |
./sbin -> /System/Index/sbin |
./share -> /System/Index/share |
./X11R6 -> /usr |
The arguments gobohide -h/-u
can be used to hide and undhide a
directory respectively. A useful example is mapping /home
to /Users
and /root
to /Users/root
.
# mkdir -p /Users/root
# ln -s /Users /home
# gobohide -h /home
# ln -s /Users/root /root
# gobohide -h /root
Then doing ls -l
will show the same structure as that in first
section, but you can do ls -l /home
and cd /home
just fine.
Compile
The design of /Data/Compile
is also interesting, referred
as the poor-man’s portage because of its minimalistic
design. The Compile and the Recipes tree are designed around the
universality of source distribution and use of common build tools. The
Recipes are declarative files that describe what the compilation process
is like rather imperative scripts.
The recipes files are hosted on GitHub @gobolinux/Recipes. The tree
structure is similar to /Programs
that is directories for every
program and subdirectories for every version. The tree can be
downloaded locally (doing swallow clone) for easy usage doing
git clone --depth=1 https://github.com/gobolinux/Recipes /Data/Compile/Recipes
That said this isn’t required for software installation. Compile
will
download a recipe when a compilation is requested. Doing Compile $pkg
will perform a case-insensitive search for a recipe named $pkg
. A
particular version may be chosen instead doing Compile $pkg $vers
.
Let’s see closer how recipes work. For example, the Recipe
for
file/5.39
(found in the directory ./File/5.39) is
TODO: Make PR to @gobolinux/Recipes
compile_version=1.9.0
url="ftp://ftp.astron.com/pub/file/file-5.39.tar.gz"
file_size=954266
file_md5=1c450306053622803a25647d88f80f25
recipe_type=configure
There’s also a Resources
directory holding metadata. This directory
is eventually copied to the /Programs
subdirectory of the program. The
files in are the following along with their contents.
BuildDependencies
LibTool
BuildInformation
Glibc 2.24
LibSeccomp 2.3.2
ZLib 1.2.3
Dependencies
ZLib 1.2.3
Description
[Name] file
[Summary] File type identification utility
[License] BSD License (original)
[Description] File attempts to classify files depending on their contents and prints a description if a match is found.
[Homepage] https://darwinsys.com/file
Then the program can be installed with Compile file
or for that
version specifically with Compile file 5.39
. Extra options can be
passed ad hoc as flag in Compile
command. This makes it a bit like
build tool-agnostic make. When the package’s files and directories have
been created and populated, Compile will then create the necessary links
in the /System/Index
.
In my opinion this model though very simple (less complexity is good) leads to some redundancy. For example the Description file will be copied unchanged between versions. Also the others files will remain mostly the same between versions with only version changes.
Concepts in other systems
GoboLinux is influenced and draws inspiration from others systems that build a different system on top of Unix based. Examples of such systems are NeXT, BeOS, and AtheOS. That said, GoboLinux isn’t a clone of any of those systems.
NeXT was already mentioned to be the originator of the top hierarchy naming. The well-known macOS (formerly OS X) is NeXT’s ancestor and traces of that heritage are still present in it. One of those is the hierarchy. Specifically, macOS has both its own user friendly as well as standard Unix directories that are hidden in Finder (macOS file manager). The standard macOS hierarchy (sans the Unix directories) is the following.
/Applications | Installed applications |
/Library | App-specific resources |
/Network | Network-accessible resources |
/System | System/Apple-provided resources |
/Users | User home directories |
/Volumes | Mount points |
The Unix specific directories are utilized by the system’s BSD layer. Those are actual directories rather symlinks as in GoboLinux case. It can be thought as macOS splitting its filesystem to directories originating from its NeXT and BSD heritage.
Interestingly, the Compile
concept of setting a build style (not sure
if GoboLinux was an inspiration) is used in Void Linux which also hosts
its templates on GitHub @void-linux/void-packages. For comparison the
template
for file
in Void Linux is (own simpler version for demo;
modified from original in upstream)
pkgname=file
version=5.39
build_style=gnu-configure
makedepends="zlib-devel"
short_desc="File type identification utility"
license="BSD-2-Clause"
homepage="https://darwinsys.com/file"
distfiles="https://astron.com/pub/file/file-${version}.tar.gz"
checksum=f05d286a76d9556243d0cb05814929c2ecf3a5ba07963f8f70bfaaa70517fad1
The declarative approach and symlink population of specified directories
is also central to Nix (and Guix) package manager. Basically, NixOS is
perhaps the most popular distro with alien filesystem. In addition, Nix
also hosts its nixpkgs tree on GitHub @NixOS/nixpkgs. For comparison
the default.nix
for file in Nix (own simpler version for demo;
modified from original in upstream)
{ lib, stdenv, fetchurl, zlib }:
stdenv.mkDerivation rec {
pkgname = "file";
version = "5.39";
src = fetchurl {
url = "https://astron.com/pub/file/$file-${version}.tar.gz";
sha256 = "f05d286a76d9556243d0cb05814929c2ecf3a5ba07963f8f70bfaaa70517fad1";
};
buildInputs = [ zlib ];
meta = with lib; {
homepage = "https://darwinsys.com/file";
description = "File type identification utility";
license = licenses.bsd2;
};
}
Informatively, every installed package is installed in a /nix/store
subdirectory which mirrors /usr
of traditional systems. Then symlinks
are made in ~/.nix-profile
which is employed by a local user, or in
/run/current-system/sw
if system-wide. The central difference is that
the file-system doesn’t function as a package manager. Rather usage of
Nix is mandatory and a central point for reproducibility by not letting
a system administrator modify any system files.
The filesystem as package manager model is also utilized by stali, which has, a described in another post, simplified (no secondary and tertiary hierarchy) form of traditional Unix filesystem. Specifically the entire rootfs is managed by git. Then upgrading is just
# cd /
# git pull
Alternatively to downgrade or checkout a specific release
# cd /
# git checkout 0.1
Comments
Alongside the /System/Links
directory mentioned in the first secion,
another thing lost from the distro’s initial times, is the rootless
GoboLinux installation. It used to be possible to install GoboLinux
inside a $HOME directory under another distro. That meant that someone
could run GoboLinux applications as an unpriviledged user. The
installation resulted in the creation of the directories ~/Programs
,
~/System
, and ~/.Settings
.
GoboLinux has slow development and few users. As a final note, its experimental nature means more possibilities for security problems. Those are issues also mentioned in Bedrock, another experimental distro. An HN user has said that in a default Gobo installation there’re multiple ways to get root privileges from an unprivileged user.
If not for its interesting concepts, then it worths trying the live ISO for its cool cyberpunk-ish themed awesome. Awesome is well-known Lua-extensible window manager commonly used in tiling set up. The installation shows that awesome is an excellent floating window manager as well.