diff --git a/cmd/fs-v1.go b/cmd/fs-v1.go index da49092ca..0fc98a03f 100644 --- a/cmd/fs-v1.go +++ b/cmd/fs-v1.go @@ -473,6 +473,7 @@ func (fs fsObjects) CopyObject(srcBucket, srcObject, dstBucket, dstObject string // startOffset indicates the starting read location of the object. // length indicates the total length of the object. func (fs fsObjects) GetObject(bucket, object string, offset int64, length int64, writer io.Writer) (err error) { + // This is a special case with object whose name ends with if err = checkGetObjArgs(bucket, object); err != nil { return err } @@ -568,12 +569,6 @@ func (fs fsObjects) getObjectInfo(bucket, object string) (ObjectInfo, error) { // GetObjectInfo - reads object metadata and replies back ObjectInfo. func (fs fsObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) { - // This is a special case with object whose name ends with - // a slash separator, we always return object not found here. - if hasSuffix(object, slashSeparator) { - return ObjectInfo{}, toObjectErr(traceError(errFileNotFound), bucket, object) - } - if err := checkGetObjArgs(bucket, object); err != nil { return ObjectInfo{}, err } @@ -591,13 +586,13 @@ func (fs fsObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) { // for future object operations. func (fs fsObjects) PutObject(bucket string, object string, size int64, data io.Reader, metadata map[string]string, sha256sum string) (objInfo ObjectInfo, retErr error) { var err error - // This is a special case with size as '0' and object ends with // a slash separator, we treat it like a valid operation and // return success. if isObjectDir(object, size) { return dirObjectInfo(bucket, object, size, metadata), nil } + if err = checkPutObjectArgs(bucket, object, fs); err != nil { return ObjectInfo{}, err } diff --git a/cmd/object-api-input-checks.go b/cmd/object-api-input-checks.go index 2975f117b..c7d47feeb 100644 --- a/cmd/object-api-input-checks.go +++ b/cmd/object-api-input-checks.go @@ -36,6 +36,10 @@ func checkBucketAndObjectNames(bucket, object string) error { } // Verify if object is valid. if !IsValidObjectName(object) { + // Objects with "/" are invalid, verify to return a different error. + if hasSuffix(object, slashSeparator) || hasPrefix(object, slashSeparator) { + return traceError(ObjectNotFound{Bucket: bucket, Object: object}) + } return traceError(ObjectNameInvalid{Bucket: bucket, Object: object}) } return nil diff --git a/cmd/object-api-utils.go b/cmd/object-api-utils.go index b313b5e6c..acb14f508 100644 --- a/cmd/object-api-utils.go +++ b/cmd/object-api-utils.go @@ -119,10 +119,7 @@ func IsValidObjectName(object string) bool { if len(object) == 0 { return false } - if hasSuffix(object, slashSeparator) { - return false - } - if hasPrefix(object, slashSeparator) { + if hasSuffix(object, slashSeparator) || hasPrefix(object, slashSeparator) { return false } return IsValidObjectPrefix(object) diff --git a/cmd/server_test.go b/cmd/server_test.go index 2a6dfc120..a3222d499 100644 --- a/cmd/server_test.go +++ b/cmd/server_test.go @@ -171,6 +171,39 @@ func (s *TestSuiteCommon) TestObjectDir(c *C) { c.Assert(err, IsNil) verifyError(c, response, "XMinioInvalidObjectName", "Object name contains unsupported characters.", http.StatusBadRequest) + + request, err = newTestSignedRequest("HEAD", getHeadObjectURL(s.endPoint, bucketName, "my-object-directory/"), + 0, nil, s.accessKey, s.secretKey, s.signer) + c.Assert(err, IsNil) + + client = http.Client{Transport: s.transport} + // execute the HTTP request. + response, err = client.Do(request) + + c.Assert(err, IsNil) + c.Assert(response.StatusCode, Equals, http.StatusNotFound) + + request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, "my-object-directory/"), + 0, nil, s.accessKey, s.secretKey, s.signer) + c.Assert(err, IsNil) + + client = http.Client{Transport: s.transport} + // execute the HTTP request. + response, err = client.Do(request) + + c.Assert(err, IsNil) + c.Assert(response.StatusCode, Equals, http.StatusNotFound) + + request, err = newTestSignedRequest("DELETE", getDeleteObjectURL(s.endPoint, bucketName, "my-object-directory/"), + 0, nil, s.accessKey, s.secretKey, s.signer) + c.Assert(err, IsNil) + + client = http.Client{Transport: s.transport} + // execute the HTTP request. + response, err = client.Do(request) + + c.Assert(err, IsNil) + c.Assert(response.StatusCode, Equals, http.StatusNoContent) } func (s *TestSuiteCommon) TestBucketSQSNotificationAMQP(c *C) { diff --git a/cmd/xl-v1-object.go b/cmd/xl-v1-object.go index ce9d8ba29..d7b041387 100644 --- a/cmd/xl-v1-object.go +++ b/cmd/xl-v1-object.go @@ -320,12 +320,6 @@ func (xl xlObjects) GetObject(bucket, object string, startOffset int64, length i // GetObjectInfo - reads object metadata and replies back ObjectInfo. func (xl xlObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) { - // This is a special case with object whose name ends with - // a slash separator, we always return object not found here. - if hasSuffix(object, slashSeparator) { - return ObjectInfo{}, toObjectErr(traceError(errFileNotFound), bucket, object) - } - if err := checkGetObjArgs(bucket, object); err != nil { return ObjectInfo{}, err } @@ -467,6 +461,7 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io. if isObjectDir(object, size) { // Check if an object is present as one of the parent dir. // -- FIXME. (needs a new kind of lock). + // -- FIXME (this also causes performance issue when disks are down). if xl.parentDirIsObject(bucket, path.Dir(object)) { return ObjectInfo{}, toObjectErr(traceError(errFileAccessDenied), bucket, object) } @@ -480,6 +475,7 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io. // Check if an object is present as one of the parent dir. // -- FIXME. (needs a new kind of lock). + // -- FIXME (this also causes performance issue when disks are down). if xl.parentDirIsObject(bucket, path.Dir(object)) { return ObjectInfo{}, toObjectErr(traceError(errFileAccessDenied), bucket, object) } diff --git a/cmd/xl-v1-object_test.go b/cmd/xl-v1-object_test.go index 40b162a5e..86ffd8648 100644 --- a/cmd/xl-v1-object_test.go +++ b/cmd/xl-v1-object_test.go @@ -73,9 +73,9 @@ func TestXLDeleteObjectBasic(t *testing.T) { {".test", "obj", BucketNameInvalid{Bucket: ".test"}}, {"----", "obj", BucketNameInvalid{Bucket: "----"}}, {"bucket", "", ObjectNameInvalid{Bucket: "bucket", Object: ""}}, - {"bucket", "obj/", ObjectNameInvalid{Bucket: "bucket", Object: "obj/"}}, - {"bucket", "/obj", ObjectNameInvalid{Bucket: "bucket", Object: "/obj"}}, {"bucket", "doesnotexist", ObjectNotFound{Bucket: "bucket", Object: "doesnotexist"}}, + {"bucket", "obj/", ObjectNotFound{Bucket: "bucket", Object: "obj/"}}, + {"bucket", "/obj", ObjectNotFound{Bucket: "bucket", Object: "/obj"}}, {"bucket", "obj", nil}, }