func (s storageTransport) ValidatePolicyConfigurationScope(scope string) error { // Check that there's a store location prefix. Values we're passed are // expected to come from PolicyConfigurationIdentity or // PolicyConfigurationNamespaces, so if there's no store location, // something's wrong. if scope[0] != '[' { return ErrInvalidReference } // Parse the store location prefix. closeIndex := strings.IndexRune(scope, ']') if closeIndex < 1 { return ErrInvalidReference } storeSpec := scope[1:closeIndex] scope = scope[closeIndex+1:] storeInfo := strings.SplitN(storeSpec, "@", 2) if len(storeInfo) == 1 && storeInfo[0] != "" { // One component: the graph root. if !filepath.IsAbs(storeInfo[0]) { return ErrPathNotAbsolute } } else if len(storeInfo) == 2 && storeInfo[0] != "" && storeInfo[1] != "" { // Two components: the driver type and the graph root. if !filepath.IsAbs(storeInfo[1]) { return ErrPathNotAbsolute } } else { // Anything else: store specified in a form we don't // recognize. return ErrInvalidReference } // That might be all of it, and that's okay. if scope == "" { return nil } // But if there is anything left, it has to be a name, with or without // a tag, with or without an ID, since we don't return namespace values // that are just bare IDs. scopeInfo := strings.SplitN(scope, "@", 2) if len(scopeInfo) == 1 && scopeInfo[0] != "" { _, err := reference.ParseNamed(scopeInfo[0]) if err != nil { return err } } else if len(scopeInfo) == 2 && scopeInfo[0] != "" && scopeInfo[1] != "" { _, err := reference.ParseNamed(scopeInfo[0]) if err != nil { return err } _, err = ddigest.Parse("sha256:" + scopeInfo[1]) if err != nil { return err } } else { return ErrInvalidReference } return nil }
// Lookup looks for a digest matching the given string representation. // If no digests could be found ErrDigestNotFound will be returned // with an empty digest value. If multiple matches are found // ErrDigestAmbiguous will be returned with an empty digest value. func (dst *Set) Lookup(d string) (digest.Digest, error) { dst.mutex.RLock() defer dst.mutex.RUnlock() if len(dst.entries) == 0 { return "", ErrDigestNotFound } var ( searchFunc func(int) bool alg digest.Algorithm hex string ) dgst, err := digest.Parse(d) if err == digest.ErrDigestInvalidFormat { hex = d searchFunc = func(i int) bool { return dst.entries[i].val >= d } } else { hex = dgst.Hex() alg = dgst.Algorithm() searchFunc = func(i int) bool { if dst.entries[i].val == hex { return dst.entries[i].alg >= alg } return dst.entries[i].val >= hex } } idx := sort.Search(len(dst.entries), searchFunc) if idx == len(dst.entries) || !checkShortMatch(dst.entries[idx].alg, dst.entries[idx].val, string(alg), hex) { return "", ErrDigestNotFound } if dst.entries[idx].alg == alg && dst.entries[idx].val == hex { return dst.entries[idx].digest, nil } if idx+1 < len(dst.entries) && checkShortMatch(dst.entries[idx+1].alg, dst.entries[idx+1].val, string(alg), hex) { return "", ErrDigestAmbiguous } return dst.entries[idx].digest, nil }