mirror of
https://github.com/versity/versitygw.git
synced 2026-05-28 14:50:20 +00:00
fix: sidecar relative path joining
This commit is contained in:
@@ -49,6 +49,7 @@ func NewSideCar(dir string) (SideCar, error) {
|
||||
|
||||
// RetrieveAttribute retrieves the value of a specific attribute for an object or a bucket.
|
||||
func (s SideCar) RetrieveAttribute(_ *os.File, bucket, object, attribute string) ([]byte, error) {
|
||||
bucket, object = trimVolume(bucket), trimVolume(object)
|
||||
metadir := filepath.Join(s.dir, bucket, object, sidecarmeta)
|
||||
if object == "" {
|
||||
metadir = filepath.Join(s.dir, bucket, sidecarmeta)
|
||||
@@ -68,6 +69,7 @@ func (s SideCar) RetrieveAttribute(_ *os.File, bucket, object, attribute string)
|
||||
|
||||
// StoreAttribute stores the value of a specific attribute for an object or a bucket.
|
||||
func (s SideCar) StoreAttribute(_ *os.File, bucket, object, attribute string, value []byte) error {
|
||||
bucket, object = trimVolume(bucket), trimVolume(object)
|
||||
metadir := filepath.Join(s.dir, bucket, object, sidecarmeta)
|
||||
if object == "" {
|
||||
metadir = filepath.Join(s.dir, bucket, sidecarmeta)
|
||||
@@ -114,6 +116,7 @@ func (s SideCar) StoreAttribute(_ *os.File, bucket, object, attribute string, va
|
||||
|
||||
// DeleteAttribute removes the value of a specific attribute for an object or a bucket.
|
||||
func (s SideCar) DeleteAttribute(bucket, object, attribute string) error {
|
||||
bucket, object = trimVolume(bucket), trimVolume(object)
|
||||
metadir := filepath.Join(s.dir, bucket, object, sidecarmeta)
|
||||
if object == "" {
|
||||
metadir = filepath.Join(s.dir, bucket, sidecarmeta)
|
||||
@@ -135,6 +138,7 @@ func (s SideCar) DeleteAttribute(bucket, object, attribute string) error {
|
||||
|
||||
// ListAttributes lists all attributes for an object or a bucket.
|
||||
func (s SideCar) ListAttributes(bucket, object string) ([]string, error) {
|
||||
bucket, object = trimVolume(bucket), trimVolume(object)
|
||||
metadir := filepath.Join(s.dir, bucket, object, sidecarmeta)
|
||||
if object == "" {
|
||||
metadir = filepath.Join(s.dir, bucket, sidecarmeta)
|
||||
@@ -160,6 +164,7 @@ func (s SideCar) ListAttributes(bucket, object string) ([]string, error) {
|
||||
// When object is empty the entire bucket sidecar directory is removed,
|
||||
// cleaning up any orphaned object or multipart metadata within it.
|
||||
func (s SideCar) DeleteAttributes(bucket, object string) error {
|
||||
bucket, object = trimVolume(bucket), trimVolume(object)
|
||||
if object == "" {
|
||||
// Remove the entire bucket sidecar directory so that orphaned
|
||||
// object/multipart metadata does not accumulate after DeleteBucket.
|
||||
@@ -184,8 +189,9 @@ func (s SideCar) DeleteAttributes(bucket, object string) error {
|
||||
// newObject so that path-based lookups continue to work after the data
|
||||
// directory has been renamed.
|
||||
func (s SideCar) RenameObject(bucket, oldObject, newObject string) error {
|
||||
oldPath := filepath.Join(s.dir, bucket, oldObject)
|
||||
newPath := filepath.Join(s.dir, bucket, newObject)
|
||||
bucket = trimVolume(bucket)
|
||||
oldPath := filepath.Join(s.dir, bucket, trimVolume(oldObject))
|
||||
newPath := filepath.Join(s.dir, bucket, trimVolume(newObject))
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(newPath), 0777); err != nil {
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
|
||||
20
backend/meta/sidecar_notwindows.go
Normal file
20
backend/meta/sidecar_notwindows.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2025 Versity Software
|
||||
// This file is licensed under the Apache License, Version 2.0
|
||||
// (the "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
//go:build !windows
|
||||
|
||||
package meta
|
||||
|
||||
// trimVolume is a no-op on non-Windows platforms.
|
||||
func trimVolume(p string) string { return p }
|
||||
29
backend/meta/sidecar_windows.go
Normal file
29
backend/meta/sidecar_windows.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2025 Versity Software
|
||||
// This file is licensed under the Apache License, Version 2.0
|
||||
// (the "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
//go:build windows
|
||||
|
||||
package meta
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// trimVolume strips the Windows drive letter (e.g. "C:") and any leading
|
||||
// path separator from p so it can be safely used as a sub-path component
|
||||
// inside filepath.Join without becoming an absolute root.
|
||||
func trimVolume(p string) string {
|
||||
return strings.TrimLeft(p[len(filepath.VolumeName(p)):], `\/`)
|
||||
}
|
||||
@@ -109,7 +109,7 @@ func (tmp *tmpfile) link() error {
|
||||
backoffMs := initialBackoffMs
|
||||
for {
|
||||
err = backend.MoveFile(tempname, objPath, defaultFilePerm)
|
||||
if !errors.Is(err, syscall.ENOENT) {
|
||||
if !os.IsNotExist(err) {
|
||||
break
|
||||
}
|
||||
// The parent directory may have been concurrently removed; backoff and retry.
|
||||
@@ -117,11 +117,12 @@ func (tmp *tmpfile) link() error {
|
||||
sleepWithJitter(backoffMs)
|
||||
backoffMs = min((backoffMs * 2), maxBackoffMs)
|
||||
|
||||
err = backend.MkdirAll(filepath.Dir(objPath), tmp.uid, tmp.gid,
|
||||
// Best-effort: recreate the parent directory. Ignore errors here;
|
||||
// if recreation fails transiently (e.g. Windows pending-delete on
|
||||
// a recently removed directory), the next MoveFile attempt will
|
||||
// return os.IsNotExist again and we will retry.
|
||||
_ = backend.MkdirAll(filepath.Dir(objPath), tmp.uid, tmp.gid,
|
||||
tmp.doChown, tmp.newDirPerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("recreate parent dir: %w", err)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user