Unix

1. GNU/Linux   linux

properties ID: ab57dccf-c9f3-4347-b9d0-5731904f3d67
CREATED: <2025-02-09 Sun 13:33>
HEADER-ARGS: :eval no
edges

>> UNIX
intro(1)


notes

At this point, I don't really care what the non-believers think - if you are not running GNU/Linux as your daily driver, you are wrong. Of course I understand the need to run dedicated Windows and MacOS machines, when it is out of your control - say you have a Macbook or need to run it for %employer. No need to stress about that. But when you are given the opportunity - given a choice, you should pick whatever Linux-based OS suits your needs best.

1.1. User Commands

properties ID: 4e8a9455-f1ca-4654-8cfa-562735661d69
CREATED: <2025-05-02 Fri 15:25>

In order to start working, you'll probably first have to open a session. The program login(1) will wait for you to type your username and password, and after that, it will start a shell (command interpreter) for you. In case of a graphical login, you get a screen with menus or icons and a mouse click will start a shell in a window. See also xterm(1).

1.2. Libraries

properties ID: 3e6b5e34-4cf0-4289-afda-bea7c2a343dd
CREATED: <2025-02-14 Fri 22:11>

1.2.1. PAM

properties ID: ebdad1cf-804a-47bc-9a8b-a8487f3b6e57
CREATED: <2026-03-31 Tue 22:30>
edges

PAM(8) - Linux manual page
PAM - ArchWiki
An introduction to Pluggable Authentication Modules (PAM) in Linux
– [BROKEN LINK: github:linux-pam/linux-pam]
>> Security


Pluggable Authentication Modules for Linux

  • core library for most Linux-based systems

PAM provides a way to develop programs that are independent of authentication scheme. These programs need "authentication modules" to be attached to them at run-time in order to work. Which authentication module is to be attached is dependent upon the local system setup and is at the discretion of the local system administrator.

1.2.2. Ublk   fs

properties ID: 46fdde04-496d-45b4-a674-367edafb8054
CREATED: <2025-03-04 Tue 17:46>
edges

Userspace block device driver (ublk driver) - The Linux Kernel documentation


# add device
ublk.loop add -f ublk-loop.img
# fmt
mkfs.xfs /dev/ublkb0
mount /dev/ublkb0 .stash/
# ...
umount .stash/

1.2.3. Tracing   test log

properties ID: 292a62ff-6d56-42e2-88fa-bd13ddbc2fb1
CREATED: <2025-03-04 Tue 17:48>
edges

Linux Tracing Technologies - The Linux Kernel documentation


  1. strace
    properties ID: ef769379-7632-4c45-b933-1e3bfd858ea1
    CREATED: <2025-03-04 Tue 17:49>
    edges

    – [BROKEN LINK: man:strace]
    strace


  2. perf
    properties ID: da34bba6-7ca1-4836-91d8-e16ae2a8fcb7
    CREATED: <2025-03-04 Tue 17:49>
    edges

    – [BROKEN LINK: man:perf]
    brendangregg/perf-tools
    Linux perf Examples


  3. iostat
    properties ID: 7e8d965e-6b39-43bb-a69a-4747977b436f
    CREATED: <2025-03-04 Tue 18:59>
    edges

    – [BROKEN LINK: man:iostat]


  4. rv
    properties ID: d77d5ce5-2857-4c17-bcaf-c3eb32f93bcc
    CREATED: <2025-03-04 Tue 19:40>
    edges

    Runtime Verification - The Linux Kernel documentation


1.2.4. BPF   log

properties ID: 97d3d07c-e576-412b-a97a-2879efa998c5
CREATED: <2025-03-04 Tue 19:02>
edges

BPF Documentation - The Linux Kernel documentation


  1. eBPF
    properties ID: cb4a79ea-64fa-4c3a-b4bf-f3f731bc04ad
    CREATED: <2025-03-04 Tue 19:03>
    edges

    Linux eBPF Tracing Tools


1.2.5. RTLA   test

properties ID: 378227a0-d265-4272-8013-73df72b5e49a
CREATED: <2025-03-04 Tue 19:06>
edges

The realtime Linux analysis tool - The Linux Kernel documentation


1.2.6. ioctl

properties ID: 94f363d8-45a2-4d48-9e25-17b1ac50771a
CREATED: <2025-07-04 Fri 20:10>
edges

ioctl(2) - Linux manual page
ioctl based interfaces — The Linux Kernel documentation


ioctl() is the most common way for applications to interface with device drivers. It is flexible and easily extended by adding new commands and can be passed through character devices, block devices as well as sockets and other special file descriptors.

1.2.7. Keyutils   crypto

properties ID: 5e859a3f-0c31-4796-85c6-7008b346f186
CREATED: <2025-02-14 Fri 22:12>
edges

keyutils(7) - Linux manual page
The Linux Kernel Key Retention Service and why you should use it in your next application
keyctl(1) - Linux manual page


1.2.8. spidev

properties ID: 93c4f02f-2b00-4741-98e4-f427530f4875
CREATED: <2025-07-04 Fri 20:02>
edges

HTML page at URL has no title


1.2.9. Netlink

properties ID: 25cc1e3f-60f0-401a-a8b6-ac8d5670233d
CREATED: <2025-03-04 Tue 19:14>
edges

Introduction to Netlink - The Linux Kernel documentation
Netlink Handbook - The Linux Kernel documentation


1.3. Kernel

properties ID: caed860f-fcef-43a2-b080-94b01352cd43
CREATED: <2025-02-16 Sun 20:12>
edges

Unreliable Guide To Hacking The Linux Kernel - The Linux Kernel documentation
The Linux Kernel documentation - The Linux Kernel documentation


1.3.1. Kbuild

properties ID: 43020c04-f96f-4992-ad56-0bbfd4e55321
CREATED: <2025-06-22 Sun 00:11>
edges

