9p: fix readDNS to consume result on read (return EOF on second read)

Previous implementation returned data forever, causing cat to loop.
Now clears the buffer after first read so subsequent reads get EOF.
This commit is contained in:
Levi Neely 2026-07-18 17:14:44 +02:00
parent ece6c19fa6
commit d33fae7946
1 changed files with 10 additions and 9 deletions

View File

@ -760,19 +760,19 @@ func (s *Server) read(cs *connState, fc *plan9.Fcall, ctx context.Context) *plan
// /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.readDNS(fc, f.completeResult)
return s.readDNS(fc, &f.completeResult)
}
// /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.readDNS(fc, f.generateResult)
return s.readDNS(fc, &f.generateResult)
}
// /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.readDNS(fc, f.routeResult)
return s.readDNS(fc, &f.routeResult)
}
s.log.Debug("Tread path=%q offset=%d count=%d", path, fc.Offset, fc.Count)
@ -852,15 +852,16 @@ func (s *Server) readSlice(fc *plan9.Fcall, content []byte) *plan9.Fcall {
// 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 {
// after a write). Returns the content once, then returns EOF on subsequent reads.
func (s *Server) readDNS(fc *plan9.Fcall, content *[]byte) *plan9.Fcall {
var data []byte
if len(content) > 0 {
if len(*content) > 0 {
end := int(fc.Count)
if end > len(content) {
end = len(content)
if end > len(*content) {
end = len(*content)
}
data = content[:end]
data = (*content)[:end]
*content = nil // consumed; next read returns EOF
}
return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Count: uint32(len(data)), Data: data}
}