From 07f84566d5c24f3f52f19fa17505392dec5c869d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 4 Aug 2007 01:22:52 +0100 Subject: Make read_user() non-blocking, and add select() call. --- src/core/posix_io.c | 94 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 35 deletions(-) (limited to 'src/core') diff --git a/src/core/posix_io.c b/src/core/posix_io.c index 21f818bfa..530ce6511 100644 --- a/src/core/posix_io.c +++ b/src/core/posix_io.c @@ -60,12 +60,6 @@ struct posix_file { /** List of open files */ static LIST_HEAD ( posix_files ); -/** Minimum file descriptor that will ever be allocated */ -#define POSIX_FD_MIN ( 1 ) - -/** Maximum file descriptor that will ever be allocated */ -#define POSIX_FD_MAX ( 255 ) - /** * Free open file * @@ -251,6 +245,38 @@ int open ( const char *uri_string ) { return rc; } +/** + * Check file descriptors for readiness + * + * @v readfds File descriptors to check + * @v wait Wait until data is ready + * @ret nready Number of ready file descriptors + */ +int select ( fd_set *readfds, int wait ) { + struct posix_file *file; + int fd; + + do { + for ( fd = POSIX_FD_MIN ; fd <= POSIX_FD_MAX ; fd++ ) { + if ( ! FD_ISSET ( fd, readfds ) ) + continue; + file = posix_fd_to_file ( fd ); + if ( ! file ) + return -EBADF; + if ( ( list_empty ( &file->data ) ) && + ( file->rc != -EINPROGRESS ) ) + continue; + /* Data is available or status has changed */ + FD_ZERO ( readfds ); + FD_SET ( fd, readfds ); + return 1; + } + step(); + } while ( wait ); + + return 0; +} + /** * Read data from file * @@ -258,47 +284,45 @@ int open ( const char *uri_string ) { * @v offset Starting offset within data buffer * @v len Maximum length to read * @ret len Actual length read, or negative error number + * + * This call is non-blocking; if no data is available to read then + * -EWOULDBLOCK will be returned. */ ssize_t read_user ( int fd, userptr_t buffer, off_t offset, size_t max_len ) { struct posix_file *file; struct io_buffer *iobuf; - size_t frag_len; - ssize_t len = 0; + size_t len; /* Identify file */ file = posix_fd_to_file ( fd ); if ( ! file ) return -EBADF; - while ( 1 ) { - /* Try to fetch more data if none available */ - if ( list_empty ( &file->data ) ) - step(); - /* Dequeue at most one received I/O buffer into user buffer */ - list_for_each_entry ( iobuf, &file->data, list ) { - frag_len = iob_len ( iobuf ); - if ( frag_len > max_len ) - frag_len = max_len; - copy_to_user ( buffer, offset, iobuf->data, - frag_len ); - iob_pull ( iobuf, frag_len ); - if ( ! iob_len ( iobuf ) ) { - list_del ( &iobuf-> list ); - free_iob ( iobuf ); - } - file->pos += frag_len; - len += frag_len; - offset += frag_len; - max_len -= frag_len; - break; + /* Try to fetch more data if none available */ + if ( list_empty ( &file->data ) ) + step(); + + /* Dequeue at most one received I/O buffer into user buffer */ + list_for_each_entry ( iobuf, &file->data, list ) { + len = iob_len ( iobuf ); + if ( len > max_len ) + len = max_len; + copy_to_user ( buffer, offset, iobuf->data, len ); + iob_pull ( iobuf, len ); + if ( ! iob_len ( iobuf ) ) { + list_del ( &iobuf->list ); + free_iob ( iobuf ); } - /* If buffer is full, return */ - if ( ! max_len ) - return len; - /* If file has completed, return */ - if ( file->rc != -EINPROGRESS ) - return ( file->rc ? file->rc : len ); + file->pos += len; + return len; } + + /* If file has completed, return (after returning all data) */ + if ( file->rc != -EINPROGRESS ) + return file->rc; + + /* No data ready and file still in progress; return -WOULDBLOCK */ + return -EWOULDBLOCK; } /** -- cgit v1.2.3-55-g7522 From cfcc41d407e99968c23c2402a600263401ee41b8 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 7 Aug 2007 06:50:12 -0700 Subject: Set current working URI to be that of the executable image when executing any image, not just a script. (This will enable pxelinux to use relative URIs, should it wish to.) --- src/core/image.c | 15 ++++++++++++--- src/image/script.c | 10 +--------- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/core/image.c b/src/core/image.c index 63c2502bd..440a68c9f 100644 --- a/src/core/image.c +++ b/src/core/image.c @@ -237,6 +237,7 @@ int image_autoload ( struct image *image ) { * @ret rc Return status code */ int image_exec ( struct image *image ) { + struct uri *old_cwuri; int rc; /* Image must be loaded first */ @@ -252,15 +253,23 @@ int image_exec ( struct image *image ) { if ( ! image->type->exec ) return -ENOEXEC; + /* Switch current working directory to be that of the image itself */ + old_cwuri = uri_get ( cwuri ); + churi ( image->uri ); + /* Try executing the image */ if ( ( rc = image->type->exec ( image ) ) != 0 ) { DBGC ( image, "IMAGE %p could not execute: %s\n", image, strerror ( rc ) ); - return rc; + goto done; } - /* Well, some formats might return... */ - return 0; + done: + /* Reset current working directory */ + churi ( old_cwuri ); + uri_put ( old_cwuri ); + + return rc; } /** diff --git a/src/image/script.c b/src/image/script.c index 2f159c97e..c8821522b 100644 --- a/src/image/script.c +++ b/src/image/script.c @@ -27,7 +27,6 @@ #include #include #include -#include struct image_type script_image_type __image_type ( PROBE_NORMAL ); @@ -38,7 +37,6 @@ struct image_type script_image_type __image_type ( PROBE_NORMAL ); * @ret rc Return status code */ static int script_exec ( struct image *image ) { - struct uri *old_cwuri; char cmdbuf[256]; size_t offset = 0; size_t remaining; @@ -53,10 +51,6 @@ static int script_exec ( struct image *image ) { image_get ( image ); unregister_image ( image ); - /* Switch current working directory to be that of the script itself */ - old_cwuri = uri_get ( cwuri ); - churi ( image->uri ); - while ( offset < image->len ) { /* Read up to cmdbuf bytes from script into buffer */ @@ -93,9 +87,7 @@ static int script_exec ( struct image *image ) { rc = 0; done: - /* Reset current working directory, re-register image and return */ - churi ( old_cwuri ); - uri_put ( old_cwuri ); + /* Re-register image and return */ register_image ( image ); image_put ( image ); return rc; -- cgit v1.2.3-55-g7522