posix_io.c File Reference

POSIX-like I/O. More...

#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_fileposix_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.


Detailed Description

POSIX-like I/O.

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.


Function Documentation

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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
xfer POSIX file data transfer interface
iobuf I/O buffer
meta Data transfer metadata
Return values:
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.

Parameters:
fd File descriptor
Return values:
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.

Return values:
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.

Parameters:
uri_string URI string
Return values:
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.

Parameters:
readfds File descriptors to check
wait Wait until data is ready
Return values:
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 }

ssize_t read_user ( int  fd,
userptr_t  buffer,
off_t  offset,
size_t  max_len 
)

Read data from file.

Parameters:
buffer Data buffer
offset Starting offset within data buffer
len Maximum length to read
Return values:
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.

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.

Parameters:
fd File descriptor
Return values:
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.

Parameters:
fd File descriptor
Return values:
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 }


Variable Documentation

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,
}
POSIX file data transfer interface operations.

Definition at line 140 of file posix_io.c.


Generated on Tue Apr 6 20:01:14 2010 for gPXE by  doxygen 1.5.7.1