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