Fix n/ directory listing when note count exceeds 9P read buffer

readDir was slicing the serialized dir entry bytes at the raw byte
boundary, splitting entries mid-stream. The plan9 client's dirUnpack
stops on a truncated entry, so 9pfuse received nothing usable.

Fix readDir to return only complete entries per read, as required by
the 9P spec. Also warn-and-skip on ExtractMetadata errors in LoadAll
instead of aborting the entire directory walk.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-03-21 21:34:15 +01:00
parent 8a6c90f160
commit 6dd103482b
2 changed files with 18 additions and 7 deletions

View File

@ -165,7 +165,8 @@ func LoadAll(dir string) (metadata.Results, error) {
note, err := ExtractMetadata(path) note, err := ExtractMetadata(path)
if err != nil { if err != nil {
return err log.Printf("warning: skipping %s: %v", path, err)
return nil
} }
// Only include files with valid identifiers // Only include files with valid identifiers

View File

@ -931,17 +931,27 @@ func (s *server) readDir(path string, offset int64, count uint32) []byte {
allData = append(allData, stat...) allData = append(allData, stat...)
} }
// Return slice starting from offset // Return only complete entries starting at offset.
// 9P requires that directory reads never split an entry across reads.
if offset >= int64(len(allData)) { if offset >= int64(len(allData)) {
return []byte{} return []byte{}
} }
end := offset + int64(count) remaining := allData[offset:]
if end > int64(len(allData)) { var result []byte
end = int64(len(allData)) for len(remaining) >= 2 {
entrySize := int(remaining[0]) | int(remaining[1])<<8
totalSize := entrySize + 2
if len(remaining) < totalSize {
break
}
if len(result)+totalSize > int(count) {
break
}
result = append(result, remaining[:totalSize]...)
remaining = remaining[totalSize:]
} }
return result
return allData[offset:end]
} }
func (s *server) pathToDir(path string, qid plan9.Qid) plan9.Dir { func (s *server) pathToDir(path string, qid plan9.Qid) plan9.Dir {