// Returns true if the MD5 and SHA256 checksums set on this file match the // checksums of the file's contents. If a checksum is not provided, then it // is not checked. If neither checksum is provided, then returns true. func (f *file) Verify() bool { r := f.Open() defer r.Close() ok, _ := util.VerifyStreamHash(r, f.MD5, f.SHA256) return ok }
// Verify computes the checksum of each file in this bag, and checks it against // the manifest files. Both payload ("data/") and tag files are checked. // The file list is read from manifest files for MD5, SHA1, SHA256, and SHA512 // hashes, although only MD5 and SHA256 hashes are actually computed and verified. // Files missing an entry in a manifest file, or manifest entires missing a // corresponding file will cause a verification error. Tag files which are // missing a manifest entry are the only execption to the verification error. func (r *Reader) Verify() error { err := r.loadManifests() if err != nil { return err } // Check the quick stuff first, and do the time consuming checksum // verification last. var dataprefix = r.t.dirname + "data/" var npayload int // Does every payload ("data/") file in this zip appear in our manifest // map? tag files may also appear in the map, we don't care yet. // // We need to do some pathname manipulation since the zip directory // names have the form "bagname/data/blah/blah" but the manifest // has names of the form "data/blah/blah". for _, f := range r.z.File { if !strings.HasPrefix(f.Name, dataprefix) { continue } npayload++ xname := strings.TrimPrefix(f.Name, r.t.dirname) if r.t.manifest[xname] == nil { return BagError{Err: ErrExtraFile, File: xname} } } // Does every file listed in the manifest exist in the zip file? // // The loop above ensures npayload <= nmanifest. // so if nmanifest != npayload, it must be because it contains files // not present in the zip file. The downside of this method is we do // not know the name of the missing file. var nmanifest int for k := range r.t.manifest { if strings.HasPrefix(k, "data/") { nmanifest++ } } if npayload != nmanifest { return BagError{Err: ErrMissingFile} } // Do all the checksums match? // Since t.manifest includes both payload and data files, we will // verify more than nmanifest files here. for _, f := range r.z.File { xname := strings.TrimPrefix(f.Name, r.t.dirname) checksum := r.t.manifest[xname] if checksum == nil { // this file is not in the manifest. We don't care // since we have already verified all the payload // files are accounted for. continue } in, err := f.Open() if err != nil { return err } ok, err := util.VerifyStreamHash(in, checksum.MD5, checksum.SHA256) _ = in.Close() if err != nil { return err } else if !ok { // checksum error! return BagError{Err: ErrChecksum, File: xname} } } return nil }