file.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * @Author: LinkLeong link@icewhale.com
  3. * @Date: 2021-12-20 14:15:46
  4. * @LastEditors: LinkLeong
  5. * @LastEditTime: 2022-07-04 16:18:23
  6. * @FilePath: /CasaOS/service/file.go
  7. * @Description:
  8. * @Website: https://www.casaos.io
  9. * Copyright (c) 2022 by icewhale, All Rights Reserved.
  10. */
  11. package service
  12. import (
  13. "context"
  14. "io"
  15. "os"
  16. "path/filepath"
  17. "strings"
  18. "sync"
  19. "time"
  20. "github.com/IceWhaleTech/CasaOS-Common/utils/logger"
  21. "github.com/IceWhaleTech/CasaOS/model"
  22. "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
  23. "github.com/moby/sys/mountinfo"
  24. "go.uber.org/zap"
  25. )
  26. var FileQueue sync.Map
  27. var OpStrArr []string
  28. type reader struct {
  29. ctx context.Context
  30. r io.Reader
  31. }
  32. // NewReader wraps an io.Reader to handle context cancellation.
  33. //
  34. // Context state is checked BEFORE every Read.
  35. func NewReader(ctx context.Context, r io.Reader) io.Reader {
  36. if r, ok := r.(*reader); ok && ctx == r.ctx {
  37. return r
  38. }
  39. return &reader{ctx: ctx, r: r}
  40. }
  41. func (r *reader) Read(p []byte) (n int, err error) {
  42. select {
  43. case <-r.ctx.Done():
  44. return 0, r.ctx.Err()
  45. default:
  46. return r.r.Read(p)
  47. }
  48. }
  49. type writer struct {
  50. ctx context.Context
  51. w io.Writer
  52. }
  53. type copier struct {
  54. writer
  55. }
  56. func NewWriter(ctx context.Context, w io.Writer) io.Writer {
  57. if w, ok := w.(*copier); ok && ctx == w.ctx {
  58. return w
  59. }
  60. return &copier{writer{ctx: ctx, w: w}}
  61. }
  62. // Write implements io.Writer, but with context awareness.
  63. func (w *writer) Write(p []byte) (n int, err error) {
  64. select {
  65. case <-w.ctx.Done():
  66. return 0, w.ctx.Err()
  67. default:
  68. return w.w.Write(p)
  69. }
  70. }
  71. func FileOperate(k string) {
  72. list, ok := FileQueue.Load(k)
  73. if !ok {
  74. return
  75. }
  76. temp := list.(model.FileOperate)
  77. if temp.ProcessedSize > 0 {
  78. return
  79. }
  80. for i := 0; i < len(temp.Item); i++ {
  81. v := temp.Item[i]
  82. if temp.Type == "move" {
  83. lastPath := v.From[strings.LastIndex(v.From, "/")+1:]
  84. if !file.CheckNotExist(temp.To + "/" + lastPath) {
  85. if temp.Style == "skip" {
  86. temp.Item[i].Finished = true
  87. continue
  88. } else {
  89. os.RemoveAll(temp.To + "/" + lastPath)
  90. }
  91. }
  92. err := os.Rename(v.From, temp.To+"/"+lastPath)
  93. if err != nil {
  94. logger.Error("file move error", zap.Any("err", err))
  95. err = file.MoveFile(v.From, temp.To+"/"+lastPath)
  96. if err != nil {
  97. logger.Error("MoveFile error", zap.Any("err", err))
  98. continue
  99. }
  100. }
  101. } else if temp.Type == "copy" {
  102. err := file.CopyDir(v.From, temp.To, temp.Style)
  103. if err != nil {
  104. continue
  105. }
  106. } else {
  107. continue
  108. }
  109. }
  110. temp.Finished = true
  111. FileQueue.Store(k, temp)
  112. }
  113. func ExecOpFile() {
  114. len := len(OpStrArr)
  115. if len == 0 {
  116. return
  117. }
  118. if len > 1 {
  119. len = 1
  120. }
  121. for i := 0; i < len; i++ {
  122. go FileOperate(OpStrArr[i])
  123. }
  124. }
  125. // file move or copy and send notify
  126. func CheckFileStatus() {
  127. for {
  128. if len(OpStrArr) == 0 {
  129. return
  130. }
  131. for _, v := range OpStrArr {
  132. var total int64 = 0
  133. item, ok := FileQueue.Load(v)
  134. if !ok {
  135. continue
  136. }
  137. temp := item.(model.FileOperate)
  138. for i := 0; i < len(temp.Item); i++ {
  139. if !temp.Item[i].Finished {
  140. size, err := file.GetFileOrDirSize(temp.To + "/" + filepath.Base(temp.Item[i].From))
  141. if err != nil {
  142. continue
  143. }
  144. temp.Item[i].ProcessedSize = size
  145. if size == temp.Item[i].Size {
  146. temp.Item[i].Finished = true
  147. }
  148. total += size
  149. } else {
  150. total += temp.Item[i].ProcessedSize
  151. }
  152. }
  153. temp.ProcessedSize = total
  154. FileQueue.Store(v, temp)
  155. }
  156. time.Sleep(time.Second * 3)
  157. }
  158. }
  159. func IsMounted(path string) bool {
  160. mounted, _ := mountinfo.Mounted(path)
  161. if mounted {
  162. return true
  163. }
  164. connections := MyService.Connections().GetConnectionsList()
  165. for _, v := range connections {
  166. if v.MountPoint == path {
  167. return true
  168. }
  169. }
  170. return false
  171. }