...

Source file src/k8s.io/kubernetes/pkg/util/removeall/removeall.go

Documentation: k8s.io/kubernetes/pkg/util/removeall

     1  /*
     2  Copyright 2017 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 removeall
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  	"os"
    23  	"syscall"
    24  
    25  	"k8s.io/mount-utils"
    26  )
    27  
    28  // RemoveAllOneFilesystemCommon removes the path and any children it contains,
    29  // using the provided remove function. It removes everything it can but returns
    30  // the first error it encounters. If the path does not exist, RemoveAll
    31  // returns nil (no error).
    32  // It makes sure it does not cross mount boundary, i.e. it does *not* remove
    33  // files from another filesystems. Like 'rm -rf --one-file-system'.
    34  // It is copied from RemoveAll() sources, with IsLikelyNotMountPoint
    35  func RemoveAllOneFilesystemCommon(mounter mount.Interface, path string, remove func(string) error) error {
    36  	// Simple case: if Remove works, we're done.
    37  	err := remove(path)
    38  	if err == nil || os.IsNotExist(err) {
    39  		return nil
    40  	}
    41  
    42  	// Otherwise, is this a directory we need to recurse into?
    43  	dir, serr := os.Lstat(path)
    44  	if serr != nil {
    45  		if serr, ok := serr.(*os.PathError); ok && (os.IsNotExist(serr.Err) || serr.Err == syscall.ENOTDIR) {
    46  			return nil
    47  		}
    48  		return serr
    49  	}
    50  	if !dir.IsDir() {
    51  		// Not a directory; return the error from remove.
    52  		return err
    53  	}
    54  
    55  	// Directory.
    56  	isNotMount, err := mounter.IsLikelyNotMountPoint(path)
    57  	if err != nil {
    58  		return err
    59  	}
    60  	if !isNotMount {
    61  		return fmt.Errorf("cannot delete directory %s: it is a mount point", path)
    62  	}
    63  
    64  	fd, err := os.Open(path)
    65  	if err != nil {
    66  		if os.IsNotExist(err) {
    67  			// Race. It was deleted between the Lstat and Open.
    68  			// Return nil per RemoveAll's docs.
    69  			return nil
    70  		}
    71  		return err
    72  	}
    73  
    74  	// Remove contents & return first error.
    75  	err = nil
    76  	for {
    77  		names, err1 := fd.Readdirnames(100)
    78  		for _, name := range names {
    79  			err1 := RemoveAllOneFilesystemCommon(mounter, path+string(os.PathSeparator)+name, remove)
    80  			if err == nil {
    81  				err = err1
    82  			}
    83  		}
    84  		if err1 == io.EOF {
    85  			break
    86  		}
    87  		// If Readdirnames returned an error, use it.
    88  		if err == nil {
    89  			err = err1
    90  		}
    91  		if len(names) == 0 {
    92  			break
    93  		}
    94  	}
    95  
    96  	// Close directory, because windows won't remove opened directory.
    97  	fd.Close()
    98  
    99  	// Remove directory.
   100  	err1 := remove(path)
   101  	if err1 == nil || os.IsNotExist(err1) {
   102  		return nil
   103  	}
   104  	if err == nil {
   105  		err = err1
   106  	}
   107  	return err
   108  }
   109  
   110  // RemoveAllOneFilesystem removes the path and any children it contains, using
   111  // the os.Remove function. It makes sure it does not cross mount boundaries,
   112  // i.e. it returns an error rather than remove files from another filesystem.
   113  // It removes everything it can but returns the first error it encounters.
   114  // If the path does not exist, it returns nil (no error).
   115  func RemoveAllOneFilesystem(mounter mount.Interface, path string) error {
   116  	return RemoveAllOneFilesystemCommon(mounter, path, os.Remove)
   117  }
   118  
   119  // RemoveDirsOneFilesystem removes the path and any empty subdirectories it
   120  // contains, using the syscall.Rmdir function. Unlike RemoveAllOneFilesystem,
   121  // RemoveDirsOneFilesystem will remove only directories and returns an error if
   122  // it encounters any files in the directory tree. It makes sure it does not
   123  // cross mount boundaries, i.e. it returns an error rather than remove dirs
   124  // from another filesystem. It removes everything it can but returns the first
   125  // error it encounters. If the path does not exist, it returns nil (no error).
   126  func RemoveDirsOneFilesystem(mounter mount.Interface, path string) error {
   127  	return RemoveAllOneFilesystemCommon(mounter, path, syscall.Rmdir)
   128  }
   129  

View as plain text