1 /* 2 Copyright 2014 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package hostutil 18 19 import ( 20 "fmt" 21 "os" 22 23 "k8s.io/mount-utils" 24 ) 25 26 // FileType enumerates the known set of possible file types. 27 type FileType string 28 29 const ( 30 // FileTypeBlockDev defines a constant for the block device FileType. 31 FileTypeBlockDev FileType = "BlockDevice" 32 // FileTypeCharDev defines a constant for the character device FileType. 33 FileTypeCharDev FileType = "CharDevice" 34 // FileTypeDirectory defines a constant for the directory FileType. 35 FileTypeDirectory FileType = "Directory" 36 // FileTypeFile defines a constant for the file FileType. 37 FileTypeFile FileType = "File" 38 // FileTypeSocket defines a constant for the socket FileType. 39 FileTypeSocket FileType = "Socket" 40 // FileTypeUnknown defines a constant for an unknown FileType. 41 FileTypeUnknown FileType = "" 42 ) 43 44 var ( 45 errUnknownFileType = fmt.Errorf("only recognise file, directory, socket, block device and character device") 46 ) 47 48 // HostUtils defines the set of methods for interacting with paths on a host. 49 type HostUtils interface { 50 // DeviceOpened determines if the device (e.g. /dev/sdc) is in use elsewhere 51 // on the system, i.e. still mounted. 52 DeviceOpened(pathname string) (bool, error) 53 // PathIsDevice determines if a path is a device. 54 PathIsDevice(pathname string) (bool, error) 55 // GetDeviceNameFromMount finds the device name by checking the mount path 56 // to get the global mount path within its plugin directory. 57 // TODO: Remove this method once the rbd and vsphere plugins are removed from in-tree. 58 GetDeviceNameFromMount(mounter mount.Interface, mountPath, pluginMountDir string) (string, error) 59 // MakeRShared checks that given path is on a mount with 'rshared' mount 60 // propagation. If not, it bind-mounts the path as rshared. 61 MakeRShared(path string) error 62 // GetFileType checks for file/directory/socket/block/character devices. 63 GetFileType(pathname string) (FileType, error) 64 // PathExists tests if the given path already exists 65 // Error is returned on any other error than "file not found". 66 PathExists(pathname string) (bool, error) 67 // EvalHostSymlinks returns the path name after evaluating symlinks. 68 EvalHostSymlinks(pathname string) (string, error) 69 // GetOwner returns the integer ID for the user and group of the given path 70 GetOwner(pathname string) (int64, int64, error) 71 // GetSELinuxSupport returns true if given path is on a mount that supports 72 // SELinux. 73 GetSELinuxSupport(pathname string) (bool, error) 74 // GetMode returns permissions of the path. 75 GetMode(pathname string) (os.FileMode, error) 76 // GetSELinuxMountContext returns value of -o context=XYZ mount option on 77 // given mount point. 78 GetSELinuxMountContext(pathname string) (string, error) 79 } 80 81 // Compile-time check to ensure all HostUtil implementations satisfy 82 // the Interface. 83 var _ HostUtils = &HostUtil{} 84 85 // getFileType checks for file/directory/socket and block/character devices. 86 func getFileType(pathname string) (FileType, error) { 87 var pathType FileType 88 info, err := os.Stat(pathname) 89 if os.IsNotExist(err) { 90 return pathType, fmt.Errorf("path %q does not exist", pathname) 91 } 92 // err in call to os.Stat 93 if err != nil { 94 return pathType, err 95 } 96 97 // checks whether the mode is the target mode. 98 isSpecificMode := func(mode, targetMode os.FileMode) bool { 99 return mode&targetMode == targetMode 100 } 101 102 mode := info.Mode() 103 if mode.IsDir() { 104 return FileTypeDirectory, nil 105 } else if mode.IsRegular() { 106 return FileTypeFile, nil 107 } else if isSpecificMode(mode, os.ModeSocket) { 108 return FileTypeSocket, nil 109 } else if isSpecificMode(mode, os.ModeDevice) { 110 if isSpecificMode(mode, os.ModeCharDevice) { 111 return FileTypeCharDev, nil 112 } 113 return FileTypeBlockDev, nil 114 } 115 116 return pathType, errUnknownFileType 117 } 118