mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
os: consolidate files
Code movement only. If someone finds function 'foo' in "foo_linux.go", they will expect that the Window version of 'foo' exists in "foo_windows.go". Current code doesn't follow this manner. For example, 'sameFile' exists in "file_unix.go", "stat_plan9.go" and "types_windows.go". The CL address that problem by following rules: * readdir family => dir.go, dir_$GOOS.go * stat family => stat.go, stat_$GOOS.go * path-functions => path_$GOOS.go * sameFile => types.go, types_$GOOS.go * process-functions => exec.go, exec_$GOOS.go * hostname => sys.go, sys_$GOOS.go Change-Id: Ic3c64663ce0b2a364d7a414351cd3c772e70187b Reviewed-on: https://go-review.googlesource.com/27035 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
c307e1628c
commit
664c4a1f87
15 changed files with 426 additions and 403 deletions
46
src/os/dir.go
Normal file
46
src/os/dir.go
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package os
|
||||
|
||||
// Readdir reads the contents of the directory associated with file and
|
||||
// returns a slice of up to n FileInfo values, as would be returned
|
||||
// by Lstat, in directory order. Subsequent calls on the same file will yield
|
||||
// further FileInfos.
|
||||
//
|
||||
// If n > 0, Readdir returns at most n FileInfo structures. In this case, if
|
||||
// Readdir returns an empty slice, it will return a non-nil error
|
||||
// explaining why. At the end of a directory, the error is io.EOF.
|
||||
//
|
||||
// If n <= 0, Readdir returns all the FileInfo from the directory in
|
||||
// a single slice. In this case, if Readdir succeeds (reads all
|
||||
// the way to the end of the directory), it returns the slice and a
|
||||
// nil error. If it encounters an error before the end of the
|
||||
// directory, Readdir returns the FileInfo read until that point
|
||||
// and a non-nil error.
|
||||
func (f *File) Readdir(n int) ([]FileInfo, error) {
|
||||
if f == nil {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
return f.readdir(n)
|
||||
}
|
||||
|
||||
// Readdirnames reads and returns a slice of names from the directory f.
|
||||
//
|
||||
// If n > 0, Readdirnames returns at most n names. In this case, if
|
||||
// Readdirnames returns an empty slice, it will return a non-nil error
|
||||
// explaining why. At the end of a directory, the error is io.EOF.
|
||||
//
|
||||
// If n <= 0, Readdirnames returns all the names from the directory in
|
||||
// a single slice. In this case, if Readdirnames succeeds (reads all
|
||||
// the way to the end of the directory), it returns the slice and a
|
||||
// nil error. If it encounters an error before the end of the
|
||||
// directory, Readdirnames returns the names read until that point and
|
||||
// a non-nil error.
|
||||
func (f *File) Readdirnames(n int) (names []string, err error) {
|
||||
if f == nil {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
return f.readdirnames(n)
|
||||
}
|
||||
|
|
@ -15,6 +15,28 @@ const (
|
|||
blockSize = 4096
|
||||
)
|
||||
|
||||
func (f *File) readdir(n int) (fi []FileInfo, err error) {
|
||||
dirname := f.name
|
||||
if dirname == "" {
|
||||
dirname = "."
|
||||
}
|
||||
names, err := f.Readdirnames(n)
|
||||
fi = make([]FileInfo, 0, len(names))
|
||||
for _, filename := range names {
|
||||
fip, lerr := lstat(dirname + "/" + filename)
|
||||
if IsNotExist(lerr) {
|
||||
// File disappeared between readdir + stat.
|
||||
// Just treat it as if it didn't exist.
|
||||
continue
|
||||
}
|
||||
if lerr != nil {
|
||||
return fi, lerr
|
||||
}
|
||||
fi = append(fi, fip)
|
||||
}
|
||||
return fi, err
|
||||
}
|
||||
|
||||
func (f *File) readdirnames(n int) (names []string, err error) {
|
||||
// If this file has no dirinfo, create one.
|
||||
if f.dirinfo == nil {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,70 @@
|
|||
|
||||
package os
|
||||
|
||||
import (
|
||||
"io"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (file *File) readdir(n int) (fi []FileInfo, err error) {
|
||||
if file == nil {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
if !file.isdir() {
|
||||
return nil, &PathError{"Readdir", file.name, syscall.ENOTDIR}
|
||||
}
|
||||
if !file.dirinfo.isempty && file.fd == syscall.InvalidHandle {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
wantAll := n <= 0
|
||||
size := n
|
||||
if wantAll {
|
||||
n = -1
|
||||
size = 100
|
||||
}
|
||||
fi = make([]FileInfo, 0, size) // Empty with room to grow.
|
||||
d := &file.dirinfo.data
|
||||
for n != 0 && !file.dirinfo.isempty {
|
||||
if file.dirinfo.needdata {
|
||||
e := syscall.FindNextFile(file.fd, d)
|
||||
if e != nil {
|
||||
if e == syscall.ERROR_NO_MORE_FILES {
|
||||
break
|
||||
} else {
|
||||
err = &PathError{"FindNextFile", file.name, e}
|
||||
if !wantAll {
|
||||
fi = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
file.dirinfo.needdata = true
|
||||
name := syscall.UTF16ToString(d.FileName[0:])
|
||||
if name == "." || name == ".." { // Useless names
|
||||
continue
|
||||
}
|
||||
f := &fileStat{
|
||||
name: name,
|
||||
sys: syscall.Win32FileAttributeData{
|
||||
FileAttributes: d.FileAttributes,
|
||||
CreationTime: d.CreationTime,
|
||||
LastAccessTime: d.LastAccessTime,
|
||||
LastWriteTime: d.LastWriteTime,
|
||||
FileSizeHigh: d.FileSizeHigh,
|
||||
FileSizeLow: d.FileSizeLow,
|
||||
},
|
||||
path: file.dirinfo.path + `\` + name,
|
||||
}
|
||||
n--
|
||||
fi = append(fi, f)
|
||||
}
|
||||
if !wantAll && len(fi) == 0 {
|
||||
return fi, io.EOF
|
||||
}
|
||||
return fi, nil
|
||||
}
|
||||
|
||||
func (file *File) readdirnames(n int) (names []string, err error) {
|
||||
fis, err := file.Readdir(n)
|
||||
names = make([]string, len(fis))
|
||||
|
|
|
|||
139
src/os/doc.go
139
src/os/doc.go
|
|
@ -1,139 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package os
|
||||
|
||||
import "time"
|
||||
|
||||
// FindProcess looks for a running process by its pid.
|
||||
//
|
||||
// The Process it returns can be used to obtain information
|
||||
// about the underlying operating system process.
|
||||
//
|
||||
// On Unix systems, FindProcess always succeeds and returns a Process
|
||||
// for the given pid, regardless of whether the process exists.
|
||||
func FindProcess(pid int) (*Process, error) {
|
||||
return findProcess(pid)
|
||||
}
|
||||
|
||||
// StartProcess starts a new process with the program, arguments and attributes
|
||||
// specified by name, argv and attr.
|
||||
//
|
||||
// StartProcess is a low-level interface. The os/exec package provides
|
||||
// higher-level interfaces.
|
||||
//
|
||||
// If there is an error, it will be of type *PathError.
|
||||
func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) {
|
||||
return startProcess(name, argv, attr)
|
||||
}
|
||||
|
||||
// Release releases any resources associated with the Process p,
|
||||
// rendering it unusable in the future.
|
||||
// Release only needs to be called if Wait is not.
|
||||
func (p *Process) Release() error {
|
||||
return p.release()
|
||||
}
|
||||
|
||||
// Kill causes the Process to exit immediately.
|
||||
func (p *Process) Kill() error {
|
||||
return p.kill()
|
||||
}
|
||||
|
||||
// Wait waits for the Process to exit, and then returns a
|
||||
// ProcessState describing its status and an error, if any.
|
||||
// Wait releases any resources associated with the Process.
|
||||
// On most operating systems, the Process must be a child
|
||||
// of the current process or an error will be returned.
|
||||
func (p *Process) Wait() (*ProcessState, error) {
|
||||
return p.wait()
|
||||
}
|
||||
|
||||
// Signal sends a signal to the Process.
|
||||
// Sending Interrupt on Windows is not implemented.
|
||||
func (p *Process) Signal(sig Signal) error {
|
||||
return p.signal(sig)
|
||||
}
|
||||
|
||||
// UserTime returns the user CPU time of the exited process and its children.
|
||||
func (p *ProcessState) UserTime() time.Duration {
|
||||
return p.userTime()
|
||||
}
|
||||
|
||||
// SystemTime returns the system CPU time of the exited process and its children.
|
||||
func (p *ProcessState) SystemTime() time.Duration {
|
||||
return p.systemTime()
|
||||
}
|
||||
|
||||
// Exited reports whether the program has exited.
|
||||
func (p *ProcessState) Exited() bool {
|
||||
return p.exited()
|
||||
}
|
||||
|
||||
// Success reports whether the program exited successfully,
|
||||
// such as with exit status 0 on Unix.
|
||||
func (p *ProcessState) Success() bool {
|
||||
return p.success()
|
||||
}
|
||||
|
||||
// Sys returns system-dependent exit information about
|
||||
// the process. Convert it to the appropriate underlying
|
||||
// type, such as syscall.WaitStatus on Unix, to access its contents.
|
||||
func (p *ProcessState) Sys() interface{} {
|
||||
return p.sys()
|
||||
}
|
||||
|
||||
// SysUsage returns system-dependent resource usage information about
|
||||
// the exited process. Convert it to the appropriate underlying
|
||||
// type, such as *syscall.Rusage on Unix, to access its contents.
|
||||
// (On Unix, *syscall.Rusage matches struct rusage as defined in the
|
||||
// getrusage(2) manual page.)
|
||||
func (p *ProcessState) SysUsage() interface{} {
|
||||
return p.sysUsage()
|
||||
}
|
||||
|
||||
// Hostname returns the host name reported by the kernel.
|
||||
func Hostname() (name string, err error) {
|
||||
return hostname()
|
||||
}
|
||||
|
||||
// Readdir reads the contents of the directory associated with file and
|
||||
// returns a slice of up to n FileInfo values, as would be returned
|
||||
// by Lstat, in directory order. Subsequent calls on the same file will yield
|
||||
// further FileInfos.
|
||||
//
|
||||
// If n > 0, Readdir returns at most n FileInfo structures. In this case, if
|
||||
// Readdir returns an empty slice, it will return a non-nil error
|
||||
// explaining why. At the end of a directory, the error is io.EOF.
|
||||
//
|
||||
// If n <= 0, Readdir returns all the FileInfo from the directory in
|
||||
// a single slice. In this case, if Readdir succeeds (reads all
|
||||
// the way to the end of the directory), it returns the slice and a
|
||||
// nil error. If it encounters an error before the end of the
|
||||
// directory, Readdir returns the FileInfo read until that point
|
||||
// and a non-nil error.
|
||||
func (f *File) Readdir(n int) ([]FileInfo, error) {
|
||||
if f == nil {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
return f.readdir(n)
|
||||
}
|
||||
|
||||
// Readdirnames reads and returns a slice of names from the directory f.
|
||||
//
|
||||
// If n > 0, Readdirnames returns at most n names. In this case, if
|
||||
// Readdirnames returns an empty slice, it will return a non-nil error
|
||||
// explaining why. At the end of a directory, the error is io.EOF.
|
||||
//
|
||||
// If n <= 0, Readdirnames returns all the names from the directory in
|
||||
// a single slice. In this case, if Readdirnames succeeds (reads all
|
||||
// the way to the end of the directory), it returns the slice and a
|
||||
// nil error. If it encounters an error before the end of the
|
||||
// directory, Readdirnames returns the names read until that point and
|
||||
// a non-nil error.
|
||||
func (f *File) Readdirnames(n int) (names []string, err error) {
|
||||
if f == nil {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
return f.readdirnames(n)
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Process stores the information about a process created by StartProcess.
|
||||
|
|
@ -70,3 +71,89 @@ func Getpid() int { return syscall.Getpid() }
|
|||
|
||||
// Getppid returns the process id of the caller's parent.
|
||||
func Getppid() int { return syscall.Getppid() }
|
||||
|
||||
// FindProcess looks for a running process by its pid.
|
||||
//
|
||||
// The Process it returns can be used to obtain information
|
||||
// about the underlying operating system process.
|
||||
//
|
||||
// On Unix systems, FindProcess always succeeds and returns a Process
|
||||
// for the given pid, regardless of whether the process exists.
|
||||
func FindProcess(pid int) (*Process, error) {
|
||||
return findProcess(pid)
|
||||
}
|
||||
|
||||
// StartProcess starts a new process with the program, arguments and attributes
|
||||
// specified by name, argv and attr.
|
||||
//
|
||||
// StartProcess is a low-level interface. The os/exec package provides
|
||||
// higher-level interfaces.
|
||||
//
|
||||
// If there is an error, it will be of type *PathError.
|
||||
func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) {
|
||||
return startProcess(name, argv, attr)
|
||||
}
|
||||
|
||||
// Release releases any resources associated with the Process p,
|
||||
// rendering it unusable in the future.
|
||||
// Release only needs to be called if Wait is not.
|
||||
func (p *Process) Release() error {
|
||||
return p.release()
|
||||
}
|
||||
|
||||
// Kill causes the Process to exit immediately.
|
||||
func (p *Process) Kill() error {
|
||||
return p.kill()
|
||||
}
|
||||
|
||||
// Wait waits for the Process to exit, and then returns a
|
||||
// ProcessState describing its status and an error, if any.
|
||||
// Wait releases any resources associated with the Process.
|
||||
// On most operating systems, the Process must be a child
|
||||
// of the current process or an error will be returned.
|
||||
func (p *Process) Wait() (*ProcessState, error) {
|
||||
return p.wait()
|
||||
}
|
||||
|
||||
// Signal sends a signal to the Process.
|
||||
// Sending Interrupt on Windows is not implemented.
|
||||
func (p *Process) Signal(sig Signal) error {
|
||||
return p.signal(sig)
|
||||
}
|
||||
|
||||
// UserTime returns the user CPU time of the exited process and its children.
|
||||
func (p *ProcessState) UserTime() time.Duration {
|
||||
return p.userTime()
|
||||
}
|
||||
|
||||
// SystemTime returns the system CPU time of the exited process and its children.
|
||||
func (p *ProcessState) SystemTime() time.Duration {
|
||||
return p.systemTime()
|
||||
}
|
||||
|
||||
// Exited reports whether the program has exited.
|
||||
func (p *ProcessState) Exited() bool {
|
||||
return p.exited()
|
||||
}
|
||||
|
||||
// Success reports whether the program exited successfully,
|
||||
// such as with exit status 0 on Unix.
|
||||
func (p *ProcessState) Success() bool {
|
||||
return p.success()
|
||||
}
|
||||
|
||||
// Sys returns system-dependent exit information about
|
||||
// the process. Convert it to the appropriate underlying
|
||||
// type, such as syscall.WaitStatus on Unix, to access its contents.
|
||||
func (p *ProcessState) Sys() interface{} {
|
||||
return p.sys()
|
||||
}
|
||||
|
||||
// SysUsage returns system-dependent resource usage information about
|
||||
// the exited process. Convert it to the appropriate underlying
|
||||
// type, such as *syscall.Rusage on Unix, to access its contents.
|
||||
// (On Unix, *syscall.Rusage matches struct rusage as defined in the
|
||||
// getrusage(2) manual page.)
|
||||
func (p *ProcessState) SysUsage() interface{} {
|
||||
return p.sysUsage()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,6 @@ import (
|
|||
"syscall"
|
||||
)
|
||||
|
||||
func sameFile(fs1, fs2 *fileStat) bool {
|
||||
return fs1.sys.Dev == fs2.sys.Dev && fs1.sys.Ino == fs2.sys.Ino
|
||||
}
|
||||
|
||||
func rename(oldname, newname string) error {
|
||||
e := syscall.Rename(oldname, newname)
|
||||
if e != nil {
|
||||
|
|
@ -147,69 +143,6 @@ func (file *file) close() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Stat returns the FileInfo structure describing file.
|
||||
// If there is an error, it will be of type *PathError.
|
||||
func (f *File) Stat() (FileInfo, error) {
|
||||
if f == nil {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
var fs fileStat
|
||||
err := syscall.Fstat(f.fd, &fs.sys)
|
||||
if err != nil {
|
||||
return nil, &PathError{"stat", f.name, err}
|
||||
}
|
||||
fillFileStatFromSys(&fs, f.name)
|
||||
return &fs, nil
|
||||
}
|
||||
|
||||
// Stat returns a FileInfo describing the named file.
|
||||
// If there is an error, it will be of type *PathError.
|
||||
func Stat(name string) (FileInfo, error) {
|
||||
var fs fileStat
|
||||
err := syscall.Stat(name, &fs.sys)
|
||||
if err != nil {
|
||||
return nil, &PathError{"stat", name, err}
|
||||
}
|
||||
fillFileStatFromSys(&fs, name)
|
||||
return &fs, nil
|
||||
}
|
||||
|
||||
// Lstat returns a FileInfo describing the named file.
|
||||
// If the file is a symbolic link, the returned FileInfo
|
||||
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
||||
// If there is an error, it will be of type *PathError.
|
||||
func Lstat(name string) (FileInfo, error) {
|
||||
var fs fileStat
|
||||
err := syscall.Lstat(name, &fs.sys)
|
||||
if err != nil {
|
||||
return nil, &PathError{"lstat", name, err}
|
||||
}
|
||||
fillFileStatFromSys(&fs, name)
|
||||
return &fs, nil
|
||||
}
|
||||
|
||||
func (f *File) readdir(n int) (fi []FileInfo, err error) {
|
||||
dirname := f.name
|
||||
if dirname == "" {
|
||||
dirname = "."
|
||||
}
|
||||
names, err := f.Readdirnames(n)
|
||||
fi = make([]FileInfo, 0, len(names))
|
||||
for _, filename := range names {
|
||||
fip, lerr := lstat(dirname + "/" + filename)
|
||||
if IsNotExist(lerr) {
|
||||
// File disappeared between readdir + stat.
|
||||
// Just treat it as if it didn't exist.
|
||||
continue
|
||||
}
|
||||
if lerr != nil {
|
||||
return fi, lerr
|
||||
}
|
||||
fi = append(fi, fip)
|
||||
}
|
||||
return fi, err
|
||||
}
|
||||
|
||||
// Darwin and FreeBSD can't read or write 2GB+ at a time,
|
||||
// even on 64-bit systems. See golang.org/issue/7812.
|
||||
// Use 1GB instead of, say, 2GB-1, to keep subsequent
|
||||
|
|
@ -324,24 +257,6 @@ func Remove(name string) error {
|
|||
return &PathError{"remove", name, e}
|
||||
}
|
||||
|
||||
// basename removes trailing slashes and the leading directory name from path name
|
||||
func basename(name string) string {
|
||||
i := len(name) - 1
|
||||
// Remove trailing slashes
|
||||
for ; i > 0 && name[i] == '/'; i-- {
|
||||
name = name[:i]
|
||||
}
|
||||
// Remove leading directory name
|
||||
for i--; i >= 0; i-- {
|
||||
if name[i] == '/' {
|
||||
name = name[i+1:]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
// TempDir returns the default directory to use for temporary files.
|
||||
func TempDir() string {
|
||||
dir := Getenv("TMPDIR")
|
||||
|
|
|
|||
|
|
@ -196,65 +196,6 @@ func (file *file) close() error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (file *File) readdir(n int) (fi []FileInfo, err error) {
|
||||
if file == nil {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
if !file.isdir() {
|
||||
return nil, &PathError{"Readdir", file.name, syscall.ENOTDIR}
|
||||
}
|
||||
if !file.dirinfo.isempty && file.fd == syscall.InvalidHandle {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
wantAll := n <= 0
|
||||
size := n
|
||||
if wantAll {
|
||||
n = -1
|
||||
size = 100
|
||||
}
|
||||
fi = make([]FileInfo, 0, size) // Empty with room to grow.
|
||||
d := &file.dirinfo.data
|
||||
for n != 0 && !file.dirinfo.isempty {
|
||||
if file.dirinfo.needdata {
|
||||
e := syscall.FindNextFile(file.fd, d)
|
||||
if e != nil {
|
||||
if e == syscall.ERROR_NO_MORE_FILES {
|
||||
break
|
||||
} else {
|
||||
err = &PathError{"FindNextFile", file.name, e}
|
||||
if !wantAll {
|
||||
fi = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
file.dirinfo.needdata = true
|
||||
name := syscall.UTF16ToString(d.FileName[0:])
|
||||
if name == "." || name == ".." { // Useless names
|
||||
continue
|
||||
}
|
||||
f := &fileStat{
|
||||
name: name,
|
||||
sys: syscall.Win32FileAttributeData{
|
||||
FileAttributes: d.FileAttributes,
|
||||
CreationTime: d.CreationTime,
|
||||
LastAccessTime: d.LastAccessTime,
|
||||
LastWriteTime: d.LastWriteTime,
|
||||
FileSizeHigh: d.FileSizeHigh,
|
||||
FileSizeLow: d.FileSizeLow,
|
||||
},
|
||||
path: file.dirinfo.path + `\` + name,
|
||||
}
|
||||
n--
|
||||
fi = append(fi, f)
|
||||
}
|
||||
if !wantAll && len(fi) == 0 {
|
||||
return fi, io.EOF
|
||||
}
|
||||
return fi, nil
|
||||
}
|
||||
|
||||
// readConsole reads utf16 characters from console File,
|
||||
// encodes them into utf8 and stores them in buffer b.
|
||||
// It returns the number of utf8 bytes read and an error, if any.
|
||||
|
|
@ -586,42 +527,3 @@ func Symlink(oldname, newname string) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fromSlash(path string) string {
|
||||
// Replace each '/' with '\\' if present
|
||||
var pathbuf []byte
|
||||
var lastSlash int
|
||||
for i, b := range path {
|
||||
if b == '/' {
|
||||
if pathbuf == nil {
|
||||
pathbuf = make([]byte, len(path))
|
||||
}
|
||||
copy(pathbuf[lastSlash:], path[lastSlash:i])
|
||||
pathbuf[i] = '\\'
|
||||
lastSlash = i + 1
|
||||
}
|
||||
}
|
||||
if pathbuf == nil {
|
||||
return path
|
||||
}
|
||||
|
||||
copy(pathbuf[lastSlash:], path[lastSlash:])
|
||||
return string(pathbuf)
|
||||
}
|
||||
|
||||
func dirname(path string) string {
|
||||
vol := volumeName(path)
|
||||
i := len(path) - 1
|
||||
for i >= len(vol) && !IsPathSeparator(path[i]) {
|
||||
i--
|
||||
}
|
||||
dir := path[len(vol) : i+1]
|
||||
last := len(dir) - 1
|
||||
if last > 0 && IsPathSeparator(dir[last]) {
|
||||
dir = dir[:last]
|
||||
}
|
||||
if dir == "" {
|
||||
dir = "."
|
||||
}
|
||||
return vol + dir
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,3 +15,21 @@ const (
|
|||
func IsPathSeparator(c uint8) bool {
|
||||
return PathSeparator == c
|
||||
}
|
||||
|
||||
// basename removes trailing slashes and the leading directory name from path name
|
||||
func basename(name string) string {
|
||||
i := len(name) - 1
|
||||
// Remove trailing slashes
|
||||
for ; i > 0 && name[i] == '/'; i-- {
|
||||
name = name[:i]
|
||||
}
|
||||
// Remove leading directory name
|
||||
for i--; i >= 0; i-- {
|
||||
if name[i] == '/' {
|
||||
name = name[i+1:]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,3 +14,116 @@ func IsPathSeparator(c uint8) bool {
|
|||
// NOTE: Windows accept / as path separator.
|
||||
return c == '\\' || c == '/'
|
||||
}
|
||||
|
||||
// basename removes trailing slashes and the leading
|
||||
// directory name and drive letter from path name.
|
||||
func basename(name string) string {
|
||||
// Remove drive letter
|
||||
if len(name) == 2 && name[1] == ':' {
|
||||
name = "."
|
||||
} else if len(name) > 2 && name[1] == ':' {
|
||||
name = name[2:]
|
||||
}
|
||||
i := len(name) - 1
|
||||
// Remove trailing slashes
|
||||
for ; i > 0 && (name[i] == '/' || name[i] == '\\'); i-- {
|
||||
name = name[:i]
|
||||
}
|
||||
// Remove leading directory name
|
||||
for i--; i >= 0; i-- {
|
||||
if name[i] == '/' || name[i] == '\\' {
|
||||
name = name[i+1:]
|
||||
break
|
||||
}
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func isAbs(path string) (b bool) {
|
||||
v := volumeName(path)
|
||||
if v == "" {
|
||||
return false
|
||||
}
|
||||
path = path[len(v):]
|
||||
if path == "" {
|
||||
return false
|
||||
}
|
||||
return IsPathSeparator(path[0])
|
||||
}
|
||||
|
||||
func volumeName(path string) (v string) {
|
||||
if len(path) < 2 {
|
||||
return ""
|
||||
}
|
||||
// with drive letter
|
||||
c := path[0]
|
||||
if path[1] == ':' &&
|
||||
('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||
|
||||
'A' <= c && c <= 'Z') {
|
||||
return path[:2]
|
||||
}
|
||||
// is it UNC
|
||||
if l := len(path); l >= 5 && IsPathSeparator(path[0]) && IsPathSeparator(path[1]) &&
|
||||
!IsPathSeparator(path[2]) && path[2] != '.' {
|
||||
// first, leading `\\` and next shouldn't be `\`. its server name.
|
||||
for n := 3; n < l-1; n++ {
|
||||
// second, next '\' shouldn't be repeated.
|
||||
if IsPathSeparator(path[n]) {
|
||||
n++
|
||||
// third, following something characters. its share name.
|
||||
if !IsPathSeparator(path[n]) {
|
||||
if path[n] == '.' {
|
||||
break
|
||||
}
|
||||
for ; n < l; n++ {
|
||||
if IsPathSeparator(path[n]) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return path[:n]
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func fromSlash(path string) string {
|
||||
// Replace each '/' with '\\' if present
|
||||
var pathbuf []byte
|
||||
var lastSlash int
|
||||
for i, b := range path {
|
||||
if b == '/' {
|
||||
if pathbuf == nil {
|
||||
pathbuf = make([]byte, len(path))
|
||||
}
|
||||
copy(pathbuf[lastSlash:], path[lastSlash:i])
|
||||
pathbuf[i] = '\\'
|
||||
lastSlash = i + 1
|
||||
}
|
||||
}
|
||||
if pathbuf == nil {
|
||||
return path
|
||||
}
|
||||
|
||||
copy(pathbuf[lastSlash:], path[lastSlash:])
|
||||
return string(pathbuf)
|
||||
}
|
||||
|
||||
func dirname(path string) string {
|
||||
vol := volumeName(path)
|
||||
i := len(path) - 1
|
||||
for i >= len(vol) && !IsPathSeparator(path[i]) {
|
||||
i--
|
||||
}
|
||||
dir := path[len(vol) : i+1]
|
||||
last := len(dir) - 1
|
||||
if last > 0 && IsPathSeparator(dir[last]) {
|
||||
dir = dir[:last]
|
||||
}
|
||||
if dir == "" {
|
||||
dir = "."
|
||||
}
|
||||
return vol + dir
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,12 +11,6 @@ import (
|
|||
|
||||
const _BIT16SZ = 2
|
||||
|
||||
func sameFile(fs1, fs2 *fileStat) bool {
|
||||
a := fs1.sys.(*syscall.Dir)
|
||||
b := fs2.sys.(*syscall.Dir)
|
||||
return a.Qid.Path == b.Qid.Path && a.Type == b.Type && a.Dev == b.Dev
|
||||
}
|
||||
|
||||
func fileInfoFromStat(d *syscall.Dir) FileInfo {
|
||||
fs := &fileStat{
|
||||
name: d.Name,
|
||||
|
|
|
|||
52
src/os/stat_unix.go
Normal file
52
src/os/stat_unix.go
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
|
||||
|
||||
package os
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Stat returns the FileInfo structure describing file.
|
||||
// If there is an error, it will be of type *PathError.
|
||||
func (f *File) Stat() (FileInfo, error) {
|
||||
if f == nil {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
var fs fileStat
|
||||
err := syscall.Fstat(f.fd, &fs.sys)
|
||||
if err != nil {
|
||||
return nil, &PathError{"stat", f.name, err}
|
||||
}
|
||||
fillFileStatFromSys(&fs, f.name)
|
||||
return &fs, nil
|
||||
}
|
||||
|
||||
// Stat returns a FileInfo describing the named file.
|
||||
// If there is an error, it will be of type *PathError.
|
||||
func Stat(name string) (FileInfo, error) {
|
||||
var fs fileStat
|
||||
err := syscall.Stat(name, &fs.sys)
|
||||
if err != nil {
|
||||
return nil, &PathError{"stat", name, err}
|
||||
}
|
||||
fillFileStatFromSys(&fs, name)
|
||||
return &fs, nil
|
||||
}
|
||||
|
||||
// Lstat returns a FileInfo describing the named file.
|
||||
// If the file is a symbolic link, the returned FileInfo
|
||||
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
||||
// If there is an error, it will be of type *PathError.
|
||||
func Lstat(name string) (FileInfo, error) {
|
||||
var fs fileStat
|
||||
err := syscall.Lstat(name, &fs.sys)
|
||||
if err != nil {
|
||||
return nil, &PathError{"lstat", name, err}
|
||||
}
|
||||
fillFileStatFromSys(&fs, name)
|
||||
return &fs, nil
|
||||
}
|
||||
|
|
@ -105,77 +105,3 @@ func Lstat(name string) (FileInfo, error) {
|
|||
}
|
||||
return fs, nil
|
||||
}
|
||||
|
||||
// basename removes trailing slashes and the leading
|
||||
// directory name and drive letter from path name.
|
||||
func basename(name string) string {
|
||||
// Remove drive letter
|
||||
if len(name) == 2 && name[1] == ':' {
|
||||
name = "."
|
||||
} else if len(name) > 2 && name[1] == ':' {
|
||||
name = name[2:]
|
||||
}
|
||||
i := len(name) - 1
|
||||
// Remove trailing slashes
|
||||
for ; i > 0 && (name[i] == '/' || name[i] == '\\'); i-- {
|
||||
name = name[:i]
|
||||
}
|
||||
// Remove leading directory name
|
||||
for i--; i >= 0; i-- {
|
||||
if name[i] == '/' || name[i] == '\\' {
|
||||
name = name[i+1:]
|
||||
break
|
||||
}
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func isAbs(path string) (b bool) {
|
||||
v := volumeName(path)
|
||||
if v == "" {
|
||||
return false
|
||||
}
|
||||
path = path[len(v):]
|
||||
if path == "" {
|
||||
return false
|
||||
}
|
||||
return IsPathSeparator(path[0])
|
||||
}
|
||||
|
||||
func volumeName(path string) (v string) {
|
||||
if len(path) < 2 {
|
||||
return ""
|
||||
}
|
||||
// with drive letter
|
||||
c := path[0]
|
||||
if path[1] == ':' &&
|
||||
('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||
|
||||
'A' <= c && c <= 'Z') {
|
||||
return path[:2]
|
||||
}
|
||||
// is it UNC
|
||||
if l := len(path); l >= 5 && IsPathSeparator(path[0]) && IsPathSeparator(path[1]) &&
|
||||
!IsPathSeparator(path[2]) && path[2] != '.' {
|
||||
// first, leading `\\` and next shouldn't be `\`. its server name.
|
||||
for n := 3; n < l-1; n++ {
|
||||
// second, next '\' shouldn't be repeated.
|
||||
if IsPathSeparator(path[n]) {
|
||||
n++
|
||||
// third, following something characters. its share name.
|
||||
if !IsPathSeparator(path[n]) {
|
||||
if path[n] == '.' {
|
||||
break
|
||||
}
|
||||
for ; n < l; n++ {
|
||||
if IsPathSeparator(path[n]) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return path[:n]
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
10
src/os/sys.go
Normal file
10
src/os/sys.go
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package os
|
||||
|
||||
// Hostname returns the host name reported by the kernel.
|
||||
func Hostname() (name string, err error) {
|
||||
return hostname()
|
||||
}
|
||||
|
|
@ -4,7 +4,10 @@
|
|||
|
||||
package os
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
|
||||
type fileStat struct {
|
||||
|
|
@ -19,3 +22,9 @@ func (fs *fileStat) Size() int64 { return fs.size }
|
|||
func (fs *fileStat) Mode() FileMode { return fs.mode }
|
||||
func (fs *fileStat) ModTime() time.Time { return fs.modTime }
|
||||
func (fs *fileStat) Sys() interface{} { return fs.sys }
|
||||
|
||||
func sameFile(fs1, fs2 *fileStat) bool {
|
||||
a := fs1.sys.(*syscall.Dir)
|
||||
b := fs2.sys.(*syscall.Dir)
|
||||
return a.Qid.Path == b.Qid.Path && a.Type == b.Type && a.Dev == b.Dev
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,3 +25,7 @@ func (fs *fileStat) Size() int64 { return fs.size }
|
|||
func (fs *fileStat) Mode() FileMode { return fs.mode }
|
||||
func (fs *fileStat) ModTime() time.Time { return fs.modTime }
|
||||
func (fs *fileStat) Sys() interface{} { return &fs.sys }
|
||||
|
||||
func sameFile(fs1, fs2 *fileStat) bool {
|
||||
return fs1.sys.Dev == fs2.sys.Dev && fs1.sys.Ino == fs2.sys.Ino
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue