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
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
if destination == source { // Cannot copy file into itself
|
||||
return probe.NewError(SameFile{
|
||||
Source: source,
|
||||
Destination: destination,
|
||||
})
|
||||
}
|
||||
rc, e := readFile(source)
|
||||
if e != nil {
|
||||
err := f.toClientError(e, destination)
|
||||
return err.Trace(destination)
|
||||
}
|
||||
defer rc.Close()
|
||||
wc, e := createFile(destination)
|
||||
if e != nil {
|
||||
err := f.toClientError(e, destination)
|
||||
return err.Trace(destination)
|
||||
}
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
_, err := f.put(rc, size, map[string][]string{}, progress)
|
||||
if err != nil {
|
||||
return err.Trace(destination, source)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -594,7 +594,7 @@ func (c *s3Client) Get(sseKey string) (io.ReadCloser, *probe.Error) {
|
||||
Bucket: bucket,
|
||||
})
|
||||
}
|
||||
if errResponse.Code == "NoSuchKey" || errResponse.Code == "InvalidArgument" {
|
||||
if errResponse.Code == "NoSuchKey" {
|
||||
return nil, probe.NewError(ObjectMissing{})
|
||||
}
|
||||
return nil, probe.NewError(e)
|
||||
@ -646,7 +646,7 @@ func (c *s3Client) Copy(source string, size int64, progress io.Reader, srcSSEKey
|
||||
Bucket: dstBucket,
|
||||
})
|
||||
}
|
||||
if errResponse.Code == "NoSuchKey" || errResponse.Code == "InvalidArgument" {
|
||||
if errResponse.Code == "NoSuchKey" {
|
||||
return probe.NewError(ObjectMissing{})
|
||||
}
|
||||
return probe.NewError(e)
|
||||
@ -742,7 +742,7 @@ func (c *s3Client) Put(ctx context.Context, reader io.Reader, size int64, metada
|
||||
Bucket: bucket,
|
||||
})
|
||||
}
|
||||
if errResponse.Code == "NoSuchKey" || errResponse.Code == "InvalidArgument" {
|
||||
if errResponse.Code == "NoSuchKey" {
|
||||
return n, probe.NewError(ObjectMissing{})
|
||||
}
|
||||
return n, probe.NewError(e)
|
||||
@ -1116,7 +1116,7 @@ func (c *s3Client) getObjectStat(bucket, object string, opts minio.StatObjectOpt
|
||||
Bucket: bucket,
|
||||
})
|
||||
}
|
||||
if errResponse.Code == "NoSuchKey" || errResponse.Code == "InvalidArgument" {
|
||||
if errResponse.Code == "NoSuchKey" {
|
||||
return nil, probe.NewError(ObjectMissing{})
|
||||
}
|
||||
return nil, probe.NewError(e)
|
||||
|
@ -97,10 +97,6 @@ func prepareCopyURLsTypeA(sourceURL string, targetURL string, encKeyDB map[strin
|
||||
// Source is not a regular file
|
||||
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
|
||||
return makeCopyContentTypeA(sourceAlias, sourceContent, targetAlias, targetURL, encKeyDB)
|
||||
|
@ -111,10 +111,3 @@ var errSourceIsDir = func(URL string) *probe.Error {
|
||||
msg := "Source `" + URL + "` is a folder."
|
||||
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