@@ -2072,6 +2072,79 @@ _PyTokenizer_Get(struct tok_state *tok,
2072
2072
return result ;
2073
2073
}
2074
2074
2075
+ #if defined(__wasi__ ) || defined(__EMSCRIPTEN__ )
2076
+ /* fdopen() with borrowed fd
2077
+
2078
+ WASI does not provide dup() and Emscripten's dup() emulation with open()
2079
+ is slow. Implement fdopen() with fd borrowing on top of fdopencookie().
2080
+ */
2081
+ typedef union {
2082
+ void * cookie ;
2083
+ int fd ;
2084
+ } borrowed ;
2085
+
2086
+ static ssize_t
2087
+ borrow_read (void * cookie , char * buf , size_t size )
2088
+ {
2089
+ borrowed b ;
2090
+ b .cookie = cookie ;
2091
+ return read (b .fd , (void * )buf , size );
2092
+ }
2093
+
2094
+ static ssize_t
2095
+ borrow_write (void * cookie , const char * buf , size_t size )
2096
+ {
2097
+ errno = ENOTSUP ;
2098
+ return -1 ;
2099
+ }
2100
+
2101
+ static int
2102
+ borrow_seek (void * cookie , off_t * off , int whence )
2103
+ {
2104
+ borrowed b ;
2105
+ b .cookie = cookie ;
2106
+ off_t pos ;
2107
+ pos = lseek (b .fd , * off , whence );
2108
+ if (pos == (off_t )- 1 ) {
2109
+ return -1 ;
2110
+ } else {
2111
+ * off = pos ;
2112
+ return 0 ;
2113
+ }
2114
+ }
2115
+
2116
+ static int
2117
+ borrow_close (void * cookie )
2118
+ {
2119
+ // does not close(fd)
2120
+ return 0 ;
2121
+ }
2122
+
2123
+ static FILE *
2124
+ fdopen_borrow (int fd , const char * mode ) {
2125
+ // only reading is supported
2126
+ if (strcmp (mode , "r" ) != 0 ) {
2127
+ return NULL ;
2128
+ }
2129
+ cookie_io_functions_t cookie_io = {
2130
+ borrow_read , borrow_write , borrow_seek , borrow_close
2131
+ };
2132
+ // cookie is just the fd
2133
+ borrowed b ;
2134
+ b .fd = fd ;
2135
+ return fopencookie (b .cookie , "r" , cookie_io );
2136
+ }
2137
+ #else
2138
+ static FILE *
2139
+ fdopen_borrow (int fd , const char * mode ) {
2140
+ fd = _Py_dup (fd );
2141
+ if (fd < 0 ) {
2142
+ return NULL ;
2143
+ }
2144
+ return fdopen (fd , mode );
2145
+ }
2146
+ #endif
2147
+
2075
2148
/* Get the encoding of a Python file. Check for the coding cookie and check if
2076
2149
the file starts with a BOM.
2077
2150
@@ -2091,12 +2164,7 @@ _PyTokenizer_FindEncodingFilename(int fd, PyObject *filename)
2091
2164
const char * p_end = NULL ;
2092
2165
char * encoding = NULL ;
2093
2166
2094
- fd = _Py_dup (fd );
2095
- if (fd < 0 ) {
2096
- return NULL ;
2097
- }
2098
-
2099
- fp = fdopen (fd , "r" );
2167
+ fp = fdopen_borrow (fd , "r" );
2100
2168
if (fp == NULL ) {
2101
2169
return NULL ;
2102
2170
}
0 commit comments