diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index 4eaef2952..e64fd937c 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -2165,7 +2165,7 @@ func checkConnection(endpointStr string, timeout time.Duration) error { // getRawDataer provides an interface for getting raw FS files. type getRawDataer interface { - GetRawData(ctx context.Context, volume, file string, fn func(r io.Reader, host string, disk string, filename string, size int64, modtime time.Time, isDir bool) error) error + GetRawData(ctx context.Context, volume, file string, fn func(r io.Reader, host string, disk string, filename string, info StatInfo) error) error } // InspectDataHandler - GET /minio/admin/v3/inspect-data @@ -2242,19 +2242,23 @@ func (a adminAPIHandlers) InspectDataHandler(w http.ResponseWriter, r *http.Requ zipWriter := zip.NewWriter(encw) defer zipWriter.Close() - err = o.GetRawData(ctx, volume, file, func(r io.Reader, host, disk, filename string, size int64, modtime time.Time, isDir bool) error { + err = o.GetRawData(ctx, volume, file, func(r io.Reader, host, disk, filename string, si StatInfo) error { // Prefix host+disk filename = path.Join(host, disk, filename) - if isDir { + if si.Dir { filename += "/" - size = 0 + si.Size = 0 + } + if si.Mode == 0 { + // Not, set it to default. + si.Mode = 0600 } header, zerr := zip.FileInfoHeader(dummyFileInfo{ name: filename, - size: size, - mode: 0600, - modTime: modtime, - isDir: isDir, + size: si.Size, + mode: os.FileMode(si.Mode), + modTime: si.ModTime, + isDir: si.Dir, sys: nil, }) if zerr != nil { diff --git a/cmd/erasure-server-pool.go b/cmd/erasure-server-pool.go index e50c899f7..650739bd7 100644 --- a/cmd/erasure-server-pool.go +++ b/cmd/erasure-server-pool.go @@ -151,7 +151,7 @@ func (z *erasureServerPools) GetDisksID(ids ...string) []StorageAPI { // GetRawData will return all files with a given raw path to the callback. // Errors are ignored, only errors from the callback are returned. // For now only direct file paths are supported. -func (z *erasureServerPools) GetRawData(ctx context.Context, volume, file string, fn func(r io.Reader, host string, disk string, filename string, size int64, modtime time.Time, isDir bool) error) error { +func (z *erasureServerPools) GetRawData(ctx context.Context, volume, file string, fn func(r io.Reader, host string, disk string, filename string, info StatInfo) error) error { found := 0 for _, s := range z.serverPools { for _, disks := range s.erasureDisks { @@ -178,7 +178,7 @@ func (z *erasureServerPools) GetRawData(ctx context.Context, volume, file string } else { r = io.NopCloser(bytes.NewBuffer([]byte{})) } - err = fn(r, disk.Hostname(), did, pathJoin(volume, si.Name), si.Size, si.ModTime, si.Dir) + err = fn(r, disk.Hostname(), did, pathJoin(volume, si.Name), si) r.Close() if err != nil { return err diff --git a/cmd/xl-storage-format-v1.go b/cmd/xl-storage-format-v1.go index ec2c17467..7a4119d61 100644 --- a/cmd/xl-storage-format-v1.go +++ b/cmd/xl-storage-format-v1.go @@ -83,6 +83,7 @@ type StatInfo struct { ModTime time.Time `json:"modTime"` // ModTime of the object `xl.meta`. Name string `json:"name"` Dir bool `json:"dir"` + Mode uint32 `json:"mode"` } // ErasureInfo holds erasure coding and bitrot related information. diff --git a/cmd/xl-storage-format-v1_gen.go b/cmd/xl-storage-format-v1_gen.go index 5e78a774f..c234071c6 100644 --- a/cmd/xl-storage-format-v1_gen.go +++ b/cmd/xl-storage-format-v1_gen.go @@ -771,6 +771,12 @@ func (z *StatInfo) DecodeMsg(dc *msgp.Reader) (err error) { err = msgp.WrapError(err, "Dir") return } + case "Mode": + z.Mode, err = dc.ReadUint32() + if err != nil { + err = msgp.WrapError(err, "Mode") + return + } default: err = dc.Skip() if err != nil { @@ -784,9 +790,9 @@ func (z *StatInfo) DecodeMsg(dc *msgp.Reader) (err error) { // EncodeMsg implements msgp.Encodable func (z *StatInfo) EncodeMsg(en *msgp.Writer) (err error) { - // map header, size 4 + // map header, size 5 // write "Size" - err = en.Append(0x84, 0xa4, 0x53, 0x69, 0x7a, 0x65) + err = en.Append(0x85, 0xa4, 0x53, 0x69, 0x7a, 0x65) if err != nil { return } @@ -825,15 +831,25 @@ func (z *StatInfo) EncodeMsg(en *msgp.Writer) (err error) { err = msgp.WrapError(err, "Dir") return } + // write "Mode" + err = en.Append(0xa4, 0x4d, 0x6f, 0x64, 0x65) + if err != nil { + return + } + err = en.WriteUint32(z.Mode) + if err != nil { + err = msgp.WrapError(err, "Mode") + return + } return } // MarshalMsg implements msgp.Marshaler func (z *StatInfo) MarshalMsg(b []byte) (o []byte, err error) { o = msgp.Require(b, z.Msgsize()) - // map header, size 4 + // map header, size 5 // string "Size" - o = append(o, 0x84, 0xa4, 0x53, 0x69, 0x7a, 0x65) + o = append(o, 0x85, 0xa4, 0x53, 0x69, 0x7a, 0x65) o = msgp.AppendInt64(o, z.Size) // string "ModTime" o = append(o, 0xa7, 0x4d, 0x6f, 0x64, 0x54, 0x69, 0x6d, 0x65) @@ -844,6 +860,9 @@ func (z *StatInfo) MarshalMsg(b []byte) (o []byte, err error) { // string "Dir" o = append(o, 0xa3, 0x44, 0x69, 0x72) o = msgp.AppendBool(o, z.Dir) + // string "Mode" + o = append(o, 0xa4, 0x4d, 0x6f, 0x64, 0x65) + o = msgp.AppendUint32(o, z.Mode) return } @@ -889,6 +908,12 @@ func (z *StatInfo) UnmarshalMsg(bts []byte) (o []byte, err error) { err = msgp.WrapError(err, "Dir") return } + case "Mode": + z.Mode, bts, err = msgp.ReadUint32Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "Mode") + return + } default: bts, err = msgp.Skip(bts) if err != nil { @@ -903,7 +928,7 @@ func (z *StatInfo) UnmarshalMsg(bts []byte) (o []byte, err error) { // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *StatInfo) Msgsize() (s int) { - s = 1 + 5 + msgp.Int64Size + 8 + msgp.TimeSize + 5 + msgp.StringPrefixSize + len(z.Name) + 4 + msgp.BoolSize + s = 1 + 5 + msgp.Int64Size + 8 + msgp.TimeSize + 5 + msgp.StringPrefixSize + len(z.Name) + 4 + msgp.BoolSize + 5 + msgp.Uint32Size return } diff --git a/cmd/xl-storage.go b/cmd/xl-storage.go index aebf67143..5f8f3e8b7 100644 --- a/cmd/xl-storage.go +++ b/cmd/xl-storage.go @@ -2270,7 +2270,7 @@ func (s *xlStorage) StatInfoFile(ctx context.Context, volume, path string, glob if os.PathSeparator != '/' { name = strings.Replace(name, string(os.PathSeparator), "/", -1) } - stat = append(stat, StatInfo{ModTime: st.ModTime(), Size: st.Size(), Name: name, Dir: st.IsDir()}) + stat = append(stat, StatInfo{ModTime: st.ModTime(), Size: st.Size(), Name: name, Dir: st.IsDir(), Mode: uint32(st.Mode())}) } return stat, nil }