Skip to content

Commit 9744aee

Browse files
authored
Merge pull request #438 from pkg/patch/bugfixes-to-filexfer
Pre-Merge filexfer Bugfixes
2 parents ba12343 + 340dc5e commit 9744aee

30 files changed

+1093
-200
lines changed

internal/encoding/ssh/filexfer/attrs.go

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,57 @@ type Attributes struct {
3434
ExtendedAttributes []ExtendedAttribute
3535
}
3636

37+
// GetSize returns the Size field and a bool that is true if and only if the value is valid/defined.
38+
func (a *Attributes) GetSize() (size uint64, ok bool) {
39+
return a.Size, a.Flags&AttrSize != 0
40+
}
41+
42+
// SetSize is a convenience function that sets the Size field,
43+
// and marks the field as valid/defined in Flags.
44+
func (a *Attributes) SetSize(size uint64) {
45+
a.Flags |= AttrSize
46+
a.Size = size
47+
}
48+
49+
// GetUIDGID returns the UID and GID fields and a bool that is true if and only if the values are valid/defined.
50+
func (a *Attributes) GetUIDGID() (uid, gid uint32, ok bool) {
51+
return a.UID, a.GID, a.Flags&AttrUIDGID != 0
52+
}
53+
54+
// SetUIDGID is a convenience function that sets the UID and GID fields,
55+
// and marks the fields as valid/defined in Flags.
56+
func (a *Attributes) SetUIDGID(uid, gid uint32) {
57+
a.Flags |= AttrUIDGID
58+
a.UID = uid
59+
a.GID = gid
60+
}
61+
62+
// GetPermissions returns the Permissions field and a bool that is true if and only if the value is valid/defined.
63+
func (a *Attributes) GetPermissions() (perms FileMode, ok bool) {
64+
return a.Permissions, a.Flags&AttrPermissions != 0
65+
}
66+
67+
// SetPermissions is a convenience function that sets the Permissions field,
68+
// and marks the field as valid/defined in Flags.
69+
func (a *Attributes) SetPermissions(perms FileMode) {
70+
a.Flags |= AttrPermissions
71+
a.Permissions = perms
72+
}
73+
74+
// GetACModTime returns the ATime and MTime fields and a bool that is true if and only if the values are valid/defined.
75+
func (a *Attributes) GetACModTime() (atime, mtime uint32, ok bool) {
76+
return a.ATime, a.MTime, a.Flags&AttrACModTime != 0
77+
return a.ATime, a.MTime, a.Flags&AttrACModTime != 0
78+
}
79+
80+
// SetACModTime is a convenience function that sets the ATime and MTime fields,
81+
// and marks the fields as valid/defined in Flags.
82+
func (a *Attributes) SetACModTime(atime, mtime uint32) {
83+
a.Flags |= AttrACModTime
84+
a.ATime = atime
85+
a.MTime = mtime
86+
}
87+
3788
// Len returns the number of bytes a would marshal into.
3889
func (a *Attributes) Len() int {
3990
length := 4
@@ -98,7 +149,7 @@ func (a *Attributes) MarshalInto(b *Buffer) {
98149

99150
// MarshalBinary returns a as the binary encoding of a.
100151
func (a *Attributes) MarshalBinary() ([]byte, error) {
101-
buf := NewBuffer(make([]byte, a.Len()))
152+
buf := NewBuffer(make([]byte, 0, a.Len()))
102153
a.MarshalInto(buf)
103154
return buf.Bytes(), nil
104155
}
@@ -107,10 +158,20 @@ func (a *Attributes) MarshalBinary() ([]byte, error) {
107158
//
108159
// NOTE: The values of fields not covered in the a.Flags are explicitly undefined.
109160
func (a *Attributes) UnmarshalFrom(b *Buffer) (err error) {
110-
if a.Flags, err = b.ConsumeUint32(); err != nil {
161+
flags, err := b.ConsumeUint32()
162+
if err != nil {
111163
return err
112164
}
113165

166+
return a.XXX_UnmarshalByFlags(flags, b)
167+
}
168+
169+
// XXX_UnmarshalByFlags uses the pre-existing a.Flags field to determine which fields to decode.
170+
// DO NOT USE THIS: it is an anti-corruption function to implement existing internal usage in pkg/sftp.
171+
// This function is not a part of any compatibility promise.
172+
func (a *Attributes) XXX_UnmarshalByFlags(flags uint32, b *Buffer) (err error) {
173+
a.Flags = flags
174+
114175
// Short-circuit dummy attributes.
115176
if a.Flags == 0 {
116177
return nil
@@ -192,7 +253,7 @@ func (e *ExtendedAttribute) MarshalInto(b *Buffer) {
192253

193254
// MarshalBinary returns e as the binary encoding of e.
194255
func (e *ExtendedAttribute) MarshalBinary() ([]byte, error) {
195-
buf := NewBuffer(make([]byte, e.Len()))
256+
buf := NewBuffer(make([]byte, 0, e.Len()))
196257
e.MarshalInto(buf)
197258
return buf.Bytes(), nil
198259
}
@@ -239,7 +300,7 @@ func (e *NameEntry) MarshalInto(b *Buffer) {
239300

240301
// MarshalBinary returns e as the binary encoding of e.
241302
func (e *NameEntry) MarshalBinary() ([]byte, error) {
242-
buf := NewBuffer(make([]byte, e.Len()))
303+
buf := NewBuffer(make([]byte, 0, e.Len()))
243304
e.MarshalInto(buf)
244305
return buf.Bytes(), nil
245306
}

internal/encoding/ssh/filexfer/attrs_test.go

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -113,60 +113,62 @@ func TestAttributes(t *testing.T) {
113113
t.Run(tt.name, func(t *testing.T) {
114114
attr.Flags = tt.flags
115115

116-
buf := new(Buffer)
117-
attr.MarshalInto(buf)
116+
buf, err := attr.MarshalBinary()
117+
if err != nil {
118+
t.Fatal("unexpected error:", err)
119+
}
118120

119-
if got, want := buf.Bytes(), tt.encoded; !bytes.Equal(got, want) {
120-
t.Fatalf("MarshalInto() = %X, but wanted %X", got, want)
121+
if !bytes.Equal(buf, tt.encoded) {
122+
t.Fatalf("MarshalBinary() = %X, but wanted %X", buf, tt.encoded)
121123
}
122124

123125
attr = Attributes{}
124126

125-
if err := attr.UnmarshalFrom(buf); err != nil {
127+
if err := attr.UnmarshalBinary(buf); err != nil {
126128
t.Fatal("unexpected error:", err)
127129
}
128130

129131
if attr.Flags != tt.flags {
130-
t.Errorf("UnmarshalFrom(): Flags was %x, but wanted %x", attr.Flags, tt.flags)
132+
t.Errorf("UnmarshalBinary(): Flags was %x, but wanted %x", attr.Flags, tt.flags)
131133
}
132134

133135
if attr.Flags&AttrSize != 0 && attr.Size != size {
134-
t.Errorf("UnmarshalFrom(): Size was %x, but wanted %x", attr.Size, size)
136+
t.Errorf("UnmarshalBinary(): Size was %x, but wanted %x", attr.Size, size)
135137
}
136138

137139
if attr.Flags&AttrUIDGID != 0 {
138140
if attr.UID != uid {
139-
t.Errorf("UnmarshalFrom(): UID was %x, but wanted %x", attr.UID, uid)
141+
t.Errorf("UnmarshalBinary(): UID was %x, but wanted %x", attr.UID, uid)
140142
}
141143

142144
if attr.GID != gid {
143-
t.Errorf("UnmarshalFrom(): GID was %x, but wanted %x", attr.GID, gid)
145+
t.Errorf("UnmarshalBinary(): GID was %x, but wanted %x", attr.GID, gid)
144146
}
145147
}
146148

147149
if attr.Flags&AttrPermissions != 0 && attr.Permissions != perms {
148-
t.Errorf("UnmarshalFrom(): Permissions was %#v, but wanted %#v", attr.Permissions, perms)
150+
t.Errorf("UnmarshalBinary(): Permissions was %#v, but wanted %#v", attr.Permissions, perms)
149151
}
150152

151153
if attr.Flags&AttrACModTime != 0 {
152154
if attr.ATime != atime {
153-
t.Errorf("UnmarshalFrom(): ATime was %x, but wanted %x", attr.ATime, atime)
155+
t.Errorf("UnmarshalBinary(): ATime was %x, but wanted %x", attr.ATime, atime)
154156
}
155157

156158
if attr.MTime != mtime {
157-
t.Errorf("UnmarshalFrom(): MTime was %x, but wanted %x", attr.MTime, mtime)
159+
t.Errorf("UnmarshalBinary(): MTime was %x, but wanted %x", attr.MTime, mtime)
158160
}
159161
}
160162

161163
if attr.Flags&AttrExtended != 0 {
162164
extAttrs := attr.ExtendedAttributes
163165

164166
if count := len(extAttrs); count != 1 {
165-
t.Fatalf("UnmarshalFrom(): len(ExtendedAttributes) was %d, but wanted %d", count, 1)
167+
t.Fatalf("UnmarshalBinary(): len(ExtendedAttributes) was %d, but wanted %d", count, 1)
166168
}
167169

168170
if got := extAttrs[0]; got != extAttr {
169-
t.Errorf("UnmarshalFrom(): ExtendedAttributes[0] was %#v, but wanted %#v", got, extAttr)
171+
t.Errorf("UnmarshalBinary(): ExtendedAttributes[0] was %#v, but wanted %#v", got, extAttr)
170172
}
171173
}
172174
})
@@ -189,8 +191,10 @@ func TestNameEntry(t *testing.T) {
189191
},
190192
}
191193

192-
buf := new(Buffer)
193-
e.MarshalInto(buf)
194+
buf, err := e.MarshalBinary()
195+
if err != nil {
196+
t.Fatal("unexpected error:", err)
197+
}
194198

195199
want := []byte{
196200
0x00, 0x00, 0x00, 0x03, 'f', 'o', 'o',
@@ -199,13 +203,13 @@ func TestNameEntry(t *testing.T) {
199203
0x87, 0x65, 0x43, 0x21,
200204
}
201205

202-
if got := buf.Bytes(); !bytes.Equal(got, want) {
203-
t.Fatalf("MarshalInto() = %X, but wanted %X", got, want)
206+
if !bytes.Equal(buf, want) {
207+
t.Fatalf("MarshalBinary() = %X, but wanted %X", buf, want)
204208
}
205209

206210
*e = NameEntry{}
207211

208-
if err := e.UnmarshalFrom(buf); err != nil {
212+
if err := e.UnmarshalBinary(buf); err != nil {
209213
t.Fatal("unexpected error:", err)
210214
}
211215

internal/encoding/ssh/filexfer/extended_packets.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ type ExtendedPacket struct {
5151
Data ExtendedData
5252
}
5353

54+
// Type returns the SSH_FXP_xy value associated with this packet type.
55+
func (p *ExtendedPacket) Type() PacketType {
56+
return PacketTypeExtended
57+
}
58+
5459
// MarshalPacket returns p as a two-part binary encoding of p.
5560
//
5661
// The Data is marshaled into binary, and returned as the payload.
@@ -97,6 +102,11 @@ type ExtendedReplyPacket struct {
97102
Data ExtendedData
98103
}
99104

105+
// Type returns the SSH_FXP_xy value associated with this packet type.
106+
func (p *ExtendedReplyPacket) Type() PacketType {
107+
return PacketTypeExtendedReply
108+
}
109+
100110
// MarshalPacket returns p as a two-part binary encoding of p.
101111
//
102112
// The Data is marshaled into binary, and returned as the payload.

0 commit comments

Comments
 (0)