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
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, UDF should eventually be removed from this list
|
|
let missingOptionsAllowed = ["cgroup", "cgroup2", "bpf", "pstore", "fuse", "udf"].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);
|
|
});
|
|
};
|