linux/Documentation/kbuild/kbuild.rst
Kbuild - The Linux Kernel documentation


  1. Kconfig
    properties ID: dae51fae-66d9-4737-9971-999d3f94eadc
    CREATED: <2025-06-22 Sun 00:12>
    edges

    Kconfig Language - The Linux Kernel documentation


1.3.2. Devices

properties ID: ad25b130-d832-4109-84ad-7cb9900ed227
CREATED: <2025-01-17 Fri 19:15>

/dev In Linux, everything is a file.

dev contains special device files - usually block or character device.

major, minor = category, device 0, 5

mknod - create special device files

redhat hints

  1. udev
    properties ID: bb85c1ce-9a29-4771-b6cf-5f22823ca600
    CREATED: <2025-06-22 Sun 00:16>
    edges

    wiki
    – [BROKEN LINK: man:udev]


    1. systemd-udevd.service
      properties ID: 0dcb6857-91e1-4319-ad00-97c742604593
      CREATED: <2025-06-22 Sun 00:18>
      edges

      – [BROKEN LINK: man:systemd-udevd.service]
      -> systemd


  2. utils
    properties ID: f8ce343e-c866-4fff-8e39-2da32a59d56e
    CREATED: <2025-02-06 Thu 19:16>
    dd if=/dev/zero of=myfile bs=1M count=32
    losetup --show -f myfile
    ls -al /dev/loop0
    losetup -d /dev/loop0 #teardown
    
    echo "sup dude" > /dev/loop0
    dd if=/dev/loop0 -bs=1
    dd if=/dev/nvme0 of=/dev/null progress=true
    #pacman -S hdparm
    hdparm -T /dev/nvme0
    
    modprobe scsi_debug add_host=5 max_luns=10 num_tgts=2 dev_size_mb=16
    

    sparsefiles: create with C, dd, or truncate

    truncate --help
    
    Usage: truncate OPTION... FILE...
    Shrink or extend the size of each FILE to the specified size
    
    A FILE argument that does not exist is created.
    
    If a FILE is larger than the specified size, the extra data is lost.
    If a FILE is shorter, it is extended and the sparse extended part (hole)
    reads as zero bytes.
    
    Mandatory arguments to long options are mandatory for short options too.
      -c, --no-create        do not create any files
      -o, --io-blocks        treat SIZE as number of IO blocks instead of bytes
      -r, --reference=RFILE  base size on RFILE
      -s, --size=SIZE        set or adjust the file size by SIZE bytes
          --help
             display this help and exit
          --version
             output version information and exit
    
    The SIZE argument is an integer and optional unit (example: 10K is 10*1024).
    Units are K,M,G,T,P,E,Z,Y,R,Q (powers of 1024) or KB,MB,... (powers of 1000).
    Binary prefixes can be used, too: KiB=K, MiB=M, and so on.
    
    SIZE may also be prefixed by one of the following modifying characters:
    '+' extend by, '-' reduce by, '<' at most, '>' at least,
    '/' round down to multiple of, '%' round up to multiple of.
    
    Report bugs to: bug-coreutils@gnu.org
    GNU coreutils home page: <https://www.gnu.org/software/coreutils/>
    General help using GNU software: <https://www.gnu.org/gethelp/>
    Full documentation <https://www.gnu.org/software/coreutils/truncate>
    or available locally via: info '(coreutils) truncate invocation'
    

    test mkfs.btrfs on 10T dummy block device

    dd if=/dev/zero of=/tmp/bb1 bs=1 count=1 seek=10T
    du -sh /tmp/bb1
    losetup --show -f /tmp/bb1
    mkfs.btrfs /dev/loop0
    

    diagnostics

    iostat # pacman -S sysstat
    blktrace # paru -S blktrace
    iotop # pacman -S iotop
    

    bcc/ trace: Who/which process is executing specific functions against block devices?

    bcc/biosnoop: Which process is accessing the block device, how many bytes are accessed, which latency for answering the requests?

    at the kernel level besides BPF we got kmods and DKMS,

    compression/de-duplication can be done via VDO kernel mod

    https://en.wikipedia.org/wiki/Dynamic_Kernel_Module_Support

  3. Frame Buffer Device
    properties ID: 639e5d85-e143-421d-86be-9bc291bc2f8b
    CREATED: <2025-01-17 Fri 19:15>
    edges

    The Frame Buffer Device - The Linux Kernel documentation


    /dev/fb*

    • used by fbgrab/fbcat program
  4. Network Block Device
    properties ID: 9e0e0782-97cb-4b3a-85a2-b9df08bee962
    CREATED: <2026-04-18 Sat 13:44>
    edges

    Network Block Device (TCP version) — The Linux Kernel documentation


    • server toml config located at /etc/nbd-server/config

      [generic]
          # The [generic] section is required, even if nothing is specified
          # there.
          # When either of these options are specified, nbd-server drops
          # privileges to the given user and group after opening ports, but
          # _before_ opening files.
          user = nbd
          group = nbd
      [export1]
          exportname = /export/nbd/export1-file
          authfile = /export/nbd/export1-authfile
          timeout = 30
          filesize = 10000000
          readonly = false
          multifile = false
          copyonwrite = false
          prerun = dd if=/dev/zero of=%s bs=1k count=500
          postrun = rm -f %s
      [otherexport]
          exportname = /export/nbd/experiment
          # The other options are all optional.
      
  5. zram
    properties ID: f35ff674-2a35-4863-a431-ee3d4dcbb634
    CREATED: <2026-04-18 Sat 13:53>
    edges

    zram: Compressed RAM-based block devices — The Linux Kernel documentation


  6. Userspace Block Device
    properties ID: d58cb494-ce43-49cc-859b-aa6a518ac314
    CREATED: <2025-02-14 Fri 22:11>
    edges

    Userspace block device driver (ublk driver)


    ublk https://github.com/ming1/ubdsrv

  7. Input Devices
    properties ID: ea9bb3f9-3607-4be2-82f8-e9b3381a0524
    CREATED: <2025-02-27 Thu 18:51>
    edges

    evdev - Wikipedia
    kernel.org input.txt


