Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 45 additions & 2 deletions opencloud/pkg/command/posixfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand All @@ -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")
Expand All @@ -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
Expand All @@ -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
}

Expand Down
26 changes: 26 additions & 0 deletions pkg/x/path/filepathx/path.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package filepathx

import (
"fmt"
"path/filepath"
"strings"
)

// JailJoin joins any number of path elements into a single path,
Expand All @@ -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
}
23 changes: 23 additions & 0 deletions pkg/x/path/filepathx/path_test.go
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down Expand Up @@ -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)
})
}
}