fs.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package filesystemstorage
  2. import (
  3. "bytes"
  4. "context"
  5. "io"
  6. "path/filepath"
  7. "strings"
  8. "google.golang.org/protobuf/proto"
  9. "github.com/v2fly/v2ray-core/v5/app/persistentstorage/protostorage"
  10. "github.com/v2fly/v2ray-core/v5/common"
  11. "github.com/v2fly/v2ray-core/v5/common/environment"
  12. "github.com/v2fly/v2ray-core/v5/common/environment/envctx"
  13. "github.com/v2fly/v2ray-core/v5/features/extension/storage"
  14. )
  15. func newFileSystemStorage(ctx context.Context, config *Config) storage.ScopedPersistentStorageService {
  16. appEnvironment := envctx.EnvironmentFromContext(ctx).(environment.AppEnvironment)
  17. fss := &fileSystemStorage{
  18. fs: appEnvironment,
  19. pathRoot: config.InstanceName,
  20. currentLocation: nil,
  21. config: config,
  22. }
  23. protoStorageInst := protostorage.NewProtoStorage(fss, config.Protojson)
  24. fss.proto = protoStorageInst
  25. return fss
  26. }
  27. type fileSystemStorage struct {
  28. fs environment.FileSystemCapabilitySet
  29. proto protostorage.ProtoPersistentStorage
  30. pathRoot string
  31. currentLocation []string
  32. config *Config
  33. }
  34. func (f *fileSystemStorage) Type() interface{} {
  35. return storage.ScopedPersistentStorageServiceType
  36. }
  37. func (f *fileSystemStorage) Start() error {
  38. return nil
  39. }
  40. func (f *fileSystemStorage) Close() error {
  41. return nil
  42. }
  43. func (f *fileSystemStorage) PutProto(ctx context.Context, key string, pb proto.Message) error {
  44. return f.proto.PutProto(ctx, key, pb)
  45. }
  46. func (f *fileSystemStorage) GetProto(ctx context.Context, key string, pb proto.Message) error {
  47. return f.proto.GetProto(ctx, key, pb)
  48. }
  49. func (f *fileSystemStorage) ScopedPersistentStorageEngine() {
  50. }
  51. func (f *fileSystemStorage) Put(ctx context.Context, key []byte, value []byte) error {
  52. finalPath := filepath.Join(f.pathRoot, filepath.Join(f.currentLocation...), string(key))
  53. if value == nil {
  54. return f.fs.RemoveFile()(finalPath)
  55. }
  56. writer, err := f.fs.OpenFileForWrite()(finalPath)
  57. if err != nil {
  58. return err
  59. }
  60. defer writer.Close()
  61. _, err = io.Copy(writer, io.NopCloser(bytes.NewReader(value)))
  62. return err
  63. }
  64. func (f *fileSystemStorage) Get(ctx context.Context, key []byte) ([]byte, error) {
  65. finalPath := filepath.Join(f.pathRoot, filepath.Join(f.currentLocation...), string(key))
  66. reader, err := f.fs.OpenFileForRead()(finalPath)
  67. if err != nil {
  68. return nil, err
  69. }
  70. defer reader.Close()
  71. return io.ReadAll(reader)
  72. }
  73. func (f *fileSystemStorage) List(ctx context.Context, keyPrefix []byte) ([][]byte, error) {
  74. res, err := f.fs.ReadDir()(filepath.Join(f.pathRoot, filepath.Join(f.currentLocation...)))
  75. if err != nil {
  76. return nil, err
  77. }
  78. var result [][]byte
  79. for _, entry := range res {
  80. if !entry.IsDir() && bytes.HasPrefix([]byte(entry.Name()), keyPrefix) {
  81. result = append(result, []byte(entry.Name()))
  82. }
  83. }
  84. return result, nil
  85. }
  86. func (f *fileSystemStorage) Clear(ctx context.Context) {
  87. allFile, err := f.List(ctx, []byte{})
  88. if err != nil {
  89. return
  90. }
  91. for _, file := range allFile {
  92. _ = f.Put(ctx, file, nil)
  93. }
  94. }
  95. func (f *fileSystemStorage) NarrowScope(ctx context.Context, key []byte) (storage.ScopedPersistentStorage, error) {
  96. escapedKey := strings.ReplaceAll(string(key), "/", "_")
  97. fss := &fileSystemStorage{
  98. fs: f.fs,
  99. pathRoot: f.pathRoot,
  100. currentLocation: append(f.currentLocation, escapedKey),
  101. config: f.config,
  102. }
  103. fss.proto = protostorage.NewProtoStorage(fss, f.config.Protojson)
  104. return fss, nil
  105. }
  106. func (f *fileSystemStorage) DropScope(ctx context.Context, key []byte) error {
  107. panic("unimplemented")
  108. }
  109. func init() {
  110. common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
  111. return newFileSystemStorage(ctx, config.(*Config)), nil
  112. }))
  113. }