github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/cmd/object-api-datatypes.go (about)

     1  // Copyright (c) 2015-2021 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package cmd
    19  
    20  import (
    21  	"io"
    22  	"math"
    23  	"net/http"
    24  	"time"
    25  
    26  	"github.com/dustin/go-humanize"
    27  	"github.com/minio/madmin-go/v3"
    28  	"github.com/minio/minio/internal/bucket/replication"
    29  	"github.com/minio/minio/internal/hash"
    30  	"github.com/minio/minio/internal/logger"
    31  )
    32  
    33  //go:generate msgp -file $GOFILE -io=false -tests=false -unexported=false
    34  
    35  // BackendType - represents different backend types.
    36  type BackendType int
    37  
    38  // Enum for different backend types.
    39  const (
    40  	Unknown = BackendType(madmin.Unknown)
    41  	// Filesystem backend.
    42  	BackendFS = BackendType(madmin.FS)
    43  	// Multi disk BackendErasure (single, distributed) backend.
    44  	BackendErasure = BackendType(madmin.Erasure)
    45  	// Add your own backend.
    46  )
    47  
    48  // StorageInfo - represents total capacity of underlying storage.
    49  type StorageInfo = madmin.StorageInfo
    50  
    51  // objectHistogramInterval is an interval that will be
    52  // used to report the histogram of objects data sizes
    53  type objectHistogramInterval struct {
    54  	name       string
    55  	start, end int64
    56  }
    57  
    58  const (
    59  	// dataUsageBucketLenV1 must be length of ObjectsHistogramIntervalsV1
    60  	dataUsageBucketLenV1 = 7
    61  	// dataUsageBucketLen must be length of ObjectsHistogramIntervals
    62  	dataUsageBucketLen  = 11
    63  	dataUsageVersionLen = 7
    64  )
    65  
    66  // ObjectsHistogramIntervalsV1 is the list of all intervals
    67  // of object sizes to be included in objects histogram(V1).
    68  var ObjectsHistogramIntervalsV1 = [dataUsageBucketLenV1]objectHistogramInterval{
    69  	{"LESS_THAN_1024_B", 0, humanize.KiByte - 1},
    70  	{"BETWEEN_1024B_AND_1_MB", humanize.KiByte, humanize.MiByte - 1},
    71  	{"BETWEEN_1_MB_AND_10_MB", humanize.MiByte, humanize.MiByte*10 - 1},
    72  	{"BETWEEN_10_MB_AND_64_MB", humanize.MiByte * 10, humanize.MiByte*64 - 1},
    73  	{"BETWEEN_64_MB_AND_128_MB", humanize.MiByte * 64, humanize.MiByte*128 - 1},
    74  	{"BETWEEN_128_MB_AND_512_MB", humanize.MiByte * 128, humanize.MiByte*512 - 1},
    75  	{"GREATER_THAN_512_MB", humanize.MiByte * 512, math.MaxInt64},
    76  }
    77  
    78  // ObjectsHistogramIntervals is the list of all intervals
    79  // of object sizes to be included in objects histogram.
    80  // Note: this histogram expands 1024B-1MB to incl. 1024B-64KB, 64KB-256KB, 256KB-512KB and 512KB-1MiB
    81  var ObjectsHistogramIntervals = [dataUsageBucketLen]objectHistogramInterval{
    82  	{"LESS_THAN_1024_B", 0, humanize.KiByte - 1},
    83  	{"BETWEEN_1024_B_AND_64_KB", humanize.KiByte, 64*humanize.KiByte - 1},         // not exported, for support use only
    84  	{"BETWEEN_64_KB_AND_256_KB", 64 * humanize.KiByte, 256*humanize.KiByte - 1},   // not exported, for support use only
    85  	{"BETWEEN_256_KB_AND_512_KB", 256 * humanize.KiByte, 512*humanize.KiByte - 1}, // not exported, for support use only
    86  	{"BETWEEN_512_KB_AND_1_MB", 512 * humanize.KiByte, humanize.MiByte - 1},       // not exported, for support use only
    87  	{"BETWEEN_1024B_AND_1_MB", humanize.KiByte, humanize.MiByte - 1},
    88  	{"BETWEEN_1_MB_AND_10_MB", humanize.MiByte, humanize.MiByte*10 - 1},
    89  	{"BETWEEN_10_MB_AND_64_MB", humanize.MiByte * 10, humanize.MiByte*64 - 1},
    90  	{"BETWEEN_64_MB_AND_128_MB", humanize.MiByte * 64, humanize.MiByte*128 - 1},
    91  	{"BETWEEN_128_MB_AND_512_MB", humanize.MiByte * 128, humanize.MiByte*512 - 1},
    92  	{"GREATER_THAN_512_MB", humanize.MiByte * 512, math.MaxInt64},
    93  }
    94  
    95  // ObjectsVersionCountIntervals is the list of all intervals
    96  // of object version count to be included in objects histogram.
    97  var ObjectsVersionCountIntervals = [dataUsageVersionLen]objectHistogramInterval{
    98  	{"UNVERSIONED", 0, 0},
    99  	{"SINGLE_VERSION", 1, 1},
   100  	{"BETWEEN_2_AND_10", 2, 9},
   101  	{"BETWEEN_10_AND_100", 10, 99},
   102  	{"BETWEEN_100_AND_1000", 100, 999},
   103  	{"BETWEEN_1000_AND_10000", 1000, 9999},
   104  	{"GREATER_THAN_10000", 10000, math.MaxInt64},
   105  }
   106  
   107  // BucketInfo - represents bucket metadata.
   108  type BucketInfo struct {
   109  	// Name of the bucket.
   110  	Name string
   111  
   112  	// Date and time when the bucket was created.
   113  	Created time.Time
   114  	Deleted time.Time
   115  
   116  	// Bucket features enabled
   117  	Versioning, ObjectLocking bool
   118  }
   119  
   120  // ObjectInfo - represents object metadata.
   121  type ObjectInfo struct {
   122  	// Name of the bucket.
   123  	Bucket string
   124  
   125  	// Name of the object.
   126  	Name string
   127  
   128  	// Date and time when the object was last modified.
   129  	ModTime time.Time
   130  
   131  	// Total object size.
   132  	Size int64
   133  
   134  	// Actual size is the real size of the object uploaded by client.
   135  	ActualSize *int64
   136  
   137  	// IsDir indicates if the object is prefix.
   138  	IsDir bool
   139  
   140  	// Hex encoded unique entity tag of the object.
   141  	ETag string
   142  
   143  	// Version ID of this object.
   144  	VersionID string
   145  
   146  	// IsLatest indicates if this is the latest current version
   147  	// latest can be true for delete marker or a version.
   148  	IsLatest bool
   149  
   150  	// DeleteMarker indicates if the versionId corresponds
   151  	// to a delete marker on an object.
   152  	DeleteMarker bool
   153  
   154  	// Transitioned object information
   155  	TransitionedObject TransitionedObject
   156  
   157  	// RestoreExpires indicates date a restored object expires
   158  	RestoreExpires time.Time
   159  
   160  	// RestoreOngoing indicates if a restore is in progress
   161  	RestoreOngoing bool
   162  
   163  	// A standard MIME type describing the format of the object.
   164  	ContentType string
   165  
   166  	// Specifies what content encodings have been applied to the object and thus
   167  	// what decoding mechanisms must be applied to obtain the object referenced
   168  	// by the Content-Type header field.
   169  	ContentEncoding string
   170  
   171  	// Date and time at which the object is no longer able to be cached
   172  	Expires time.Time
   173  
   174  	// Cache-Control - Specifies caching behavior along the request/reply chain
   175  	CacheControl string
   176  
   177  	// Specify object storage class
   178  	StorageClass string
   179  
   180  	ReplicationStatusInternal string
   181  	ReplicationStatus         replication.StatusType
   182  	// User-Defined metadata
   183  	UserDefined map[string]string
   184  
   185  	// User-Defined object tags
   186  	UserTags string
   187  
   188  	// List of individual parts, maximum size of upto 10,000
   189  	Parts []ObjectPartInfo `json:"-"`
   190  
   191  	// Implements writer and reader used by CopyObject API
   192  	Writer       io.WriteCloser `json:"-" msg:"-"`
   193  	Reader       *hash.Reader   `json:"-" msg:"-"`
   194  	PutObjReader *PutObjReader  `json:"-" msg:"-"`
   195  
   196  	metadataOnly bool
   197  	versionOnly  bool // adds a new version, only used by CopyObject
   198  	keyRotation  bool
   199  
   200  	// Date and time when the object was last accessed.
   201  	AccTime time.Time
   202  
   203  	Legacy bool // indicates object on disk is in legacy data format
   204  
   205  	// internal representation of version purge status
   206  	VersionPurgeStatusInternal string
   207  	VersionPurgeStatus         VersionPurgeStatusType
   208  
   209  	replicationDecision string // internal representation of replication decision for use by DeleteObject handler
   210  	// The total count of all versions of this object
   211  	NumVersions int
   212  	//  The modtime of the successor object version if any
   213  	SuccessorModTime time.Time
   214  
   215  	// Checksums added on upload.
   216  	// Encoded, maybe encrypted.
   217  	Checksum []byte
   218  
   219  	// Inlined
   220  	Inlined bool
   221  
   222  	DataBlocks   int
   223  	ParityBlocks int
   224  }
   225  
   226  // ExpiresStr returns a stringified version of Expires header in http.TimeFormat
   227  func (o ObjectInfo) ExpiresStr() string {
   228  	var expires string
   229  	if !o.Expires.IsZero() {
   230  		expires = o.Expires.UTC().Format(http.TimeFormat)
   231  	}
   232  	return expires
   233  }
   234  
   235  // ArchiveInfo returns any saved zip archive meta information.
   236  // It will be decrypted if needed.
   237  func (o *ObjectInfo) ArchiveInfo() []byte {
   238  	if len(o.UserDefined) == 0 {
   239  		return nil
   240  	}
   241  	z, ok := o.UserDefined[archiveInfoMetadataKey]
   242  	if !ok {
   243  		return nil
   244  	}
   245  	data := []byte(z)
   246  	if v, ok := o.UserDefined[archiveTypeMetadataKey]; ok && v == archiveTypeEnc {
   247  		decrypted, err := o.metadataDecrypter()(archiveTypeEnc, data)
   248  		if err != nil {
   249  			logger.LogIf(GlobalContext, err)
   250  			return nil
   251  		}
   252  		data = decrypted
   253  	}
   254  	return data
   255  }
   256  
   257  // Clone - Returns a cloned copy of current objectInfo
   258  func (o *ObjectInfo) Clone() (cinfo ObjectInfo) {
   259  	cinfo = ObjectInfo{
   260  		Bucket:                     o.Bucket,
   261  		Name:                       o.Name,
   262  		ModTime:                    o.ModTime,
   263  		Size:                       o.Size,
   264  		IsDir:                      o.IsDir,
   265  		ETag:                       o.ETag,
   266  		VersionID:                  o.VersionID,
   267  		IsLatest:                   o.IsLatest,
   268  		DeleteMarker:               o.DeleteMarker,
   269  		TransitionedObject:         o.TransitionedObject,
   270  		RestoreExpires:             o.RestoreExpires,
   271  		RestoreOngoing:             o.RestoreOngoing,
   272  		ContentType:                o.ContentType,
   273  		ContentEncoding:            o.ContentEncoding,
   274  		Expires:                    o.Expires,
   275  		StorageClass:               o.StorageClass,
   276  		ReplicationStatus:          o.ReplicationStatus,
   277  		UserTags:                   o.UserTags,
   278  		Parts:                      o.Parts,
   279  		Writer:                     o.Writer,
   280  		Reader:                     o.Reader,
   281  		PutObjReader:               o.PutObjReader,
   282  		metadataOnly:               o.metadataOnly,
   283  		versionOnly:                o.versionOnly,
   284  		keyRotation:                o.keyRotation,
   285  		AccTime:                    o.AccTime,
   286  		Legacy:                     o.Legacy,
   287  		VersionPurgeStatus:         o.VersionPurgeStatus,
   288  		NumVersions:                o.NumVersions,
   289  		SuccessorModTime:           o.SuccessorModTime,
   290  		ReplicationStatusInternal:  o.ReplicationStatusInternal,
   291  		VersionPurgeStatusInternal: o.VersionPurgeStatusInternal,
   292  	}
   293  	cinfo.UserDefined = make(map[string]string, len(o.UserDefined))
   294  	for k, v := range o.UserDefined {
   295  		cinfo.UserDefined[k] = v
   296  	}
   297  	return cinfo
   298  }
   299  
   300  func (o ObjectInfo) tierStats() tierStats {
   301  	ts := tierStats{
   302  		TotalSize:   uint64(o.Size),
   303  		NumVersions: 1,
   304  	}
   305  	// the current version of an object is accounted towards objects count
   306  	if o.IsLatest {
   307  		ts.NumObjects = 1
   308  	}
   309  	return ts
   310  }
   311  
   312  // ToObjectInfo converts a replication object info to a partial ObjectInfo
   313  // do not rely on this function to give you correct ObjectInfo, this
   314  // function is merely and optimization.
   315  func (ri ReplicateObjectInfo) ToObjectInfo() ObjectInfo {
   316  	return ObjectInfo{
   317  		Name:                       ri.Name,
   318  		Bucket:                     ri.Bucket,
   319  		VersionID:                  ri.VersionID,
   320  		ModTime:                    ri.ModTime,
   321  		UserTags:                   ri.UserTags,
   322  		Size:                       ri.Size,
   323  		ActualSize:                 &ri.ActualSize,
   324  		ReplicationStatus:          ri.ReplicationStatus,
   325  		ReplicationStatusInternal:  ri.ReplicationStatusInternal,
   326  		VersionPurgeStatus:         ri.VersionPurgeStatus,
   327  		VersionPurgeStatusInternal: ri.VersionPurgeStatusInternal,
   328  		DeleteMarker:               true,
   329  		UserDefined:                map[string]string{},
   330  	}
   331  }
   332  
   333  // ReplicateObjectInfo represents object info to be replicated
   334  type ReplicateObjectInfo struct {
   335  	Name                       string
   336  	Bucket                     string
   337  	VersionID                  string
   338  	ETag                       string
   339  	Size                       int64
   340  	ActualSize                 int64
   341  	ModTime                    time.Time
   342  	UserTags                   string
   343  	SSEC                       bool
   344  	ReplicationStatus          replication.StatusType
   345  	ReplicationStatusInternal  string
   346  	VersionPurgeStatusInternal string
   347  	VersionPurgeStatus         VersionPurgeStatusType
   348  	ReplicationState           ReplicationState
   349  	DeleteMarker               bool
   350  
   351  	OpType               replication.Type
   352  	EventType            string
   353  	RetryCount           uint32
   354  	ResetID              string
   355  	Dsc                  ReplicateDecision
   356  	ExistingObjResync    ResyncDecision
   357  	TargetArn            string
   358  	TargetStatuses       map[string]replication.StatusType
   359  	TargetPurgeStatuses  map[string]VersionPurgeStatusType
   360  	ReplicationTimestamp time.Time
   361  }
   362  
   363  // MultipartInfo captures metadata information about the uploadId
   364  // this data structure is used primarily for some internal purposes
   365  // for verifying upload type such as was the upload
   366  // - encrypted
   367  // - compressed
   368  type MultipartInfo struct {
   369  	// Name of the bucket.
   370  	Bucket string
   371  
   372  	// Name of the object.
   373  	Object string
   374  
   375  	// Upload ID identifying the multipart upload whose parts are being listed.
   376  	UploadID string
   377  
   378  	// Date and time at which the multipart upload was initiated.
   379  	Initiated time.Time
   380  
   381  	// Any metadata set during InitMultipartUpload, including encryption headers.
   382  	UserDefined map[string]string
   383  }
   384  
   385  // ListPartsInfo - represents list of all parts.
   386  type ListPartsInfo struct {
   387  	// Name of the bucket.
   388  	Bucket string
   389  
   390  	// Name of the object.
   391  	Object string
   392  
   393  	// Upload ID identifying the multipart upload whose parts are being listed.
   394  	UploadID string
   395  
   396  	// The class of storage used to store the object.
   397  	StorageClass string
   398  
   399  	// Part number after which listing begins.
   400  	PartNumberMarker int
   401  
   402  	// When a list is truncated, this element specifies the last part in the list,
   403  	// as well as the value to use for the part-number-marker request parameter
   404  	// in a subsequent request.
   405  	NextPartNumberMarker int
   406  
   407  	// Maximum number of parts that were allowed in the response.
   408  	MaxParts int
   409  
   410  	// Indicates whether the returned list of parts is truncated.
   411  	IsTruncated bool
   412  
   413  	// List of all parts.
   414  	Parts []PartInfo
   415  
   416  	// Any metadata set during InitMultipartUpload, including encryption headers.
   417  	UserDefined map[string]string
   418  
   419  	// ChecksumAlgorithm if set
   420  	ChecksumAlgorithm string
   421  }
   422  
   423  // Lookup - returns if uploadID is valid
   424  func (lm ListMultipartsInfo) Lookup(uploadID string) bool {
   425  	for _, upload := range lm.Uploads {
   426  		if upload.UploadID == uploadID {
   427  			return true
   428  		}
   429  	}
   430  	return false
   431  }
   432  
   433  // ListMultipartsInfo - represents bucket resources for incomplete multipart uploads.
   434  type ListMultipartsInfo struct {
   435  	// Together with upload-id-marker, this parameter specifies the multipart upload
   436  	// after which listing should begin.
   437  	KeyMarker string
   438  
   439  	// Together with key-marker, specifies the multipart upload after which listing
   440  	// should begin. If key-marker is not specified, the upload-id-marker parameter
   441  	// is ignored.
   442  	UploadIDMarker string
   443  
   444  	// When a list is truncated, this element specifies the value that should be
   445  	// used for the key-marker request parameter in a subsequent request.
   446  	NextKeyMarker string
   447  
   448  	// When a list is truncated, this element specifies the value that should be
   449  	// used for the upload-id-marker request parameter in a subsequent request.
   450  	NextUploadIDMarker string
   451  
   452  	// Maximum number of multipart uploads that could have been included in the
   453  	// response.
   454  	MaxUploads int
   455  
   456  	// Indicates whether the returned list of multipart uploads is truncated. A
   457  	// value of true indicates that the list was truncated. The list can be truncated
   458  	// if the number of multipart uploads exceeds the limit allowed or specified
   459  	// by max uploads.
   460  	IsTruncated bool
   461  
   462  	// List of all pending uploads.
   463  	Uploads []MultipartInfo
   464  
   465  	// When a prefix is provided in the request, The result contains only keys
   466  	// starting with the specified prefix.
   467  	Prefix string
   468  
   469  	// A character used to truncate the object prefixes.
   470  	// NOTE: only supported delimiter is '/'.
   471  	Delimiter string
   472  
   473  	// CommonPrefixes contains all (if there are any) keys between Prefix and the
   474  	// next occurrence of the string specified by delimiter.
   475  	CommonPrefixes []string
   476  
   477  	EncodingType string // Not supported yet.
   478  }
   479  
   480  // TransitionedObject transitioned object tier and status.
   481  type TransitionedObject struct {
   482  	Name        string
   483  	VersionID   string
   484  	Tier        string
   485  	FreeVersion bool
   486  	Status      string
   487  }
   488  
   489  // DeletedObjectInfo - container for list objects versions deleted objects.
   490  type DeletedObjectInfo struct {
   491  	// Name of the bucket.
   492  	Bucket string
   493  
   494  	// Name of the object.
   495  	Name string
   496  
   497  	// Date and time when the object was last modified.
   498  	ModTime time.Time
   499  
   500  	// Version ID of this object.
   501  	VersionID string
   502  
   503  	// Indicates the deleted marker is latest
   504  	IsLatest bool
   505  }
   506  
   507  // ListObjectVersionsInfo - container for list objects versions.
   508  type ListObjectVersionsInfo struct {
   509  	// Indicates whether the returned list objects response is truncated. A
   510  	// value of true indicates that the list was truncated. The list can be truncated
   511  	// if the number of objects exceeds the limit allowed or specified
   512  	// by max keys.
   513  	IsTruncated bool
   514  
   515  	// When response is truncated (the IsTruncated element value in the response is true),
   516  	// you can use the key name in this field as marker in the subsequent
   517  	// request to get next set of objects.
   518  	//
   519  	// NOTE: AWS S3 returns NextMarker only if you have delimiter request parameter specified,
   520  	//       MinIO always returns NextMarker.
   521  	NextMarker string
   522  
   523  	// NextVersionIDMarker may be set of IsTruncated is true
   524  	NextVersionIDMarker string
   525  
   526  	// List of objects info for this request.
   527  	Objects []ObjectInfo
   528  
   529  	// List of prefixes for this request.
   530  	Prefixes []string
   531  }
   532  
   533  // ListObjectsInfo - container for list objects.
   534  type ListObjectsInfo struct {
   535  	// Indicates whether the returned list objects response is truncated. A
   536  	// value of true indicates that the list was truncated. The list can be truncated
   537  	// if the number of objects exceeds the limit allowed or specified
   538  	// by max keys.
   539  	IsTruncated bool
   540  
   541  	// When response is truncated (the IsTruncated element value in the response is true),
   542  	// you can use the key name in this field as marker in the subsequent
   543  	// request to get next set of objects.
   544  	//
   545  	// NOTE: AWS S3 returns NextMarker only if you have delimiter request parameter specified,
   546  	//       MinIO always returns NextMarker.
   547  	NextMarker string
   548  
   549  	// List of objects info for this request.
   550  	Objects []ObjectInfo
   551  
   552  	// List of prefixes for this request.
   553  	Prefixes []string
   554  }
   555  
   556  // ListObjectsV2Info - container for list objects version 2.
   557  type ListObjectsV2Info struct {
   558  	// Indicates whether the returned list objects response is truncated. A
   559  	// value of true indicates that the list was truncated. The list can be truncated
   560  	// if the number of objects exceeds the limit allowed or specified
   561  	// by max keys.
   562  	IsTruncated bool
   563  
   564  	// When response is truncated (the IsTruncated element value in the response
   565  	// is true), you can use the key name in this field as marker in the subsequent
   566  	// request to get next set of objects.
   567  	//
   568  	// NOTE: This element is returned only if you have delimiter request parameter
   569  	// specified.
   570  	ContinuationToken     string
   571  	NextContinuationToken string
   572  
   573  	// List of objects info for this request.
   574  	Objects []ObjectInfo
   575  
   576  	// List of prefixes for this request.
   577  	Prefixes []string
   578  }
   579  
   580  // PartInfo - represents individual part metadata.
   581  type PartInfo struct {
   582  	// Part number that identifies the part. This is a positive integer between
   583  	// 1 and 10,000.
   584  	PartNumber int
   585  
   586  	// Date and time at which the part was uploaded.
   587  	LastModified time.Time
   588  
   589  	// Entity tag returned when the part was initially uploaded.
   590  	ETag string
   591  
   592  	// Size in bytes of the part.
   593  	Size int64
   594  
   595  	// Real size of the object uploaded by client.
   596  	ActualSize int64
   597  
   598  	// Checksum values
   599  	ChecksumCRC32  string
   600  	ChecksumCRC32C string
   601  	ChecksumSHA1   string
   602  	ChecksumSHA256 string
   603  }
   604  
   605  // CompletePart - represents the part that was completed, this is sent by the client
   606  // during CompleteMultipartUpload request.
   607  type CompletePart struct {
   608  	// Part number identifying the part. This is a positive integer between 1 and
   609  	// 10,000
   610  	PartNumber int
   611  
   612  	// Entity tag returned when the part was uploaded.
   613  	ETag string
   614  
   615  	// Checksum values. Optional.
   616  	ChecksumCRC32  string
   617  	ChecksumCRC32C string
   618  	ChecksumSHA1   string
   619  	ChecksumSHA256 string
   620  }
   621  
   622  // CompleteMultipartUpload - represents list of parts which are completed, this is sent by the
   623  // client during CompleteMultipartUpload request.
   624  type CompleteMultipartUpload struct {
   625  	Parts []CompletePart `xml:"Part"`
   626  }
   627  
   628  // NewMultipartUploadResult contains information about a newly created multipart upload.
   629  type NewMultipartUploadResult struct {
   630  	UploadID     string
   631  	ChecksumAlgo string
   632  }
   633  
   634  type getObjectAttributesResponse struct {
   635  	ETag         string                    `xml:",omitempty"`
   636  	Checksum     *objectAttributesChecksum `xml:",omitempty"`
   637  	ObjectParts  *objectAttributesParts    `xml:",omitempty"`
   638  	StorageClass string                    `xml:",omitempty"`
   639  	ObjectSize   int64                     `xml:",omitempty"`
   640  }
   641  
   642  type objectAttributesChecksum struct {
   643  	ChecksumCRC32  string `xml:",omitempty"`
   644  	ChecksumCRC32C string `xml:",omitempty"`
   645  	ChecksumSHA1   string `xml:",omitempty"`
   646  	ChecksumSHA256 string `xml:",omitempty"`
   647  }
   648  
   649  type objectAttributesParts struct {
   650  	IsTruncated          bool
   651  	MaxParts             int
   652  	NextPartNumberMarker int
   653  	PartNumberMarker     int
   654  	PartsCount           int
   655  	Parts                []*objectAttributesPart `xml:"Part"`
   656  }
   657  
   658  type objectAttributesPart struct {
   659  	PartNumber     int
   660  	Size           int64
   661  	ChecksumCRC32  string `xml:",omitempty"`
   662  	ChecksumCRC32C string `xml:",omitempty"`
   663  	ChecksumSHA1   string `xml:",omitempty"`
   664  	ChecksumSHA256 string `xml:",omitempty"`
   665  }
   666  
   667  type objectAttributesErrorResponse struct {
   668  	ArgumentValue *string `xml:"ArgumentValue,omitempty"`
   669  	ArgumentName  *string `xml:"ArgumentName"`
   670  	APIErrorResponse
   671  }