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