github.com/stolowski/snapd@v0.0.0-20210407085831-115137ce5a22/osutil/mount/mount_linux.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2019 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package mount
    21  
    22  import (
    23  	"math/bits"
    24  	"syscall"
    25  )
    26  
    27  type flagInfo struct {
    28  	mask uint32
    29  	name string
    30  }
    31  
    32  func knownMask(knownFlags []flagInfo) uint32 {
    33  	var mask uint32
    34  	for _, fi := range knownFlags {
    35  		mask |= fi.mask
    36  	}
    37  	return mask
    38  }
    39  
    40  // UMOUNT_NOFOLLOW is not defined in go's syscall package
    41  const UMOUNT_NOFOLLOW = 8
    42  
    43  var mountFlags = []flagInfo{
    44  	{name: "MS_REMOUNT", mask: syscall.MS_REMOUNT},
    45  	{name: "MS_BIND", mask: syscall.MS_BIND},
    46  	{name: "MS_REC", mask: syscall.MS_REC},
    47  	{name: "MS_RDONLY", mask: syscall.MS_RDONLY},
    48  	{name: "MS_SHARED", mask: syscall.MS_SHARED},
    49  	{name: "MS_SLAVE", mask: syscall.MS_SLAVE},
    50  	{name: "MS_PRIVATE", mask: syscall.MS_PRIVATE},
    51  	{name: "MS_UNBINDABLE", mask: syscall.MS_UNBINDABLE},
    52  }
    53  
    54  var mountFlagsMask = knownMask(mountFlags)
    55  
    56  var unmountFlags = []flagInfo{
    57  	{name: "UMOUNT_NOFOLLOW", mask: UMOUNT_NOFOLLOW},
    58  	{name: "MNT_FORCE", mask: syscall.MNT_FORCE},
    59  	{name: "MNT_DETACH", mask: syscall.MNT_DETACH},
    60  	{name: "MNT_EXPIRE", mask: syscall.MNT_EXPIRE},
    61  }
    62  
    63  var unmountFlagsMask = knownMask(unmountFlags)
    64  
    65  func flagOptSearch(flags int, knownFlags []flagInfo, knownMask uint32) (opts []string, unknown int) {
    66  	var f uint32 = uint32(flags)
    67  	for _, fi := range knownFlags {
    68  		if f&knownMask == 0 {
    69  			break
    70  		}
    71  		if f&fi.mask != 0 {
    72  			if opts == nil {
    73  				opts = make([]string, 0, bits.OnesCount32(f))
    74  			}
    75  			f ^= fi.mask
    76  			opts = append(opts, fi.name)
    77  		}
    78  	}
    79  	return opts, int(f)
    80  }
    81  
    82  // MountFlagsToOpts returns the symbolic representation of mount flags.
    83  func MountFlagsToOpts(flags int) (opts []string, unknown int) {
    84  	return flagOptSearch(flags, mountFlags, mountFlagsMask)
    85  }
    86  
    87  // UnmountFlagsToOpts returns the symbolic representation of unmount flags.
    88  func UnmountFlagsToOpts(flags int) (opts []string, unknown int) {
    89  	return flagOptSearch(flags, unmountFlags, unmountFlagsMask)
    90  }