github.com/pelicanplatform/pelican@v1.0.5/client/unique_hash_windows.go (about) 1 //go:build windows 2 // +build windows 3 4 /*************************************************************** 5 * 6 * Copyright (C) 2023, Pelican Project, Morgridge Institute for Research 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); you 9 * may not use this file except in compliance with the License. You may 10 * obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 ***************************************************************/ 21 22 package client 23 24 import ( 25 "bytes" 26 "crypto/sha256" 27 "encoding/binary" 28 "fmt" 29 "os" 30 "time" 31 32 log "github.com/sirupsen/logrus" 33 ) 34 35 // Given a local filename, create a unique identifier from filesystem 36 // metadata; anytime the file contents change, the unique identifier 37 // should also change. The hash changes once every 24 hours to allow 38 // the shadow origin to do garbage collection. 39 // 40 // The current algorithm to generate the unique identifier is to 41 // take the concatenation of the following byte buffers: 42 // 43 // - basename of the path. 44 // - mtime # as a double string 45 // - Current unix epoch time, as integer, divided by 86400 46 // 47 // and then running it through a SHA256 sum to produce a digest. 48 // 49 // The hex digest of the SHA256 sum is returned along with the file size 50 func unique_hash(filePath string) (string, uint64, error) { 51 log.Debugf("Creating a unique hash for filename %s", filePath) 52 53 st, err := os.Stat(filePath) 54 if err != nil { 55 log.Debugln("Error while stat'ing file for metadata:", err) 56 return "", 0, err 57 } 58 59 digest := sha256.New() 60 digest.Write([]byte(filePath)) 61 digest.Write([]byte(st.ModTime().Format(time.RFC3339Nano))) 62 63 buf := new(bytes.Buffer) 64 if err := binary.Write(buf, binary.BigEndian, time.Now().Unix()/86400); err != nil { 65 log.Debugln("Error while writing current Unix time to buffer:", err) 66 return "", 0, err 67 } 68 digest.Write(buf.Bytes()) 69 70 return fmt.Sprintf("%x", digest.Sum(nil)), uint64(st.Size()), nil 71 }