k8s.io/kubernetes@v1.29.3/pkg/volume/util/hostutil/hostutil.go (about)

     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  // HostUtils defines the set of methods for interacting with paths on a host.
    45  type HostUtils interface {
    46  	// DeviceOpened determines if the device (e.g. /dev/sdc) is in use elsewhere
    47  	// on the system, i.e. still mounted.
    48  	DeviceOpened(pathname string) (bool, error)
    49  	// PathIsDevice determines if a path is a device.
    50  	PathIsDevice(pathname string) (bool, error)
    51  	// GetDeviceNameFromMount finds the device name by checking the mount path
    52  	// to get the global mount path within its plugin directory.
    53  	GetDeviceNameFromMount(mounter mount.Interface, mountPath, pluginMountDir string) (string, error)
    54  	// MakeRShared checks that given path is on a mount with 'rshared' mount
    55  	// propagation. If not, it bind-mounts the path as rshared.
    56  	MakeRShared(path string) error
    57  	// GetFileType checks for file/directory/socket/block/character devices.
    58  	GetFileType(pathname string) (FileType, error)
    59  	// PathExists tests if the given path already exists
    60  	// Error is returned on any other error than "file not found".
    61  	PathExists(pathname string) (bool, error)
    62  	// EvalHostSymlinks returns the path name after evaluating symlinks.
    63  	EvalHostSymlinks(pathname string) (string, error)
    64  	// GetOwner returns the integer ID for the user and group of the given path
    65  	GetOwner(pathname string) (int64, int64, error)
    66  	// GetSELinuxSupport returns true if given path is on a mount that supports
    67  	// SELinux.
    68  	GetSELinuxSupport(pathname string) (bool, error)
    69  	// GetMode returns permissions of the path.
    70  	GetMode(pathname string) (os.FileMode, error)
    71  	// GetSELinuxMountContext returns value of -o context=XYZ mount option on
    72  	// given mount point.
    73  	GetSELinuxMountContext(pathname string) (string, error)
    74  }
    75  
    76  // Compile-time check to ensure all HostUtil implementations satisfy
    77  // the Interface.
    78  var _ HostUtils = &HostUtil{}
    79  
    80  // getFileType checks for file/directory/socket and block/character devices.
    81  func getFileType(pathname string) (FileType, error) {
    82  	var pathType FileType
    83  	info, err := os.Stat(pathname)
    84  	if os.IsNotExist(err) {
    85  		return pathType, fmt.Errorf("path %q does not exist", pathname)
    86  	}
    87  	// err in call to os.Stat
    88  	if err != nil {
    89  		return pathType, err
    90  	}
    91  
    92  	// checks whether the mode is the target mode.
    93  	isSpecificMode := func(mode, targetMode os.FileMode) bool {
    94  		return mode&targetMode == targetMode
    95  	}
    96  
    97  	mode := info.Mode()
    98  	if mode.IsDir() {
    99  		return FileTypeDirectory, nil
   100  	} else if mode.IsRegular() {
   101  		return FileTypeFile, nil
   102  	} else if isSpecificMode(mode, os.ModeSocket) {
   103  		return FileTypeSocket, nil
   104  	} else if isSpecificMode(mode, os.ModeDevice) {
   105  		if isSpecificMode(mode, os.ModeCharDevice) {
   106  			return FileTypeCharDev, nil
   107  		}
   108  		return FileTypeBlockDev, nil
   109  	}
   110  
   111  	return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
   112  }