#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <gpxe/list.h>
#include <gpxe/xfer.h>
#include <gpxe/open.h>
#include <gpxe/process.h>
#include <gpxe/posix_io.h>
Go to the source code of this file.
Data Structures | |
| struct | posix_file |
| An open file. More... | |
Functions | |
| FILE_LICENCE (GPL2_OR_LATER) | |
| static | LIST_HEAD (posix_files) |
| List of open files. | |
| static void | posix_file_free (struct refcnt *refcnt) |
| Free open file. | |
| static void | posix_file_finished (struct posix_file *file, int rc) |
| Terminate file data transfer. | |
| static void | posix_file_xfer_close (struct xfer_interface *xfer, int rc) |
| Handle close() event. | |
| static int | posix_file_xfer_deliver_iob (struct xfer_interface *xfer, struct io_buffer *iobuf, struct xfer_metadata *meta) |
| Handle deliver_iob() event. | |
| static struct posix_file * | posix_fd_to_file (int fd) |
| Identify file by file descriptor. | |
| static int | posix_find_free_fd (void) |
| Find an available file descriptor. | |
| int | open (const char *uri_string) |
| Open file. | |
| int | select (fd_set *readfds, int wait) |
| Check file descriptors for readiness. | |
| ssize_t | read_user (int fd, userptr_t buffer, off_t offset, size_t max_len) |
| Read data from file. | |
| ssize_t | fsize (int fd) |
| Determine file size. | |
| int | close (int fd) |
| Close file. | |
Variables | |
| static struct xfer_interface_operations | posix_file_xfer_operations |
| POSIX file data transfer interface operations. | |
These functions provide traditional blocking I/O semantics. They are designed to be used by the PXE TFTP API. Because they block, they may not be used by most other portions of the gPXE codebase.
Definition in file posix_io.c.
| FILE_LICENCE | ( | GPL2_OR_LATER | ) |
| static LIST_HEAD | ( | posix_files | ) | [static] |
List of open files.
| static void posix_file_free | ( | struct refcnt * | refcnt | ) | [static] |
Free open file.
| refcnt | Reference counter |
Definition at line 70 of file posix_io.c.
References container_of, posix_file::data, free(), free_iob(), io_buffer::list, list_del, and list_for_each_entry_safe.
Referenced by open().
00070 { 00071 struct posix_file *file = 00072 container_of ( refcnt, struct posix_file, refcnt ); 00073 struct io_buffer *iobuf; 00074 struct io_buffer *tmp; 00075 00076 list_for_each_entry_safe ( iobuf, tmp, &file->data, list ) { 00077 list_del ( &iobuf->list ); 00078 free_iob ( iobuf ); 00079 } 00080 free ( file ); 00081 }
| static void posix_file_finished | ( | struct posix_file * | file, | |
| int | rc | |||
| ) | [static] |
Terminate file data transfer.
| file | POSIX file | |
| rc | Reason for termination |
Definition at line 89 of file posix_io.c.
References posix_file::rc, posix_file::xfer, and xfer_close().
Referenced by close(), open(), and posix_file_xfer_close().
00089 { 00090 xfer_nullify ( &file->xfer ); 00091 xfer_close ( &file->xfer, rc ); 00092 file->rc = rc; 00093 }
| static void posix_file_xfer_close | ( | struct xfer_interface * | xfer, | |
| int | rc | |||
| ) | [static] |
Handle close() event.
| xfer | POSIX file data transfer interface | |
| rc | Reason for close |
Definition at line 101 of file posix_io.c.
References container_of, and posix_file_finished().
00101 { 00102 struct posix_file *file = 00103 container_of ( xfer, struct posix_file, xfer ); 00104 00105 posix_file_finished ( file, rc ); 00106 }
| static int posix_file_xfer_deliver_iob | ( | struct xfer_interface * | xfer, | |
| struct io_buffer * | iobuf, | |||
| struct xfer_metadata * | meta | |||
| ) | [static] |
Handle deliver_iob() event.
| xfer | POSIX file data transfer interface | |
| iobuf | I/O buffer | |
| meta | Data transfer metadata |
| rc | Return status code |
Definition at line 117 of file posix_io.c.
References container_of, posix_file::data, posix_file::filesize, free_iob(), iob_len(), io_buffer::list, list_add_tail, xfer_metadata::offset, posix_file::pos, SEEK_CUR, and xfer_metadata::whence.
00119 { 00120 struct posix_file *file = 00121 container_of ( xfer, struct posix_file, xfer ); 00122 00123 /* Keep track of file position solely for the filesize */ 00124 if ( meta->whence != SEEK_CUR ) 00125 file->pos = 0; 00126 file->pos += meta->offset; 00127 if ( file->filesize < file->pos ) 00128 file->filesize = file->pos; 00129 00130 if ( iob_len ( iobuf ) ) { 00131 list_add_tail ( &iobuf->list, &file->data ); 00132 } else { 00133 free_iob ( iobuf ); 00134 } 00135 00136 return 0; 00137 }
| static struct posix_file* posix_fd_to_file | ( | int | fd | ) | [static, read] |
Identify file by file descriptor.
| fd | File descriptor |
| file | Corresponding file, or NULL |
Definition at line 155 of file posix_io.c.
References posix_file::fd, posix_file::list, list_for_each_entry, and NULL.
Referenced by close(), fsize(), posix_find_free_fd(), read_user(), and select().
00155 { 00156 struct posix_file *file; 00157 00158 list_for_each_entry ( file, &posix_files, list ) { 00159 if ( file->fd == fd ) 00160 return file; 00161 } 00162 return NULL; 00163 }
| static int posix_find_free_fd | ( | void | ) | [static] |
Find an available file descriptor.
| fd | File descriptor, or negative error number |
Definition at line 170 of file posix_io.c.
References DBG, ENFILE, posix_file::fd, POSIX_FD_MAX, POSIX_FD_MIN, and posix_fd_to_file().
Referenced by open().
00170 { 00171 int fd; 00172 00173 for ( fd = POSIX_FD_MIN ; fd <= POSIX_FD_MAX ; fd++ ) { 00174 if ( ! posix_fd_to_file ( fd ) ) 00175 return fd; 00176 } 00177 DBG ( "POSIX could not find free file descriptor\n" ); 00178 return -ENFILE; 00179 }
| int open | ( | const char * | uri_string | ) |
Open file.
| uri_string | URI string |
| fd | File descriptor, or negative error number |
Definition at line 187 of file posix_io.c.
References posix_file::data, DBG, EINPROGRESS, ENOMEM, posix_file::fd, refcnt::free, INIT_LIST_HEAD, posix_file::list, list_add, list_empty(), posix_file_finished(), posix_file_free(), posix_find_free_fd(), posix_file::rc, ref_put(), posix_file::refcnt, step(), posix_file::xfer, xfer_init(), xfer_open_uri_string(), and zalloc().
Referenced by int22(), and pxenv_file_open().
00187 { 00188 struct posix_file *file; 00189 int fd; 00190 int rc; 00191 00192 /* Find a free file descriptor to use */ 00193 fd = posix_find_free_fd(); 00194 if ( fd < 0 ) 00195 return fd; 00196 00197 /* Allocate and initialise structure */ 00198 file = zalloc ( sizeof ( *file ) ); 00199 if ( ! file ) 00200 return -ENOMEM; 00201 file->refcnt.free = posix_file_free; 00202 file->fd = fd; 00203 file->rc = -EINPROGRESS; 00204 xfer_init ( &file->xfer, &posix_file_xfer_operations, 00205 &file->refcnt ); 00206 INIT_LIST_HEAD ( &file->data ); 00207 00208 /* Open URI on data transfer interface */ 00209 if ( ( rc = xfer_open_uri_string ( &file->xfer, uri_string ) ) != 0 ) 00210 goto err; 00211 00212 /* Wait for open to succeed or fail */ 00213 while ( list_empty ( &file->data ) ) { 00214 step(); 00215 if ( file->rc == 0 ) 00216 break; 00217 if ( file->rc != -EINPROGRESS ) { 00218 rc = file->rc; 00219 goto err; 00220 } 00221 } 00222 00223 /* Add to list of open files. List takes reference ownership. */ 00224 list_add ( &file->list, &posix_files ); 00225 DBG ( "POSIX opened %s as file %d\n", uri_string, fd ); 00226 return fd; 00227 00228 err: 00229 posix_file_finished ( file, rc ); 00230 ref_put ( &file->refcnt ); 00231 return rc; 00232 }
| int select | ( | fd_set * | readfds, | |
| int | wait | |||
| ) |
Check file descriptors for readiness.
| readfds | File descriptors to check | |
| wait | Wait until data is ready |
| nready | Number of ready file descriptors |
Definition at line 241 of file posix_io.c.
References posix_file::data, EBADF, EINPROGRESS, posix_file::fd, list_empty(), POSIX_FD_MAX, POSIX_FD_MIN, posix_fd_to_file(), posix_file::rc, and step().
Referenced by int22(), and pxenv_file_select().
00241 { 00242 struct posix_file *file; 00243 int fd; 00244 00245 do { 00246 for ( fd = POSIX_FD_MIN ; fd <= POSIX_FD_MAX ; fd++ ) { 00247 if ( ! FD_ISSET ( fd, readfds ) ) 00248 continue; 00249 file = posix_fd_to_file ( fd ); 00250 if ( ! file ) 00251 return -EBADF; 00252 if ( ( list_empty ( &file->data ) ) && 00253 ( file->rc == -EINPROGRESS ) ) 00254 continue; 00255 /* Data is available or status has changed */ 00256 FD_ZERO ( readfds ); 00257 FD_SET ( fd, readfds ); 00258 return 1; 00259 } 00260 step(); 00261 } while ( wait ); 00262 00263 return 0; 00264 }
Read data from file.
| buffer | Data buffer | |
| offset | Starting offset within data buffer | |
| len | Maximum length to read |
| len | Actual length read, or negative error number |
Definition at line 277 of file posix_io.c.
References assert, copy_to_user(), io_buffer::data, posix_file::data, EBADF, EINPROGRESS, EWOULDBLOCK, free_iob(), iob_len(), iob_pull, io_buffer::list, list_del, list_empty(), list_for_each_entry, posix_file::pos, posix_fd_to_file(), posix_file::rc, and step().
Referenced by int22(), and pxenv_file_read().
00277 { 00278 struct posix_file *file; 00279 struct io_buffer *iobuf; 00280 size_t len; 00281 00282 /* Identify file */ 00283 file = posix_fd_to_file ( fd ); 00284 if ( ! file ) 00285 return -EBADF; 00286 00287 /* Try to fetch more data if none available */ 00288 if ( list_empty ( &file->data ) ) 00289 step(); 00290 00291 /* Dequeue at most one received I/O buffer into user buffer */ 00292 list_for_each_entry ( iobuf, &file->data, list ) { 00293 len = iob_len ( iobuf ); 00294 if ( len > max_len ) 00295 len = max_len; 00296 copy_to_user ( buffer, offset, iobuf->data, len ); 00297 iob_pull ( iobuf, len ); 00298 if ( ! iob_len ( iobuf ) ) { 00299 list_del ( &iobuf->list ); 00300 free_iob ( iobuf ); 00301 } 00302 file->pos += len; 00303 assert ( len != 0 ); 00304 return len; 00305 } 00306 00307 /* If file has completed, return (after returning all data) */ 00308 if ( file->rc != -EINPROGRESS ) { 00309 assert ( list_empty ( &file->data ) ); 00310 return file->rc; 00311 } 00312 00313 /* No data ready and file still in progress; return -WOULDBLOCK */ 00314 return -EWOULDBLOCK; 00315 }
| ssize_t fsize | ( | int | fd | ) |
Determine file size.
| fd | File descriptor |
| size | File size, or negative error number |
Definition at line 323 of file posix_io.c.
References EBADF, posix_file::filesize, and posix_fd_to_file().
Referenced by int22(), and pxenv_get_file_size().
00323 { 00324 struct posix_file *file; 00325 00326 /* Identify file */ 00327 file = posix_fd_to_file ( fd ); 00328 if ( ! file ) 00329 return -EBADF; 00330 00331 return file->filesize; 00332 }
| int close | ( | int fd | ) |
Close file.
| fd | File descriptor |
| rc | Return status code |
Definition at line 340 of file posix_io.c.
References EBADF, posix_file::list, list_del, posix_fd_to_file(), posix_file_finished(), ref_put(), and posix_file::refcnt.
Referenced by int22(), and pxenv_file_close().
00340 { 00341 struct posix_file *file; 00342 00343 /* Identify file */ 00344 file = posix_fd_to_file ( fd ); 00345 if ( ! file ) 00346 return -EBADF; 00347 00348 /* Terminate data transfer */ 00349 posix_file_finished ( file, 0 ); 00350 00351 /* Remove from list of open files and drop reference */ 00352 list_del ( &file->list ); 00353 ref_put ( &file->refcnt ); 00354 return 0; 00355 }
struct xfer_interface_operations posix_file_xfer_operations [static] |
Initial value:
{
.close = posix_file_xfer_close,
.vredirect = xfer_vreopen,
.window = unlimited_xfer_window,
.alloc_iob = default_xfer_alloc_iob,
.deliver_iob = posix_file_xfer_deliver_iob,
.deliver_raw = xfer_deliver_as_iob,
}
Definition at line 140 of file posix_io.c.
1.5.7.1