1.3.3. Systems

properties ID: 1f728d2c-edf1-4502-9560-d0a6c45d5df8
CREATED: <2025-02-27 Thu 19:38>
edges

syscalls(2) - Linux manual page
System Calls - The Linux Kernel documentation
linux/arch/x86/entry/syscalls/syscall_64.tbl


syscalls are the primary interface between an application and the Linux kernel.

  1. Core
    properties ID: c670fcee-f9b1-4acd-ab32-3b795748b544
    CREATED: <2025-03-07 Fri 15:35>
    edges

    Core Subsystems


  2. Security
    properties ID: ff7219fb-ee6f-4db2-a0da-05546e09bdd4
    CREATED: <2026-04-01 Wed 20:34>
    edges

    Security Documentation — The Linux Kernel documentation
    << PAM


    1. CoCo
      properties ID: 2452fe4f-dc42-49a8-8e9d-54f6f094f342
      CREATED: <2026-04-01 Wed 20:36>
      edges

      Confidential Computing in Linux for x86 virtualization — The Linux Kernel documentation


      Confidential Computing - stuff covering TEEs (Trusted Execution Environment)

    2. Landlock
      properties ID: 85afe36e-21ae-4792-87d7-84efeb046cc3
      CREATED: <2026-04-03 Fri 00:00>
      edges

      Landlock: unprivileged access control — The Linux Kernel documentation
      Landlock: Unprivileged Sandboxing — Landlock documentation


      Unprivileged sandboxing

    3. Seccomp
      properties ID: 66441b6d-4141-4582-9f9e-75bcbc38339d
      CREATED: <2026-04-01 Wed 20:38>
      edges

      seccomp(2) - Linux manual page
      Seccomp BPF (SECure COMPuting with filters) — The Linux Kernel documentation


      Security Computing (syscall)

      • BPF programs make TOCTOU attacks impossible.
  3. Storage
    properties ID: f28b16e2-97e5-4575-a3d6-941efeb8942d
    CREATED: <2025-03-07 Fri 15:36>
    edges

    Storage interfaces


    1. Filesystem   fs
      properties ID: 1f938c20-8d8e-460c-8fb7-f4afaac432cc
      CREATED: <2025-02-22 Sat 19:04>
      edges

      Filesystem Hierarchy Standard - Wikipedia


  4. ACPI   hw
    properties ID: ac0ae4dd-21d4-4b45-9751-a102a48f30e6
    CREATED: <2025-03-04 Tue 19:16>
    edges

    ACP - Wikipedia
    ACPI Support - The Linux Kernel documentation


    Advanced Configuration and Power Interface

  5. SPI
    properties ID: cde3ff32-1ad9-43ab-9ac7-05efd3f88490
    CREATED: <2025-03-04 Tue 19:20>
    edges

    Serial Peripheral Interface (SPI) - The Linux Kernel documentation


  6. DFL   hw
    properties ID: 5499a81e-1c6e-48d5-b906-9d2155afc562
    CREATED: <2025-03-04 Tue 19:19>
    edges

    FPGA Device Feature List (DFL) Framework Overview - The Linux Kernel documentation


  7. Networking   net
    properties ID: 8ed2735d-d259-4a78-8891-ded98f857846
    CREATED: <2025-03-07 Fri 15:31>
    1. NAPI
      properties ID: 883daf4b-7084-4356-ab2d-877a8af2cd45
      CREATED: <2025-03-07 Fri 15:31>
      edges

      NAPI - The Linux Kernel documentation


  8. Human Interfaces
    properties ID: 19f3c5da-0f20-4eca-b142-7fc71095ca18
    CREATED: <2025-03-07 Fri 15:38>
    edges

    Human Interfaces


    1. Frame Buffer
      properties ID: 0c37073d-0322-410b-8258-00ffd8215eaa
      CREATED: <2025-03-07 Fri 15:38>
      edges

      Frame Buffer


  9. IO   io
    properties ID: 9d49d145-2c94-4d6f-a4e1-5016df6cbedc
    CREATED: <2025-02-27 Thu 19:39>

    Input/Output operations

    1. epoll
      properties ID: 74367b29-6a50-4eb4-ac6b-1c1b96dabd89
      CREATED: <2025-02-27 Thu 19:39>
      edges

      epoll(7) - Linux manual page


      The epoll event distribution interface is able to behave both as edge-triggered (ET) and as level-triggered (LT). The difference between the two mechanisms can be described as follows. Suppose that this scenario happens:

      (1) The file descriptor that represents the read side of a pipe (rfd) is registered on the epoll instance.

      (2) A pipe writer writes 2 kB of data on the write side of the pipe.

      (3) A call to epoll_wait(2) is done that will return rfd as a ready file descriptor.

      (4) The pipe reader reads 1 kB of data from rfd.

      (5) A call to epoll_wait(2) is done.

      If the rfd file descriptor has been added to the epoll interface using the EPOLLET (edge-triggered) flag, the call to epoll_wait(2) done in step 5 will probably hang despite the available data still present in the file input buffer; meanwhile the remote peer might be expecting a response based on the data it already sent. The reason for this is that edge-triggered mode delivers events only when changes occur on the monitored file descriptor, that is, an event will be generated upon each receipt of a chunk of data. So, in step 5 the caller might end up waiting for some data that is already present inside the input buffer. In the above example, an event on rfd will be generated because of the write done in 2 and the event is consumed in 3. Since the read operation done in 4 does not consume the whole buffer data, the call to epoll_wait(2) done in step 5 might block indefinitely.

      An application that employs the EPOLLET flag should use nonblocking file descriptors to avoid having a blocking read or write starve a task that is handling multiple file descriptors. The suggested way to use epoll as an edge-triggered (EPOLLET) interface is as follows:

      (1) with nonblocking file descriptors; and

      (2) by waiting for an event only after read(2) or write(2) return EAGAIN.

      By contrast, when used as a level-triggered interface (the default, when EPOLLET is not specified), epoll is simply a faster poll(2), and can be used wherever the latter is used since it shares the same semantics.

      Since even with edge-triggered epoll, multiple events can be generated upon receipt of multiple chunks of data, the caller has the option to specify the EPOLLONESHOT flag, to tell epoll to disable the associated file descriptor after the receipt of an event with epoll_wait(2). When the EPOLLONESHOT flag is specified, it is the caller's responsibility to rearm the file descriptor using epoll_ctl(2) with EPOLL_CTL_MOD.

      If multiple threads (or processes, if child processes have inherited the epoll file descriptor across fork(2)) are blocked in epoll_wait(2) waiting on the same epoll file descriptor and a file descriptor in the interest list that is marked for edge-triggered (EPOLLET) notification becomes ready, just one of the threads (or processes) is awoken from epoll_wait(2). This provides a useful optimization for avoiding "thundering herd" wake-ups in some scenarios.

    2. io_uring
      properties ID: 92c2a9aa-6584-470e-977a-3547bca79414
      CREATED: <2025-02-27 Thu 19:39>
      edges

      io_uring is not an event system · blog · despair labs
      GitHub - noteflakes/awesome-io_uring: Awesome io_uring
      Zero Copy Rx with io_uring
      io_uring(7) - Linux manual page
      Missing Manuals - io_uring worker pool
      Lord of the io_uring
      io_uring for High-Performance DBMSs: When and How to Use It
      io_uring for Systems Engineers


      • increasingly being preferred for high-io systems where batching is a must and pipelines can be optimized
      • implementing io_uring support in our core io/mux protocol AO
      • cat with liburing

        #include <fcntl.h>
        #include <stdio.h>
        #include <string.h>
        #include <sys/stat.h>
        #include <sys/ioctl.h>
        #include <liburing.h>
        #include <stdlib.h>
        
        #define QUEUE_DEPTH 1
        #define BLOCK_SZ    1024
        
        struct file_info {
            off_t file_sz;
            struct iovec iovecs[];      /* Referred by readv/writev */
        };
        
        /*
        * Returns the size of the file whose open file descriptor is passed in.
        * Properly handles regular file and block devices as well. Pretty.
        * */
        
        off_t get_file_size(int fd) {
            struct stat st;
        
            if(fstat(fd, &st) < 0) {
                perror("fstat");
                return -1;
            }
        
            if (S_ISBLK(st.st_mode)) {
                unsigned long long bytes;
                if (ioctl(fd, BLKGETSIZE64, &bytes) != 0) {
                    perror("ioctl");
                    return -1;
                }
                return bytes;
            } else if (S_ISREG(st.st_mode))
                return st.st_size;
        
            return -1;
        }
        
        /*
         * Output a string of characters of len length to stdout.
         * We use buffered output here to be efficient,
         * since we need to output character-by-character.
         * */
        void output_to_console(char *buf, int len) {
            while (len--) {
                fputc(*buf++, stdout);
            }
        }
        
        /*
         * Wait for a completion to be available, fetch the data from
         * the readv operation and print it to the console.
         * */
        
        int get_completion_and_print(struct io_uring *ring) {
            struct io_uring_cqe *cqe;
            int ret = io_uring_wait_cqe(ring, &cqe);
            if (ret < 0) {
                perror("io_uring_wait_cqe");
                return 1;
            }
            if (cqe->res < 0) {
                fprintf(stderr, "Async readv failed.\n");
                return 1;
            }
            struct file_info *fi = io_uring_cqe_get_data(cqe);
            int blocks = (int) fi->file_sz / BLOCK_SZ;
            if (fi->file_sz % BLOCK_SZ) blocks++;
            for (int i = 0; i < blocks; i ++)
                output_to_console(fi->iovecs[i].iov_base, fi->iovecs[i].iov_len);
        
            io_uring_cqe_seen(ring, cqe);
            return 0;
        }
        
        /*
         * Submit the readv request via liburing
         * */
        int submit_read_request(char *file_path, struct io_uring *ring) {
            int file_fd = open(file_path, O_RDONLY);
            if (file_fd < 0) {
                perror("open");
                return 1;
            }
            off_t file_sz = get_file_size(file_fd);
            off_t bytes_remaining = file_sz;
            off_t offset = 0;
            int current_block = 0;
            int blocks = (int) file_sz / BLOCK_SZ;
            if (file_sz % BLOCK_SZ) blocks++;
            struct file_info *fi = malloc(sizeof(*fi) +
                                                  (sizeof(struct iovec) * blocks));
            char *buff = malloc(file_sz);
            if (!buff) {
                fprintf(stderr, "Unable to allocate memory.\n");
                return 1;
            }
        
            /*
             * For each block of the file we need to read, we allocate an iovec struct
             * which is indexed into the iovecs array. This array is passed in as part
             * of the submission. If you don't understand this, then you need to look
             * up how the readv() and writev() system calls work.
             * */
            while (bytes_remaining) {
                off_t bytes_to_read = bytes_remaining;
                if (bytes_to_read > BLOCK_SZ)
                    bytes_to_read = BLOCK_SZ;
        
                offset += bytes_to_read;
                fi->iovecs[current_block].iov_len = bytes_to_read;
                void *buf;
                if( posix_memalign(&buf, BLOCK_SZ, BLOCK_SZ)) {
                    perror("posix_memalign");
                    return 1;
                }
                fi->iovecs[current_block].iov_base = buf;
        
                current_block++;
                bytes_remaining -= bytes_to_read;
            }
            fi->file_sz = file_sz;
        
            /* Get an SQE */
            struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
            /* Setup a readv operation */
            io_uring_prep_readv(sqe, file_fd, fi->iovecs, blocks, 0);
            /* Set user data */
            io_uring_sqe_set_data(sqe, fi);
            /* Finally, submit the request */
            io_uring_submit(ring);
        
            return 0;
        }
        
        int main(int argc, char *argv[]) {
            struct io_uring ring;
        
            if (argc < 2) {
                fprintf(stderr, "Usage: %s [file name] <[file name] ...>\n",
                        argv[0]);
                return 1;
            }
        
            /* Initialize io_uring */
            io_uring_queue_init(QUEUE_DEPTH, &ring, 0);
        
            for (int i = 1; i < argc; i++) {
                int ret = submit_read_request(argv[i], &ring);
                if (ret) {
                    fprintf(stderr, "Error reading file: %s\n", argv[i]);
                    return 1;
                }
                get_completion_and_print(&ring);
            }
        
            /* Call the clean-up function. */
            io_uring_queue_exit(&ring);
            return 0;
        }
        
      • cp with liburing

        #include <stdio.h>
        #include <fcntl.h>
        #include <string.h>
        #include <stdlib.h>
        #include <unistd.h>
        #include <assert.h>
        #include <errno.h>
        #include <sys/stat.h>
        #include <sys/ioctl.h>
        #include <liburing.h>
        
        #define QD  2
        #define BS (16 * 1024)
        
        static int infd, outfd;
        
        struct io_data {
            int read;
            off_t first_offset, offset;
            size_t first_len;
            struct iovec iov;
        };
        
        static int setup_context(unsigned entries, struct io_uring *ring) {
            int ret;
        
            ret = io_uring_queue_init(entries, ring, 0);
            if( ret < 0) {
                fprintf(stderr, "queue_init: %s\n", strerror(-ret));
                return -1;
            }
        
            return 0;
        }
        
        static int get_file_size(int fd, off_t *size) {
            struct stat st;
        
            if (fstat(fd, &st) < 0 )
                return -1;
            if(S_ISREG(st.st_mode)) {
                *size = st.st_size;
                return 0;
            } else if (S_ISBLK(st.st_mode)) {
                unsigned long long bytes;
        
                if (ioctl(fd, BLKGETSIZE64, &bytes) != 0)
                    return -1;
        
                *size = bytes;
                return 0;
            }
            return -1;
        }
        
        static void queue_prepped(struct io_uring *ring, struct io_data *data) {
            struct io_uring_sqe *sqe;
        
            sqe = io_uring_get_sqe(ring);
            assert(sqe);
        
            if (data->read)
                io_uring_prep_readv(sqe, infd, &data->iov, 1, data->offset);
            else
                io_uring_prep_writev(sqe, outfd, &data->iov, 1, data->offset);
        
            io_uring_sqe_set_data(sqe, data);
        }
        
        static int queue_read(struct io_uring *ring, off_t size, off_t offset) {
            struct io_uring_sqe *sqe;
            struct io_data *data;
        
            data = malloc(size + sizeof(*data));
            if (!data)
                return 1;
        
            sqe = io_uring_get_sqe(ring);
            if (!sqe) {
                free(data);
                return 1;
            }
        
            data->read = 1;
            data->offset = data->first_offset = offset;
        
            data->iov.iov_base = data + 1;
            data->iov.iov_len = size;
            data->first_len = size;
        
            io_uring_prep_readv(sqe, infd, &data->iov, 1, offset);
            io_uring_sqe_set_data(sqe, data);
            return 0;
        }
        
        static void queue_write(struct io_uring *ring, struct io_data *data) {
            data->read = 0;
            data->offset = data->first_offset;
        
            data->iov.iov_base = data + 1;
            data->iov.iov_len = data->first_len;
        
            queue_prepped(ring, data);
            io_uring_submit(ring);
        }
        
        int copy_file(struct io_uring *ring, off_t insize) {
            unsigned long reads, writes;
            struct io_uring_cqe *cqe;
            off_t write_left, offset;
            int ret;
        
            write_left = insize;
            writes = reads = offset = 0;
        
            while (insize || write_left) {
                int had_reads, got_comp;
        
                /* Queue up as many reads as we can */
                had_reads = reads;
                while (insize) {
                    off_t this_size = insize;
        
                    if (reads + writes >= QD)
                        break;
                    if (this_size > BS)
                        this_size = BS;
                    else if (!this_size)
                        break;
        
                    if (queue_read(ring, this_size, offset))
                        break;
        
                    insize -= this_size;
                    offset += this_size;
                    reads++;
                }
        
                if (had_reads != reads) {
                    ret = io_uring_submit(ring);
                    if (ret < 0) {
                        fprintf(stderr, "io_uring_submit: %s\n", strerror(-ret));
                        break;
                    }
                }
        
                /* Queue is full at this point. Let's find at least one completion */
                got_comp = 0;
                while (write_left) {
                    struct io_data *data;
        
                    if (!got_comp) {
                        ret = io_uring_wait_cqe(ring, &cqe);
                        got_comp = 1;
                    } else {
                        ret = io_uring_peek_cqe(ring, &cqe);
                        if (ret == -EAGAIN) {
                            cqe = NULL;
                            ret = 0;
                        }
                    }
                    if (ret < 0) {
                        fprintf(stderr, "io_uring_peek_cqe: %s\n",
                                strerror(-ret));
                        return 1;
                    }
                    if (!cqe)
                        break;
        
                    data = io_uring_cqe_get_data(cqe);
                    if (cqe->res < 0) {
                        if (cqe->res == -EAGAIN) {
                            queue_prepped(ring, data);
                            io_uring_cqe_seen(ring, cqe);
                            continue;
                        }
                        fprintf(stderr, "cqe failed: %s\n",
                                strerror(-cqe->res));
                        return 1;
                    } else if (cqe->res != data->iov.iov_len) {
                        /* short read/write; adjust and requeue */
                        data->iov.iov_base += cqe->res;
                        data->iov.iov_len -= cqe->res;
                        queue_prepped(ring, data);
                        io_uring_cqe_seen(ring, cqe);
                        continue;
                    }
        
                    /*
                     * All done. If write, nothing else to do. If read,
                     * queue up corresponding write.
                     * */
        
                    if (data->read) {
                        queue_write(ring, data);
                        write_left -= data->first_len;
                        reads--;
                        writes++;
                    } else {
                        free(data);
                        writes--;
                    }
                    io_uring_cqe_seen(ring, cqe);
                }
            }
        
            return 0;
        }
        
        int main(int argc, char *argv[]) {
            struct io_uring ring;
            off_t insize;
            int ret;
        
            if (argc < 3) {
                printf("Usage: %s <infile> <outfile>\n", argv[0]);
                return 1;
            }
        
            infd = open(argv[1], O_RDONLY);
            if (infd < 0) {
                perror("open infile");
                return 1;
            }
        
            outfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
            if (outfd < 0) {
                perror("open outfile");
                return 1;
            }
        
            if (setup_context(QD, &ring))
                return 1;
        
            if (get_file_size(infd, &insize))
                return 1;
        
            ret = copy_file(&ring, insize);
        
            close(infd);
            close(outfd);
            io_uring_queue_exit(&ring);
            return ret;
        }
        
    3. poll
      properties ID: d43311bf-7f5f-4d21-aad8-4b35548813b5
      CREATED: <2025-02-27 Thu 19:43>
      edges

      poll(2) - Linux manual page


