/* * Minio Cloud Storage, (C) 2016 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package main import ( "encoding/json" "os" "path" "sort" "strings" ) const ( fsMetaJSONFile = "fs.json" fsFormatJSONFile = "format.json" ) // A fsMetaV1 represents a metadata header mapping keys to sets of values. type fsMetaV1 struct { Version string `json:"version"` Format string `json:"format"` Minio struct { Release string `json:"release"` } `json:"minio"` // Metadata map for current object `fs.json`. Meta map[string]string `json:"meta,omitempty"` Parts []objectPartInfo `json:"parts,omitempty"` } // ObjectPartIndex - returns the index of matching object part number. func (m fsMetaV1) ObjectPartIndex(partNumber int) (partIndex int) { for i, part := range m.Parts { if partNumber == part.Number { partIndex = i return partIndex } } return -1 } // AddObjectPart - add a new object part in order. func (m *fsMetaV1) AddObjectPart(partNumber int, partName string, partETag string, partSize int64) { partInfo := objectPartInfo{ Number: partNumber, Name: partName, ETag: partETag, Size: partSize, } // Update part info if it already exists. for i, part := range m.Parts { if partNumber == part.Number { m.Parts[i] = partInfo return } } // Proceed to include new part info. m.Parts = append(m.Parts, partInfo) // Parts in fsMeta should be in sorted order by part number. sort.Sort(byObjectPartNumber(m.Parts)) } // readFSMetadata - returns the object metadata `fs.json` content. func readFSMetadata(disk StorageAPI, bucket, object string) (fsMeta fsMetaV1, err error) { // Read all `fs.json`. buf, err := disk.ReadAll(bucket, path.Join(object, fsMetaJSONFile)) if err != nil { return fsMetaV1{}, err } // Decode `fs.json` into fsMeta structure. if err = json.Unmarshal(buf, &fsMeta); err != nil { return fsMetaV1{}, err } // Success. return fsMeta, nil } // newFSMetaV1 - initializes new fsMetaV1. func newFSMetaV1() (fsMeta fsMetaV1) { fsMeta = fsMetaV1{} fsMeta.Version = "1.0.0" fsMeta.Format = "fs" fsMeta.Minio.Release = minioReleaseTag return fsMeta } // newFSFormatV1 - initializes new formatConfigV1 with FS format info. func newFSFormatV1() (format formatConfigV1) { return formatConfigV1{ Version: "1", Format: "fs", FS: &fsFormat{ Version: "1", }, } } // isFSFormat - returns whether given formatConfigV1 is FS type or not. func isFSFormat(format formatConfigV1) bool { return format.Format == "fs" } // writes FS format (format.json) into minioMetaBucket. func writeFSFormatData(storage StorageAPI, fsFormat formatConfigV1) error { metadataBytes, err := json.Marshal(fsFormat) if err != nil { return err } // fsFormatJSONFile - format.json file stored in minioMetaBucket(.minio) directory. if err = storage.AppendFile(minioMetaBucket, fsFormatJSONFile, metadataBytes); err != nil { return err } return nil } // writeFSMetadata - writes `fs.json` metadata, marshals fsMeta object into json // and saves it to disk. func writeFSMetadata(storage StorageAPI, bucket, path string, fsMeta fsMetaV1) error { metadataBytes, err := json.Marshal(fsMeta) if err != nil { return err } if err = storage.AppendFile(bucket, path, metadataBytes); err != nil { return err } return nil } var extendedHeaders = []string{ "X-Amz-Meta-", "X-Minio-Meta-", // Add new extended headers. } // isExtendedHeader validates if input string matches extended headers. func isExtendedHeader(header string) bool { for _, extendedHeader := range extendedHeaders { if strings.HasPrefix(header, extendedHeader) { return true } } return false } // Return true if extended HTTP headers are set, false otherwise. func hasExtendedHeader(metadata map[string]string) bool { if os.Getenv("MINIO_ENABLE_FSMETA") == "1" { return true } for k := range metadata { if isExtendedHeader(k) { return true } } return false }