mirror of
https://github.com/openziti/zrok.git
synced 2025-01-09 07:28:15 +01:00
start of 'copy to'; more plumbing to support passing modification times through (#438)
This commit is contained in:
parent
f40fd83b82
commit
d955a77af7
43
cmd/zrok/copyTo.go
Normal file
43
cmd/zrok/copyTo.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/openziti/zrok/util/sync"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
copyCmd.AddCommand(newCopyToCommand().cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
type copyToCommand struct {
|
||||||
|
cmd *cobra.Command
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCopyToCommand() *copyToCommand {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "to <share> <source>",
|
||||||
|
Short: "Copy files to a zrok drive from source",
|
||||||
|
Args: cobra.ExactArgs(2),
|
||||||
|
}
|
||||||
|
command := ©ToCommand{cmd: cmd}
|
||||||
|
cmd.Run = command.run
|
||||||
|
return command
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *copyToCommand) run(_ *cobra.Command, args []string) {
|
||||||
|
dst, err := sync.NewWebDAVTarget(&sync.WebDAVTargetConfig{
|
||||||
|
URL: args[0],
|
||||||
|
Username: "",
|
||||||
|
Password: "",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
src := sync.NewFilesystemTarget(&sync.FilesystemTargetConfig{
|
||||||
|
Root: args[1],
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := sync.Synchronize(src, dst); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
@ -6,10 +6,9 @@ package webdav
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/md5"
|
"crypto/sha512"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -66,27 +65,24 @@ type webdavFile struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *webdavFile) DeadProps() (map[xml.Name]Property, error) {
|
func (f *webdavFile) DeadProps() (map[xml.Name]Property, error) {
|
||||||
logrus.Infof("DeadProps(%v)", f.name)
|
|
||||||
var (
|
var (
|
||||||
xmlName xml.Name
|
xmlName xml.Name
|
||||||
property Property
|
property Property
|
||||||
properties = make(map[xml.Name]Property)
|
properties = make(map[xml.Name]Property)
|
||||||
checksum, err = f.md5()
|
checksum, err = f.checksum()
|
||||||
)
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
xmlName.Space = "http://owncloud.org/ns"
|
xmlName.Space = "zrok:"
|
||||||
xmlName.Local = "checksums"
|
xmlName.Local = "checksum"
|
||||||
property.XMLName = xmlName
|
property.XMLName = xmlName
|
||||||
property.InnerXML = append(property.InnerXML, "<checksum xmlns=\"http://owncloud.org/ns\">"...)
|
property.InnerXML = []byte(checksum)
|
||||||
property.InnerXML = append(property.InnerXML, checksum...)
|
|
||||||
property.InnerXML = append(property.InnerXML, "</checksum>"...)
|
|
||||||
properties[xmlName] = property
|
properties[xmlName] = property
|
||||||
}
|
}
|
||||||
|
|
||||||
var stat fs.FileInfo
|
var stat fs.FileInfo
|
||||||
stat, err = f.Stat()
|
stat, err = f.Stat()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
xmlName.Space = "DAV:"
|
xmlName.Space = "zrok:"
|
||||||
xmlName.Local = "lastmodified"
|
xmlName.Local = "lastmodified"
|
||||||
property.XMLName = xmlName
|
property.XMLName = xmlName
|
||||||
property.InnerXML = strconv.AppendInt(nil, stat.ModTime().Unix(), 10)
|
property.InnerXML = strconv.AppendInt(nil, stat.ModTime().Unix(), 10)
|
||||||
@ -102,19 +98,17 @@ func (f *webdavFile) Patch(proppatches []Proppatch) ([]Propstat, error) {
|
|||||||
return []Propstat{stat}, nil
|
return []Propstat{stat}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *webdavFile) md5() (string, error) {
|
func (f *webdavFile) checksum() (string, error) {
|
||||||
file, err := os.Open(f.name)
|
file, err := os.Open(f.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
hash := md5.New()
|
hash := sha512.New()
|
||||||
if _, err := io.Copy(hash, file); err != nil {
|
if _, err := io.Copy(hash, file); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
xhash := fmt.Sprintf("%x", hash.Sum(nil))
|
return fmt.Sprintf("%x", hash.Sum(nil)), nil
|
||||||
logrus.Infof("hashed %v = %v", f.name, xhash)
|
|
||||||
return xhash, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Dir implements FileSystem using the native file system restricted to a
|
// A Dir implements FileSystem using the native file system restricted to a
|
||||||
|
@ -8,6 +8,7 @@ package webdav // import "golang.org/x/net/webdav"
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -287,6 +288,10 @@ func (h *Handler) handlePut(w http.ResponseWriter, r *http.Request) (status int,
|
|||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
w.Header().Set("ETag", etag)
|
w.Header().Set("ETag", etag)
|
||||||
|
ts := r.Header.Get("zrok-timestamp")
|
||||||
|
if ts != "" {
|
||||||
|
logrus.Infof("zrok-timestamp = %v", ts)
|
||||||
|
}
|
||||||
return http.StatusCreated, nil
|
return http.StatusCreated, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ func (t *FilesystemTarget) recurse(path string, d fs.DirEntry, err error) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *FilesystemTarget) ReadStream(path string) (io.ReadCloser, error) {
|
func (t *FilesystemTarget) ReadStream(path string) (io.ReadCloser, error) {
|
||||||
return os.Open(path)
|
return os.Open(filepath.Join(t.cfg.Root, path))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *FilesystemTarget) WriteStream(path string, stream io.Reader, mode os.FileMode) error {
|
func (t *FilesystemTarget) WriteStream(path string, stream io.Reader, mode os.FileMode) error {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package sync
|
package sync
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/openziti/zrok/util/sync/webdavClient"
|
"github.com/openziti/zrok/util/sync/webdavClient"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"io"
|
"io"
|
||||||
@ -66,6 +67,7 @@ func (t *WebDAVTarget) ReadStream(path string) (io.ReadCloser, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *WebDAVTarget) WriteStream(path string, stream io.Reader, mode os.FileMode) error {
|
func (t *WebDAVTarget) WriteStream(path string, stream io.Reader, mode os.FileMode) error {
|
||||||
|
t.c.SetHeader("zrok-timestamp", fmt.Sprintf("%d", time.Now().UnixNano()))
|
||||||
return t.c.WriteStream(path, stream, mode)
|
return t.c.WriteStream(path, stream, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ func NewAuthClient(uri string, auth Authorizer) *Client {
|
|||||||
|
|
||||||
// SetHeader lets us set arbitrary headers for a given client
|
// SetHeader lets us set arbitrary headers for a given client
|
||||||
func (c *Client) SetHeader(key, value string) {
|
func (c *Client) SetHeader(key, value string) {
|
||||||
c.headers.Add(key, value)
|
c.headers.Set(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetInterceptor lets us set an arbitrary interceptor for a given client
|
// SetInterceptor lets us set an arbitrary interceptor for a given client
|
||||||
@ -417,7 +417,6 @@ func (c *Client) Write(path string, data []byte, _ os.FileMode) (err error) {
|
|||||||
|
|
||||||
// WriteStream writes a stream
|
// WriteStream writes a stream
|
||||||
func (c *Client) WriteStream(path string, stream io.Reader, _ os.FileMode) (err error) {
|
func (c *Client) WriteStream(path string, stream io.Reader, _ os.FileMode) (err error) {
|
||||||
|
|
||||||
err = c.createParentCollection(path)
|
err = c.createParentCollection(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
Loading…
Reference in New Issue
Block a user