1.4. Community

properties ID: d494d0ab-53ee-4c01-8276-638351d86368
CREATED: <2025-03-11 Tue 21:46>

1.4.1. UAPI Group

properties ID: 1196e1fc-7d87-430d-9b68-c5a8a240b82e
CREATED: <2025-03-11 Tue 21:46>
edges

The Linux Userspace API (UAPI) Group | The Linux Userspace API Group
<< UKI


The Linux Userspace API Group

1.5. Distros

properties ID: 34966e81-ab92-4b85-b11e-073784261db5
CREATED: <2025-02-22 Sat 19:31>
edges

List of Linux distributions - Wikipedia


Linux Distributions

1.5.1. Fedora

properties ID: c9fdd74c-0eb2-4d8f-bc22-0cf40996f186
CREATED: <2025-02-22 Sat 19:32>
edges

Fedora Linux | The Fedora Project


  • RHEL is based on Fedora
    • RH has influence over roadmap
  1. bootc
    properties ID: 101c2239-6e98-4899-b552-17e8ae9c55c8
    CREATED: <2025-04-16 Wed 18:52>
    edges

    Fedora/CentOS bootc Documentation :: Fedora Docs
    bootc-dev


  2. CoreOS
    properties ID: ca6795ee-4b2c-4ec3-9bdc-f6be67c2f1ec
    CREATED: <2025-02-22 Sat 19:32>
    AKA: FCOS
    PROPERTIES: :header-args :export both :eval no-export :session coreos :async t
    edges

    Fedora CoreOS Documentation


    • Configuring Users
    • CoreOS Installer

      cargo install coreos-installer
      
    • core
    • Ignition documentation
    • Provisioning Fedora CoreOS on QEMU
      • requires ignition config file
      • should provide ssh key for core user
      • fetch the qcow2 image

          # stream = stable,testing,next
        coreos-installer download -s $stream -p qemu -f qcow2.xz --decompress -C ~/.stash/scratch/
        
        /home/ellis/.stash/scratch/fedora-coreos-41.20250215.3.0-qemu.x86_64.qcow2
        
      • setup a new vm

        IGNITION_CONFIG=$config
        IMAGE=$image
        # for x86/aarch64:
        IGNITION_DEVICE_ARG="-fw_cfg name=opt/com.coreos/config,file=${IGNITION_CONFIG}"
        
        # for s390x/ppc64le:
        IGNITION_DEVICE_ARG="-drive file=${IGNITION_CONFIG},if=none,format=raw,readonly=on,id=ignition -device virtio-blk,serial=ignition,drive=ignition"
        
        qemu-system-x86_64 -m 2048 -cpu host -nographic -snapshot \
          -drive "if=virtio,file=${IMAGE}" ${IGNITION_DEVICE_ARG} \
          -nic user,model=virtio,hostfwd=tcp::2222-:22
        
      • launch it

        qemu-img create -f qcow2 -F qcow2 -b "${IMAGE}" my-fcos-vm.qcow2
        qemu-system-x86_64 -m 2048 -cpu host -nographic \
          -drive if=virtio,file=my-fcos-vm.qcow2 ${IGNITION_DEVICE_ARG} \
          -nic user,model=virtio,hostfwd=tcp::2222-:22
        
  3. IoT
    properties ID: 79c00d69-0624-4e85-a237-79e73e612dca
    CREATED: <2025-02-22 Sat 19:34>
    edges

    Fedora IoT Documentation


  4. dnf
    properties ID: 26b32ae2-b49c-42cb-a0d7-4823221b79f2
    CREATED: <2025-02-22 Sat 18:57>
    edges

    rpm-software-management/dnf5
    Changes in Fedora 41 For System Administrators :: Fedora Docs


    Dandified YUM

  5. rpm
    properties ID: 0a40d25f-0fe5-4b71-9d22-07d4bb355ff4
    CREATED: <2025-02-22 Sat 19:02>
    edges

    rpm.org - Home
    RPM Packaging Guide
    RPM-based Linux distributions - Wikipedia


    1. rpm-ostree
      properties ID: 836933b5-3035-4e8c-a2b9-63a773a359db
      CREATED: <2025-02-22 Sat 19:18>
      edges

      A true hybrid image/package system | rpm-ostree


      DNF Count Me support | rpm-ostree

