diff --git a/go.mod b/go.mod index 50c34bf..ff68aa7 100644 --- a/go.mod +++ b/go.mod @@ -48,6 +48,7 @@ require ( github.com/picosh/pubsub v0.0.0-20241114191831-ec8f16c0eb88 github.com/picosh/utils v0.0.0-20250528150332-0721504d3a96 github.com/pkg/sftp v1.13.9 + github.com/pkg/xattr v0.4.11 github.com/prometheus/client_golang v1.21.1 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 github.com/sendgrid/sendgrid-go v3.16.0+incompatible diff --git a/go.sum b/go.sum index a63ea40..c22dd98 100644 --- a/go.sum +++ b/go.sum @@ -652,6 +652,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.9 h1:4NGkvGudBL7GteO3m6qnaQ4pC0Kvf0onSVc9gR3EWBw= github.com/pkg/sftp v1.13.9/go.mod h1:OBN7bVXdstkFFN/gdnHPUb5TE8eb8G1Rp9wCItqjkkA= +github.com/pkg/xattr v0.4.11 h1:DA7usy0rTMNMGvm06b5LhZUwiPj708D89S8DkXpMB1E= +github.com/pkg/xattr v0.4.11/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1086,6 +1088,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/pkg/pobj/storage/fs.go b/pkg/pobj/storage/fs.go index c703b90..1f4204e 100644 --- a/pkg/pobj/storage/fs.go +++ b/pkg/pobj/storage/fs.go @@ -1,6 +1,8 @@ package storage import ( + "crypto/md5" + "encoding/hex" "fmt" "io" "io/fs" @@ -14,6 +16,7 @@ import ( "github.com/picosh/pico/pkg/send/utils" "github.com/picosh/pico/pkg/shared/mime" + "github.com/pkg/xattr" ) // https://stackoverflow.com/a/32482941 @@ -113,6 +116,14 @@ func (s *StorageFS) GetObject(bucket Bucket, fpath string) (utils.ReadAndReaderA return nil, objInfo, err } + attr, err := xattr.FGet(dat, "user.etag") + if err != nil { + s.Logger.Error("xattr read etag", "err", err) + } + etag := string(attr) + s.Logger.Info("xattr get etag", "etag", etag) + + objInfo.ETag = etag objInfo.Size = info.Size() objInfo.LastModified = info.ModTime() objInfo.Metadata.Set("content-type", mime.GetMimeType(fpath)) @@ -130,11 +141,26 @@ func (s *StorageFS) PutObject(bucket Bucket, fpath string, contents io.Reader, e return "", 0, err } + // calculate etag + h := md5.New() + tr := io.TeeReader(contents, h) + if _, err := io.Copy(h, tr); err != nil { + return "", 0, err + } + md5Sum := h.Sum(nil) + etag := hex.EncodeToString(md5Sum) + size, err := io.Copy(f, contents) if err != nil { return "", 0, err } + s.Logger.Info("xattr set etag", "etag", etag) + err = xattr.FSet(f, "user.etag", []byte(etag)) + if err != nil { + s.Logger.Error("xattr set etag", "err", err) + } + err = f.Close() if err != nil { return "", 0, err