github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/cmd/os_other.go (about)

     1  //go:build plan9 || solaris
     2  // +build plan9 solaris
     3  
     4  // Copyright (c) 2015-2021 MinIO, Inc.
     5  //
     6  // This file is part of MinIO Object Storage stack
     7  //
     8  // This program is free software: you can redistribute it and/or modify
     9  // it under the terms of the GNU Affero General Public License as published by
    10  // the Free Software Foundation, either version 3 of the License, or
    11  // (at your option) any later version.
    12  //
    13  // This program is distributed in the hope that it will be useful
    14  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  // GNU Affero General Public License for more details.
    17  //
    18  // You should have received a copy of the GNU Affero General Public License
    19  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    20  
    21  package cmd
    22  
    23  import (
    24  	"io"
    25  	"os"
    26  	"syscall"
    27  )
    28  
    29  func access(name string) error {
    30  	_, err := os.Lstat(name)
    31  	return err
    32  }
    33  
    34  func osMkdirAll(dirPath string, perm os.FileMode, _ string) error {
    35  	// baseDir is not honored in plan9 and solaris platforms.
    36  	return os.MkdirAll(dirPath, perm)
    37  }
    38  
    39  // readDirFn applies the fn() function on each entries at dirPath, doesn't recurse into
    40  // the directory itself, if the dirPath doesn't exist this function doesn't return
    41  // an error.
    42  func readDirFn(dirPath string, filter func(name string, typ os.FileMode) error) error {
    43  	d, err := Open(dirPath)
    44  	if err != nil {
    45  		if osErrToFileErr(err) == errFileNotFound {
    46  			return nil
    47  		}
    48  		return osErrToFileErr(err)
    49  	}
    50  	defer d.Close()
    51  
    52  	maxEntries := 1000
    53  	for {
    54  		// Read up to max number of entries.
    55  		fis, err := d.Readdir(maxEntries)
    56  		if err != nil {
    57  			if err == io.EOF {
    58  				break
    59  			}
    60  			err = osErrToFileErr(err)
    61  			if err == errFileNotFound {
    62  				return nil
    63  			}
    64  			return err
    65  		}
    66  		for _, fi := range fis {
    67  			if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
    68  				fi, err = Stat(pathJoin(dirPath, fi.Name()))
    69  				if err != nil {
    70  					// It got deleted in the meantime, not found
    71  					// or returns too many symlinks ignore this
    72  					// file/directory.
    73  					if osIsNotExist(err) || isSysErrPathNotFound(err) ||
    74  						isSysErrTooManySymlinks(err) {
    75  						continue
    76  					}
    77  					return err
    78  				}
    79  
    80  				// Ignore symlinked directories.
    81  				if fi.IsDir() {
    82  					continue
    83  				}
    84  			}
    85  			if err = filter(fi.Name(), fi.Mode()); err == errDoneForNow {
    86  				// filtering requested to return by caller.
    87  				return nil
    88  			}
    89  		}
    90  	}
    91  	return nil
    92  }
    93  
    94  // Return entries at the directory dirPath.
    95  func readDirWithOpts(dirPath string, opts readDirOpts) (entries []string, err error) {
    96  	d, err := Open(dirPath)
    97  	if err != nil {
    98  		return nil, osErrToFileErr(err)
    99  	}
   100  	defer d.Close()
   101  
   102  	maxEntries := 1000
   103  	if opts.count > 0 && opts.count < maxEntries {
   104  		maxEntries = opts.count
   105  	}
   106  
   107  	done := false
   108  	remaining := opts.count
   109  
   110  	for !done {
   111  		// Read up to max number of entries.
   112  		fis, err := d.Readdir(maxEntries)
   113  		if err != nil {
   114  			if err == io.EOF {
   115  				break
   116  			}
   117  			return nil, osErrToFileErr(err)
   118  		}
   119  		if opts.count > -1 {
   120  			if remaining <= len(fis) {
   121  				fis = fis[:remaining]
   122  				done = true
   123  			}
   124  		}
   125  		for _, fi := range fis {
   126  			if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
   127  				fi, err = Stat(pathJoin(dirPath, fi.Name()))
   128  				if err != nil {
   129  					// It got deleted in the meantime, not found
   130  					// or returns too many symlinks ignore this
   131  					// file/directory.
   132  					if osIsNotExist(err) || isSysErrPathNotFound(err) ||
   133  						isSysErrTooManySymlinks(err) {
   134  						continue
   135  					}
   136  					return nil, err
   137  				}
   138  
   139  				// Ignore symlinked directories.
   140  				if !opts.followDirSymlink && fi.IsDir() {
   141  					continue
   142  				}
   143  			}
   144  
   145  			if fi.IsDir() {
   146  				// Append SlashSeparator instead of "\" so that sorting is achieved as expected.
   147  				entries = append(entries, fi.Name()+SlashSeparator)
   148  			} else if fi.Mode().IsRegular() {
   149  				entries = append(entries, fi.Name())
   150  			}
   151  			if opts.count > 0 {
   152  				remaining--
   153  			}
   154  		}
   155  	}
   156  	return entries, nil
   157  }
   158  
   159  func globalSync() {
   160  	// no-op not sure about plan9/solaris support for syscall support
   161  	defer globalOSMetrics.time(osMetricSync)()
   162  	syscall.Sync()
   163  }