mkdirall_windows.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. //
  3. // Redistribution and use in source and binary forms, with or without
  4. // modification, are permitted provided that the following conditions are
  5. // met:
  6. //
  7. // * Redistributions of source code must retain the above copyright
  8. // notice, this list of conditions and the following disclaimer.
  9. // * Redistributions in binary form must reproduce the above
  10. // copyright notice, this list of conditions and the following disclaimer
  11. // in the documentation and/or other materials provided with the
  12. // distribution.
  13. // * Neither the name of Google Inc. nor the names of its
  14. // contributors may be used to endorse or promote products derived from
  15. // this software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  20. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  21. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  22. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  23. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  27. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. //
  29. // Modified by Zillode to fix https://github.com/syncthing/syncthing/issues/1822
  30. // Sync with https://github.com/golang/go/blob/master/src/os/path.go
  31. // See https://github.com/golang/go/issues/10900
  32. package osutil
  33. import (
  34. "os"
  35. "path/filepath"
  36. "syscall"
  37. )
  38. // MkdirAll creates a directory named path, along with any necessary parents,
  39. // and returns nil, or else returns an error.
  40. // The permission bits perm are used for all directories that MkdirAll creates.
  41. // If path is already a directory, MkdirAll does nothing and returns nil.
  42. func MkdirAll(path string, perm os.FileMode) error {
  43. // Fast path: if we can tell whether path is a directory or file, stop with success or error.
  44. dir, err := os.Stat(path)
  45. if err == nil {
  46. if dir.IsDir() {
  47. return nil
  48. }
  49. return &os.PathError{
  50. Op: "mkdir",
  51. Path: path,
  52. Err: syscall.ENOTDIR,
  53. }
  54. }
  55. // Slow path: make sure parent exists and then call Mkdir for path.
  56. i := len(path)
  57. for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator.
  58. i--
  59. }
  60. j := i
  61. for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element.
  62. j--
  63. }
  64. if j > 1 {
  65. // Create parent
  66. parent := path[0 : j-1]
  67. if parent != filepath.VolumeName(parent) {
  68. err = MkdirAll(parent, perm)
  69. if err != nil {
  70. return err
  71. }
  72. }
  73. }
  74. // Parent now exists; invoke Mkdir and use its result.
  75. err = os.Mkdir(path, perm)
  76. if err != nil {
  77. // Handle arguments like "foo/." by
  78. // double-checking that directory doesn't exist.
  79. dir, err1 := os.Lstat(path)
  80. if err1 == nil && dir.IsDir() {
  81. return nil
  82. }
  83. return err
  84. }
  85. return nil
  86. }