mkdirall_windows.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  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. // Modified by Zillode to fix https://github.com/syncthing/syncthing/issues/1822
  5. // Sync with https://github.com/golang/go/blob/master/src/os/path.go
  6. // See https://github.com/golang/go/issues/10900
  7. package osutil
  8. import (
  9. "os"
  10. "path/filepath"
  11. "syscall"
  12. )
  13. // MkdirAll creates a directory named path, along with any necessary parents,
  14. // and returns nil, or else returns an error.
  15. // The permission bits perm are used for all directories that MkdirAll creates.
  16. // If path is already a directory, MkdirAll does nothing and returns nil.
  17. func MkdirAll(path string, perm os.FileMode) error {
  18. // Fast path: if we can tell whether path is a directory or file, stop with success or error.
  19. dir, err := os.Stat(path)
  20. if err == nil {
  21. if dir.IsDir() {
  22. return nil
  23. }
  24. return &os.PathError{
  25. Op: "mkdir",
  26. Path: path,
  27. Err: syscall.ENOTDIR,
  28. }
  29. }
  30. // Slow path: make sure parent exists and then call Mkdir for path.
  31. i := len(path)
  32. for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator.
  33. i--
  34. }
  35. j := i
  36. for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element.
  37. j--
  38. }
  39. if j > 1 {
  40. // Create parent
  41. parent := path[0 : j-1]
  42. if parent != filepath.VolumeName(parent) {
  43. err = MkdirAll(parent, perm)
  44. if err != nil {
  45. return err
  46. }
  47. }
  48. }
  49. // Parent now exists; invoke Mkdir and use its result.
  50. err = os.Mkdir(path, perm)
  51. if err != nil {
  52. // Handle arguments like "foo/." by
  53. // double-checking that directory doesn't exist.
  54. dir, err1 := os.Lstat(path)
  55. if err1 == nil && dir.IsDir() {
  56. return nil
  57. }
  58. return err
  59. }
  60. return nil
  61. }