OSDN Git Service

libgo: Update to weekly.2012-01-15.
[pf3gnuchains/gcc-fork.git] / libgo / go / os / path.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 "io"
8
9 // MkdirAll creates a directory named path,
10 // along with any necessary parents, and returns nil,
11 // or else returns an error.
12 // The permission bits perm are used for all
13 // directories that MkdirAll creates.
14 // If path is already a directory, MkdirAll does nothing
15 // and returns nil.
16 func MkdirAll(path string, perm uint32) error {
17         // If path exists, stop with success or error.
18         dir, err := Stat(path)
19         if err == nil {
20                 if dir.IsDir() {
21                         return nil
22                 }
23                 return &PathError{"mkdir", path, ENOTDIR}
24         }
25
26         // Doesn't already exist; make sure parent does.
27         i := len(path)
28         for i > 0 && IsPathSeparator(path[i-1]) { // Skip trailing path separator.
29                 i--
30         }
31
32         j := i
33         for j > 0 && !IsPathSeparator(path[j-1]) { // Scan backward over element.
34                 j--
35         }
36
37         if j > 1 {
38                 // Create parent
39                 err = MkdirAll(path[0:j-1], perm)
40                 if err != nil {
41                         return err
42                 }
43         }
44
45         // Now parent exists, try to create.
46         err = Mkdir(path, perm)
47         if err != nil {
48                 // Handle arguments like "foo/." by
49                 // double-checking that directory doesn't exist.
50                 dir, err1 := Lstat(path)
51                 if err1 == nil && dir.IsDir() {
52                         return nil
53                 }
54                 return err
55         }
56         return nil
57 }
58
59 // RemoveAll removes path and any children it contains.
60 // It removes everything it can but returns the first error
61 // it encounters.  If the path does not exist, RemoveAll
62 // returns nil (no error).
63 func RemoveAll(path string) error {
64         // Simple case: if Remove works, we're done.
65         err := Remove(path)
66         if err == nil {
67                 return nil
68         }
69
70         // Otherwise, is this a directory we need to recurse into?
71         dir, serr := Lstat(path)
72         if serr != nil {
73                 if serr, ok := serr.(*PathError); ok && (serr.Err == ENOENT || serr.Err == ENOTDIR) {
74                         return nil
75                 }
76                 return serr
77         }
78         if !dir.IsDir() {
79                 // Not a directory; return the error from Remove.
80                 return err
81         }
82
83         // Directory.
84         fd, err := Open(path)
85         if err != nil {
86                 return err
87         }
88
89         // Remove contents & return first error.
90         err = nil
91         for {
92                 names, err1 := fd.Readdirnames(100)
93                 for _, name := range names {
94                         err1 := RemoveAll(path + string(PathSeparator) + name)
95                         if err == nil {
96                                 err = err1
97                         }
98                 }
99                 if err1 == io.EOF {
100                         break
101                 }
102                 // If Readdirnames returned an error, use it.
103                 if err == nil {
104                         err = err1
105                 }
106                 if len(names) == 0 {
107                         break
108                 }
109         }
110
111         // Close directory, because windows won't remove opened directory.
112         fd.Close()
113
114         // Remove directory.
115         err1 := Remove(path)
116         if err == nil {
117                 err = err1
118         }
119         return err
120 }