aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/moby/sys
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/moby/sys')
-rw-r--r--vendor/github.com/moby/sys/mount/LICENSE202
-rw-r--r--vendor/github.com/moby/sys/mount/flags.go137
-rw-r--r--vendor/github.com/moby/sys/mount/flags_freebsd.go48
-rw-r--r--vendor/github.com/moby/sys/mount/flags_linux.go87
-rw-r--r--vendor/github.com/moby/sys/mount/flags_unsupported.go30
-rw-r--r--vendor/github.com/moby/sys/mount/go.mod8
-rw-r--r--vendor/github.com/moby/sys/mount/go.sum4
-rw-r--r--vendor/github.com/moby/sys/mount/mount.go67
-rw-r--r--vendor/github.com/moby/sys/mount/mount_errors.go46
-rw-r--r--vendor/github.com/moby/sys/mount/mounter_freebsd.go59
-rw-r--r--vendor/github.com/moby/sys/mount/mounter_linux.go73
-rw-r--r--vendor/github.com/moby/sys/mount/mounter_unsupported.go7
-rw-r--r--vendor/github.com/moby/sys/mount/sharedsubtree_linux.go73
-rw-r--r--vendor/github.com/moby/sys/mount/unmount_unix.go26
-rw-r--r--vendor/github.com/moby/sys/mount/unmount_unsupported.go11
-rw-r--r--vendor/github.com/moby/sys/mountinfo/doc.go47
-rw-r--r--vendor/github.com/moby/sys/mountinfo/go.mod2
-rw-r--r--vendor/github.com/moby/sys/mountinfo/go.sum2
-rw-r--r--vendor/github.com/moby/sys/mountinfo/mounted_linux.go58
-rw-r--r--vendor/github.com/moby/sys/mountinfo/mounted_unix.go66
-rw-r--r--vendor/github.com/moby/sys/mountinfo/mountinfo.go23
-rw-r--r--vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go4
-rw-r--r--vendor/github.com/moby/sys/mountinfo/mountinfo_freebsd.go12
-rw-r--r--vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go76
-rw-r--r--vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go8
-rw-r--r--vendor/github.com/moby/sys/mountinfo/mountinfo_windows.go4
26 files changed, 1162 insertions, 18 deletions
diff --git a/vendor/github.com/moby/sys/mount/LICENSE b/vendor/github.com/moby/sys/mount/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/moby/sys/mount/flags.go b/vendor/github.com/moby/sys/mount/flags.go
new file mode 100644
index 000000000..d514a9d8e
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/flags.go
@@ -0,0 +1,137 @@
+package mount
+
+import (
+ "fmt"
+ "strings"
+)
+
+var flags = map[string]struct {
+ clear bool
+ flag int
+}{
+ "defaults": {false, 0},
+ "ro": {false, RDONLY},
+ "rw": {true, RDONLY},
+ "suid": {true, NOSUID},
+ "nosuid": {false, NOSUID},
+ "dev": {true, NODEV},
+ "nodev": {false, NODEV},
+ "exec": {true, NOEXEC},
+ "noexec": {false, NOEXEC},
+ "sync": {false, SYNCHRONOUS},
+ "async": {true, SYNCHRONOUS},
+ "dirsync": {false, DIRSYNC},
+ "remount": {false, REMOUNT},
+ "mand": {false, MANDLOCK},
+ "nomand": {true, MANDLOCK},
+ "atime": {true, NOATIME},
+ "noatime": {false, NOATIME},
+ "diratime": {true, NODIRATIME},
+ "nodiratime": {false, NODIRATIME},
+ "bind": {false, BIND},
+ "rbind": {false, RBIND},
+ "unbindable": {false, UNBINDABLE},
+ "runbindable": {false, RUNBINDABLE},
+ "private": {false, PRIVATE},
+ "rprivate": {false, RPRIVATE},
+ "shared": {false, SHARED},
+ "rshared": {false, RSHARED},
+ "slave": {false, SLAVE},
+ "rslave": {false, RSLAVE},
+ "relatime": {false, RELATIME},
+ "norelatime": {true, RELATIME},
+ "strictatime": {false, STRICTATIME},
+ "nostrictatime": {true, STRICTATIME},
+}
+
+var validFlags = map[string]bool{
+ "": true,
+ "size": true,
+ "mode": true,
+ "uid": true,
+ "gid": true,
+ "nr_inodes": true,
+ "nr_blocks": true,
+ "mpol": true,
+}
+
+var propagationFlags = map[string]bool{
+ "bind": true,
+ "rbind": true,
+ "unbindable": true,
+ "runbindable": true,
+ "private": true,
+ "rprivate": true,
+ "shared": true,
+ "rshared": true,
+ "slave": true,
+ "rslave": true,
+}
+
+// MergeTmpfsOptions merge mount options to make sure there is no duplicate.
+func MergeTmpfsOptions(options []string) ([]string, error) {
+ // We use collisions maps to remove duplicates.
+ // For flag, the key is the flag value (the key for propagation flag is -1)
+ // For data=value, the key is the data
+ flagCollisions := map[int]bool{}
+ dataCollisions := map[string]bool{}
+
+ var newOptions []string
+ // We process in reverse order
+ for i := len(options) - 1; i >= 0; i-- {
+ option := options[i]
+ if option == "defaults" {
+ continue
+ }
+ if f, ok := flags[option]; ok && f.flag != 0 {
+ // There is only one propagation mode
+ key := f.flag
+ if propagationFlags[option] {
+ key = -1
+ }
+ // Check to see if there is collision for flag
+ if !flagCollisions[key] {
+ // We prepend the option and add to collision map
+ newOptions = append([]string{option}, newOptions...)
+ flagCollisions[key] = true
+ }
+ continue
+ }
+ opt := strings.SplitN(option, "=", 2)
+ if len(opt) != 2 || !validFlags[opt[0]] {
+ return nil, fmt.Errorf("Invalid tmpfs option %q", opt)
+ }
+ if !dataCollisions[opt[0]] {
+ // We prepend the option and add to collision map
+ newOptions = append([]string{option}, newOptions...)
+ dataCollisions[opt[0]] = true
+ }
+ }
+
+ return newOptions, nil
+}
+
+// Parse fstab type mount options into mount() flags
+// and device specific data
+func parseOptions(options string) (int, string) {
+ var (
+ flag int
+ data []string
+ )
+
+ for _, o := range strings.Split(options, ",") {
+ // If the option does not exist in the flags table or the flag
+ // is not supported on the platform,
+ // then it is a data value for a specific fs type
+ if f, exists := flags[o]; exists && f.flag != 0 {
+ if f.clear {
+ flag &= ^f.flag
+ } else {
+ flag |= f.flag
+ }
+ } else {
+ data = append(data, o)
+ }
+ }
+ return flag, strings.Join(data, ",")
+}
diff --git a/vendor/github.com/moby/sys/mount/flags_freebsd.go b/vendor/github.com/moby/sys/mount/flags_freebsd.go
new file mode 100644
index 000000000..69c50680d
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/flags_freebsd.go
@@ -0,0 +1,48 @@
+// +build freebsd,cgo
+
+package mount
+
+/*
+#include <sys/mount.h>
+*/
+import "C"
+
+const (
+ // RDONLY will mount the filesystem as read-only.
+ RDONLY = C.MNT_RDONLY
+
+ // NOSUID will not allow set-user-identifier or set-group-identifier bits to
+ // take effect.
+ NOSUID = C.MNT_NOSUID
+
+ // NOEXEC will not allow execution of any binaries on the mounted file system.
+ NOEXEC = C.MNT_NOEXEC
+
+ // SYNCHRONOUS will allow any I/O to the file system to be done synchronously.
+ SYNCHRONOUS = C.MNT_SYNCHRONOUS
+
+ // NOATIME will not update the file access time when reading from a file.
+ NOATIME = C.MNT_NOATIME
+)
+
+// These flags are unsupported.
+const (
+ BIND = 0
+ DIRSYNC = 0
+ MANDLOCK = 0
+ NODEV = 0
+ NODIRATIME = 0
+ UNBINDABLE = 0
+ RUNBINDABLE = 0
+ PRIVATE = 0
+ RPRIVATE = 0
+ SHARED = 0
+ RSHARED = 0
+ SLAVE = 0
+ RSLAVE = 0
+ RBIND = 0
+ RELATIME = 0
+ REMOUNT = 0
+ STRICTATIME = 0
+ mntDetach = 0
+)
diff --git a/vendor/github.com/moby/sys/mount/flags_linux.go b/vendor/github.com/moby/sys/mount/flags_linux.go
new file mode 100644
index 000000000..0425d0dd6
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/flags_linux.go
@@ -0,0 +1,87 @@
+package mount
+
+import (
+ "golang.org/x/sys/unix"
+)
+
+const (
+ // RDONLY will mount the file system read-only.
+ RDONLY = unix.MS_RDONLY
+
+ // NOSUID will not allow set-user-identifier or set-group-identifier bits to
+ // take effect.
+ NOSUID = unix.MS_NOSUID
+
+ // NODEV will not interpret character or block special devices on the file
+ // system.
+ NODEV = unix.MS_NODEV
+
+ // NOEXEC will not allow execution of any binaries on the mounted file system.
+ NOEXEC = unix.MS_NOEXEC
+
+ // SYNCHRONOUS will allow I/O to the file system to be done synchronously.
+ SYNCHRONOUS = unix.MS_SYNCHRONOUS
+
+ // DIRSYNC will force all directory updates within the file system to be done
+ // synchronously. This affects the following system calls: create, link,
+ // unlink, symlink, mkdir, rmdir, mknod and rename.
+ DIRSYNC = unix.MS_DIRSYNC
+
+ // REMOUNT will attempt to remount an already-mounted file system. This is
+ // commonly used to change the mount flags for a file system, especially to
+ // make a readonly file system writeable. It does not change device or mount
+ // point.
+ REMOUNT = unix.MS_REMOUNT
+
+ // MANDLOCK will force mandatory locks on a filesystem.
+ MANDLOCK = unix.MS_MANDLOCK
+
+ // NOATIME will not update the file access time when reading from a file.
+ NOATIME = unix.MS_NOATIME
+
+ // NODIRATIME will not update the directory access time.
+ NODIRATIME = unix.MS_NODIRATIME
+
+ // BIND remounts a subtree somewhere else.
+ BIND = unix.MS_BIND
+
+ // RBIND remounts a subtree and all possible submounts somewhere else.
+ RBIND = unix.MS_BIND | unix.MS_REC
+
+ // UNBINDABLE creates a mount which cannot be cloned through a bind operation.
+ UNBINDABLE = unix.MS_UNBINDABLE
+
+ // RUNBINDABLE marks the entire mount tree as UNBINDABLE.
+ RUNBINDABLE = unix.MS_UNBINDABLE | unix.MS_REC
+
+ // PRIVATE creates a mount which carries no propagation abilities.
+ PRIVATE = unix.MS_PRIVATE
+
+ // RPRIVATE marks the entire mount tree as PRIVATE.
+ RPRIVATE = unix.MS_PRIVATE | unix.MS_REC
+
+ // SLAVE creates a mount which receives propagation from its master, but not
+ // vice versa.
+ SLAVE = unix.MS_SLAVE
+
+ // RSLAVE marks the entire mount tree as SLAVE.
+ RSLAVE = unix.MS_SLAVE | unix.MS_REC
+
+ // SHARED creates a mount which provides the ability to create mirrors of
+ // that mount such that mounts and unmounts within any of the mirrors
+ // propagate to the other mirrors.
+ SHARED = unix.MS_SHARED
+
+ // RSHARED marks the entire mount tree as SHARED.
+ RSHARED = unix.MS_SHARED | unix.MS_REC
+
+ // RELATIME updates inode access times relative to modify or change time.
+ RELATIME = unix.MS_RELATIME
+
+ // STRICTATIME allows to explicitly request full atime updates. This makes
+ // it possible for the kernel to default to relatime or noatime but still
+ // allow userspace to override it.
+ STRICTATIME = unix.MS_STRICTATIME
+
+ mntDetach = unix.MNT_DETACH
+)
diff --git a/vendor/github.com/moby/sys/mount/flags_unsupported.go b/vendor/github.com/moby/sys/mount/flags_unsupported.go
new file mode 100644
index 000000000..e1d64f6b9
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/flags_unsupported.go
@@ -0,0 +1,30 @@
+// +build !linux,!freebsd freebsd,!cgo
+
+package mount
+
+// These flags are unsupported.
+const (
+ BIND = 0
+ DIRSYNC = 0
+ MANDLOCK = 0
+ NOATIME = 0
+ NODEV = 0
+ NODIRATIME = 0
+ NOEXEC = 0
+ NOSUID = 0
+ UNBINDABLE = 0
+ RUNBINDABLE = 0
+ PRIVATE = 0
+ RPRIVATE = 0
+ SHARED = 0
+ RSHARED = 0
+ SLAVE = 0
+ RSLAVE = 0
+ RBIND = 0
+ RELATIME = 0
+ REMOUNT = 0
+ STRICTATIME = 0
+ SYNCHRONOUS = 0
+ RDONLY = 0
+ mntDetach = 0
+)
diff --git a/vendor/github.com/moby/sys/mount/go.mod b/vendor/github.com/moby/sys/mount/go.mod
new file mode 100644
index 000000000..21cef0a95
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/go.mod
@@ -0,0 +1,8 @@
+module github.com/moby/sys/mount
+
+go 1.14
+
+require (
+ github.com/moby/sys/mountinfo v0.1.0
+ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae
+)
diff --git a/vendor/github.com/moby/sys/mount/go.sum b/vendor/github.com/moby/sys/mount/go.sum
new file mode 100644
index 000000000..ae99f8596
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/go.sum
@@ -0,0 +1,4 @@
+github.com/moby/sys/mountinfo v0.1.0 h1:r8vMRbMAFEAfiNptYVokP+nfxPJzvRuia5e2vzXtENo=
+github.com/moby/sys/mountinfo v0.1.0/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/vendor/github.com/moby/sys/mount/mount.go b/vendor/github.com/moby/sys/mount/mount.go
new file mode 100644
index 000000000..4a7bb27b1
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/mount.go
@@ -0,0 +1,67 @@
+// +build go1.13
+
+package mount
+
+import (
+ "fmt"
+ "sort"
+
+ "github.com/moby/sys/mountinfo"
+)
+
+// Mount will mount filesystem according to the specified configuration.
+// Options must be specified like the mount or fstab unix commands:
+// "opt1=val1,opt2=val2". See flags.go for supported option flags.
+func Mount(device, target, mType, options string) error {
+ flag, data := parseOptions(options)
+ return mount(device, target, mType, uintptr(flag), data)
+}
+
+// Unmount lazily unmounts a filesystem on supported platforms, otherwise does
+// a normal unmount. If target is not a mount point, no error is returned.
+func Unmount(target string) error {
+ return unmount(target, mntDetach)
+}
+
+// RecursiveUnmount unmounts the target and all mounts underneath, starting
+// with the deepest mount first. The argument does not have to be a mount
+// point itself.
+func RecursiveUnmount(target string) error {
+ // Fast path, works if target is a mount point that can be unmounted.
+ // On Linux, mntDetach flag ensures a recursive unmount. For other
+ // platforms, if there are submounts, we'll get EBUSY (and fall back
+ // to the slow path). NOTE we do not ignore EINVAL here as target might
+ // not be a mount point itself (but there can be mounts underneath).
+ if err := unmountBare(target, mntDetach); err == nil {
+ return nil
+ }
+
+ // Slow path: get all submounts, sort, unmount one by one.
+ mounts, err := mountinfo.GetMounts(mountinfo.PrefixFilter(target))
+ if err != nil {
+ return err
+ }
+
+ // Make the deepest mount be first
+ sort.Slice(mounts, func(i, j int) bool {
+ return len(mounts[i].Mountpoint) > len(mounts[j].Mountpoint)
+ })
+
+ var suberr error
+ for i, m := range mounts {
+ err = unmount(m.Mountpoint, mntDetach)
+ if err != nil {
+ if i == len(mounts)-1 { // last mount
+ return fmt.Errorf("%w (possible cause: %s)", err, suberr)
+ }
+ // This is a submount, we can ignore the error for now,
+ // the final unmount will fail if this is a real problem.
+ // With that in mind, the _first_ failed unmount error
+ // might be the real error cause, so let's keep it.
+ if suberr == nil {
+ suberr = err
+ }
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/moby/sys/mount/mount_errors.go b/vendor/github.com/moby/sys/mount/mount_errors.go
new file mode 100644
index 000000000..936a26373
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/mount_errors.go
@@ -0,0 +1,46 @@
+// +build !windows
+
+package mount
+
+import "strconv"
+
+// mountError records an error from mount or unmount operation
+type mountError struct {
+ op string
+ source, target string
+ flags uintptr
+ data string
+ err error
+}
+
+func (e *mountError) Error() string {
+ out := e.op + " "
+
+ if e.source != "" {
+ out += e.source + ":" + e.target
+ } else {
+ out += e.target
+ }
+
+ if e.flags != uintptr(0) {
+ out += ", flags: 0x" + strconv.FormatUint(uint64(e.flags), 16)
+ }
+ if e.data != "" {
+ out += ", data: " + e.data
+ }
+
+ out += ": " + e.err.Error()
+ return out
+}
+
+// Cause returns the underlying cause of the error.
+// This is a convention used in github.com/pkg/errors
+func (e *mountError) Cause() error {
+ return e.err
+}
+
+// Unwrap returns the underlying error.
+// This is a convention used in golang 1.13+
+func (e *mountError) Unwrap() error {
+ return e.err
+}
diff --git a/vendor/github.com/moby/sys/mount/mounter_freebsd.go b/vendor/github.com/moby/sys/mount/mounter_freebsd.go
new file mode 100644
index 000000000..3964af4f7
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/mounter_freebsd.go
@@ -0,0 +1,59 @@
+package mount
+
+/*
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/_iovec.h>
+#include <sys/mount.h>
+#include <sys/param.h>
+*/
+import "C"
+
+import (
+ "strings"
+ "syscall"
+ "unsafe"
+)
+
+func allocateIOVecs(options []string) []C.struct_iovec {
+ out := make([]C.struct_iovec, len(options))
+ for i, option := range options {
+ out[i].iov_base = unsafe.Pointer(C.CString(option))
+ out[i].iov_len = C.size_t(len(option) + 1)
+ }
+ return out
+}
+
+func mount(device, target, mType string, flag uintptr, data string) error {
+ isNullFS := false
+
+ xs := strings.Split(data, ",")
+ for _, x := range xs {
+ if x == "bind" {
+ isNullFS = true
+ }
+ }
+
+ options := []string{"fspath", target}
+ if isNullFS {
+ options = append(options, "fstype", "nullfs", "target", device)
+ } else {
+ options = append(options, "fstype", mType, "from", device)
+ }
+ rawOptions := allocateIOVecs(options)
+ for _, rawOption := range rawOptions {
+ defer C.free(rawOption.iov_base)
+ }
+
+ if errno := C.nmount(&rawOptions[0], C.uint(len(options)), C.int(flag)); errno != 0 {
+ return &mountError{
+ op: "mount",
+ source: device,
+ target: target,
+ flags: flag,
+ err: syscall.Errno(errno),
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/moby/sys/mount/mounter_linux.go b/vendor/github.com/moby/sys/mount/mounter_linux.go
new file mode 100644
index 000000000..0c477cc3d
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/mounter_linux.go
@@ -0,0 +1,73 @@
+package mount
+
+import (
+ "golang.org/x/sys/unix"
+)
+
+const (
+ // ptypes is the set propagation types.
+ ptypes = unix.MS_SHARED | unix.MS_PRIVATE | unix.MS_SLAVE | unix.MS_UNBINDABLE
+
+ // pflags is the full set valid flags for a change propagation call.
+ pflags = ptypes | unix.MS_REC | unix.MS_SILENT
+
+ // broflags is the combination of bind and read only
+ broflags = unix.MS_BIND | unix.MS_RDONLY
+)
+
+// isremount returns true if either device name or flags identify a remount request, false otherwise.
+func isremount(device string, flags uintptr) bool {
+ switch {
+ // We treat device "" and "none" as a remount request to provide compatibility with
+ // requests that don't explicitly set MS_REMOUNT such as those manipulating bind mounts.
+ case flags&unix.MS_REMOUNT != 0, device == "", device == "none":
+ return true
+ default:
+ return false
+ }
+}
+
+func mount(device, target, mType string, flags uintptr, data string) error {
+ oflags := flags &^ ptypes
+ if !isremount(device, flags) || data != "" {
+ // Initial call applying all non-propagation flags for mount
+ // or remount with changed data
+ if err := unix.Mount(device, target, mType, oflags, data); err != nil {
+ return &mountError{
+ op: "mount",
+ source: device,
+ target: target,
+ flags: oflags,
+ data: data,
+ err: err,
+ }
+ }
+ }
+
+ if flags&ptypes != 0 {
+ // Change the propagation type.
+ if err := unix.Mount("", target, "", flags&pflags, ""); err != nil {
+ return &mountError{
+ op: "remount",
+ target: target,
+ flags: flags & pflags,
+ err: err,
+ }
+ }
+ }
+
+ if oflags&broflags == broflags {
+ // Remount the bind to apply read only.
+ if err := unix.Mount("", target, "", oflags|unix.MS_REMOUNT, ""); err != nil {
+ return &mountError{
+ op: "remount-ro",
+ target: target,
+ flags: oflags | unix.MS_REMOUNT,
+ err: err,
+ }
+
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/moby/sys/mount/mounter_unsupported.go b/vendor/github.com/moby/sys/mount/mounter_unsupported.go
new file mode 100644
index 000000000..15380671c
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/mounter_unsupported.go
@@ -0,0 +1,7 @@
+// +build !linux,!freebsd freebsd,!cgo
+
+package mount
+
+func mount(device, target, mType string, flag uintptr, data string) error {
+ panic("Not implemented")
+}
diff --git a/vendor/github.com/moby/sys/mount/sharedsubtree_linux.go b/vendor/github.com/moby/sys/mount/sharedsubtree_linux.go
new file mode 100644
index 000000000..948e6bacd
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/sharedsubtree_linux.go
@@ -0,0 +1,73 @@
+package mount
+
+import "github.com/moby/sys/mountinfo"
+
+// MakeShared ensures a mounted filesystem has the SHARED mount option enabled.
+// See the supported options in flags.go for further reference.
+func MakeShared(mountPoint string) error {
+ return ensureMountedAs(mountPoint, SHARED)
+}
+
+// MakeRShared ensures a mounted filesystem has the RSHARED mount option enabled.
+// See the supported options in flags.go for further reference.
+func MakeRShared(mountPoint string) error {
+ return ensureMountedAs(mountPoint, RSHARED)
+}
+
+// MakePrivate ensures a mounted filesystem has the PRIVATE mount option enabled.
+// See the supported options in flags.go for further reference.
+func MakePrivate(mountPoint string) error {
+ return ensureMountedAs(mountPoint, PRIVATE)
+}
+
+// MakeRPrivate ensures a mounted filesystem has the RPRIVATE mount option
+// enabled. See the supported options in flags.go for further reference.
+func MakeRPrivate(mountPoint string) error {
+ return ensureMountedAs(mountPoint, RPRIVATE)
+}
+
+// MakeSlave ensures a mounted filesystem has the SLAVE mount option enabled.
+// See the supported options in flags.go for further reference.
+func MakeSlave(mountPoint string) error {
+ return ensureMountedAs(mountPoint, SLAVE)
+}
+
+// MakeRSlave ensures a mounted filesystem has the RSLAVE mount option enabled.
+// See the supported options in flags.go for further reference.
+func MakeRSlave(mountPoint string) error {
+ return ensureMountedAs(mountPoint, RSLAVE)
+}
+
+// MakeUnbindable ensures a mounted filesystem has the UNBINDABLE mount option
+// enabled. See the supported options in flags.go for further reference.
+func MakeUnbindable(mountPoint string) error {
+ return ensureMountedAs(mountPoint, UNBINDABLE)
+}
+
+// MakeRUnbindable ensures a mounted filesystem has the RUNBINDABLE mount
+// option enabled. See the supported options in flags.go for further reference.
+func MakeRUnbindable(mountPoint string) error {
+ return ensureMountedAs(mountPoint, RUNBINDABLE)
+}
+
+// MakeMount ensures that the file or directory given is a mount point,
+// bind mounting it to itself it case it is not.
+func MakeMount(mnt string) error {
+ mounted, err := mountinfo.Mounted(mnt)
+ if err != nil {
+ return err
+ }
+ if mounted {
+ return nil
+ }
+
+ return mount(mnt, mnt, "none", uintptr(BIND), "")
+}
+
+func ensureMountedAs(mnt string, flags int) error {
+ if err := MakeMount(mnt); err != nil {
+ return err
+ }
+
+ return mount("", mnt, "none", uintptr(flags), "")
+}
diff --git a/vendor/github.com/moby/sys/mount/unmount_unix.go b/vendor/github.com/moby/sys/mount/unmount_unix.go
new file mode 100644
index 000000000..924d059a7
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/unmount_unix.go
@@ -0,0 +1,26 @@
+// +build !windows
+
+package mount
+
+import "golang.org/x/sys/unix"
+
+func unmountBare(target string, flags int) error {
+ return unix.Unmount(target, flags)
+}
+
+func unmount(target string, flags int) error {
+ err := unmountBare(target, flags)
+ if err == nil || err == unix.EINVAL {
+ // Ignore "not mounted" error here. Note the same error
+ // can be returned if flags are invalid, so this code
+ // assumes that the flags value is always correct.
+ return nil
+ }
+
+ return &mountError{
+ op: "umount",
+ target: target,
+ flags: uintptr(flags),
+ err: err,
+ }
+}
diff --git a/vendor/github.com/moby/sys/mount/unmount_unsupported.go b/vendor/github.com/moby/sys/mount/unmount_unsupported.go
new file mode 100644
index 000000000..4d6073ec6
--- /dev/null
+++ b/vendor/github.com/moby/sys/mount/unmount_unsupported.go
@@ -0,0 +1,11 @@
+// +build windows
+
+package mount
+
+func unmountBare(_ string, _ int) error {
+ panic("Not implemented")
+}
+
+func unmount(_ string, _ int) error {
+ panic("Not implemented")
+}
diff --git a/vendor/github.com/moby/sys/mountinfo/doc.go b/vendor/github.com/moby/sys/mountinfo/doc.go
new file mode 100644
index 000000000..21aa8dd59
--- /dev/null
+++ b/vendor/github.com/moby/sys/mountinfo/doc.go
@@ -0,0 +1,47 @@
+// Package mountinfo provides a set of functions to retrieve information about OS mounts.
+// Currently it supports Linux. For historical reasons, there is also some support for FreeBSD,
+// and a shallow implementation for Windows, but in general this is Linux-only package, so
+// the rest of the document only applies to Linux, unless explicitly specified otherwise.
+//
+// In Linux, information about mounts seen by the current process is available from
+// /proc/self/mountinfo. Note that due to mount namespaces, different processes can
+// see different mounts. A per-process mountinfo table is available from /proc/<PID>/mountinfo,
+// where <PID> is a numerical process identifier.
+//
+// In general, /proc is not a very effective interface, and mountinfo is not an exception.
+// For example, there is no way to get information about a specific mount point (i.e. it
+// is all-or-nothing). This package tries to hide the /proc ineffectiveness by using
+// parse filters while reading mountinfo. A filter can skip some entries, or stop
+// processing the rest of the file once the needed information is found.
+//
+// For mountinfo filters that accept path as an argument, the path must be:
+// - absolute;
+// - having all symlinks resolved;
+// - being cleaned.
+//
+// One way to achieve all of the above is to employ filepath.Abs followed by
+// filepath.EvalSymlinks (the latter calls filepath.Clean on the result so
+// there is no need to explicitly call filepath.Clean).
+//
+// NOTE that in many cases there is no need to consult mountinfo at all. Here are some
+// of the cases where mountinfo should not be parsed:
+//
+// 1. Before performing a mount. Usually, this is not needed, but if required (say to
+// prevent overmounts), to check whether a directory is mounted, call os.Lstat
+// on it and its parent directory, and compare their st.Sys().(*syscall.Stat_t).Dev
+// fields -- if they differ, then the directory is the mount point. NOTE this does
+// not work for bind mounts. Optionally, the filesystem type can also be checked
+// by calling unix.Statfs and checking the Type field (i.e. filesystem type).
+//
+// 2. After performing a mount. If there is no error returned, the mount succeeded;
+// checking the mount table for a new mount is redundant and expensive.
+//
+// 3. Before performing an unmount. It is more efficient to do an unmount and ignore
+// a specific error (EINVAL) which tells the directory is not mounted.
+//
+// 4. After performing an unmount. If there is no error returned, the unmount succeeded.
+//
+// 5. To find the mount point root of a specific directory. You can perform os.Stat()
+// on the directory and traverse up until the Dev field of a parent directory differs.
+
+package mountinfo
diff --git a/vendor/github.com/moby/sys/mountinfo/go.mod b/vendor/github.com/moby/sys/mountinfo/go.mod
index 10d9a15a6..9749ea96d 100644
--- a/vendor/github.com/moby/sys/mountinfo/go.mod
+++ b/vendor/github.com/moby/sys/mountinfo/go.mod
@@ -1,3 +1,5 @@
module github.com/moby/sys/mountinfo
go 1.14
+
+require golang.org/x/sys v0.0.0-20200909081042-eff7692f9009
diff --git a/vendor/github.com/moby/sys/mountinfo/go.sum b/vendor/github.com/moby/sys/mountinfo/go.sum
new file mode 100644
index 000000000..2a5be7ea8
--- /dev/null
+++ b/vendor/github.com/moby/sys/mountinfo/go.sum
@@ -0,0 +1,2 @@
+golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM=
+golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/vendor/github.com/moby/sys/mountinfo/mounted_linux.go b/vendor/github.com/moby/sys/mountinfo/mounted_linux.go
new file mode 100644
index 000000000..bc9f6b2ad
--- /dev/null
+++ b/vendor/github.com/moby/sys/mountinfo/mounted_linux.go
@@ -0,0 +1,58 @@
+package mountinfo
+
+import (
+ "os"
+ "path/filepath"
+
+ "golang.org/x/sys/unix"
+)
+
+// mountedByOpenat2 is a method of detecting a mount that works for all kinds
+// of mounts (incl. bind mounts), but requires a recent (v5.6+) linux kernel.
+func mountedByOpenat2(path string) (bool, error) {
+ dir, last := filepath.Split(path)
+
+ dirfd, err := unix.Openat2(unix.AT_FDCWD, dir, &unix.OpenHow{
+ Flags: unix.O_PATH | unix.O_CLOEXEC,
+ })
+ if err != nil {
+ if err == unix.ENOENT { // not a mount
+ return false, nil
+ }
+ return false, &os.PathError{Op: "openat2", Path: dir, Err: err}
+ }
+ fd, err := unix.Openat2(dirfd, last, &unix.OpenHow{
+ Flags: unix.O_PATH | unix.O_CLOEXEC | unix.O_NOFOLLOW,
+ Resolve: unix.RESOLVE_NO_XDEV,
+ })
+ _ = unix.Close(dirfd)
+ switch err {
+ case nil: // definitely not a mount
+ _ = unix.Close(fd)
+ return false, nil
+ case unix.EXDEV: // definitely a mount
+ return true, nil
+ case unix.ENOENT: // not a mount
+ return false, nil
+ }
+ // not sure
+ return false, &os.PathError{Op: "openat2", Path: path, Err: err}
+}
+
+func mounted(path string) (bool, error) {
+ // Try a fast path, using openat2() with RESOLVE_NO_XDEV.
+ mounted, err := mountedByOpenat2(path)
+ if err == nil {
+ return mounted, nil
+ }
+ // Another fast path: compare st.st_dev fields.
+ mounted, err = mountedByStat(path)
+ // This does not work for bind mounts, so false negative
+ // is possible, therefore only trust if return is true.
+ if mounted && err == nil {
+ return mounted, nil
+ }
+
+ // Fallback to parsing mountinfo
+ return mountedByMountinfo(path)
+}
diff --git a/vendor/github.com/moby/sys/mountinfo/mounted_unix.go b/vendor/github.com/moby/sys/mountinfo/mounted_unix.go
new file mode 100644
index 000000000..c4d66b2f4
--- /dev/null
+++ b/vendor/github.com/moby/sys/mountinfo/mounted_unix.go
@@ -0,0 +1,66 @@
+// +build linux freebsd,cgo
+
+package mountinfo
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+
+ "golang.org/x/sys/unix"
+)
+
+func mountedByStat(path string) (bool, error) {
+ var st unix.Stat_t
+
+ if err := unix.Lstat(path, &st); err != nil {
+ if err == unix.ENOENT {
+ // Treat ENOENT as "not mounted".
+ return false, nil
+ }
+ return false, &os.PathError{Op: "stat", Path: path, Err: err}
+ }
+ dev := st.Dev
+ parent := filepath.Dir(path)
+ if err := unix.Lstat(parent, &st); err != nil {
+ return false, &os.PathError{Op: "stat", Path: parent, Err: err}
+ }
+ if dev != st.Dev {
+ // Device differs from that of parent,
+ // so definitely a mount point.
+ return true, nil
+ }
+ // NB: this does not detect bind mounts on Linux.
+ return false, nil
+}
+
+func normalizePath(path string) (realPath string, err error) {
+ if realPath, err = filepath.Abs(path); err != nil {
+ return "", fmt.Errorf("unable to get absolute path for %q: %w", path, err)
+ }
+ if realPath, err = filepath.EvalSymlinks(realPath); err != nil {
+ return "", fmt.Errorf("failed to canonicalise path for %q: %w", path, err)
+ }
+ if _, err := os.Stat(realPath); err != nil {
+ return "", fmt.Errorf("failed to stat target of %q: %w", path, err)
+ }
+ return realPath, nil
+}
+
+func mountedByMountinfo(path string) (bool, error) {
+ path, err := normalizePath(path)
+ if err != nil {
+ if errors.Is(err, unix.ENOENT) {
+ // treat ENOENT as "not mounted"
+ return false, nil
+ }
+ return false, err
+ }
+ entries, err := GetMounts(SingleEntryFilter(path))
+ if err != nil {
+ return false, err
+ }
+
+ return len(entries) > 0, nil
+}
diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo.go b/vendor/github.com/moby/sys/mountinfo/mountinfo.go
index 136b14167..1987fcbb2 100644
--- a/vendor/github.com/moby/sys/mountinfo/mountinfo.go
+++ b/vendor/github.com/moby/sys/mountinfo/mountinfo.go
@@ -1,6 +1,9 @@
package mountinfo
-import "io"
+import (
+ "io"
+ "os"
+)
// GetMounts retrieves a list of mounts for the current running process,
// with an optional filter applied (use nil for no filter).
@@ -16,15 +19,17 @@ func GetMountsFromReader(reader io.Reader, f FilterFunc) ([]*Info, error) {
return parseInfoFile(reader, f)
}
-// Mounted determines if a specified mountpoint has been mounted.
-// On Linux it looks at /proc/self/mountinfo.
-func Mounted(mountpoint string) (bool, error) {
- entries, err := GetMounts(SingleEntryFilter(mountpoint))
- if err != nil {
- return false, err
+// Mounted determines if a specified path is a mount point.
+//
+// The argument must be an absolute path, with all symlinks resolved, and clean.
+// One way to ensure it is to process the path using filepath.Abs followed by
+// filepath.EvalSymlinks before calling this function.
+func Mounted(path string) (bool, error) {
+ // root is always mounted
+ if path == string(os.PathSeparator) {
+ return true, nil
}
-
- return len(entries) > 0, nil
+ return mounted(path)
}
// Info reveals information about a particular mounted filesystem. This
diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go
index 795026465..8aebe1ad4 100644
--- a/vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go
+++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go
@@ -15,7 +15,7 @@ import "strings"
type FilterFunc func(*Info) (skip, stop bool)
// PrefixFilter discards all entries whose mount points
-// do not start with a specific prefix
+// do not start with a specific prefix.
func PrefixFilter(prefix string) FilterFunc {
return func(m *Info) (bool, bool) {
skip := !strings.HasPrefix(m.Mountpoint, prefix)
@@ -23,7 +23,7 @@ func PrefixFilter(prefix string) FilterFunc {
}
}
-// SingleEntryFilter looks for a specific entry
+// SingleEntryFilter looks for a specific entry.
func SingleEntryFilter(mp string) FilterFunc {
return func(m *Info) (bool, bool) {
if m.Mountpoint == mp {
diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_freebsd.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_freebsd.go
index a7dbb1b46..b30dc1625 100644
--- a/vendor/github.com/moby/sys/mountinfo/mountinfo_freebsd.go
+++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_freebsd.go
@@ -51,3 +51,15 @@ func parseMountTable(filter FilterFunc) ([]*Info, error) {
}
return out, nil
}
+
+func mounted(path string) (bool, error) {
+ // Fast path: compare st.st_dev fields.
+ // This should always work for FreeBSD.
+ mounted, err := mountedByStat(path)
+ if err == nil {
+ return mounted, nil
+ }
+
+ // Fallback to parsing mountinfo
+ return mountedByMountinfo(path)
+}
diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go
index 2d630c8dc..cdfd37da5 100644
--- a/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go
+++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go
@@ -71,12 +71,18 @@ func parseInfoFile(r io.Reader, filter FilterFunc) ([]*Info, error) {
p := &Info{}
// Fill in the fields that a filter might check
- p.Mountpoint, err = strconv.Unquote(`"` + fields[4] + `"`)
+ p.Mountpoint, err = unescape(fields[4])
if err != nil {
- return nil, fmt.Errorf("Parsing '%s' failed: unable to unquote mount point field: %w", fields[4], err)
+ return nil, fmt.Errorf("Parsing '%s' failed: mount point: %w", fields[4], err)
+ }
+ p.Fstype, err = unescape(fields[sepIdx+1])
+ if err != nil {
+ return nil, fmt.Errorf("Parsing '%s' failed: fstype: %w", fields[sepIdx+1], err)
+ }
+ p.Source, err = unescape(fields[sepIdx+2])
+ if err != nil {
+ return nil, fmt.Errorf("Parsing '%s' failed: source: %w", fields[sepIdx+2], err)
}
- p.Fstype = fields[sepIdx+1]
- p.Source = fields[sepIdx+2]
p.VfsOpts = fields[sepIdx+3]
// Run a filter soon so we can skip parsing/adding entries
@@ -101,9 +107,9 @@ func parseInfoFile(r io.Reader, filter FilterFunc) ([]*Info, error) {
p.Major, _ = strconv.Atoi(mm[0])
p.Minor, _ = strconv.Atoi(mm[1])
- p.Root, err = strconv.Unquote(`"` + fields[3] + `"`)
+ p.Root, err = unescape(fields[3])
if err != nil {
- return nil, fmt.Errorf("Parsing '%s' failed: unable to unquote root field: %w", fields[3], err)
+ return nil, fmt.Errorf("Parsing '%s' failed: root: %w", fields[3], err)
}
p.Opts = fields[5]
@@ -150,3 +156,61 @@ func PidMountInfo(pid int) ([]*Info, error) {
return parseInfoFile(f, nil)
}
+
+// A few specific characters in mountinfo path entries (root and mountpoint)
+// are escaped using a backslash followed by a character's ascii code in octal.
+//
+// space -- as \040
+// tab (aka \t) -- as \011
+// newline (aka \n) -- as \012
+// backslash (aka \\) -- as \134
+//
+// This function converts path from mountinfo back, i.e. it unescapes the above sequences.
+func unescape(path string) (string, error) {
+ // try to avoid copying
+ if strings.IndexByte(path, '\\') == -1 {
+ return path, nil
+ }
+
+ // The following code is UTF-8 transparent as it only looks for some
+ // specific characters (backslach and 0..7) with values < utf8.RuneSelf,
+ // and everything else is passed through as is.
+ buf := make([]byte, len(path))
+ bufLen := 0
+ for i := 0; i < len(path); i++ {
+ if path[i] != '\\' {
+ buf[bufLen] = path[i]
+ bufLen++
+ continue
+ }
+ s := path[i:]
+ if len(s) < 4 {
+ // too short
+ return "", fmt.Errorf("bad escape sequence %q: too short", s)
+ }
+ c := s[1]
+ switch c {
+ case '0', '1', '2', '3', '4', '5', '6', '7':
+ v := c - '0'
+ for j := 2; j < 4; j++ { // one digit already; two more
+ if s[j] < '0' || s[j] > '7' {
+ return "", fmt.Errorf("bad escape sequence %q: not a digit", s[:3])
+ }
+ x := s[j] - '0'
+ v = (v << 3) | x
+ }
+ if v > 255 {
+ return "", fmt.Errorf("bad escape sequence %q: out of range" + s[:3])
+ }
+ buf[bufLen] = v
+ bufLen++
+ i += 3
+ continue
+ default:
+ return "", fmt.Errorf("bad escape sequence %q: not a digit" + s[:3])
+
+ }
+ }
+
+ return string(buf[:bufLen]), nil
+}
diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go
index dc1869211..1eb8558c8 100644
--- a/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go
+++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go
@@ -8,10 +8,16 @@ import (
"runtime"
)
+var errNotImplemented = fmt.Errorf("not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+
func parseMountTable(_ FilterFunc) ([]*Info, error) {
- return nil, fmt.Errorf("mount.parseMountTable is not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+ return nil, errNotImplemented
}
func parseInfoFile(_ io.Reader, f FilterFunc) ([]*Info, error) {
return parseMountTable(f)
}
+
+func mounted(path string) (bool, error) {
+ return false, errNotImplemented
+}
diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_windows.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_windows.go
index 69ffdc52b..5659c1b0f 100644
--- a/vendor/github.com/moby/sys/mountinfo/mountinfo_windows.go
+++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_windows.go
@@ -10,3 +10,7 @@ func parseMountTable(_ FilterFunc) ([]*Info, error) {
func parseInfoFile(_ io.Reader, f FilterFunc) ([]*Info, error) {
return parseMountTable(f)
}
+
+func mounted(_ string) (bool, error) {
+ return false, nil
+}