Skip to content

Instantly share code, notes, and snippets.

@jspc
Last active May 13, 2021 06:07
Show Gist options
  • Save jspc/ad5326040e0d25991e7a9a83bfd1f003 to your computer and use it in GitHub Desktop.
Save jspc/ad5326040e0d25991e7a9a83bfd1f003 to your computer and use it in GitHub Desktop.

The SeoulOS Files, and a Filesystem Hierarchy Standard

The linux foundation FHS is well understood, and partially supported in many places. It's also a bit shit.

Parts of the FHS come from making reatroactive rules around whichever directory name Ken Thompson or Dennis Ritchie chose in the early 70s. Seriously.

Additionally, some directories don't even make a lot of sense these days- who is distinguishing between mounting data in /media, or /mnt? What about people mounting directories in their home directory?

Tackling directories also allows us to rethink what a file looks like to SeoulOS, what modes files have, and how we can interact with them.

Thus, let's rethink things a bit.

Files and Directories

Ignoring, for a minute, the tedious cliche of "eVeRyThInGs a FiLe", and forgetting everything we know about POSIX files (fuck it, for now do we even care about such distinctions as whether a file must end with an eol, and whether an eol contains a newline (it doesn, but that doesn't matter for this file, either), there are a number of important types of files and directories which we're going to want

Files

File Purpose Notes
sda1, usb1 Device files Exposing these as files makes a certain amount of sense, especially for cloning or zeroing
anything in proc, sys Kernel tunables, details Tunables should exist outside of read-only details, and stuff should be well gated
binaries, configs, logs to do stuff /shrug Do we really need to separate this stuff off from one another? Perhaps for backing up config files, or putting logs in a tmpfs or something. Maybe opening files in different ways helps this
user files Whatever files a user wants Obviously not going to fuck around with these. Users can do whatever the hell they want
header files, kernel sources Bootstrapping files, building software This is another one of those things that makes sense to be completely freeform

Realistically there are only a few classifications of files we care about

  1. Devices
  2. Psuedo files (kernel stuffs)
  3. Application files (logs, configs, binaries)
  4. Bootstrap files
  5. User files

Within this, then, most files are 'regular' files. Create, write, delete. They don't need much beyond an ACL of some sort, and modes (R/RW/A). Executionable files are pretty much the same; (R/RW/RWX/RX/ whatever) but with the addition of capabilities (kernel plugins, for instance).

Additionally, creating files as logs or configs makes sense. Log files should be append-only, with some kind of strategy for stopping them getting too large. Labelling config files as such (or maybe with a backupable flag) and granting an interface to find these would be useful.

User files could come with a cool flag that, amongst other things, allows for the logging access by any other user (including root, or whatever)

A rough demonstration of this may be found here https://gist.github.com/rust-play/abc41037cceb0adf64fa2d6365834526

Thus: it becomes much easier to accomplish many of the things that shunting things into different directories gives us- no need to separate configs to one directory, binaries to another, logs to yet another. Keep them in one place, and then you get cool things like chroot without needing to do anything else.

Directories

The FHS directory structure is based on fifty year old problems, made official by some sketchy backronyms and rules, and cemented by practice and convention (backing up /etc and /home, for instance, or mounting /tmp as a tmpfs). These directories are familiar; lots of operating systems use them, or at least a la carte, and lots of tools have been designed to work with them.

The problem comes, though, when there's a non-standard use case. Perhaps configuration for one program is in /opt, and for another /etc. Some tools store config in /etc/prog/prog.conf, others /etc/prog.conf, and others yet in /etc/prog.d/prog.conf. Maybe config is then stored in /u01 (for those nasty oracle types). This stuff can be configured via xdg per instance and is just bloody ridiculous again.

The FHS is just not fit for purpose anymore.

Instead, we have the hierarchy:

Directory Purpose Notes
/ Root of the filesystem Umming and ahhing over this. Should it be an actual filesystem? Or an in-memory construct? Perhaps any file saved directly on / should disappear on reboot
/device Device files Pretty much as the FHS. Pseudo filesystem
/application Applications These applications are installed for all users
/user Home directories Like a non-shitty /Users on macos. Default cascading fileflags: FileFlags::USER_FILE
/user/foo/application Applications Applications installed for user foo only
/process ‘proc’ alike This should contain just processes, like Plan9. Things like CPU or Memory info are device information, so put them in /device/cpu or /device/memory
/toolchain Bootstrapping files, building software Anything that usually goes in **/lib or **/src or so on- why bother with the distinction?

Of note is that top-level directories are both full spelled out (we don't need to worry about files with too many characters- it's 2021 for fuck's sake), and singular. This is on purpose: paths should make semantic sense, conveying some information about what the file means in a wider context.

All a file name like /dev/sda1 tells you is that you have a date with the manual, if you've never seen this before. Hopefully a file like /device/disk-a/partition-1 tells you something more useful.

Further to the /application directory, there's the convention:

Path Access Notes
/application/foo/bin $ foo A shell would look for command ‘$cmd’ as per: /application/$cmd/bin which is expected to be an executable
/application/foo/some-command $ foo/some-command As above, in essence
/application/foo/something.log open(‘something.log’, FLAG_LOG) Paths are relative to where the command is run from, probably. Maybe that’s a bad idea. In any case, FLAG_LOG sets stuff like max size, append_only
/application/foo/blag.conf open(‘blag.conf’, FLAG_CONFIG) Ditto paths, dunno. A config flag might mean ‘persist to disk, and back me up’

The idea is that no matter where an application is installed, whatever resources an application needs (config files, logs, caches) should be accessible via a relative path. Files should be opened with the correct flags to ensure lifetimes and everything should work. An application can call its files whatever it wants, with the exception of the magic bin file. When an application is called without an explicit second part, then bin is assumed.

Emacs, then, might be stored with $ emacs, which is expanded to /application/emacs/bin.

This all should mean we no longer need to PREFIX=$HOME make, or cp /usr/share/faa/laa/laa.conf.sample /etc/faa/laa.conf or whatever.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment