Merge branch 'origin/main' into 'next-release/main'

This commit is contained in:
oauth
2026-07-31 14:42:02 +00:00
3 changed files with 94 additions and 2 deletions

View File

@@ -13,6 +13,7 @@ import (
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
"github.com/opencloud-eu/opencloud/pkg/config/parser"
oclog "github.com/opencloud-eu/opencloud/pkg/log"
"github.com/opencloud-eu/opencloud/pkg/x/path/filepathx"
storageUsersParser "github.com/opencloud-eu/opencloud/services/storage-users/pkg/config/parser"
"github.com/opencloud-eu/opencloud/services/storage-users/pkg/event"
"github.com/opencloud-eu/opencloud/services/storage-users/pkg/revaconfig"
@@ -95,6 +96,39 @@ func scanCmd(ocCfg *config.Config) *cobra.Command {
os.Exit(1)
}
storageRoot := cfg.Drivers.Posix.Root
root := storageRoot
defaultRoot := true
if v, err := cmd.Flags().GetString("basepath"); err != nil {
fmt.Fprintf(os.Stderr, "Failed to parse command-line parameter '--basepath': %v\n", err)
os.Exit(1)
} else if v != "" {
root = v
if !filepath.IsAbs(v) {
if v, err = filepath.Abs(v); err != nil {
fmt.Fprintf(os.Stderr, "Failed to make the basepath mentioned using '--basepath' absolute: %v\n", err)
os.Exit(1)
} else {
root = v
}
} else {
root = v
}
root = filepath.Clean(root)
defaultRoot = false
}
// ensure that, if a basepath has been indicated, it is under the storage root
if !defaultRoot {
if contained, err := filepathx.IsSameOrContainedBy(storageRoot, root); err != nil {
fmt.Fprintf(os.Stderr, "Failed to determine whether the specified basepath %q is contained by the storage root %q: %v\n", root, storageRoot, err)
os.Exit(1)
} else if !contained {
fmt.Fprintf(os.Stderr, "The specified basepath %q is neither the storage root %q, nor a subdirectory thereof, nor a file underneath it\n", root, storageRoot)
os.Exit(1)
}
}
// We want to initialize the driver but disable scanfs on boot, so we can trigger it manually afterwards
drivers := revaconfig.StorageProviderDrivers(cfg)
drivers["posix"] = revaconfig.Posix(cfg, false, false)
@@ -112,6 +146,10 @@ func scanCmd(ocCfg *config.Config) *cobra.Command {
oclog.Pretty(true),
oclog.Color(false)).Logger
if !defaultRoot {
log = log.With().Str("basepath", root).Logger()
}
f, ok := registry.NewFuncs["posix"]
if !ok {
fmt.Fprintf(os.Stderr, "posix driver not found in registry\n")
@@ -130,8 +168,12 @@ func scanCmd(ocCfg *config.Config) *cobra.Command {
os.Exit(1)
}
fmt.Println("Starting posixfs scan...")
err = cacher.WarmupIDCache(cfg.Drivers.Posix.Root, true, false)
if defaultRoot {
fmt.Println("Starting posixfs scan...")
} else {
fmt.Printf("Starting posixfs scan at '%s'...\n", root)
}
err = cacher.WarmupIDCache(root, true, false)
if err != nil {
fmt.Fprintf(os.Stderr, "Scan failed: %v\n", err)
return err
@@ -141,6 +183,7 @@ func scanCmd(ocCfg *config.Config) *cobra.Command {
return nil
},
}
cmd.Flags().StringP("basepath", "p", "", "the root under which to scan files, which may be a directory or a file (when omitted, detaults to using the storage root)")
return cmd
}

View File

@@ -1,7 +1,9 @@
package filepathx
import (
"fmt"
"path/filepath"
"strings"
)
// JailJoin joins any number of path elements into a single path,
@@ -10,3 +12,27 @@ import (
func JailJoin(jail string, elem ...string) string {
return filepath.Join(jail, filepath.Join(append([]string{"/"}, elem...)...))
}
// Determines whether the file or directory 'child' is same as or underneath the directory 'parent'.
//
// Note that 'parent' is expected to be a directory.
func IsSameOrContainedBy(parent string, child string) (bool, error) {
absParent, err := filepath.Abs(parent)
if err != nil {
return false, fmt.Errorf("failed to make parent directory absolute: %q: %w", parent, err)
}
absChild, err := filepath.Abs(child)
if err != nil {
return false, fmt.Errorf("failed to make child file/directory absolute: %q: %w", child, err)
}
rel, err := filepath.Rel(absParent, absChild)
if err != nil {
return false, fmt.Errorf("failed to determine the relative path between the parent directory %q and the child file/directory: %q: %w", absParent, absChild, err)
}
if rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
return false, nil
}
return true, nil
}

View File

@@ -1,9 +1,12 @@
package filepathx_test
import (
"fmt"
"strings"
"testing"
"github.com/opencloud-eu/opencloud/pkg/x/path/filepathx"
"github.com/stretchr/testify/require"
)
func TestJailJoin(t *testing.T) {
@@ -61,3 +64,23 @@ func TestJailJoin(t *testing.T) {
})
}
}
func TestIsSameOrContainedBy(t *testing.T) {
for _, tt := range []struct {
parent string
child string
expected bool
}{
{"foo", "foo", true},
{"/foo", "/foo", true},
{"foo", "foo/bar", true},
{"foo", "bar", false},
} {
t.Run(fmt.Sprintf("%s: %s vs %s", t.Name(), strings.ReplaceAll(tt.parent, "/", "."), strings.ReplaceAll(tt.child, "/", ".")), func(t *testing.T) {
require := require.New(t)
b, err := filepathx.IsSameOrContainedBy(tt.parent, tt.child)
require.NoError(err)
require.Equal(tt.expected, b)
})
}
}