@@ -96,6 +96,32 @@ extension FileManager {
96
96
return nil
97
97
}
98
98
urls = mountPoints ( statBuf, Int ( fsCount) )
99
+ #elseif os(WASI)
100
+ // Skip the first three file descriptors, which are reserved for stdin, stdout, and stderr.
101
+ var fd : __wasi_fd_t = 3
102
+ let __WASI_PREOPENTYPE_DIR : UInt8 = 0
103
+ while true {
104
+ var prestat = __wasi_prestat_t ( )
105
+ guard __wasi_fd_prestat_get ( fd, & prestat) == 0 else {
106
+ break
107
+ }
108
+
109
+ if prestat. tag == __WASI_PREOPENTYPE_DIR {
110
+ var buf = [ UInt8] ( repeating: 0 , count: Int ( prestat. u. dir. pr_name_len) )
111
+ guard __wasi_fd_prestat_dir_name ( fd, & buf, prestat. u. dir. pr_name_len) == 0 else {
112
+ break
113
+ }
114
+ let path = buf. withUnsafeBufferPointer { buf in
115
+ guard let baseAddress = buf. baseAddress else {
116
+ return " "
117
+ }
118
+ let base = UnsafeRawPointer ( baseAddress) . assumingMemoryBound ( to: Int8 . self)
119
+ return string ( withFileSystemRepresentation: base, length: buf. count)
120
+ }
121
+ urls. append ( URL ( fileURLWithPath: path, isDirectory: true ) )
122
+ }
123
+ fd += 1
124
+ }
99
125
#else
100
126
#error("Requires a platform-specific implementation")
101
127
#endif
@@ -446,6 +472,10 @@ extension FileManager {
446
472
}
447
473
448
474
internal func _attributesOfFileSystemIncludingBlockSize( forPath path: String ) throws -> ( attributes: [ FileAttributeKey : Any ] , blockSize: UInt64 ? ) {
475
+ #if os(WASI)
476
+ // WASI doesn't have statvfs
477
+ throw _NSErrorWithErrno ( ENOTSUP, reading: true , path: path)
478
+ #else
449
479
var result : [ FileAttributeKey : Any ] = [ : ]
450
480
var finalBlockSize : UInt64 ?
451
481
@@ -478,6 +508,7 @@ extension FileManager {
478
508
finalBlockSize = blockSize
479
509
}
480
510
return ( attributes: result, blockSize: finalBlockSize)
511
+ #endif // os(WASI)
481
512
}
482
513
483
514
internal func _createSymbolicLink( atPath path: String , withDestinationPath destPath: String ) throws {
@@ -507,6 +538,11 @@ extension FileManager {
507
538
}
508
539
509
540
internal func _recursiveDestinationOfSymbolicLink( atPath path: String ) throws -> String {
541
+ #if os(WASI)
542
+ // TODO: Remove this guard when realpath implementation will be released
543
+ // See https://github.com/WebAssembly/wasi-libc/pull/473
544
+ throw _NSErrorWithErrno ( ENOTSUP, reading: true , path: path)
545
+ #else
510
546
// Throw error if path is not a symbolic link:
511
547
let path = try _destinationOfSymbolicLink ( atPath: path)
512
548
@@ -520,10 +556,16 @@ extension FileManager {
520
556
}
521
557
522
558
return String ( cString: resolvedPath)
559
+ #endif
523
560
}
524
561
525
562
/* Returns a String with a canonicalized path for the element at the specified path. */
526
563
internal func _canonicalizedPath( toFileAtPath path: String ) throws -> String {
564
+ #if os(WASI)
565
+ // TODO: Remove this guard when realpath implementation will be released
566
+ // See https://github.com/WebAssembly/wasi-libc/pull/473
567
+ throw _NSErrorWithErrno ( ENOTSUP, reading: true , path: path)
568
+ #else
527
569
let bufSize = Int ( PATH_MAX + 1 )
528
570
var buf = [ Int8] ( repeating: 0 , count: bufSize)
529
571
let done = try _fileSystemRepresentation ( withPath: path) {
@@ -534,6 +576,7 @@ extension FileManager {
534
576
}
535
577
536
578
return self . string ( withFileSystemRepresentation: buf, length: strlen ( buf) )
579
+ #endif
537
580
}
538
581
539
582
internal func _readFrom( fd: Int32 , toBuffer buffer: UnsafeMutablePointer < UInt8 > , length bytesToRead: Int , filename: String ) throws -> Int {
@@ -591,12 +634,14 @@ extension FileManager {
591
634
}
592
635
defer { close ( dstfd) }
593
636
637
+ #if !os(WASI) // WASI doesn't have ownership concept
594
638
// Set the file permissions using fchmod() instead of when open()ing to avoid umask() issues
595
639
let permissions = fileInfo. st_mode & ~ S_IFMT
596
640
guard fchmod ( dstfd, permissions) == 0 else {
597
641
throw _NSErrorWithErrno ( errno, reading: false , path: dstPath,
598
642
extraUserInfo: extraErrorInfo ( srcPath: srcPath, dstPath: dstPath, userVariant: variant) )
599
643
}
644
+ #endif
600
645
601
646
if fileInfo. st_size == 0 {
602
647
// no copying required
@@ -741,6 +786,10 @@ extension FileManager {
741
786
if rmdir ( fsRep) == 0 {
742
787
return
743
788
} else if errno == ENOTEMPTY {
789
+ #if os(WASI)
790
+ // wasi-libc, which is based on musl, does not provide fts(3)
791
+ throw _NSErrorWithErrno ( ENOTSUP, reading: false , path: path)
792
+ #else
744
793
let ps = UnsafeMutablePointer< UnsafeMutablePointer< Int8>?> . allocate( capacity: 2 )
745
794
ps. initialize ( to: UnsafeMutablePointer ( mutating: fsRep) )
746
795
ps. advanced ( by: 1 ) . initialize ( to: nil )
@@ -783,6 +832,7 @@ extension FileManager {
783
832
} else {
784
833
let _ = _NSErrorWithErrno ( ENOTEMPTY, reading: false , path: path)
785
834
}
835
+ #endif
786
836
} else if errno != ENOTDIR {
787
837
throw _NSErrorWithErrno ( errno, reading: false , path: path)
788
838
} else if unlink ( fsRep) != 0 {
@@ -885,6 +935,7 @@ extension FileManager {
885
935
return false
886
936
}
887
937
938
+ #if !os(WASI) // WASI doesn't have ownership concept
888
939
// Stat the parent directory, if that fails, return false.
889
940
let parentS = try _lstatFile ( atPath: path, withFileSystemRepresentation: parentFsRep)
890
941
@@ -895,6 +946,7 @@ extension FileManager {
895
946
// If the current user owns the file, return true.
896
947
return s. st_uid == getuid ( )
897
948
}
949
+ #endif
898
950
899
951
// Return true as the best guess.
900
952
return true
@@ -1065,6 +1117,26 @@ extension FileManager {
1065
1117
return temp. _bridgeToObjectiveC ( ) . appendingPathComponent ( dest)
1066
1118
}
1067
1119
1120
+ #if os(WASI)
1121
+ // For platforms that don't support FTS, we just throw an error for now.
1122
+ // TODO: Provide readdir(2) based implementation here or FTS in wasi-libc?
1123
+ internal class NSURLDirectoryEnumerator : DirectoryEnumerator {
1124
+ var _url : URL
1125
+ var _errorHandler : ( ( URL , Error ) -> Bool ) ?
1126
+
1127
+ init ( url: URL , options: FileManager . DirectoryEnumerationOptions , errorHandler: ( ( URL , Error ) -> Bool ) ? ) {
1128
+ _url = url
1129
+ _errorHandler = errorHandler
1130
+ }
1131
+
1132
+ override func nextObject( ) -> Any ? {
1133
+ if let handler = _errorHandler {
1134
+ _ = handler ( _url, _NSErrorWithErrno ( ENOTSUP, reading: true , url: _url) )
1135
+ }
1136
+ return nil
1137
+ }
1138
+ }
1139
+ #else
1068
1140
internal class NSURLDirectoryEnumerator : DirectoryEnumerator {
1069
1141
var _url : URL
1070
1142
var _options : FileManager . DirectoryEnumerationOptions
@@ -1198,6 +1270,7 @@ extension FileManager {
1198
1270
return nil
1199
1271
}
1200
1272
}
1273
+ #endif
1201
1274
1202
1275
internal func _updateTimes( atPath path: String , withFileSystemRepresentation fsr: UnsafePointer < Int8 > , creationTime: Date ? = nil , accessTime: Date ? = nil , modificationTime: Date ? = nil ) throws {
1203
1276
let stat = try _lstatFile ( atPath: path, withFileSystemRepresentation: fsr)
0 commit comments