Inspect: Preserve permission flags (#13490)

Preserve permission from disk files. Can help identify issues.

Refactor GetRawData function to be cleaner.
This commit is contained in:
Klaus Post 2021-10-21 11:20:13 -07:00 committed by GitHub
parent ac36a377b0
commit 23d6770ff9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 16 deletions

View File

@ -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 {

View File

@ -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

View File

@ -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.

View File

@ -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
}

View File

@ -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
}