github.com/moby/docker@v26.1.3+incompatible/internal/safepath/safepath.go (about) 1 package safepath 2 3 import ( 4 "context" 5 "fmt" 6 "sync" 7 8 "github.com/containerd/log" 9 ) 10 11 type SafePath struct { 12 path string 13 cleanup func(ctx context.Context) error 14 mutex sync.Mutex 15 16 // Immutable fields 17 sourceBase, sourceSubpath string 18 } 19 20 // Close releases the resources used by the path. 21 func (s *SafePath) Close(ctx context.Context) error { 22 s.mutex.Lock() 23 defer s.mutex.Unlock() 24 25 if s.path == "" { 26 base, sub := s.SourcePath() 27 log.G(ctx).WithFields(log.Fields{ 28 "path": s.Path(), 29 "sourceBase": base, 30 "sourceSubpath": sub, 31 }).Warn("an attempt to close an already closed SafePath") 32 return nil 33 } 34 35 s.path = "" 36 if s.cleanup != nil { 37 return s.cleanup(ctx) 38 } 39 return nil 40 } 41 42 // IsValid return true when path can still be used and wasn't cleaned up by Close. 43 func (s *SafePath) IsValid() bool { 44 s.mutex.Lock() 45 defer s.mutex.Unlock() 46 return s.path != "" 47 } 48 49 // Path returns a safe, temporary path that can be used to access the original path. 50 func (s *SafePath) Path() string { 51 s.mutex.Lock() 52 defer s.mutex.Unlock() 53 if s.path == "" { 54 panic(fmt.Sprintf("use-after-close attempted for safepath with source [%s, %s]", s.sourceBase, s.sourceSubpath)) 55 } 56 return s.path 57 } 58 59 // SourcePath returns the source path the safepath points to. 60 func (s *SafePath) SourcePath() (string, string) { 61 // No mutex lock because these are immutable. 62 return s.sourceBase, s.sourceSubpath 63 }