You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.7 KiB
JavaScript

"use strict";
const Promise = require("bluebird");
const execBinary = require("../exec-binary");
const parseIECBytes = require("../parse-bytes-iec");
const parseMountOptions = require("../parse-mount-options");
const createJsonParser = require("../text-parser-json");
// TODO: Should we replace this with a read from /proc/mounts directly?
// Ref. https://unix.stackexchange.com/a/18067
function mapMountList(mounts) {
return mounts.map((mount) => {
// Some poorly-documented pseudo-filesystems were not worth investigating mount options for, yet. For those, we silently ignore missing/unknown entries.
// TODO: FUSE should eventually be removed from this list
let missingOptionsAllowed = ["cgroup", "cgroup2", "bpf", "pstore", "fuse"].includes(mount.fstype);
let parsedOptions = parseMountOptions(mount.fstype, mount.options);
// For dealing with bind mounts, which have a path suffix, like eg.:
// /dev/disk/by-uuid/692937db-d74c-4110-b55b-41a20f1b9342[/nix/store]
let cleanSourceDevice = (mount.source.startsWith("/"))
? mount.source.replace(/\[.+$/, "")
: null; // Pseudo-filesystems
if (missingOptionsAllowed || parsedOptions.missing.length === 0) {
return {
id: mount.id,
sourceDevice: cleanSourceDevice,
isBindMount: (cleanSourceDevice != null)
? mount.source.includes("[") // FIXME: Is this actually correct? Can a square bracket ever appear in a device path legitimately?
: false, // Pseudo-filesystems
mountpoint: mount.target,
filesystem: mount.fstype,
options: parsedOptions.parsed,
label: mount.label,
uuid: mount.uuid,
partitionLabel: mount.partlabel,
partitionUUID: mount.partuuid,
deviceNumber: mount["maj:min"],
totalSpace: parseIECBytes(mount.size),
freeSpace: parseIECBytes(mount.avail),
usedSpace: parseIECBytes(mount.used),
rootPath: mount.fsroot,
taskID: mount.tid,
optionalFields: mount["opt-fields"],
propagationFlags: mount.propagation,
children: (mount.children != null) ? mapMountList(mount.children) : []
};
} else {
throw new Error(`Encountered unrecognized mount options for mount '${mount.target}': ${parsedOptions.missing.join(", ")}`);
}
});
}
let columns = [
"SOURCE",
"TARGET",
"FSTYPE",
"OPTIONS",
"LABEL",
"UUID",
"PARTLABEL",
"PARTUUID",
"MAJ:MIN",
"SIZE",
"AVAIL",
"USED",
"FSROOT",
"TID",
"ID",
"OPT-FIELDS",
"PROPAGATION"
];
module.exports = function findmnt() {
return Promise.try(() => {
return execBinary("findmnt")
.withFlags({
json: true,
o: columns.join(",")
})
.requireOnStdout(createJsonParser())
.execute();
}).then((output) => {
return mapMountList(output.result.filesystems);
});
};