|
@@ -60,12 +60,6 @@ struct posix_file {
|
60
|
60
|
/** List of open files */
|
61
|
61
|
static LIST_HEAD ( posix_files );
|
62
|
62
|
|
63
|
|
-/** Minimum file descriptor that will ever be allocated */
|
64
|
|
-#define POSIX_FD_MIN ( 1 )
|
65
|
|
-
|
66
|
|
-/** Maximum file descriptor that will ever be allocated */
|
67
|
|
-#define POSIX_FD_MAX ( 255 )
|
68
|
|
-
|
69
|
63
|
/**
|
70
|
64
|
* Free open file
|
71
|
65
|
*
|
|
@@ -251,6 +245,38 @@ int open ( const char *uri_string ) {
|
251
|
245
|
return rc;
|
252
|
246
|
}
|
253
|
247
|
|
|
248
|
+/**
|
|
249
|
+ * Check file descriptors for readiness
|
|
250
|
+ *
|
|
251
|
+ * @v readfds File descriptors to check
|
|
252
|
+ * @v wait Wait until data is ready
|
|
253
|
+ * @ret nready Number of ready file descriptors
|
|
254
|
+ */
|
|
255
|
+int select ( fd_set *readfds, int wait ) {
|
|
256
|
+ struct posix_file *file;
|
|
257
|
+ int fd;
|
|
258
|
+
|
|
259
|
+ do {
|
|
260
|
+ for ( fd = POSIX_FD_MIN ; fd <= POSIX_FD_MAX ; fd++ ) {
|
|
261
|
+ if ( ! FD_ISSET ( fd, readfds ) )
|
|
262
|
+ continue;
|
|
263
|
+ file = posix_fd_to_file ( fd );
|
|
264
|
+ if ( ! file )
|
|
265
|
+ return -EBADF;
|
|
266
|
+ if ( ( list_empty ( &file->data ) ) &&
|
|
267
|
+ ( file->rc != -EINPROGRESS ) )
|
|
268
|
+ continue;
|
|
269
|
+ /* Data is available or status has changed */
|
|
270
|
+ FD_ZERO ( readfds );
|
|
271
|
+ FD_SET ( fd, readfds );
|
|
272
|
+ return 1;
|
|
273
|
+ }
|
|
274
|
+ step();
|
|
275
|
+ } while ( wait );
|
|
276
|
+
|
|
277
|
+ return 0;
|
|
278
|
+}
|
|
279
|
+
|
254
|
280
|
/**
|
255
|
281
|
* Read data from file
|
256
|
282
|
*
|
|
@@ -258,47 +284,45 @@ int open ( const char *uri_string ) {
|
258
|
284
|
* @v offset Starting offset within data buffer
|
259
|
285
|
* @v len Maximum length to read
|
260
|
286
|
* @ret len Actual length read, or negative error number
|
|
287
|
+ *
|
|
288
|
+ * This call is non-blocking; if no data is available to read then
|
|
289
|
+ * -EWOULDBLOCK will be returned.
|
261
|
290
|
*/
|
262
|
291
|
ssize_t read_user ( int fd, userptr_t buffer, off_t offset, size_t max_len ) {
|
263
|
292
|
struct posix_file *file;
|
264
|
293
|
struct io_buffer *iobuf;
|
265
|
|
- size_t frag_len;
|
266
|
|
- ssize_t len = 0;
|
|
294
|
+ size_t len;
|
267
|
295
|
|
268
|
296
|
/* Identify file */
|
269
|
297
|
file = posix_fd_to_file ( fd );
|
270
|
298
|
if ( ! file )
|
271
|
299
|
return -EBADF;
|
272
|
300
|
|
273
|
|
- while ( 1 ) {
|
274
|
|
- /* Try to fetch more data if none available */
|
275
|
|
- if ( list_empty ( &file->data ) )
|
276
|
|
- step();
|
277
|
|
- /* Dequeue at most one received I/O buffer into user buffer */
|
278
|
|
- list_for_each_entry ( iobuf, &file->data, list ) {
|
279
|
|
- frag_len = iob_len ( iobuf );
|
280
|
|
- if ( frag_len > max_len )
|
281
|
|
- frag_len = max_len;
|
282
|
|
- copy_to_user ( buffer, offset, iobuf->data,
|
283
|
|
- frag_len );
|
284
|
|
- iob_pull ( iobuf, frag_len );
|
285
|
|
- if ( ! iob_len ( iobuf ) ) {
|
286
|
|
- list_del ( &iobuf-> list );
|
287
|
|
- free_iob ( iobuf );
|
288
|
|
- }
|
289
|
|
- file->pos += frag_len;
|
290
|
|
- len += frag_len;
|
291
|
|
- offset += frag_len;
|
292
|
|
- max_len -= frag_len;
|
293
|
|
- break;
|
|
301
|
+ /* Try to fetch more data if none available */
|
|
302
|
+ if ( list_empty ( &file->data ) )
|
|
303
|
+ step();
|
|
304
|
+
|
|
305
|
+ /* Dequeue at most one received I/O buffer into user buffer */
|
|
306
|
+ list_for_each_entry ( iobuf, &file->data, list ) {
|
|
307
|
+ len = iob_len ( iobuf );
|
|
308
|
+ if ( len > max_len )
|
|
309
|
+ len = max_len;
|
|
310
|
+ copy_to_user ( buffer, offset, iobuf->data, len );
|
|
311
|
+ iob_pull ( iobuf, len );
|
|
312
|
+ if ( ! iob_len ( iobuf ) ) {
|
|
313
|
+ list_del ( &iobuf->list );
|
|
314
|
+ free_iob ( iobuf );
|
294
|
315
|
}
|
295
|
|
- /* If buffer is full, return */
|
296
|
|
- if ( ! max_len )
|
297
|
|
- return len;
|
298
|
|
- /* If file has completed, return */
|
299
|
|
- if ( file->rc != -EINPROGRESS )
|
300
|
|
- return ( file->rc ? file->rc : len );
|
|
316
|
+ file->pos += len;
|
|
317
|
+ return len;
|
301
|
318
|
}
|
|
319
|
+
|
|
320
|
+ /* If file has completed, return (after returning all data) */
|
|
321
|
+ if ( file->rc != -EINPROGRESS )
|
|
322
|
+ return file->rc;
|
|
323
|
+
|
|
324
|
+ /* No data ready and file still in progress; return -WOULDBLOCK */
|
|
325
|
+ return -EWOULDBLOCK;
|
302
|
326
|
}
|
303
|
327
|
|
304
|
328
|
/**
|