glob_windows.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // Copyright (C) 2015 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at http://mozilla.org/MPL/2.0/.
  6. // +build windows
  7. package osutil
  8. import (
  9. "os"
  10. "path/filepath"
  11. "sort"
  12. "strings"
  13. )
  14. // Deals with https://github.com/golang/go/issues/10577
  15. func Glob(pattern string) (matches []string, err error) {
  16. if !hasMeta(pattern) {
  17. if _, err = os.Lstat(pattern); err != nil {
  18. return nil, nil
  19. }
  20. return []string{pattern}, nil
  21. }
  22. dir, file := filepath.Split(pattern)
  23. switch dir {
  24. case "":
  25. dir = "."
  26. case string(filepath.Separator):
  27. // nothing
  28. default:
  29. dir = dir[0 : len(dir)-1] // chop off trailing separator
  30. }
  31. if !hasMeta(dir) {
  32. return glob(dir, file, nil)
  33. }
  34. var m []string
  35. m, err = Glob(dir)
  36. if err != nil {
  37. return
  38. }
  39. for _, d := range m {
  40. matches, err = glob(d, file, matches)
  41. if err != nil {
  42. return
  43. }
  44. }
  45. return
  46. }
  47. func hasMeta(path string) bool {
  48. // Strip off Windows long path prefix if it exists.
  49. if strings.HasPrefix(path, "\\\\?\\") {
  50. path = path[4:]
  51. }
  52. // TODO(niemeyer): Should other magic characters be added here?
  53. return strings.IndexAny(path, "*?[") >= 0
  54. }
  55. func glob(dir, pattern string, matches []string) (m []string, e error) {
  56. m = matches
  57. fi, err := os.Stat(dir)
  58. if err != nil {
  59. return
  60. }
  61. if !fi.IsDir() {
  62. return
  63. }
  64. d, err := os.Open(dir)
  65. if err != nil {
  66. return
  67. }
  68. defer d.Close()
  69. names, _ := d.Readdirnames(-1)
  70. sort.Strings(names)
  71. for _, n := range names {
  72. matched, err := filepath.Match(pattern, n)
  73. if err != nil {
  74. return m, err
  75. }
  76. if matched {
  77. m = append(m, filepath.Join(dir, n))
  78. }
  79. }
  80. return
  81. }