storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/lock/lock_solaris.go (about)

     1  //go:build solaris
     2  // +build solaris
     3  
     4  /*
     5   * MinIO Cloud Storage, (C) 2017 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 lock
    21  
    22  import (
    23  	"os"
    24  	"syscall"
    25  )
    26  
    27  // lockedOpenFile is an internal function.
    28  func lockedOpenFile(path string, flag int, perm os.FileMode, rlockType int) (*LockedFile, error) {
    29  	var lockType int16
    30  	switch flag {
    31  	case syscall.O_RDONLY:
    32  		lockType = syscall.F_RDLCK
    33  	case syscall.O_WRONLY:
    34  		fallthrough
    35  	case syscall.O_RDWR:
    36  		fallthrough
    37  	case syscall.O_WRONLY | syscall.O_CREAT:
    38  		fallthrough
    39  	case syscall.O_RDWR | syscall.O_CREAT:
    40  		lockType = syscall.F_WRLCK
    41  	default:
    42  		return nil, &os.PathError{
    43  			Op:   "open",
    44  			Path: path,
    45  			Err:  syscall.EINVAL,
    46  		}
    47  	}
    48  
    49  	var lock = syscall.Flock_t{
    50  		Start:  0,
    51  		Len:    0,
    52  		Pid:    0,
    53  		Type:   lockType,
    54  		Whence: 0,
    55  	}
    56  
    57  	f, err := os.OpenFile(path, flag, perm)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	if err = syscall.FcntlFlock(f.Fd(), rlockType, &lock); err != nil {
    63  		f.Close()
    64  		if err == syscall.EAGAIN {
    65  			err = ErrAlreadyLocked
    66  		}
    67  		return nil, err
    68  	}
    69  
    70  	st, err := os.Stat(path)
    71  	if err != nil {
    72  		f.Close()
    73  		return nil, err
    74  	}
    75  
    76  	if st.IsDir() {
    77  		f.Close()
    78  		return nil, &os.PathError{
    79  			Op:   "open",
    80  			Path: path,
    81  			Err:  syscall.EISDIR,
    82  		}
    83  	}
    84  
    85  	return &LockedFile{f}, nil
    86  }
    87  
    88  // TryLockedOpenFile - tries a new write lock, functionality
    89  // it is similar to LockedOpenFile with with syscall.LOCK_EX
    90  // mode but along with syscall.LOCK_NB such that the function
    91  // doesn't wait forever but instead returns if it cannot
    92  // acquire a write lock.
    93  func TryLockedOpenFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
    94  	return lockedOpenFile(path, flag, perm, syscall.F_SETLK)
    95  }
    96  
    97  // LockedOpenFile - initializes a new lock and protects
    98  // the file from concurrent access across mount points.
    99  // This implementation doesn't support all the open
   100  // flags and shouldn't be considered as replacement
   101  // for os.OpenFile().
   102  func LockedOpenFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
   103  	return lockedOpenFile(path, flag, perm, syscall.F_SETLKW)
   104  }
   105  
   106  // Open - Call os.OpenFile
   107  func Open(path string, flag int, perm os.FileMode) (*os.File, error) {
   108  	return os.OpenFile(path, flag, perm)
   109  }