summaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-12-06 02:00:13 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-12-06 02:00:13 +0000
commitccc7a47f9e250e1fcd4079dcb9d11c6aecd320f9 (patch)
treecc71dfa39df4e1b16b96f13ad38293dbc9f135e7 /libgo
parent25522845e74f2d4c50893f9b1893b0a45e043d55 (diff)
downloadgcc-ccc7a47f9e250e1fcd4079dcb9d11c6aecd320f9.tar.gz
os: Clean up directory reading code.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@194237 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo')
-rw-r--r--libgo/go/os/dir.go56
-rw-r--r--libgo/go/os/file_unix.go9
2 files changed, 41 insertions, 24 deletions
diff --git a/libgo/go/os/dir.go b/libgo/go/os/dir.go
index a35d525319a..d811c9fdd86 100644
--- a/libgo/go/os/dir.go
+++ b/libgo/go/os/dir.go
@@ -6,6 +6,7 @@ package os
import (
"io"
+ "sync/atomic"
"syscall"
"unsafe"
)
@@ -29,27 +30,42 @@ func clen(n []byte) int {
return len(n)
}
-var elen int
+var nameMax int32
func (file *File) readdirnames(n int) (names []string, err error) {
- if elen == 0 {
- var dummy syscall.Dirent
- elen = (int(unsafe.Offsetof(dummy.Name)) +
- libc_pathconf(syscall.StringBytePtr(file.name), syscall.PC_NAME_MAX) +
- 1)
- }
-
if file.dirinfo == nil {
- file.dirinfo = new(dirInfo)
- file.dirinfo.buf = make([]byte, elen)
- p := syscall.StringBytePtr(file.name)
+ p, err := syscall.BytePtrFromString(file.name)
+ if err != nil {
+ return nil, err
+ }
+
+ elen := int(atomic.LoadInt32(&nameMax))
+ if elen == 0 {
+ syscall.Entersyscall()
+ plen := libc_pathconf(p, syscall.PC_NAME_MAX)
+ syscall.Exitsyscall()
+ if plen < 1024 {
+ plen = 1024
+ }
+ var dummy syscall.Dirent
+ elen = int(unsafe.Offsetof(dummy.Name)) + plen + 1
+ atomic.StoreInt32(&nameMax, int32(elen))
+ }
+
syscall.Entersyscall()
r := libc_opendir(p)
+ errno := syscall.GetErrno()
syscall.Exitsyscall()
+ if r == nil {
+ return nil, &PathError{"opendir", file.name, errno}
+ }
+
+ file.dirinfo = new(dirInfo)
+ file.dirinfo.buf = make([]byte, elen)
file.dirinfo.dir = r
}
- entry_dirent := (*syscall.Dirent)(unsafe.Pointer(&file.dirinfo.buf[0]))
+ entryDirent := (*syscall.Dirent)(unsafe.Pointer(&file.dirinfo.buf[0]))
size := n
if size <= 0 {
@@ -59,24 +75,20 @@ func (file *File) readdirnames(n int) (names []string, err error) {
names = make([]string, 0, size) // Empty with room to grow.
- dir := file.dirinfo.dir
- if dir == nil {
- return names, NewSyscallError("opendir", syscall.GetErrno())
- }
-
for n != 0 {
- var result *syscall.Dirent
- pr := &result
+ var dirent *syscall.Dirent
+ pr := &dirent
syscall.Entersyscall()
- i := libc_readdir_r(dir, entry_dirent, pr)
+ i := libc_readdir_r(file.dirinfo.dir, entryDirent, pr)
syscall.Exitsyscall()
if i != 0 {
return names, NewSyscallError("readdir_r", i)
}
- if result == nil {
+ if dirent == nil {
break // EOF
}
- var name = string(result.Name[0:clen(result.Name[0:])])
+ bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
+ var name = string(bytes[0:clen(bytes[:])])
if name == "." || name == ".." { // Useless names
continue
}
diff --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go
index f677dbb986a..68f4be88d06 100644
--- a/libgo/go/os/file_unix.go
+++ b/libgo/go/os/file_unix.go
@@ -108,8 +108,13 @@ func (file *file) close() error {
}
if file.dirinfo != nil {
- if libc_closedir(file.dirinfo.dir) < 0 && err == nil {
- err = &PathError{"closedir", file.name, syscall.GetErrno()}
+ syscall.Entersyscall()
+ i := libc_closedir(file.dirinfo.dir)
+ errno := syscall.GetErrno()
+ syscall.Exitsyscall()
+ file.dirinfo = nil
+ if i < 0 && err == nil {
+ err = &PathError{"closedir", file.name, errno}
}
}