func (o Scanner) generateHashes(f *models.File, file SourceFile, regenerate bool) (changed bool, err error) {
	existing := *f

	var src io.ReadCloser
	if o.CalculateOSHash && (regenerate || f.OSHash == "") {
		logger.Infof("Calculating oshash for %s ...", f.Path)

		size := file.FileInfo().Size()

		// #2196 for symlinks
		// get the size of the actual file, not the symlink
		if file.FileInfo().Mode()&os.ModeSymlink == os.ModeSymlink {
			fi, err := os.Stat(f.Path)
			if err != nil {
				return false, err
			}
			logger.Debugf("File <%s> is symlink. Size changed from <%d> to <%d>", f.Path, size, fi.Size())
			size = fi.Size()
		}

		src, err = file.Open()
		if err != nil {
			return false, err
		}
		defer src.Close()

		seekSrc, valid := src.(io.ReadSeeker)
		if !valid {
			return false, fmt.Errorf("invalid source file type: %s", file.Path())
		}

		// regenerate hash
		var oshash string
		oshash, err = o.Hasher.OSHash(seekSrc, size)
		if err != nil {
			return false, fmt.Errorf("error generating oshash for %s: %w", file.Path(), err)
		}

		f.OSHash = oshash

		// reset reader to start of file
		_, err = seekSrc.Seek(0, io.SeekStart)
		if err != nil {
			return false, fmt.Errorf("error seeking to start of file in %s: %w", file.Path(), err)
		}
	}

	// always generate if MD5 is nil
	// only regenerate MD5 if:
	// - OSHash was not calculated, or
	// - existing OSHash is different to generated one
	// or if it was different to the previous version
	if o.CalculateMD5 && (f.Checksum == "" || (regenerate && (!o.CalculateOSHash || existing.OSHash != f.OSHash))) {
		logger.Infof("Calculating checksum for %s...", f.Path)

		if src == nil {
			src, err = file.Open()
			if err != nil {
				return false, err
			}
			defer src.Close()
		}

		// regenerate checksum
		var checksum string
		checksum, err = o.Hasher.MD5(src)
		if err != nil {
			return
		}

		f.Checksum = checksum
	}

	changed = (o.CalculateOSHash && (f.OSHash != existing.OSHash)) || (o.CalculateMD5 && (f.Checksum != existing.Checksum))

	return
}
// generateHashes regenerates and sets the hashes in the provided File.
// It will not recalculate unless specified.
generateHashes regenerates and sets the hashes in the provided File.
It will not recalculate unless specified.
// generateHashes regenerates and sets the hashes in the provided File . // It will not recalculate unless specified .
func (o Scanner) generateHashes(f *models.File, file SourceFile, regenerate bool) (changed bool, err error) {
	existing := *f
	var src io.ReadCloser
	if o.CalculateOSHash && (regenerate || f.OSHash == "") {
		logger.Infof("Calculating oshash for %s ...", f.Path)
		size := file.FileInfo().Size()
		if file.FileInfo().Mode()&os.ModeSymlink == os.ModeSymlink {
			fi, err := os.Stat(f.Path)
			if err != nil {
				return false, err
			}
			logger.Debugf("File <%s> is symlink. Size changed from <%d> to <%d>", f.Path, size, fi.Size())
			size = fi.Size()
		}
		src, err = file.Open()
		if err != nil {
			return false, err
		}
		defer src.Close()
		seekSrc, valid := src.(io.ReadSeeker)
		if !valid {
			return false, fmt.Errorf("invalid source file type: %s", file.Path())
		}
		var oshash string
		oshash, err = o.Hasher.OSHash(seekSrc, size)
		if err != nil {
			return false, fmt.Errorf("error generating oshash for %s: %w", file.Path(), err)
		}
		f.OSHash = oshash
		_, err = seekSrc.Seek(0, io.SeekStart)
		if err != nil {
			return false, fmt.Errorf("error seeking to start of file in %s: %w", file.Path(), err)
		}
	}
	if o.CalculateMD5 && (f.Checksum == "" || (regenerate && (!o.CalculateOSHash || existing.OSHash != f.OSHash))) {
		logger.Infof("Calculating checksum for %s...", f.Path)
		if src == nil {
			src, err = file.Open()
			if err != nil {
				return false, err
			}
			defer src.Close()
		}
		var checksum string
		checksum, err = o.Hasher.MD5(src)
		if err != nil {
			return
		}
		f.Checksum = checksum
	}
	changed = (o.CalculateOSHash && (f.OSHash != existing.OSHash)) || (o.CalculateMD5 && (f.Checksum != existing.Checksum))
	return
}
func ( o Scanner ) generateHashes ( f * models . File , file SourceFile , regenerate bool ) ( changed bool , err error ) { existing := * f var src io . ReadCloser if o . CalculateOSHash && ( regenerate || f . OSHash == " " ) { logger . Infof ( " " , f . Path ) size := file . FileInfo ( ) . Size ( ) if file . FileInfo ( ) . Mode ( ) & os . ModeSymlink == os . ModeSymlink { fi , err := os . Stat ( f . Path ) if err != nil { return false , err } logger . Debugf ( " " , f . Path , size , fi . Size ( ) ) size = fi . Size ( ) } src , err = file . Open ( ) if err != nil { return false , err } defer src . Close ( ) seekSrc , valid := src . ( io . ReadSeeker ) if ! valid { return false , fmt . Errorf ( " " , file . Path ( ) ) } var oshash string oshash , err = o . Hasher . OSHash ( seekSrc , size ) if err != nil { return false , fmt . Errorf ( " " , file . Path ( ) , err ) } f . OSHash = oshash _ , err = seekSrc . Seek ( 0 , io . SeekStart ) if err != nil { return false , fmt . Errorf ( " " , file . Path ( ) , err ) } } if o . CalculateMD5 && ( f . Checksum == " " || ( regenerate && ( ! o . CalculateOSHash || existing . OSHash != f . OSHash ) ) ) { logger . Infof ( " " , f . Path ) if src == nil { src , err = file . Open ( ) if err != nil { return false , err } defer src . Close ( ) } var checksum string checksum , err = o . Hasher . MD5 ( src ) if err != nil { return } f . Checksum = checksum } changed = ( o . CalculateOSHash && ( f . OSHash != existing . OSHash ) ) || ( o . CalculateMD5 && ( f . Checksum != existing . Checksum ) ) return }
generateHashes regenerates and sets the hashes in the provided File.
generateHashes regenerates and sets the hashes in the provided File .
// #2196 for symlinks // get the size of the actual file, not the symlink // regenerate hash // reset reader to start of file // always generate if MD5 is nil // only regenerate MD5 if: // - OSHash was not calculated, or // - existing OSHash is different to generated one // or if it was different to the previous version // regenerate checksum