mirror of
https://github.com/minio/mc.git
synced 2025-07-30 07:23:03 +03:00
Allow copying file onto itself (#2617)
This allows encrypting an unencrypted file using server side CopyObject API.
This commit is contained in:
committed by
kannappanr
parent
f3eaa54a32
commit
2073642656
@ -365,58 +365,19 @@ func readFile(fpath string) (io.ReadCloser, error) {
|
|||||||
return fileData, nil
|
return fileData, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// createFile creates an empty file at the provided filepath
|
|
||||||
// if one does not exist already.
|
|
||||||
func createFile(fpath string) (io.WriteCloser, error) {
|
|
||||||
if e := os.MkdirAll(filepath.Dir(fpath), 0777); e != nil {
|
|
||||||
return nil, e
|
|
||||||
}
|
|
||||||
file, e := os.Create(fpath)
|
|
||||||
if e != nil {
|
|
||||||
return nil, e
|
|
||||||
}
|
|
||||||
return file, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy - copy data from source to destination
|
// Copy - copy data from source to destination
|
||||||
func (f *fsClient) Copy(source string, size int64, progress io.Reader, srcSSEKey, tgtSSEKey string) *probe.Error {
|
func (f *fsClient) Copy(source string, size int64, progress io.Reader, srcSSEKey, tgtSSEKey string) *probe.Error {
|
||||||
// Don't use f.Get() f.Put() directly. Instead use readFile and createFile
|
|
||||||
destination := f.PathURL.Path
|
destination := f.PathURL.Path
|
||||||
if destination == source { // Cannot copy file into itself
|
|
||||||
return probe.NewError(SameFile{
|
|
||||||
Source: source,
|
|
||||||
Destination: destination,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
rc, e := readFile(source)
|
rc, e := readFile(source)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
err := f.toClientError(e, destination)
|
err := f.toClientError(e, destination)
|
||||||
return err.Trace(destination)
|
return err.Trace(destination)
|
||||||
}
|
}
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
wc, e := createFile(destination)
|
|
||||||
if e != nil {
|
_, err := f.put(rc, size, map[string][]string{}, progress)
|
||||||
err := f.toClientError(e, destination)
|
if err != nil {
|
||||||
return err.Trace(destination)
|
return err.Trace(destination, source)
|
||||||
}
|
|
||||||
defer wc.Close()
|
|
||||||
reader := hookreader.NewHook(rc, progress)
|
|
||||||
// Perform copy
|
|
||||||
n, _ := io.CopyN(wc, reader, size) // e == nil only if n != size
|
|
||||||
// Only check size related errors if size is positive
|
|
||||||
if size > 0 {
|
|
||||||
if n < size { // Unexpected early EOF
|
|
||||||
return probe.NewError(UnexpectedEOF{
|
|
||||||
TotalSize: size,
|
|
||||||
TotalWritten: n,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if n > size { // Unexpected ExcessRead
|
|
||||||
return probe.NewError(UnexpectedExcessRead{
|
|
||||||
TotalSize: size,
|
|
||||||
TotalWritten: n,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -594,7 +594,7 @@ func (c *s3Client) Get(sseKey string) (io.ReadCloser, *probe.Error) {
|
|||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if errResponse.Code == "NoSuchKey" || errResponse.Code == "InvalidArgument" {
|
if errResponse.Code == "NoSuchKey" {
|
||||||
return nil, probe.NewError(ObjectMissing{})
|
return nil, probe.NewError(ObjectMissing{})
|
||||||
}
|
}
|
||||||
return nil, probe.NewError(e)
|
return nil, probe.NewError(e)
|
||||||
@ -646,7 +646,7 @@ func (c *s3Client) Copy(source string, size int64, progress io.Reader, srcSSEKey
|
|||||||
Bucket: dstBucket,
|
Bucket: dstBucket,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if errResponse.Code == "NoSuchKey" || errResponse.Code == "InvalidArgument" {
|
if errResponse.Code == "NoSuchKey" {
|
||||||
return probe.NewError(ObjectMissing{})
|
return probe.NewError(ObjectMissing{})
|
||||||
}
|
}
|
||||||
return probe.NewError(e)
|
return probe.NewError(e)
|
||||||
@ -742,7 +742,7 @@ func (c *s3Client) Put(ctx context.Context, reader io.Reader, size int64, metada
|
|||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if errResponse.Code == "NoSuchKey" || errResponse.Code == "InvalidArgument" {
|
if errResponse.Code == "NoSuchKey" {
|
||||||
return n, probe.NewError(ObjectMissing{})
|
return n, probe.NewError(ObjectMissing{})
|
||||||
}
|
}
|
||||||
return n, probe.NewError(e)
|
return n, probe.NewError(e)
|
||||||
@ -1116,7 +1116,7 @@ func (c *s3Client) getObjectStat(bucket, object string, opts minio.StatObjectOpt
|
|||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if errResponse.Code == "NoSuchKey" || errResponse.Code == "InvalidArgument" {
|
if errResponse.Code == "NoSuchKey" {
|
||||||
return nil, probe.NewError(ObjectMissing{})
|
return nil, probe.NewError(ObjectMissing{})
|
||||||
}
|
}
|
||||||
return nil, probe.NewError(e)
|
return nil, probe.NewError(e)
|
||||||
|
@ -97,10 +97,6 @@ func prepareCopyURLsTypeA(sourceURL string, targetURL string, encKeyDB map[strin
|
|||||||
// Source is not a regular file
|
// Source is not a regular file
|
||||||
return URLs{Error: errInvalidSource(sourceURL).Trace(sourceURL)}
|
return URLs{Error: errInvalidSource(sourceURL).Trace(sourceURL)}
|
||||||
}
|
}
|
||||||
if sourceContent.URL.String() == targetURL {
|
|
||||||
// source and target can not be same
|
|
||||||
return URLs{Error: errSourceTargetSame(sourceURL).Trace(sourceURL)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// All OK.. We can proceed. Type A
|
// All OK.. We can proceed. Type A
|
||||||
return makeCopyContentTypeA(sourceAlias, sourceContent, targetAlias, targetURL, encKeyDB)
|
return makeCopyContentTypeA(sourceAlias, sourceContent, targetAlias, targetURL, encKeyDB)
|
||||||
|
@ -111,10 +111,3 @@ var errSourceIsDir = func(URL string) *probe.Error {
|
|||||||
msg := "Source `" + URL + "` is a folder."
|
msg := "Source `" + URL + "` is a folder."
|
||||||
return probe.NewError(sourceIsDirErr(errors.New(msg))).Untrace()
|
return probe.NewError(sourceIsDirErr(errors.New(msg))).Untrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
type sourceTargetSameErr error
|
|
||||||
|
|
||||||
var errSourceTargetSame = func(URL string) *probe.Error {
|
|
||||||
msg := "Source and target URL can not be same : " + URL
|
|
||||||
return probe.NewError(sourceTargetSameErr(errors.New(msg))).Untrace()
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user