1package filexfer 2 3// ClosePacket defines the SSH_FXP_CLOSE packet. 4type ClosePacket struct { 5 Handle string 6} 7 8// Type returns the SSH_FXP_xy value associated with this packet type. 9func (p *ClosePacket) Type() PacketType { 10 return PacketTypeClose 11} 12 13// MarshalPacket returns p as a two-part binary encoding of p. 14func (p *ClosePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) { 15 buf := NewBuffer(b) 16 if buf.Cap() < 9 { 17 size := 4 + len(p.Handle) // string(handle) 18 buf = NewMarshalBuffer(size) 19 } 20 21 buf.StartPacket(PacketTypeClose, reqid) 22 buf.AppendString(p.Handle) 23 24 return buf.Packet(payload) 25} 26 27// UnmarshalPacketBody unmarshals the packet body from the given Buffer. 28// It is assumed that the uint32(request-id) has already been consumed. 29func (p *ClosePacket) UnmarshalPacketBody(buf *Buffer) (err error) { 30 if p.Handle, err = buf.ConsumeString(); err != nil { 31 return err 32 } 33 34 return nil 35} 36 37// ReadPacket defines the SSH_FXP_READ packet. 38type ReadPacket struct { 39 Handle string 40 Offset uint64 41 Len uint32 42} 43 44// Type returns the SSH_FXP_xy value associated with this packet type. 45func (p *ReadPacket) Type() PacketType { 46 return PacketTypeRead 47} 48 49// MarshalPacket returns p as a two-part binary encoding of p. 50func (p *ReadPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) { 51 buf := NewBuffer(b) 52 if buf.Cap() < 9 { 53 // string(handle) + uint64(offset) + uint32(len) 54 size := 4 + len(p.Handle) + 8 + 4 55 buf = NewMarshalBuffer(size) 56 } 57 58 buf.StartPacket(PacketTypeRead, reqid) 59 buf.AppendString(p.Handle) 60 buf.AppendUint64(p.Offset) 61 buf.AppendUint32(p.Len) 62 63 return buf.Packet(payload) 64} 65 66// UnmarshalPacketBody unmarshals the packet body from the given Buffer. 67// It is assumed that the uint32(request-id) has already been consumed. 68func (p *ReadPacket) UnmarshalPacketBody(buf *Buffer) (err error) { 69 if p.Handle, err = buf.ConsumeString(); err != nil { 70 return err 71 } 72 73 if p.Offset, err = buf.ConsumeUint64(); err != nil { 74 return err 75 } 76 77 if p.Len, err = buf.ConsumeUint32(); err != nil { 78 return err 79 } 80 81 return nil 82} 83 84// WritePacket defines the SSH_FXP_WRITE packet. 85type WritePacket struct { 86 Handle string 87 Offset uint64 88 Data []byte 89} 90 91// Type returns the SSH_FXP_xy value associated with this packet type. 92func (p *WritePacket) Type() PacketType { 93 return PacketTypeWrite 94} 95 96// MarshalPacket returns p as a two-part binary encoding of p. 97func (p *WritePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) { 98 buf := NewBuffer(b) 99 if buf.Cap() < 9 { 100 // string(handle) + uint64(offset) + uint32(len(data)); data content in payload 101 size := 4 + len(p.Handle) + 8 + 4 102 buf = NewMarshalBuffer(size) 103 } 104 105 buf.StartPacket(PacketTypeWrite, reqid) 106 buf.AppendString(p.Handle) 107 buf.AppendUint64(p.Offset) 108 buf.AppendUint32(uint32(len(p.Data))) 109 110 return buf.Packet(p.Data) 111} 112 113// UnmarshalPacketBody unmarshals the packet body from the given Buffer. 114// It is assumed that the uint32(request-id) has already been consumed. 115// 116// If p.Data is already populated, and of sufficient length to hold the data, 117// then this will copy the data into that byte slice. 118// 119// If p.Data has a length insufficient to hold the data, 120// then this will make a new slice of sufficient length, and copy the data into that. 121// 122// This means this _does not_ alias any of the data buffer that is passed in. 123func (p *WritePacket) UnmarshalPacketBody(buf *Buffer) (err error) { 124 if p.Handle, err = buf.ConsumeString(); err != nil { 125 return err 126 } 127 128 if p.Offset, err = buf.ConsumeUint64(); err != nil { 129 return err 130 } 131 132 data, err := buf.ConsumeByteSlice() 133 if err != nil { 134 return err 135 } 136 137 if len(p.Data) < len(data) { 138 p.Data = make([]byte, len(data)) 139 } 140 141 n := copy(p.Data, data) 142 p.Data = p.Data[:n] 143 return nil 144} 145 146// FStatPacket defines the SSH_FXP_FSTAT packet. 147type FStatPacket struct { 148 Handle string 149} 150 151// Type returns the SSH_FXP_xy value associated with this packet type. 152func (p *FStatPacket) Type() PacketType { 153 return PacketTypeFStat 154} 155 156// MarshalPacket returns p as a two-part binary encoding of p. 157func (p *FStatPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) { 158 buf := NewBuffer(b) 159 if buf.Cap() < 9 { 160 size := 4 + len(p.Handle) // string(handle) 161 buf = NewMarshalBuffer(size) 162 } 163 164 buf.StartPacket(PacketTypeFStat, reqid) 165 buf.AppendString(p.Handle) 166 167 return buf.Packet(payload) 168} 169 170// UnmarshalPacketBody unmarshals the packet body from the given Buffer. 171// It is assumed that the uint32(request-id) has already been consumed. 172func (p *FStatPacket) UnmarshalPacketBody(buf *Buffer) (err error) { 173 if p.Handle, err = buf.ConsumeString(); err != nil { 174 return err 175 } 176 177 return nil 178} 179 180// FSetstatPacket defines the SSH_FXP_FSETSTAT packet. 181type FSetstatPacket struct { 182 Handle string 183 Attrs Attributes 184} 185 186// Type returns the SSH_FXP_xy value associated with this packet type. 187func (p *FSetstatPacket) Type() PacketType { 188 return PacketTypeFSetstat 189} 190 191// MarshalPacket returns p as a two-part binary encoding of p. 192func (p *FSetstatPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) { 193 buf := NewBuffer(b) 194 if buf.Cap() < 9 { 195 size := 4 + len(p.Handle) + p.Attrs.Len() // string(handle) + ATTRS(attrs) 196 buf = NewMarshalBuffer(size) 197 } 198 199 buf.StartPacket(PacketTypeFSetstat, reqid) 200 buf.AppendString(p.Handle) 201 202 p.Attrs.MarshalInto(buf) 203 204 return buf.Packet(payload) 205} 206 207// UnmarshalPacketBody unmarshals the packet body from the given Buffer. 208// It is assumed that the uint32(request-id) has already been consumed. 209func (p *FSetstatPacket) UnmarshalPacketBody(buf *Buffer) (err error) { 210 if p.Handle, err = buf.ConsumeString(); err != nil { 211 return err 212 } 213 214 return p.Attrs.UnmarshalFrom(buf) 215} 216 217// ReadDirPacket defines the SSH_FXP_READDIR packet. 218type ReadDirPacket struct { 219 Handle string 220} 221 222// Type returns the SSH_FXP_xy value associated with this packet type. 223func (p *ReadDirPacket) Type() PacketType { 224 return PacketTypeReadDir 225} 226 227// MarshalPacket returns p as a two-part binary encoding of p. 228func (p *ReadDirPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) { 229 buf := NewBuffer(b) 230 if buf.Cap() < 9 { 231 size := 4 + len(p.Handle) // string(handle) 232 buf = NewMarshalBuffer(size) 233 } 234 235 buf.StartPacket(PacketTypeReadDir, reqid) 236 buf.AppendString(p.Handle) 237 238 return buf.Packet(payload) 239} 240 241// UnmarshalPacketBody unmarshals the packet body from the given Buffer. 242// It is assumed that the uint32(request-id) has already been consumed. 243func (p *ReadDirPacket) UnmarshalPacketBody(buf *Buffer) (err error) { 244 if p.Handle, err = buf.ConsumeString(); err != nil { 245 return err 246 } 247 248 return nil 249} 250