github.com/dara-project/godist@v0.0.0-20200823115410-e0c80c8f0c78/src/os/file_posix.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
     6  
     7  package os
     8  
     9  import (
    10  	"dara"
    11  	"runtime"
    12  	"syscall"
    13  	"time"
    14  )
    15  
    16  func sigpipe() // implemented in package runtime
    17  
    18  // Readlink returns the destination of the named symbolic link.
    19  // If there is an error, it will be of type *PathError.
    20  func Readlink(name string) (string, error) {
    21  	for len := 128; ; len *= 2 {
    22  		b := make([]byte, len)
    23  		n, e := fixCount(syscall.Readlink(fixLongPath(name), b))
    24  		if e != nil {
    25  			// DARA Instrumentation
    26  			if runtime.Is_dara_profiling_on() {
    27                  runtime.Dara_Debug_Print(func() {
    28  				    print("[READLINK] : ")
    29  				    println(name)
    30                  })
    31  				argInfo := dara.GeneralType{Type: dara.STRING}
    32                  copy(argInfo.String[:], name)
    33  				retInfo1 := dara.GeneralType{Type: dara.STRING}
    34  				retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported : dara.UNSUPPORTEDVAL}
    35  				syscallInfo := dara.GeneralSyscall{dara.DSYS_READLINK, 1, 2, [10]dara.GeneralType{argInfo}, [10]dara.GeneralType{retInfo1, retInfo2}}
    36  				runtime.Report_Syscall_To_Scheduler(dara.DSYS_READLINK, syscallInfo)
    37  			}
    38  			return "", &PathError{"readlink", name, e}
    39  		}
    40  		if n < len {
    41  			// DARA Instrumentation
    42  			if runtime.Is_dara_profiling_on() {
    43                  runtime.Dara_Debug_Print(func() {
    44  				    print("[READLINK] : ")
    45  				    println(name)
    46                  })
    47  				argInfo := dara.GeneralType{Type: dara.STRING}
    48                  copy(argInfo.String[:], name)
    49  				retInfo1 := dara.GeneralType{Type: dara.STRING}
    50                  copy(retInfo1.String[:], b[0:n])
    51  				retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported : dara.UNSUPPORTEDVAL}
    52  				syscallInfo := dara.GeneralSyscall{dara.DSYS_READLINK, 1, 2, [10]dara.GeneralType{argInfo}, [10]dara.GeneralType{retInfo1, retInfo2}}
    53  				runtime.Report_Syscall_To_Scheduler(dara.DSYS_READLINK, syscallInfo)
    54  			}
    55  			return string(b[0:n]), nil
    56  		}
    57  	}
    58  }
    59  
    60  // syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
    61  func syscallMode(i FileMode) (o uint32) {
    62  	o |= uint32(i.Perm())
    63  	if i&ModeSetuid != 0 {
    64  		o |= syscall.S_ISUID
    65  	}
    66  	if i&ModeSetgid != 0 {
    67  		o |= syscall.S_ISGID
    68  	}
    69  	if i&ModeSticky != 0 {
    70  		o |= syscall.S_ISVTX
    71  	}
    72  	// No mapping for Go's ModeTemporary (plan9 only).
    73  	return
    74  }
    75  
    76  // See docs in file.go:Chmod.
    77  func chmod(name string, mode FileMode) error {
    78  	// DARA Instrumentation
    79  	if runtime.Is_dara_profiling_on() {
    80          runtime.Dara_Debug_Print(func() {
    81  		    print("[CHMOD] : ")
    82  		    print(name)
    83  		    print(" ")
    84  		    println(mode)
    85          })
    86  		argInfo1 := dara.GeneralType{Type: dara.STRING}
    87          copy(argInfo1.String[:], name)
    88  		argInfo2 := dara.GeneralType{Type: dara.INTEGER, Integer: int(mode)}
    89  		retInfo := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL}
    90  		syscallInfo := dara.GeneralSyscall{dara.DSYS_CHMOD, 1, 2, [10]dara.GeneralType{argInfo1, argInfo2}, [10]dara.GeneralType{retInfo}}
    91  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_CHMOD, syscallInfo)
    92  	}
    93  	if e := syscall.Chmod(fixLongPath(name), syscallMode(mode)); e != nil {
    94  		return &PathError{"chmod", name, e}
    95  	}
    96  	return nil
    97  }
    98  
    99  // See docs in file.go:(*File).Chmod.
   100  func (f *File) chmod(mode FileMode) error {
   101  	// DARA Instrumentation
   102  	if runtime.Is_dara_profiling_on() {
   103          runtime.Dara_Debug_Print(func() {
   104  		    print("[FCHMOD] : ")
   105  		    print(f.file.name)
   106  		    print(" ")
   107  		    println(mode)
   108          })
   109  		argInfo1 := dara.GeneralType{Type: dara.FILE}
   110          copy(argInfo1.String[:], f.name)
   111  		argInfo2 := dara.GeneralType{Type: dara.INTEGER, Integer: int(mode)}
   112  		retInfo := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL}
   113  		syscallInfo := dara.GeneralSyscall{dara.DSYS_FCHMOD, 2, 1, [10]dara.GeneralType{argInfo1, argInfo2}, [10]dara.GeneralType{retInfo}}
   114  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_FCHMOD, syscallInfo)
   115  	}
   116  	if err := f.checkValid("chmod"); err != nil {
   117  		return err
   118  	}
   119  	if e := f.pfd.Fchmod(syscallMode(mode)); e != nil {
   120  		return f.wrapErr("chmod", e)
   121  	}
   122  	return nil
   123  }
   124  
   125  // Chown changes the numeric uid and gid of the named file.
   126  // If the file is a symbolic link, it changes the uid and gid of the link's target.
   127  // If there is an error, it will be of type *PathError.
   128  //
   129  // On Windows, it always returns the syscall.EWINDOWS error, wrapped
   130  // in *PathError.
   131  func Chown(name string, uid, gid int) error {
   132  	// DARA Instrumentation
   133  	if runtime.Is_dara_profiling_on() {
   134          runtime.Dara_Debug_Print(func() {
   135  		    print("[CHOWN] : ")
   136  		    print(name)
   137  		    print(" ")
   138  		    print(uid)
   139  		    print(" ")
   140  		    println(gid)
   141          })
   142  		argInfo1 := dara.GeneralType{Type: dara.STRING}
   143          copy(argInfo1.String[:], name)
   144  		argInfo2 := dara.GeneralType{Type: dara.INTEGER, Integer: int(uid)}
   145  		argInfo3 := dara.GeneralType{Type: dara.INTEGER, Integer: int(gid)}
   146  		retInfo := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL}
   147  		syscallInfo := dara.GeneralSyscall{dara.DSYS_CHOWN, 3, 1, [10]dara.GeneralType{argInfo1, argInfo2, argInfo3}, [10]dara.GeneralType{retInfo}}
   148  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_CHOWN, syscallInfo)
   149  	}
   150  	if e := syscall.Chown(name, uid, gid); e != nil {
   151  		return &PathError{"chown", name, e}
   152  	}
   153  	return nil
   154  }
   155  
   156  // Lchown changes the numeric uid and gid of the named file.
   157  // If the file is a symbolic link, it changes the uid and gid of the link itself.
   158  // If there is an error, it will be of type *PathError.
   159  //
   160  // On Windows, it always returns the syscall.EWINDOWS error, wrapped
   161  // in *PathError.
   162  func Lchown(name string, uid, gid int) error {
   163  	// DARA Instrumentation
   164  	if runtime.Is_dara_profiling_on() {
   165          runtime.Dara_Debug_Print(func() {
   166  		    print("[LCHOWN] : ")
   167  		    print(name)
   168  		    print(" ")
   169  		    print(uid)
   170  		    print(" ")
   171  		    println(gid)
   172          })
   173  		argInfo1 := dara.GeneralType{Type: dara.STRING}
   174          copy(argInfo1.String[:], name)
   175  		argInfo2 := dara.GeneralType{Type: dara.INTEGER, Integer: int(uid)}
   176  		argInfo3 := dara.GeneralType{Type: dara.INTEGER, Integer: int(gid)}
   177  		retInfo := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL}
   178  		syscallInfo := dara.GeneralSyscall{dara.DSYS_LCHOWN, 3, 1, [10]dara.GeneralType{argInfo1, argInfo2, argInfo3}, [10]dara.GeneralType{retInfo}}
   179  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_LCHOWN, syscallInfo)
   180  	}
   181  	if e := syscall.Lchown(name, uid, gid); e != nil {
   182  		return &PathError{"lchown", name, e}
   183  	}
   184  	return nil
   185  }
   186  
   187  // Chown changes the numeric uid and gid of the named file.
   188  // If there is an error, it will be of type *PathError.
   189  //
   190  // On Windows, it always returns the syscall.EWINDOWS error, wrapped
   191  // in *PathError.
   192  func (f *File) Chown(uid, gid int) error {
   193  	// DARA Instrumentation
   194  	if runtime.Is_dara_profiling_on() {
   195          runtime.Dara_Debug_Print(func() {
   196  		    print("[FCHOWN] : ")
   197  		    print(f.file.name)
   198  		    print(" ")
   199  		    print(uid)
   200  		    print(" ")
   201  		    println(gid)
   202          })
   203  		argInfo1 := dara.GeneralType{Type: dara.STRING}
   204          copy(argInfo1.String[:], f.name)
   205  		argInfo2 := dara.GeneralType{Type: dara.INTEGER, Integer: int(uid)}
   206  		argInfo3 := dara.GeneralType{Type: dara.INTEGER, Integer: int(gid)}
   207  		retInfo := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL}
   208  		syscallInfo := dara.GeneralSyscall{dara.DSYS_FCHOWN, 3, 1, [10]dara.GeneralType{argInfo1, argInfo2, argInfo3}, [10]dara.GeneralType{retInfo}}
   209  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_FCHOWN, syscallInfo)
   210  	}
   211  	if err := f.checkValid("chown"); err != nil {
   212  		return err
   213  	}
   214  	if e := f.pfd.Fchown(uid, gid); e != nil {
   215  		return f.wrapErr("chown", e)
   216  	}
   217  	return nil
   218  }
   219  
   220  // Truncate changes the size of the file.
   221  // It does not change the I/O offset.
   222  // If there is an error, it will be of type *PathError.
   223  func (f *File) Truncate(size int64) error {
   224  	// DARA Instrumentation
   225  	if runtime.Is_dara_profiling_on() {
   226          runtime.Dara_Debug_Print(func() {
   227  		    print("[FTRUNCATE] : ")
   228  		    print(f.file.name)
   229  		    print(" ")
   230  		    println(size)
   231          })
   232  		argInfo1 := dara.GeneralType{Type: dara.FILE}
   233          copy(argInfo1.String[:], f.name)
   234  		argInfo2 := dara.GeneralType{Type: dara.INTEGER64, Integer64: size}
   235  		retInfo := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL}
   236  		syscallInfo := dara.GeneralSyscall{dara.DSYS_FTRUNCATE, 2, 1, [10]dara.GeneralType{argInfo1, argInfo2}, [10]dara.GeneralType{retInfo}}
   237  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_FTRUNCATE, syscallInfo)
   238  	}
   239  	if err := f.checkValid("truncate"); err != nil {
   240  		return err
   241  	}
   242  	if e := f.pfd.Ftruncate(size); e != nil {
   243  		return f.wrapErr("truncate", e)
   244  	}
   245  	return nil
   246  }
   247  
   248  // Sync commits the current contents of the file to stable storage.
   249  // Typically, this means flushing the file system's in-memory copy
   250  // of recently written data to disk.
   251  func (f *File) Sync() error {
   252  	// DARA Instrumentation
   253  	if runtime.Is_dara_profiling_on() {
   254          runtime.Dara_Debug_Print(func() {
   255  		    print("[FSYNC] : ")
   256  		    println(f.file.name)
   257          })
   258  		argInfo1 := dara.GeneralType{Type: dara.FILE}
   259          copy(argInfo1.String[:], f.name)
   260  		retInfo := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL}
   261  		syscallInfo := dara.GeneralSyscall{dara.DSYS_FSYNC, 1, 1, [10]dara.GeneralType{argInfo1}, [10]dara.GeneralType{retInfo}}
   262  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_FSYNC, syscallInfo)
   263  	}
   264  	if err := f.checkValid("sync"); err != nil {
   265  		return err
   266  	}
   267  	if e := f.pfd.Fsync(); e != nil {
   268  		return f.wrapErr("sync", e)
   269  	}
   270  	return nil
   271  }
   272  
   273  // Chtimes changes the access and modification times of the named
   274  // file, similar to the Unix utime() or utimes() functions.
   275  //
   276  // The underlying filesystem may truncate or round the values to a
   277  // less precise time unit.
   278  // If there is an error, it will be of type *PathError.
   279  func Chtimes(name string, atime time.Time, mtime time.Time) error {
   280  	// DARA Instrumentation
   281  	if runtime.Is_dara_profiling_on() {
   282          runtime.Dara_Debug_Print(func() {
   283  		    print("[UTIMES] : ")
   284  		    print(name)
   285  		    print(" ")
   286  		    print(atime.String())
   287  		    print(" ")
   288  		    println(mtime.String())
   289          })
   290  		argInfo1 := dara.GeneralType{Type:dara.STRING}
   291          copy(argInfo1.String[:], name)
   292  		argInfo2 := dara.GeneralType{Type:dara.TIME}
   293          copy(argInfo2.String[:], atime.String())
   294  		argInfo3 := dara.GeneralType{Type:dara.TIME}
   295          copy(argInfo3.String[:], mtime.String())
   296  		retInfo := dara.GeneralType{Type:dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL}
   297  		syscallInfo := dara.GeneralSyscall{dara.DSYS_UTIMES, 3, 1, [10]dara.GeneralType{argInfo1, argInfo2, argInfo3}, [10]dara.GeneralType{retInfo}}
   298  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_UTIMES, syscallInfo)
   299  	}
   300  	var utimes [2]syscall.Timespec
   301  	utimes[0] = syscall.NsecToTimespec(atime.UnixNano())
   302  	utimes[1] = syscall.NsecToTimespec(mtime.UnixNano())
   303  	if e := syscall.UtimesNano(fixLongPath(name), utimes[0:]); e != nil {
   304  		return &PathError{"chtimes", name, e}
   305  	}
   306  	return nil
   307  }
   308  
   309  // Chdir changes the current working directory to the file,
   310  // which must be a directory.
   311  // If there is an error, it will be of type *PathError.
   312  func (f *File) Chdir() error {
   313  	// DARA Instrumentation
   314  	if runtime.Is_dara_profiling_on() {
   315          runtime.Dara_Debug_Print(func() {
   316  		    print("[FCHDIR] : ")
   317  		    println(f.file.name)
   318          })
   319  		argInfo1 := dara.GeneralType{Type:dara.FILE}
   320          copy(argInfo1.String[:], f.name)
   321  		retInfo := dara.GeneralType{Type:dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL}
   322  		syscallInfo := dara.GeneralSyscall{dara.DSYS_FCHDIR, 1, 1, [10]dara.GeneralType{argInfo1}, [10]dara.GeneralType{retInfo}}
   323  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_FCHDIR, syscallInfo)
   324  	}
   325  	if err := f.checkValid("chdir"); err != nil {
   326  		return err
   327  	}
   328  	if e := f.pfd.Fchdir(); e != nil {
   329  		return f.wrapErr("chdir", e)
   330  	}
   331  	return nil
   332  }
   333  
   334  // setDeadline sets the read and write deadline.
   335  func (f *File) setDeadline(t time.Time) error {
   336  	// DARA Instrumentation
   337  	if runtime.Is_dara_profiling_on() {
   338          runtime.Dara_Debug_Print(func() {
   339  		    print("[SetDeadline] : ")
   340  		    print(f.file.name)
   341  		    print(" ")
   342  		    println(t.String())
   343          })
   344  		argInfo1 := dara.GeneralType{Type:dara.FILE}
   345          copy(argInfo1.String[:], f.name)
   346  		argInfo2 := dara.GeneralType{Type:dara.TIME}
   347          copy(argInfo2.String[:], t.String())
   348  		retInfo := dara.GeneralType{Type:dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL}
   349  		syscallInfo := dara.GeneralSyscall{dara.DSYS_SETDEADLINE, 2, 1, [10]dara.GeneralType{argInfo1, argInfo2}, [10]dara.GeneralType{retInfo}}
   350  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_SETDEADLINE, syscallInfo)
   351  	}
   352  	if err := f.checkValid("SetDeadline"); err != nil {
   353  		return err
   354  	}
   355  	return f.pfd.SetDeadline(t)
   356  }
   357  
   358  // setReadDeadline sets the read deadline.
   359  func (f *File) setReadDeadline(t time.Time) error {
   360  	// DARA Instrumentation
   361  	if runtime.Is_dara_profiling_on() {
   362          runtime.Dara_Debug_Print(func() {
   363  		    print("[SetReadDeadline] : ")
   364  		    print(f.file.name)
   365  		    print(" ")
   366  		    println(t.String())
   367          })
   368  		argInfo1 := dara.GeneralType{Type:dara.FILE}
   369          copy(argInfo1.String[:], f.name)
   370  		argInfo2 := dara.GeneralType{Type:dara.TIME}
   371          copy(argInfo2.String[:], t.String())
   372  		retInfo := dara.GeneralType{Type:dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL}
   373  		syscallInfo := dara.GeneralSyscall{dara.DSYS_SETREADDEADLINE, 2, 1, [10]dara.GeneralType{argInfo1, argInfo2}, [10]dara.GeneralType{retInfo}}
   374  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_SETREADDEADLINE, syscallInfo)
   375  	}
   376  	if err := f.checkValid("SetReadDeadline"); err != nil {
   377  		return err
   378  	}
   379  	return f.pfd.SetReadDeadline(t)
   380  }
   381  
   382  // setWriteDeadline sets the write deadline.
   383  func (f *File) setWriteDeadline(t time.Time) error {
   384  	// DARA Instrumentation
   385  	if runtime.Is_dara_profiling_on() {
   386          runtime.Dara_Debug_Print(func() {
   387  		    print("[SetWriteDeadline] : ")
   388  		    print(f.file.name)
   389  		    print(" ")
   390  		    println(t.String())
   391          })
   392  		argInfo1 := dara.GeneralType{Type:dara.FILE}
   393          copy(argInfo1.String[:], f.name)
   394  		argInfo2 := dara.GeneralType{Type:dara.TIME}
   395          copy(argInfo2.String[:], t.String())
   396  		retInfo := dara.GeneralType{Type:dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL}
   397  		syscallInfo := dara.GeneralSyscall{dara.DSYS_SETWRITEDEADLINE, 2, 1, [10]dara.GeneralType{argInfo1, argInfo2}, [10]dara.GeneralType{retInfo}}
   398  		runtime.Report_Syscall_To_Scheduler(dara.DSYS_SETWRITEDEADLINE, syscallInfo)
   399  	}
   400  	if err := f.checkValid("SetWriteDeadline"); err != nil {
   401  		return err
   402  	}
   403  	return f.pfd.SetWriteDeadline(t)
   404  }
   405  
   406  // checkValid checks whether f is valid for use.
   407  // If not, it returns an appropriate error, perhaps incorporating the operation name op.
   408  func (f *File) checkValid(op string) error {
   409  	if f == nil {
   410  		return ErrInvalid
   411  	}
   412  	return nil
   413  }