mkdirall_windows.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  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{"mkdir", path, syscall.ENOTDIR}
  25. }
  26. // Slow path: make sure parent exists and then call Mkdir for path.
  27. i := len(path)
  28. for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator.
  29. i--
  30. }
  31. j := i
  32. for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element.
  33. j--
  34. }
  35. if j > 1 {
  36. // Create parent
  37. parent := path[0 : j-1]
  38. if parent != filepath.VolumeName(parent) {
  39. err = MkdirAll(parent, perm)
  40. if err != nil {
  41. return err
  42. }
  43. }
  44. }
  45. // Parent now exists; invoke Mkdir and use its result.
  46. err = os.Mkdir(path, perm)
  47. if err != nil {
  48. // Handle arguments like "foo/." by
  49. // double-checking that directory doesn't exist.
  50. dir, err1 := os.Lstat(path)
  51. if err1 == nil && dir.IsDir() {
  52. return nil
  53. }
  54. return err
  55. }
  56. return nil
  57. }