1.5.2. Arch Linux   arch

properties ID: 6ef3fb84-6805-46f7-ad13-8929a023b43c
CREATED: <2025-02-22 Sat 19:39>
edges

home
-> Pacman


  1. Arch Boot Process
    properties ID: f673f776-03c7-4db0-ab0d-fae463f8e8ff
    CREATED: <2026-05-18 Mon 20:26>
    edges

    Arch boot process


    We really don't care much for BIOS, so we'll only be considering the UEFI boot process here.

    UEFI launches EFI applications, e.g. boot loaders, boot managers, UEFI shell, etc. These applications are usually stored as files in the EFI system partition. Each vendor can store its files in the EFI system partition under the /EFI/vendor_name directory. The applications can be launched by adding a boot entry to the NVRAM or from the UEFI shell.

    Starting from UEFI firmware launch, we first encounter a UEFI application, either a boot manager or an EFI boot stub.

  2. Pacman
    properties ID: 3c814d4d-8635-4c6f-a849-5c7d72db20fe
    CREATED: <2025-03-03 Mon 16:28>
    edges

    Pacman Home Page
    pacman - ArchWiki
    <- Arch


    pacman is a utility which manages software packages in Linux. It uses simple compressed files as a package format, and maintains a text-based package database (more of a hierarchy), just in case some hand tweaking is necessary.

    pacman does not strive to "do everything." It will add, remove and upgrade packages in the system, and it will allow you to query the package database for installed packages, files and owners. It also attempts to handle dependencies automatically and can download packages from a remote server.

    1. pacman.conf
      properties ID: 089909cf-4fd0-4124-a19e-f8ec619f8a63
      CREATED: <2026-05-13 Wed 21:10>
      edges

      man


      #
      # pacman.conf
      #
      [options]
      NoUpgrade = etc/passwd etc/group etc/shadow
      NoUpgrade = etc/fstab
      [core]
      Include = /etc/pacman.d/core
      [custom]
      Server = file:///home/pkgs
      
    2. Pacman Hooks
      properties ID: 05cc62c7-db2a-4bf6-b94d-e04a2b17aed0
      CREATED: <2025-06-08 Sun 19:29>
      edges

      pacman hooks - ArchWiki


      Pacman can run pre- and post-transaction hooks from the usr/share/libalpm/hooks directory; more directories can be specified with the HookDir option in pacman.conf, which defaults to /etc/pacman.d/hooks. Hook file names must be suffixed with .hook. Pacman hooks are not interactive.

    3. libalpm
      properties ID: cb4a3977-f53c-4d43-a5fa-78d6d49b948d
      CREATED: <2026-05-13 Wed 21:15>
      edges

      man
      lib/libalpm/alpm.h


      A package management library primarily used by Pacman.

    4. Extras
      properties ID: 219f8bb6-b324-4a33-87e0-69114948c0f6
      CREATED: <2025-06-08 Sun 19:31>
      edges

      pactree(8) - Arch manual pages


      • show dependencies of a package
      • not included with pacman - install pacman-contrib
      • see also pakbak and pacolog (AUR)
  3. Archiso
    properties ID: 06ee60a3-9a98-40d2-893b-39ce992fc0dc
    CREATED: <2025-06-08 Sun 19:23>
    edges

    archiso - ArchWiki


    Archiso is a highly-customizable tool for building Arch Linux live CD/USB ISO images, netboot artifacts and bootstrap tarballs. The official images are built with archiso and include these packages. It can be used as the basis for rescue systems, Linux installers or other systems.

    • supports cloud-init service
    • sshd on by default (requires sudo disabled)
    mkarchiso -h
    
    usage: mkarchiso [options] <profile_dir>
      options:
         -A <application> Set an application name for the ISO
                          Default: ''
         -C <file>        pacman configuration file.
                          Default: ''
         -D <install_dir> Set an install_dir. All files will be located here.
                          Default: ''
                          NOTE: Max 8 characters, use only [a-z0-9]
         -L <label>       Set the ISO volume label
                          Default: ''
         -P <publisher>   Set the ISO publisher
                          Default: ''
         -c [cert ..]     Provide certificates for codesigning of netboot artifacts as
                          well as the rootfs artifact.
                          Multiple files are provided as quoted, space delimited list.
                          The first file is considered as the signing certificate,
                          the second as the key and the third as the optional certificate authority.
         -g <gpg_key>     Set the PGP key ID to be used for signing the rootfs image.
                          Passed to gpg as the value for --default-key
         -G <mbox>        Set the PGP signer (must include an email address)
                          Passed to gpg as the value for --sender
         -h               This message
         -m [mode ..]     Build mode(s) to use (valid modes are: 'bootstrap', 'iso' and 'netboot').
                          Multiple build modes are provided as quoted, space delimited list.
         -o <out_dir>     Set the output directory
                          Default: ''
         -p [package ..]  Package(s) to install.
                          Multiple packages are provided as quoted, space delimited list.
         -r               Delete the working directory at the end.
         -v               Enable verbose output
         -w <work_dir>    Set the working directory
                          Default: ''
    
      profile_dir:        Directory of the archiso profile to build
    
    run_archiso -h
    
    Usage:
        run_archiso [options]
    
    Options:
        -A [arch]       change architecture (defaults to the host architecture; supports: x86_64, i686, aarch64 and riscv64)
        -a              set accessibility support using brltty
        -b              set boot type to 'BIOS'
        -d              set image type to hard disk instead of optical disc
        -h              print help
        -i [image]      image to boot into
        -s              use Secure Boot (only relevant when using UEFI)
        -u              set boot type to 'UEFI' (default)
        -v              use VNC display (instead of default SDL)
        -c [image]      attach an additional optical disc image (e.g. for cloud-init)
    
    Example:
        Run an image using UEFI:
        $ run_archiso -i archiso-2020.05.23-x86_64.iso
    
  4. ABS
    properties ID: 03215632-83da-48c0-9f36-df72a9e956b5
    CREATED: <2025-07-09 Wed 17:04>
    AKA: Arch build system
    edges

    Arch build system - ArchWiki


    The Arch build system (ABS) is a system for building and packaging software from source code. While pacman is the specialized Arch tool for binary package management, the Arch build system is a collection of tools for compiling source into installable .pkg.tar.zst packages.

    The Arch build system can be compared to ports for *BSD, which automates the process of building software from source code. The system uses a port to download, unpack, patch, compile, and install the given software. A port is merely a small directory on the user's computer, named after the corresponding software to be installed, that contains a few files with the instructions for building and installing the software from source. This makes installing software as simple as typing make or make install clean within the port's directory.

    The Arch build system is based on a similar concept. It comprises a collection of git repositories for every package available in Arch Linux. Each repository contains a PKGBUILD file (and sometimes other files), and does not contain the software source nor binary. By running makepkg inside a directory, the software sources are downloaded, the software is compiled, and then packaged within the build directory. Then you can use pacman to install the package.

    (makepkg, makechrootpkg, etc)

    1. PKGBUILD
      properties ID: 59eb9925-ec78-4202-b42e-53456c04ac27
      CREATED: <2026-05-09 Sat 21:08>
      edges

      archwiki


      • If you need to create any custom variables for use in your build process, it is recommended to prefix their name with an _ (underscore). This will prevent any possible name clashes with internal makepkg variables. For example, to store the base kernel version in a variable, use something similar to $_basekernver.
  5. AUR
    properties ID: 133e5971-2952-45b7-889a-36dc77312211
    CREATED: <2026-05-09 Sat 22:34>
    AKA: Arch User Repository
    edges

    AUR (en) - Home


    There are several 'pacman extensions' out there (yaru/paru/?) which support AUR searching and other such things - for our purposes we are content with copying the git link (by clicking in browser) and cloning it, then running makepkg -si.

  6. Configuration
    properties ID: 85f0992c-fc87-42dc-8946-0384dfe1ccb8
    CREATED: <2025-10-26 Sun 20:28>

    Arch Linux system configuration is either too complex or too trivial to discuss depending on who you ask. Here we simply cover topics with useful tips and tricks as I encounter them.

    1. Bootstrapping
      properties ID: a3078d9b-457c-4545-a058-098ad1bed196
      CREATED: <2025-10-30 Thu 20:21>

      I like Arch everywhere so we ought to have a good way of bootstrapping images for different machines and containers.

    2. Networking
      properties ID: 6c02fd4a-b7dd-4838-b39f-b84f6ba20e97
      CREATED: <2025-10-30 Thu 20:13>
    3. cloud-init
      properties ID: 1e726b53-266d-4020-a48a-0405de5a0365
      CREATED: <2026-05-17 Sun 18:47>
      edges

      >> cloud-init
      Cloud-init - ArchWiki
      Install Arch Linux via SSH - ArchWiki


