1
2
3
4
5 package os
6
7 import (
8 "syscall"
9 )
10
11
12
13
14
15 func Getwd() (string, Error) {
16
17 if syscall.ImplementsGetwd {
18 s, e := syscall.Getwd()
19 return s, NewSyscallError("getwd", e)
20 }
21
22
23 dot, err := Stat(".")
24 if err != nil {
25 return "", err
26 }
27
28
29
30 pwd := Getenv("PWD")
31 if len(pwd) > 0 && pwd[0] == '/' {
32 d, err := Stat(pwd)
33 if err == nil && d.Dev == dot.Dev && d.Ino == dot.Ino {
34 return pwd, nil
35 }
36 }
37
38
39
40 root, err := Stat("/")
41 if err != nil {
42
43 return "", err
44 }
45 if root.Dev == dot.Dev && root.Ino == dot.Ino {
46 return "/", nil
47 }
48
49
50
51
52 pwd = ""
53 for parent := ".."; ; parent = "../" + parent {
54 if len(parent) >= 1024 {
55 return "", 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 d.Dev == dot.Dev && d.Ino == dot.Ino {
71 pwd = "/" + name + pwd
72 goto Found
73 }
74 }
75 }
76 fd.Close()
77 return "", ENOENT
78
79 Found:
80 pd, err := fd.Stat()
81 if err != nil {
82 return "", err
83 }
84 fd.Close()
85 if pd.Dev == root.Dev && pd.Ino == root.Ino {
86 break
87 }
88
89 dot = pd
90 }
91 return pwd, nil
92 }