+
+ type DirEntry struct {
+ IsDirectory bool
+ Name string
+ Encoding string
+ Inode *Block
+ }
+
+ func dirEntry(data []byte) ([]byte, DirEntry, error) {
+ var d DirEntry
+ var err error
+ data, d.IsDirectory, err = mapValue(uint16LE, func(n uint16) bool {
+ return n&0x200 != 0
+ })(data)
+ if err != err {
+ return data, d, err
+ }
+
+ _, _, err = tuple(
+ assign(&d.Name, toString(lengthData(uint64LE))),
+ assign(&d.Encoding, mapValue(option(toString(lengthData(uint64LE))), func(p *string) string {
+ if p == nil {
+ return ""
+ }
+ return *p
+ })),
+ )(data)
+ if err != nil {
+ d.Name = string(data)
+ }
+ return nil, d, nil
+ }
+
+ func ReadDir(dirInode *Block) ([]DirEntry, error) {
+ var entries []DirEntry
+ for _, e := range dirInode.Edges {
+ if e.Flag&EdgeFlagsDeleted != 0 {
+ continue
+ }
+ if e.Flag&EdgeFlagsFolder == 0 {
+ return nil, errors.New("ReadDir: found an edge that doesn't have Folder flag set")
+ }
+ b := e.To
+ _, entry, err := dirEntry(b.Content)
+ if err != nil {
+ return nil, fmt.Errorf("not a valid directory entry: %q", b.Content)
+ }
+ for _, inodeEdge := range b.Edges {
+ if inodeEdge.Flag&EdgeFlagsDeleted != 0 {
+ continue
+ }
+ if inodeEdge.Flag&EdgeFlagsFolder == 0 {
+ return nil, fmt.Errorf("directory entry for %s has an edge without Folder flag", entry.Name)
+ }
+ entry.Inode = inodeEdge.To
+ break
+ }
+ if entry.Inode == nil {
+ return nil, fmt.Errorf("directory entry for %s has no inode", entry.Name)
+ }
+ entries = append(entries, entry)
+ }
+ return entries, nil
+ }