1.5.3. Ubuntu

properties ID: 5d1223c7-0ded-44b9-b494-3a3593a2fe02
CREATED: <2025-02-22 Sat 19:39>
edges

Enterprise Open Source and Linux | Ubuntu


1.5.4. Debian

properties ID: f03769bc-abf2-4f58-809f-b672c66120f3
CREATED: <2025-02-22 Sat 19:39>
edges

Debian – The Universal Operating System


1.5.5. Alpine

properties ID: 4e717401-7b7b-4ce6-83c7-6f8420e01b93
CREATED: <2025-02-22 Sat 19:40>
edges

Alpine Linux


  1. APK
    properties ID: b52fdc61-2fcc-42e0-a1df-66ebd0ca0488
    CREATED: <2025-03-04 Tue 15:52>
    edges

    Working with the Alpine Package Keeper (apk) - Alpine Linux Documentation


1.5.6. Adélie

properties ID: b54a3fef-192f-4767-bec2-c10058e69a89
CREATED: <2025-03-04 Tue 15:27>
edges

Adélie Linux | Welcome


1.5.7. Gentoo

properties ID: 5cbe7ad4-008a-4ed7-889d-e7ec5663dfd1
CREATED: <2025-02-22 Sat 19:40>
edges

Gentoo Linux


