"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 ) ;
} ) ;
} ;