Ucode-based mountpoint command for OpenWrt

February 17, 2025 by Daniel F Dickinson5 minutes

Due to an OpenWrt issue, the author needed a version of the 'mountpoint' command. Since the author wanted to learn ucode, they coded a version of the command using it.

It was OpenWrt issue 13873 that led to the author’s need for the moundpoint command for OpenWrt. As an opportunity to learn ucode, an interesting ECMAscript-like language1, the author translated a C-based 'mountpoint command into ucode. This may be moot as enabling the busybox mountpoint applet could be more space-efficient, but the author enjoyed the exercise.


The following code is a fairly quick and dirty translation of mountpoint from util-linux, written in ‘C’, to this code written in ucode.

Comments, suggestions and discussion of the following code should be done on the mountpoint-ucode Gist.

With the code in place, you can issue mountpoint /path/to/check which returns 0 (POSIX shell true) if /path/to/check is a mounted mountpoint, 1 if is not a mounted mountpoint, unless an error occurs, in which case the script returns -1 (255).

mountpoint -v /path/to/check will show a written message such as: /path/to/check is a mountpoint.

mountpoint -vv /path/to/check will additionally output a message like Could not stat '/path/to/check' if there is no file or directory at path/to/check.


Place the following script as /usr/bin/mountpoint on a device with ucode installed, and make it executable (chmod 0755 /usr/bin/mountpoint).

#!/usr/bin/env ucode

import { print_is_mountpoint } from "mountpoint";

let args = ARGV;

const arg1 = shift(args);

let do_message = false;
let show_errors = false;

if (arg1 == "-v") {
    do_message = true;
} else if (arg1 == "-vv") {
    do_message = true;
    show_errors = true;
} else {
    unshift(args, arg1);
}

exit(print_is_mountpoint(join(" ", args), do_message, show_errors));

And place the following module as /usr/share/ucode/mountpoint.uc.

// based on https://github.com/util-linux/util-linux/blob/master/sys-utils/mountpoint.c

import { access, dirname, open, realpath, stat } from 'fs';

function _is_dm_devname(canonical) {

    let dmpath = null;

    const spos = rindex(canonical, "/");
    if (spos != null) {
        dmpath = substr(canonical, spos + 1);
    } else {
        return {
            error: true,
            dmpath: null,
            error_message: "Not a device path"
        };
    }

    const can_stat = stat(canonical);

    if (can_stat == null) {
        return {
            error: true,
            dmpath: null,
            error_message: sprintf("Unable to access path %s", canonical)
        };
    }

    if (
        (length(dmpath) < 5) ||
        (substr(dmpath, 0, 4) != "/dm-") ||
        (int(substr(dmpath, 4)) == NaN) ||
        (can_stat.type != "block")
    ) {
        return {
            error: false,
            dmpath: null,
            error_message: null
        };
    }

    return {
        error: false,
        dmpath: dmpath,
        error_message: null
    };
}

function _canonicalize_dm_name(path) {

    if (path == null) {
        return {
            error: true,
            dmpath: null,
            error_message: "No input path"
        };
    }

    const fpath = sprintf("/sys/block/%s/dm/name", path);
    const f = open(fpath, "r");
    if (f == null) {
        return {
            error: true,
            dmpath: null,
            error_message: sprintf("Unable to open '%s'", fpath)
        };
    }

    const dmname = f.read("\n");
    f.close();

    if (dmname == null) {
        return {
            error: true,
            dmpath: null,
            error_message: sprintf("Failed to read '%s'", fpath)
        };
    }

    const dmpath = sprintf("/dev/mapper/%s", dmname);
    if (!access(dmpath)) {
        return {
            error: true,
            dmpath: null,
            error_message: sprintf("Unable to access '%s'", dmpath)
        };
    }

    return {
        error: false,
        dmpath: dmpath,
        error_message: null
    };
}