1.5.8. Slackware

properties ID: 21e5a881-54d0-410e-b48a-f32ee26ef90d
CREATED: <2025-02-22 Sat 19:43>
edges

The Slackware Linux Project


1.6. Fundamentals

properties ID: 7c93b796-dc69-451f-9d70-bfb831f0e2fe
CREATED: <2025-08-29 Fri 19:54>

1.6.1. Processes

properties ID: 45978aae-af9d-440a-93c7-c1d004b1f3a6
CREATED: <2025-08-29 Fri 19:54>

AME fork ­ create a child process SYNOPSIS #include <sys/types.h> #include <unistd.h> pid_t fork(void); DESCRIPTION fork creates a child process that differs from the parent process only in its PID and PPID, and in the fact that resource utilizations are set to 0. File locks and pending signals are not inherited. Under Linux, fork is implemented using copy­on­write pages, so the only penalty incurred by fork is the time and memory required to duplicate the parent's page tables, and to create a unique task structure for the child. RETURN VALUE On success, the PID of the child process is returned in the parent's thread of execution, and a 0 is returned in the child's thread of exe­ cution. On failure, a ­1 will be returned in the parent's context, no child process will be created, and errno will be set appropriately.

1.6.2. Signals

properties ID: 37740e21-e0a8-4d09-9292-72be229a65f9
CREATED: <2026-03-09 Mon 19:00>
edges

sigaction(2) - Linux manual page
signal(7) - Linux manual page
sigaltstack(2) - Linux manual page


2. Plan 9

properties ID: 3c707aa1-be3a-4258-bcd8-195216e658b5
CREATED: <2025-03-06 Thu 09:11>

:EDGES: Plan 9 from Bell Labs Plan 9 - The Documents (Volume 2)

3. OpenBSD

properties ID: 82110e71-748d-4dd6-ba91-22a6a41df76c
CREATED: <2025-06-22 Sun 14:56>
edges

OpenBSD


4. Android

properties ID: 027a4ebc-2b25-4ece-9a66-ee9bdc34d833
CREATED: <2026-04-16 Thu 21:45>
edges

Platform architecture


4.1. GrapheneOS

properties ID: bb21bcd1-4ff4-4718-bceb-6ba0ef95d69f
CREATED: <2026-04-16 Thu 21:45>
edges

GrapheneOS: the private and secure mobile OS


  • Web installer
  • NOTE - OEM is often gate-kept by carrier (verizon at&t t-mobile) - need to get around that via customer support somehow or don't buy vendor-locked hardware. what a load of BS.