Skip to content

Commit

Permalink
simplify attrs for sshFxpOpenPacket
Browse files Browse the repository at this point in the history
  • Loading branch information
mafredri committed Dec 16, 2023
1 parent 8218e92 commit 211f87b
Showing 1 changed file with 6 additions and 71 deletions.
77 changes: 6 additions & 71 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,85 +462,20 @@ func (p *sshFxpOpenPacket) respond(svr *Server) responsePacket {
osFlags |= os.O_EXCL
}

name := svr.toLocalPath(p.Path)
mode := os.FileMode(0o644)

var applyAttrs []func(*os.File) error

// Both `sshFileXferAttrPermissions` and `sshFileXferAttrACmodTime` are set
// by e.g. `sftp`. Just in case, we handle all other cases as well.
// Only apply for newly created files.
var err error
useAttrs := true
if _, err := os.Stat(name); err == nil {
useAttrs = false
}
if b, ok := p.Attrs.([]byte); useAttrs && ok {
if (p.Flags & sshFileXferAttrSize) != 0 {
var size uint64
if size, b, err = unmarshalUint64Safe(b); err == nil {
applyAttrs = append(applyAttrs, func(f *os.File) error {
return f.Truncate(int64(size))
})
}
}
if err != nil {
return statusFromError(p.ID, err)
}
if (p.Flags & sshFileXferAttrUIDGID) != 0 {
var uid uint32
var gid uint32
if uid, b, err = unmarshalUint32Safe(b); err != nil {
} else if gid, b, err = unmarshalUint32Safe(b); err != nil {
} else {
applyAttrs = append(applyAttrs, func(f *os.File) error {
return f.Chown(int(uid), int(gid))
})
}
}
if err != nil {
return statusFromError(p.ID, err)
}
if (p.Flags & sshFileXferAttrPermissions) != 0 {
var attrMode uint32
if attrMode, b, err = unmarshalUint32Safe(b); err == nil {
// Optionally, we could apply umask here.
mode = os.FileMode(attrMode)
}
}
if err != nil {
return statusFromError(p.ID, err)
}
if (p.Flags & sshFileXferAttrACmodTime) != 0 {
var atime uint32
var mtime uint32
if atime, b, err = unmarshalUint32Safe(b); err != nil {
} else if mtime, _, err = unmarshalUint32Safe(b); err != nil {
} else {
atimeT := time.Unix(int64(atime), 0)
mtimeT := time.Unix(int64(mtime), 0)
applyAttrs = append(applyAttrs, func(f *os.File) error {
return os.Chtimes(f.Name(), atimeT, mtimeT)
})
}
}
if err != nil {
return statusFromError(p.ID, err)
}
// Like OpenSSH, we only handle permissions here if the file is
// being created. Otherwise, the permissions are ignored.
if b, ok := p.Attrs.([]byte); ok && (p.Flags&sshFileXferAttrPermissions) != 0 {
fs, _ := unmarshalFileStat(p.Flags, b)
mode = os.FileMode(fs.Mode)
}

name := svr.toLocalPath(p.Path)
f, err := os.OpenFile(name, osFlags, mode)
if err != nil {
return statusFromError(p.ID, err)
}

for _, applyAttr := range applyAttrs {
if err := applyAttr(f); err != nil {
_ = f.Close()
return statusFromError(p.ID, err)
}
}

handle := svr.nextHandle(f)
return &sshFxpHandlePacket{ID: p.ID, Handle: handle}
}
Expand Down

0 comments on commit 211f87b

Please sign in to comment.