function _canonicalize_device_path(path) {

    if (!path) {
        return {
            error: true,
            canonical: null,
            error_message: "No input path"
        };
    }

    let canonical = realpath(path);
    if (!canonical) {
        return {
            error: true,
            canonical: null,
            error_message: sprintf("'%s' has no canonical path", path)
        };
    }

    const dmname_result = _is_dm_devname(canonical);
    if (!dmname_result.error) {
        if (dmname_result.dmname != null) {
            const dmcanonical_result = _canonicalize_dm_name(dmname_result.dmname);
            if (dmcanonical_result.dmname != null) {
                canonical = dmcanonical_result.dmname;
            } else if (dmcanonical_result.error) {
                return {
                    error: true,
                    canonical: null,
                    error_message: sprintf("'%s' could not be canonicalized: %s", path, dmcanonical_result.error_message)
                };
            }
        }
    } else if (dmname_result.error_message != "Not a device path") {
        return {
            error: true,
            canonical: null,
            error_message: sprintf("'%s' could not be read: %s", canonical, dmname_result.error_message)
        };
    }
    return {
        error: false,
        canonical: canonical,
        error_message: null
    };
}

function _dir_to_device(in_stat, in_path) {

    if (in_path == null) {
        return {
            error: true,
            device: null,
            error_message: "No input path"
        };
    }

    const canonical_result = _canonicalize_device_path(in_path);

    if (canonical_result.error) {
        return {
            error: true,
            device: null,
            error_message: canonical_result.error_message
        };
    }

    const canstat_result = stat(canonical_result.canonical);

    if (canstat_result == null) {
        return {
            error: true,
            device: null,
            error_message: sprintf("Could not stat '%s' (canonical path for '%s')", canonical_result.canonical, in_path)
        };
    }

    let parent_path = sprintf("%s/..", canonical_result.canonical);

    if (canstat_result.type != "directory") {
        parent_path = dirname(canonical_result.canonical);
    }

    const parent_stat = stat(parent_path);

    if (parent_stat == null) {
        return {
            error: true,
            device: null,
            error_message: sprintf("Could not stat parent directory of '%s' (canonical path for '%s')", canonical_result.canonical, in_path)
        };
    }

    if ((in_stat.dev.major != parent_stat.dev.major) || (in_stat.dev.minor != parent_stat.dev.minor) || (in_stat.inode == parent_stat.inode)) {
        return {
            error: false,
            device: in_stat.dev,
            error_message: null
        };
    }

    return {
        error: false,
        device: null,
        error_message: null
    };
}

function _is_mountpoint(path) {

    const path_stat = stat(path);
    if (path_stat == null) {
        return {
            error: true,
            is_mountpoint: null,
            device: null,
            error_message: sprintf("Could not stat '%s'", path)
        };
    }

    const path_device_result = _dir_to_device(path_stat, path);

    if (path_device_result.error) {
        return {
            error: true,
            is_mountpoint: null,
            device: null,
            error_message: sprintf("Could not get device for '%s': %s", path, path_device_result.error_message)
        };
    } else {
        return {
            error: false,
            is_mountpoint: (path_device_result.device != null),
            device: path_device_result.device,
            error_message: null
        }
    }
}

function is_mountpoint(path, show_error) {
    const is_mp_result = _is_mountpoint(path);
    if (is_mp_result.error) {
        if (show_error) {
            printf("%s\n", is_mp_result.error_message);
        }
        return -1;

    } else {
        return (is_mp_result.is_mountpoint ? 0 : 1);
    }
}

function print_is_mountpoint(path, show_message, show_error) {
    const is_mp = is_mountpoint(path, show_error);

    if (is_mp == -1) {
        exit(-1);
    }

    if (is_mp == 0) {
        if (show_message) {
            printf("%s is a mountpoint\n", path);
        }
        exit(0);
    } else {
        if (show_message) {
            printf("%s is not a mountpoint\n", path);
        }
        exit(1);
    }
}

export { is_mountpoint, print_is_mountpoint };

  1. Javascript is an ECMAscript language ↩︎