// downloadMeta downloads top-level metadata from remote storage and verifies // it using the given file metadata. func (c *Client) downloadMeta(name string, m data.FileMeta) ([]byte, error) { r, size, err := c.download(name, c.remote.GetMeta, m.Hashes) if err != nil { if IsNotFound(err) { return nil, ErrMissingRemoteMetadata{name} } return nil, err } defer r.Close() // return ErrWrongSize if the reported size is known and incorrect if size >= 0 && size != m.Length { return nil, ErrWrongSize{name, size, m.Length} } // wrap the data in a LimitReader so we download at most m.Length bytes stream := io.LimitReader(r, m.Length) // read the data, simultaneously writing it to buf and generating metadata var buf bytes.Buffer meta, err := util.GenerateFileMeta(io.TeeReader(stream, &buf), m.HashAlgorithms()...) if err != nil { return nil, err } if err := util.FileMetaEqual(meta, m); err != nil { return nil, ErrDownloadFailed{name, err} } return buf.Bytes(), nil }
// hasMeta checks whether local metadata has the given file meta func (c *Client) hasMeta(name string, m data.FileMeta) bool { b, ok := c.localMeta[name] if !ok { return false } meta, err := util.GenerateFileMeta(bytes.NewReader(b), m.HashAlgorithms()...) if err != nil { return false } err = util.FileMetaEqual(meta, m) return err == nil }