OSDN Git Service

compiler, libgo: unsafe.{Sizeof,Alignof,Offsetof} return uintptr.
[pf3gnuchains/gcc-fork.git] / libgo / go / os / getwd.go
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 package os
6
7 import (
8         "syscall"
9 )
10
11 // Getwd returns a rooted path name corresponding to the
12 // current directory.  If the current directory can be
13 // reached via multiple paths (due to symbolic links),
14 // Getwd may return any one of them.
15 func Getwd() (pwd string, err error) {
16         // If the operating system provides a Getwd call, use it.
17         if syscall.ImplementsGetwd {
18                 s, e := syscall.Getwd()
19                 return s, NewSyscallError("getwd", e)
20         }
21
22         // Otherwise, we're trying to find our way back to ".".
23         dot, err := Stat(".")
24         if err != nil {
25                 return "", err
26         }
27
28         // Clumsy but widespread kludge:
29         // if $PWD is set and matches ".", use it.
30         pwd = Getenv("PWD")
31         if len(pwd) > 0 && pwd[0] == '/' {
32                 d, err := Stat(pwd)
33                 if err == nil && SameFile(dot, d) {
34                         return pwd, nil
35                 }
36         }
37
38         // Root is a special case because it has no parent
39         // and ends in a slash.
40         root, err := Stat("/")
41         if err != nil {
42                 // Can't stat root - no hope.
43                 return "", err
44         }
45         if SameFile(root, dot) {
46                 return "/", nil
47         }
48
49         // General algorithm: find name in parent
50         // and then find name of parent.  Each iteration
51         // adds /name to the beginning of pwd.
52         pwd = ""
53         for parent := ".."; ; parent = "../" + parent {
54                 if len(parent) >= 1024 { // Sanity check
55                         return "", syscall.ENAMETOOLONG
56                 }
57                 fd, err := Open(parent)
58                 if err != nil {
59                         return "", err
60                 }
61
62                 for {
63                         names, err := fd.Readdirnames(100)
64                         if err != nil {
65                                 fd.Close()
66                                 return "", err
67                         }
68                         for _, name := range names {
69                                 d, _ := Lstat(parent + "/" + name)
70                                 if SameFile(d, dot) {
71                                         pwd = "/" + name + pwd
72                                         goto Found
73                                 }
74                         }
75                 }
76                 fd.Close()
77                 return "", ErrNotExist
78
79         Found:
80                 pd, err := fd.Stat()
81                 if err != nil {
82                         return "", err
83                 }
84                 fd.Close()
85                 if SameFile(pd, root) {
86                         break
87                 }
88                 // Set up for next round.
89                 dot = pd
90         }
91         return pwd, nil
92 }