@@ -848,23 +848,120 @@ func errorCodeToErrno(err types.ErrorCode) Errno {
848
848
return Errno (err )
849
849
}
850
850
851
+ type libc_DIR struct {
852
+ d types.DirectoryEntryStream
853
+ }
854
+
851
855
// DIR *fdopendir(int);
852
856
//
853
857
//go:export fdopendir
854
858
func fdopendir (fd int32 ) unsafe.Pointer {
855
- return nil
859
+ if _ , ok := wasiStreams [fd ]; ok {
860
+ libcErrno = EBADF
861
+ return nil
862
+ }
863
+
864
+ stream , ok := wasiFiles [fd ]
865
+ if ! ok {
866
+ libcErrno = EBADF
867
+ return nil
868
+ }
869
+ if stream .d == cm .ResourceNone {
870
+ libcErrno = EBADF
871
+ return nil
872
+ }
873
+
874
+ result := stream .d .ReadDirectory ()
875
+ if err := result .Err (); err != nil {
876
+ libcErrno = errorCodeToErrno (* err )
877
+ return nil
878
+ }
879
+
880
+ return unsafe .Pointer (& libc_DIR {d : * result .OK ()})
856
881
}
857
882
858
883
// int fdclosedir(DIR *);
859
884
//
860
885
//go:export fdclosedir
861
- func fdclosedir (unsafe.Pointer ) int32 {
886
+ func fdclosedir (dirp unsafe.Pointer ) int32 {
887
+ if dirp == nil {
888
+ return 0
889
+
890
+ }
891
+ dir := (* libc_DIR )(dirp )
892
+ if dir .d == cm .ResourceNone {
893
+ return 0
894
+ }
895
+
896
+ dir .d .ResourceDrop ()
897
+ dir .d = cm .ResourceNone
898
+
862
899
return 0
863
900
}
864
901
865
902
// struct dirent *readdir(DIR *);
866
903
//
867
904
//go:export readdir
868
- func readdir (unsafe.Pointer ) * Dirent {
869
- return nil
905
+ func readdir (dirp unsafe.Pointer ) * Dirent {
906
+ if dirp == nil {
907
+ return nil
908
+
909
+ }
910
+ dir := (* libc_DIR )(dirp )
911
+ if dir .d == cm .ResourceNone {
912
+ return nil
913
+ }
914
+
915
+ result := dir .d .ReadDirectoryEntry ()
916
+ if err := result .Err (); err != nil {
917
+ libcErrno = errorCodeToErrno (* err )
918
+ return nil
919
+ }
920
+
921
+ entry := result .OK ().Some ()
922
+ if entry == nil {
923
+ libcErrno = 0
924
+ return nil
925
+ }
926
+
927
+ // The dirent C struct uses a flexible array member to indicate that the
928
+ // directory name is laid out in memory right after the struct data:
929
+ //
930
+ // struct dirent {
931
+ // ino_t d_ino;
932
+ // unsigned char d_type;
933
+ // char d_name[];
934
+ // };
935
+ buf := make ([]byte , unsafe .Sizeof (Dirent {})+ uintptr (len (entry .Name )))
936
+ dirent := (* Dirent )((unsafe .Pointer )(& buf [0 ]))
937
+
938
+ // No inodes in wasi
939
+ dirent .Ino = 0
940
+ dirent .Type = p2fileTypeToLibcType (entry .Type )
941
+ copy (buf [unsafe .Offsetof (dirent .Type )+ 1 :], entry .Name )
942
+
943
+ return dirent
944
+ }
945
+
946
+ func p2fileTypeToLibcType (t types.DescriptorType ) uint8 {
947
+ switch t {
948
+ case types .DescriptorTypeUnknown :
949
+ return DT_UNKNOWN
950
+ case types .DescriptorTypeBlockDevice :
951
+ return DT_BLK
952
+ case types .DescriptorTypeCharacterDevice :
953
+ return DT_CHR
954
+ case types .DescriptorTypeDirectory :
955
+ return DT_DIR
956
+ case types .DescriptorTypeFIFO :
957
+ return DT_FIFO
958
+ case types .DescriptorTypeSymbolicLink :
959
+ return DT_LNK
960
+ case types .DescriptorTypeRegularFile :
961
+ return DT_REG
962
+ case types .DescriptorTypeSocket :
963
+ return DT_FIFO
964
+ }
965
+
966
+ return DT_UNKNOWN
870
967
}
0 commit comments