storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/os-readdir_other.go (about)

     1  //go:build plan9 || solaris
     2  // +build plan9 solaris
     3  
     4  /*
     5   * MinIO Cloud Storage, (C) 2016-2020 MinIO, Inc.
     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 cmd
    21  
    22  import (
    23  	"io"
    24  	"os"
    25  	"syscall"
    26  )
    27  
    28  func access(name string) error {
    29  	_, err := os.Lstat(name)
    30  	return err
    31  }
    32  
    33  // Return all the entries at the directory dirPath.
    34  func readDir(dirPath string) (entries []string, err error) {
    35  	return readDirN(dirPath, -1)
    36  }
    37  
    38  // readDirFn applies the fn() function on each entries at dirPath, doesn't recurse into
    39  // the directory itself, if the dirPath doesn't exist this function doesn't return
    40  // an error.
    41  func readDirFn(dirPath string, filter func(name string, typ os.FileMode) error) error {
    42  	d, err := Open(dirPath)
    43  	if err != nil {
    44  		if osErrToFileErr(err) == errFileNotFound {
    45  			return nil
    46  		}
    47  		return osErrToFileErr(err)
    48  	}
    49  	defer d.Close()
    50  
    51  	maxEntries := 1000
    52  	for {
    53  		// Read up to max number of entries.
    54  		fis, err := d.Readdir(maxEntries)
    55  		if err != nil {
    56  			if err == io.EOF {
    57  				break
    58  			}
    59  			err = osErrToFileErr(err)
    60  			if err == errFileNotFound {
    61  				return nil
    62  			}
    63  			return err
    64  		}
    65  		for _, fi := range fis {
    66  			if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
    67  				fi, err = Stat(pathJoin(dirPath, fi.Name()))
    68  				if err != nil {
    69  					// It got deleted in the meantime, not found
    70  					// or returns too many symlinks ignore this
    71  					// file/directory.
    72  					if osIsNotExist(err) || isSysErrPathNotFound(err) ||
    73  						isSysErrTooManySymlinks(err) {
    74  						continue
    75  					}
    76  					return err
    77  				}
    78  
    79  				// Ignore symlinked directories.
    80  				if fi.IsDir() {
    81  					continue
    82  				}
    83  			}
    84  			if err = filter(fi.Name(), fi.Mode()); err == errDoneForNow {
    85  				// filtering requested to return by caller.
    86  				return nil
    87  			}
    88  		}
    89  	}
    90  	return nil
    91  }
    92  
    93  // Return N entries at the directory dirPath. If count is -1, return all entries
    94  func readDirN(dirPath string, count int) (entries []string, err error) {
    95  	d, err := Open(dirPath)
    96  	if err != nil {
    97  		return nil, osErrToFileErr(err)
    98  	}
    99  	defer d.Close()
   100  
   101  	maxEntries := 1000
   102  	if count > 0 && count < maxEntries {
   103  		maxEntries = count
   104  	}
   105  
   106  	done := false
   107  	remaining := count
   108  
   109  	for !done {
   110  		// Read up to max number of entries.
   111  		fis, err := d.Readdir(maxEntries)
   112  		if err != nil {
   113  			if err == io.EOF {
   114  				break
   115  			}
   116  			return nil, osErrToFileErr(err)
   117  		}
   118  		if count > -1 {
   119  			if remaining <= len(fis) {
   120  				fis = fis[:remaining]
   121  				done = true
   122  			}
   123  		}
   124  		for _, fi := range fis {
   125  			if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
   126  				fi, err = Stat(pathJoin(dirPath, fi.Name()))
   127  				if err != nil {
   128  					// It got deleted in the meantime, not found
   129  					// or returns too many symlinks ignore this
   130  					// file/directory.
   131  					if osIsNotExist(err) || isSysErrPathNotFound(err) ||
   132  						isSysErrTooManySymlinks(err) {
   133  						continue
   134  					}
   135  					return nil, err
   136  				}
   137  
   138  				// Ignore symlinked directories.
   139  				if fi.IsDir() {
   140  					continue
   141  				}
   142  			}
   143  
   144  			if fi.IsDir() {
   145  				// Append SlashSeparator instead of "\" so that sorting is achieved as expected.
   146  				entries = append(entries, fi.Name()+SlashSeparator)
   147  			} else if fi.Mode().IsRegular() {
   148  				entries = append(entries, fi.Name())
   149  			}
   150  			if count > 0 {
   151  				remaining--
   152  			}
   153  		}
   154  	}
   155  	return entries, nil
   156  }
   157  
   158  func globalSync() {
   159  	// no-op not sure about plan9/solaris support for syscall support
   160  	syscall.Sync()
   161  }