mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-12-24 11:51:13 +08:00
146 lines
3.2 KiB
Go
146 lines
3.2 KiB
Go
package cp
|
|
|
|
import (
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
type fileSpec struct {
|
|
PodName string
|
|
PodNamespace string
|
|
File pathSpec
|
|
}
|
|
|
|
type pathSpec interface {
|
|
String() string
|
|
}
|
|
|
|
// localPath represents a client-native path, which will differ based
|
|
// on the client OS, its methods will use path/filepath package which
|
|
// is OS dependant
|
|
type localPath struct {
|
|
file string
|
|
}
|
|
|
|
func newLocalPath(fileName string) localPath {
|
|
file := stripTrailingSlash(fileName)
|
|
return localPath{file: file}
|
|
}
|
|
|
|
func (p localPath) String() string {
|
|
return p.file
|
|
}
|
|
|
|
func (p localPath) Dir() localPath {
|
|
return newLocalPath(filepath.Dir(p.file))
|
|
}
|
|
|
|
func (p localPath) Base() localPath {
|
|
return newLocalPath(filepath.Base(p.file))
|
|
}
|
|
|
|
func (p localPath) Clean() localPath {
|
|
return newLocalPath(filepath.Clean(p.file))
|
|
}
|
|
|
|
func (p localPath) Join(elem pathSpec) localPath {
|
|
return newLocalPath(filepath.Join(p.file, elem.String()))
|
|
}
|
|
|
|
func (p localPath) Glob() (matches []string, err error) {
|
|
return filepath.Glob(p.file)
|
|
}
|
|
|
|
func (p localPath) StripSlashes() localPath {
|
|
return newLocalPath(stripLeadingSlash(p.file))
|
|
}
|
|
|
|
func isRelative(base, target localPath) bool {
|
|
relative, err := filepath.Rel(base.String(), target.String())
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return relative == "." || relative == stripPathShortcuts(relative)
|
|
}
|
|
|
|
// remotePath represents always UNIX path, its methods will use path
|
|
// package which is always using `/`
|
|
type remotePath struct {
|
|
file string
|
|
}
|
|
|
|
func newRemotePath(fileName string) remotePath {
|
|
// we assume remote file is a linux container but we need to convert
|
|
// windows path separators to unix style for consistent processing
|
|
file := strings.ReplaceAll(stripTrailingSlash(fileName), `\`, "/")
|
|
return remotePath{file: file}
|
|
}
|
|
|
|
func (p remotePath) String() string {
|
|
return p.file
|
|
}
|
|
|
|
func (p remotePath) Dir() remotePath {
|
|
return newRemotePath(path.Dir(p.file))
|
|
}
|
|
|
|
func (p remotePath) Base() remotePath {
|
|
return newRemotePath(path.Base(p.file))
|
|
}
|
|
|
|
func (p remotePath) Clean() remotePath {
|
|
return newRemotePath(path.Clean(p.file))
|
|
}
|
|
|
|
func (p remotePath) Join(elem pathSpec) remotePath {
|
|
return newRemotePath(path.Join(p.file, elem.String()))
|
|
}
|
|
|
|
func (p remotePath) StripShortcuts() remotePath {
|
|
p = p.Clean()
|
|
return newRemotePath(stripPathShortcuts(p.file))
|
|
}
|
|
|
|
func (p remotePath) StripSlashes() remotePath {
|
|
return newRemotePath(stripLeadingSlash(p.file))
|
|
}
|
|
|
|
// strips trailing slash (if any) both unix and windows style
|
|
func stripTrailingSlash(file string) string {
|
|
if len(file) == 0 {
|
|
return file
|
|
}
|
|
if file != "/" && strings.HasSuffix(string(file[len(file)-1]), "/") {
|
|
return file[:len(file)-1]
|
|
}
|
|
return file
|
|
}
|
|
|
|
func stripLeadingSlash(file string) string {
|
|
// tar strips the leading '/' and '\' if it's there, so we will too
|
|
return strings.TrimLeft(file, `/\`)
|
|
}
|
|
|
|
// stripPathShortcuts removes any leading or trailing "../" from a given path
|
|
func stripPathShortcuts(p string) string {
|
|
newPath := p
|
|
trimmed := strings.TrimPrefix(newPath, "../")
|
|
|
|
for trimmed != newPath {
|
|
newPath = trimmed
|
|
trimmed = strings.TrimPrefix(newPath, "../")
|
|
}
|
|
|
|
// trim leftover {".", ".."}
|
|
if newPath == "." || newPath == ".." {
|
|
newPath = ""
|
|
}
|
|
|
|
if len(newPath) > 0 && string(newPath[0]) == "/" {
|
|
return newPath[1:]
|
|
}
|
|
|
|
return newPath
|
|
}
|