exec_windows.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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. // Fork, exec, wait, etc.
  5. package windows
  6. import "syscall"
  7. // EscapeArg rewrites command line argument s as prescribed
  8. // in http://msdn.microsoft.com/en-us/library/ms880421.
  9. // This function returns "" (2 double quotes) if s is empty.
  10. // Alternatively, these transformations are done:
  11. // - every back slash (\) is doubled, but only if immediately
  12. // followed by double quote (");
  13. // - every double quote (") is escaped by back slash (\);
  14. // - finally, s is wrapped with double quotes (arg -> "arg"),
  15. // but only if there is space or tab inside s.
  16. func EscapeArg(s string) string {
  17. if len(s) == 0 {
  18. return "\"\""
  19. }
  20. n := len(s)
  21. hasSpace := false
  22. for i := 0; i < len(s); i++ {
  23. switch s[i] {
  24. case '"', '\\':
  25. n++
  26. case ' ', '\t':
  27. hasSpace = true
  28. }
  29. }
  30. if hasSpace {
  31. n += 2
  32. }
  33. if n == len(s) {
  34. return s
  35. }
  36. qs := make([]byte, n)
  37. j := 0
  38. if hasSpace {
  39. qs[j] = '"'
  40. j++
  41. }
  42. slashes := 0
  43. for i := 0; i < len(s); i++ {
  44. switch s[i] {
  45. default:
  46. slashes = 0
  47. qs[j] = s[i]
  48. case '\\':
  49. slashes++
  50. qs[j] = s[i]
  51. case '"':
  52. for ; slashes > 0; slashes-- {
  53. qs[j] = '\\'
  54. j++
  55. }
  56. qs[j] = '\\'
  57. j++
  58. qs[j] = s[i]
  59. }
  60. j++
  61. }
  62. if hasSpace {
  63. for ; slashes > 0; slashes-- {
  64. qs[j] = '\\'
  65. j++
  66. }
  67. qs[j] = '"'
  68. j++
  69. }
  70. return string(qs[:j])
  71. }
  72. func CloseOnExec(fd Handle) {
  73. SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
  74. }
  75. // FullPath retrieves the full path of the specified file.
  76. func FullPath(name string) (path string, err error) {
  77. p, err := UTF16PtrFromString(name)
  78. if err != nil {
  79. return "", err
  80. }
  81. buf := make([]uint16, 100)
  82. n, err := GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
  83. if err != nil {
  84. return "", err
  85. }
  86. if n > uint32(len(buf)) {
  87. // Windows is asking for bigger buffer.
  88. buf = make([]uint16, n)
  89. n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
  90. if err != nil {
  91. return "", err
  92. }
  93. if n > uint32(len(buf)) {
  94. return "", syscall.EINVAL
  95. }
  96. }
  97. return UTF16ToString(buf[:n]), nil
  98. }