diff options
author | Michael Brown <mcb30@etherboot.org> | 2007-08-04 01:22:52 +0100 |
---|---|---|
committer | Michael Brown <mcb30@etherboot.org> | 2007-08-04 01:22:52 +0100 |
commit | 07f84566d5c24f3f52f19fa17505392dec5c869d (patch) | |
tree | 87234e6916c880c2535650645d717a02f1d65736 /src/interface | |
parent | 218651e1259da924a19db66e7cb9ae885075892f (diff) | |
download | ipxe-07f84566d5c24f3f52f19fa17505392dec5c869d.tar.gz |
Make read_user() non-blocking, and add select() call.
Diffstat (limited to 'src/interface')
-rw-r--r-- | src/interface/pxe/pxe_tftp.c | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/src/interface/pxe/pxe_tftp.c b/src/interface/pxe/pxe_tftp.c index 5197a631..64f7ffd5 100644 --- a/src/interface/pxe/pxe_tftp.c +++ b/src/interface/pxe/pxe_tftp.c @@ -79,6 +79,37 @@ static void pxe_tftp_build_uri ( char *uri_string, } /** + * Read as much as possible from file + * + * @v fd File descriptor + * @v buffer Data buffer + * @v max_len Maximum length to read + * @ret len Actual length read, or negative error + */ +static ssize_t pxe_tftp_read_all ( int fd, userptr_t buffer, + size_t max_len ) { + fd_set fdset; + off_t offset = 0; + int ready; + ssize_t len; + + do { + FD_ZERO ( &fdset ); + FD_SET ( fd, &fdset ); + ready = select ( &fdset, 1 ); + if ( ready < 0 ) + return ready; + len = read_user ( fd, buffer, offset, max_len ); + if ( len < 0 ) + return len; + offset += len; + max_len -= len; + } while ( max_len && len ); + + return offset; +} + +/** * TFTP OPEN * * @v tftp_open Pointer to a struct s_PXENV_TFTP_OPEN @@ -251,11 +282,12 @@ PXENV_EXIT_t pxenv_tftp_read ( struct s_PXENV_TFTP_READ *tftp_read ) { buffer = real_to_user ( tftp_read->Buffer.segment, tftp_read->Buffer.offset ); - len = read_user ( pxe_single_fd, buffer, 0, pxe_single_blksize ); + len = pxe_tftp_read_all ( pxe_single_fd, buffer, pxe_single_blksize ); if ( len < 0 ) { tftp_read->Status = PXENV_STATUS ( len ); return PXENV_EXIT_FAILURE; } + tftp_read->BufferSize = len; tftp_read->PacketNumber = ++pxe_single_blkidx; @@ -359,10 +391,8 @@ PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE char uri_string[PXE_URI_LEN]; int fd; userptr_t buffer; - size_t max_len; - ssize_t frag_len; - size_t len = 0; - int rc = -ENOBUFS; + ssize_t len; + int rc = 0; DBG ( "PXENV_TFTP_READ_FILE" ); @@ -384,16 +414,9 @@ PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE /* Read file */ buffer = phys_to_user ( tftp_read_file->Buffer ); - max_len = tftp_read_file->BufferSize; - while ( max_len ) { - frag_len = read_user ( fd, buffer, len, max_len ); - if ( frag_len <= 0 ) { - rc = frag_len; - break; - } - len += frag_len; - max_len -= frag_len; - } + len = pxe_tftp_read_all ( fd, buffer, tftp_read_file->BufferSize ); + if ( len < 0 ) + rc = len; close ( fd ); tftp_read_file->BufferSize = len; |