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

     1  //go:build windows
     2  // +build windows
     3  
     4  /*
     5  Copyright 2017 The Kubernetes Authors.
     6  
     7  Licensed under the Apache License, Version 2.0 (the "License");
     8  you may not use this file except in compliance with the License.
     9  You may obtain a copy of the License at
    10  
    11      http://www.apache.org/licenses/LICENSE-2.0
    12  
    13  Unless required by applicable law or agreed to in writing, software
    14  distributed under the License is distributed on an "AS IS" BASIS,
    15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  See the License for the specific language governing permissions and
    17  limitations under the License.
    18  */
    19  
    20  package hostutil
    21  
    22  import (
    23  	"fmt"
    24  	"io/fs"
    25  	"os"
    26  	"path"
    27  	"path/filepath"
    28  	"strings"
    29  	"syscall"
    30  
    31  	"golang.org/x/sys/windows"
    32  	"k8s.io/klog/v2"
    33  	"k8s.io/kubernetes/pkg/util/filesystem"
    34  	"k8s.io/mount-utils"
    35  	utilpath "k8s.io/utils/path"
    36  )
    37  
    38  // HostUtil implements HostUtils for Windows platforms.
    39  type HostUtil struct{}
    40  
    41  // NewHostUtil returns a struct that implements HostUtils on Windows platforms
    42  func NewHostUtil() *HostUtil {
    43  	return &HostUtil{}
    44  }
    45  
    46  // GetDeviceNameFromMount given a mnt point, find the device
    47  func (hu *HostUtil) GetDeviceNameFromMount(mounter mount.Interface, mountPath, pluginMountDir string) (string, error) {
    48  	return getDeviceNameFromMount(mounter, mountPath, pluginMountDir)
    49  }
    50  
    51  // getDeviceNameFromMount find the device(drive) name in which
    52  // the mount path reference should match the given plugin mount directory. In case no mount path reference
    53  // matches, returns the volume name taken from its given mountPath
    54  func getDeviceNameFromMount(mounter mount.Interface, mountPath, pluginMountDir string) (string, error) {
    55  	refs, err := mounter.GetMountRefs(mountPath)
    56  	if err != nil {
    57  		klog.V(4).Infof("GetMountRefs failed for mount path %q: %v", mountPath, err)
    58  		return "", err
    59  	}
    60  	if len(refs) == 0 {
    61  		return "", fmt.Errorf("directory %s is not mounted", mountPath)
    62  	}
    63  	basemountPath := mount.NormalizeWindowsPath(pluginMountDir)
    64  	for _, ref := range refs {
    65  		if strings.Contains(ref, basemountPath) {
    66  			volumeID, err := filepath.Rel(mount.NormalizeWindowsPath(basemountPath), ref)
    67  			if err != nil {
    68  				klog.Errorf("Failed to get volume id from mount %s - %v", mountPath, err)
    69  				return "", err
    70  			}
    71  			return volumeID, nil
    72  		}
    73  	}
    74  
    75  	return path.Base(mountPath), nil
    76  }
    77  
    78  // DeviceOpened determines if the device is in use elsewhere
    79  func (hu *HostUtil) DeviceOpened(pathname string) (bool, error) {
    80  	return false, nil
    81  }
    82  
    83  // PathIsDevice determines if a path is a device.
    84  func (hu *HostUtil) PathIsDevice(pathname string) (bool, error) {
    85  	return false, nil
    86  }
    87  
    88  // MakeRShared checks that given path is on a mount with 'rshared' mount
    89  // propagation. Empty implementation here.
    90  func (hu *HostUtil) MakeRShared(path string) error {
    91  	return nil
    92  }
    93  
    94  func isSystemCannotAccessErr(err error) bool {
    95  	if fserr, ok := err.(*fs.PathError); ok {
    96  		errno, ok := fserr.Err.(syscall.Errno)
    97  		return ok && errno == windows.ERROR_CANT_ACCESS_FILE
    98  	}
    99  
   100  	return false
   101  }
   102  
   103  // GetFileType checks for sockets/block/character devices
   104  func (hu *(HostUtil)) GetFileType(pathname string) (FileType, error) {
   105  	filetype, err := getFileType(pathname)
   106  
   107  	// os.Stat will return a 1920 error (windows.ERROR_CANT_ACCESS_FILE) if we use it on a Unix Socket
   108  	// on Windows. In this case, we need to use a different method to check if it's a Unix Socket.
   109  	if isSystemCannotAccessErr(err) {
   110  		if isSocket, errSocket := filesystem.IsUnixDomainSocket(pathname); errSocket == nil && isSocket {
   111  			return FileTypeSocket, nil
   112  		}
   113  	}
   114  
   115  	return filetype, err
   116  }
   117  
   118  // PathExists checks whether the path exists
   119  func (hu *HostUtil) PathExists(pathname string) (bool, error) {
   120  	return utilpath.Exists(utilpath.CheckFollowSymlink, pathname)
   121  }
   122  
   123  // EvalHostSymlinks returns the path name after evaluating symlinks
   124  func (hu *HostUtil) EvalHostSymlinks(pathname string) (string, error) {
   125  	return filepath.EvalSymlinks(pathname)
   126  }
   127  
   128  // GetOwner returns the integer ID for the user and group of the given path
   129  // Note that on windows, it always returns 0. We actually don't set Group on
   130  // windows platform, see SetVolumeOwnership implementation.
   131  func (hu *HostUtil) GetOwner(pathname string) (int64, int64, error) {
   132  	return -1, -1, nil
   133  }
   134  
   135  // GetSELinuxSupport returns a boolean indicating support for SELinux.
   136  // Windows does not support SELinux.
   137  func (hu *HostUtil) GetSELinuxSupport(pathname string) (bool, error) {
   138  	return false, nil
   139  }
   140  
   141  // GetMode returns permissions of the path.
   142  func (hu *HostUtil) GetMode(pathname string) (os.FileMode, error) {
   143  	info, err := os.Stat(pathname)
   144  	if err != nil {
   145  		return 0, err
   146  	}
   147  	return info.Mode(), nil
   148  }
   149  
   150  // GetSELinuxMountContext returns value of -o context=XYZ mount option on
   151  // given mount point.
   152  func (hu *HostUtil) GetSELinuxMountContext(pathname string) (string, error) {
   153  	return "", nil
   154  }