path.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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. package os
  5. import (
  6. "syscall"
  7. )
  8. // MkdirAll creates a directory named path,
  9. // along with any necessary parents, and returns nil,
  10. // or else returns an error.
  11. // The permission bits perm (before umask) are used for all
  12. // directories that MkdirAll creates.
  13. // If path is already a directory, MkdirAll does nothing
  14. // and returns nil.
  15. func MkdirAll(path string, perm FileMode) error {
  16. // Fast path: if we can tell whether path is a directory or file, stop with success or error.
  17. dir, err := Stat(path)
  18. if err == nil {
  19. if dir.IsDir() {
  20. return nil
  21. }
  22. return &PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR}
  23. }
  24. // Slow path: make sure parent exists and then call Mkdir for path.
  25. i := len(path)
  26. for i > 0 && IsPathSeparator(path[i-1]) { // Skip trailing path separator.
  27. i--
  28. }
  29. j := i
  30. for j > 0 && !IsPathSeparator(path[j-1]) { // Scan backward over element.
  31. j--
  32. }
  33. if j > 1 {
  34. // Create parent.
  35. err = MkdirAll(fixRootDirectory(path[:j-1]), perm)
  36. if err != nil {
  37. return err
  38. }
  39. }
  40. // Parent now exists; invoke Mkdir and use its result.
  41. err = Mkdir(path, perm)
  42. if err != nil {
  43. // Handle arguments like "foo/." by
  44. // double-checking that directory doesn't exist.
  45. dir, err1 := Lstat(path)
  46. if err1 == nil && dir.IsDir() {
  47. return nil
  48. }
  49. return err
  50. }
  51. return nil
  52. }
  53. // RemoveAll removes path and any children it contains.
  54. // It removes everything it can but returns the first error
  55. // it encounters. If the path does not exist, RemoveAll
  56. // returns nil (no error).
  57. // If there is an error, it will be of type *PathError.
  58. func RemoveAll(path string) error {
  59. return removeAll(path)
  60. }
  61. // endsWithDot reports whether the final component of path is ".".
  62. func endsWithDot(path string) bool {
  63. if path == "." {
  64. return true
  65. }
  66. if len(path) >= 2 && path[len(path)-1] == '.' && IsPathSeparator(path[len(path)-2]) {
  67. return true
  68. }
  69. return false
  70. }