github.com/mckael/restic@v0.8.3/internal/backend/b2/config.go (about) 1 package b2 2 3 import ( 4 "path" 5 "regexp" 6 "strings" 7 8 "github.com/restic/restic/internal/errors" 9 "github.com/restic/restic/internal/options" 10 ) 11 12 // Config contains all configuration necessary to connect to an b2 compatible 13 // server. 14 type Config struct { 15 AccountID string 16 Key string 17 Bucket string 18 Prefix string 19 20 Connections uint `option:"connections" help:"set a limit for the number of concurrent connections (default: 5)"` 21 } 22 23 // NewConfig returns a new config with default options applied. 24 func NewConfig() Config { 25 return Config{ 26 Connections: 5, 27 } 28 } 29 30 func init() { 31 options.Register("b2", Config{}) 32 } 33 34 var bucketName = regexp.MustCompile("^[a-zA-Z0-9-]+$") 35 36 // checkBucketName tests the bucket name against the rules at 37 // https://help.backblaze.com/hc/en-us/articles/217666908-What-you-need-to-know-about-B2-Bucket-names 38 func checkBucketName(name string) error { 39 if name == "" { 40 return errors.New("bucket name is empty") 41 } 42 43 if len(name) < 6 { 44 return errors.New("bucket name is too short") 45 } 46 47 if len(name) > 50 { 48 return errors.New("bucket name is too long") 49 } 50 51 if !bucketName.MatchString(name) { 52 return errors.New("bucket name contains invalid characters, allowed are: a-z, 0-9, dash (-)") 53 } 54 55 return nil 56 } 57 58 // ParseConfig parses the string s and extracts the b2 config. The supported 59 // configuration format is b2:bucketname/prefix. If no prefix is given the 60 // prefix "restic" will be used. 61 func ParseConfig(s string) (interface{}, error) { 62 if !strings.HasPrefix(s, "b2:") { 63 return nil, errors.New("invalid format, want: b2:bucket-name[:path]") 64 } 65 66 s = s[3:] 67 data := strings.SplitN(s, ":", 2) 68 if len(data) == 0 || len(data[0]) == 0 { 69 return nil, errors.New("bucket name not found") 70 } 71 72 cfg := NewConfig() 73 cfg.Bucket = data[0] 74 75 if err := checkBucketName(cfg.Bucket); err != nil { 76 return nil, err 77 } 78 79 if len(data) == 2 { 80 p := data[1] 81 if len(p) > 0 { 82 p = path.Clean(p) 83 } 84 85 if len(p) > 0 && path.IsAbs(p) { 86 p = p[1:] 87 } 88 89 cfg.Prefix = p 90 } 91 92 return cfg, nil 93 }