You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

remove.go 2.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package util
  4. import (
  5. "os"
  6. "runtime"
  7. "syscall"
  8. "time"
  9. )
  10. const windowsSharingViolationError syscall.Errno = 32
  11. // Remove removes the named file or (empty) directory with at most 5 attempts.
  12. func Remove(name string) error {
  13. var err error
  14. for i := 0; i < 5; i++ {
  15. err = os.Remove(name)
  16. if err == nil {
  17. break
  18. }
  19. unwrapped := err.(*os.PathError).Err
  20. if unwrapped == syscall.EBUSY || unwrapped == syscall.ENOTEMPTY || unwrapped == syscall.EPERM || unwrapped == syscall.EMFILE || unwrapped == syscall.ENFILE {
  21. // try again
  22. <-time.After(100 * time.Millisecond)
  23. continue
  24. }
  25. if unwrapped == windowsSharingViolationError && runtime.GOOS == "windows" {
  26. // try again
  27. <-time.After(100 * time.Millisecond)
  28. continue
  29. }
  30. if unwrapped == syscall.ENOENT {
  31. // it's already gone
  32. return nil
  33. }
  34. }
  35. return err
  36. }
  37. // RemoveAll removes the named file or (empty) directory with at most 5 attempts.
  38. func RemoveAll(name string) error {
  39. var err error
  40. for i := 0; i < 5; i++ {
  41. err = os.RemoveAll(name)
  42. if err == nil {
  43. break
  44. }
  45. unwrapped := err.(*os.PathError).Err
  46. if unwrapped == syscall.EBUSY || unwrapped == syscall.ENOTEMPTY || unwrapped == syscall.EPERM || unwrapped == syscall.EMFILE || unwrapped == syscall.ENFILE {
  47. // try again
  48. <-time.After(100 * time.Millisecond)
  49. continue
  50. }
  51. if unwrapped == windowsSharingViolationError && runtime.GOOS == "windows" {
  52. // try again
  53. <-time.After(100 * time.Millisecond)
  54. continue
  55. }
  56. if unwrapped == syscall.ENOENT {
  57. // it's already gone
  58. return nil
  59. }
  60. }
  61. return err
  62. }
  63. // Rename renames (moves) oldpath to newpath with at most 5 attempts.
  64. func Rename(oldpath, newpath string) error {
  65. var err error
  66. for i := 0; i < 5; i++ {
  67. err = os.Rename(oldpath, newpath)
  68. if err == nil {
  69. break
  70. }
  71. unwrapped := err.(*os.LinkError).Err
  72. if unwrapped == syscall.EBUSY || unwrapped == syscall.ENOTEMPTY || unwrapped == syscall.EPERM || unwrapped == syscall.EMFILE || unwrapped == syscall.ENFILE {
  73. // try again
  74. <-time.After(100 * time.Millisecond)
  75. continue
  76. }
  77. if unwrapped == windowsSharingViolationError && runtime.GOOS == "windows" {
  78. // try again
  79. <-time.After(100 * time.Millisecond)
  80. continue
  81. }
  82. if i == 0 && os.IsNotExist(err) {
  83. return err
  84. }
  85. if unwrapped == syscall.ENOENT {
  86. // it's already gone
  87. return nil
  88. }
  89. }
  90. return err
  91. }