9p: fix /net/dns read pattern — ignore offset for write-then-read

Shell fd position advances after write, so the subsequent read
arrives with offset=N (write length). readDNS always serves from
offset 0, fixing empty reads from exec 3<>file; echo >&3; cat <&3.
This commit is contained in:
Levi Neely 2026-07-18 17:13:01 +02:00
parent a01891621d
commit ece6c19fa6
1 changed files with 21 additions and 6 deletions

View File

@ -757,22 +757,22 @@ func (s *Server) read(cs *connState, fc *plan9.Fcall, ctx context.Context) *plan
return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Count: uint32(len(data)), Data: data}
}
// /complete: return per-fid result from previous write
// /complete: return per-fid result from previous write (offset 0-based)
if path == "/complete" {
s.log.Debug("Tread path=%q offset=%d count=%d", path, fc.Offset, fc.Count)
return s.readSlice(fc, f.completeResult)
return s.readDNS(fc, f.completeResult)
}
// /generate: return per-fid result from previous write
// /generate: return per-fid result from previous write (offset 0-based)
if path == "/generate" {
s.log.Debug("Tread path=%q offset=%d count=%d", path, fc.Offset, fc.Count)
return s.readSlice(fc, f.generateResult)
return s.readDNS(fc, f.generateResult)
}
// /route: return per-fid result from previous write
// /route: return per-fid result from previous write (offset 0-based)
if path == "/route" {
s.log.Debug("Tread path=%q offset=%d count=%d", path, fc.Offset, fc.Count)
return s.readSlice(fc, f.routeResult)
return s.readDNS(fc, f.routeResult)
}
s.log.Debug("Tread path=%q offset=%d count=%d", path, fc.Offset, fc.Count)
@ -850,6 +850,21 @@ func (s *Server) readSlice(fc *plan9.Fcall, content []byte) *plan9.Fcall {
return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Count: uint32(len(data)), Data: data}
}
// readDNS implements the Plan 9 /net/dns read pattern: the result is always
// read from offset 0 regardless of the client's file position (which advances
// after a write). This allows write-then-read on the same fd.
func (s *Server) readDNS(fc *plan9.Fcall, content []byte) *plan9.Fcall {
var data []byte
if len(content) > 0 {
end := int(fc.Count)
if end > len(content) {
end = len(content)
}
data = content[:end]
}
return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Count: uint32(len(data)), Data: data}
}
func (s *Server) helpPath() string {
return paths.CfgDir() + "/help.md"
}