iPXE
Data Structures | Functions | Variables
posix_io.c File Reference

POSIX-like I/O. More...

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ipxe/list.h>
#include <ipxe/iobuf.h>
#include <ipxe/xfer.h>
#include <ipxe/open.h>
#include <ipxe/process.h>
#include <ipxe/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_OR_UBDL)
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 int posix_file_xfer_deliver (struct posix_file *file, 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 interface_operation posix_file_xfer_operations []
 POSIX file data transfer interface operations.
static struct interface_descriptor posix_file_xfer_desc
 POSIX file data transfer interface descriptor.

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 iPXE codebase.

Definition in file posix_io.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static LIST_HEAD ( posix_files  ) [static]

List of open files.

static void posix_file_free ( struct refcnt refcnt) [static]

Free open file.

Parameters:
refcntReference counter

Definition at line 76 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().

                                                      {
        struct posix_file *file =
                container_of ( refcnt, struct posix_file, refcnt );
        struct io_buffer *iobuf;
        struct io_buffer *tmp;

        list_for_each_entry_safe ( iobuf, tmp, &file->data, list ) {
                list_del ( &iobuf->list );
                free_iob ( iobuf );
        }
        free ( file );
}
static void posix_file_finished ( struct posix_file file,
int  rc 
) [static]

Terminate file data transfer.

Parameters:
filePOSIX file
rcReason for termination

Definition at line 95 of file posix_io.c.

References intf_shutdown(), posix_file::rc, rc, and posix_file::xfer.

Referenced by close(), and open().

                                                                    {
        intf_shutdown ( &file->xfer, rc );
        file->rc = rc;
}
static int posix_file_xfer_deliver ( struct posix_file file,
struct io_buffer iobuf,
struct xfer_metadata meta 
) [static]

Handle deliver_iob() event.

Parameters:
filePOSIX file
iobufI/O buffer
metaData transfer metadata
Return values:
rcReturn status code

Definition at line 108 of file posix_io.c.

References posix_file::data, posix_file::filesize, xfer_metadata::flags, free_iob(), iob_len(), io_buffer::list, list_add_tail, xfer_metadata::offset, posix_file::pos, and XFER_FL_ABS_OFFSET.

                                                                  {

        /* Keep track of file position solely for the filesize */
        if ( meta->flags & XFER_FL_ABS_OFFSET )
                file->pos = 0;
        file->pos += meta->offset;
        if ( file->filesize < file->pos )
                file->filesize = file->pos;

        if ( iob_len ( iobuf ) ) {
                list_add_tail ( &iobuf->list, &file->data );
        } else {
                free_iob ( iobuf );
        }

        return 0;
}
static struct posix_file* posix_fd_to_file ( int  fd) [static, read]

Identify file by file descriptor.

Parameters:
fdFile descriptor
Return values:
fileCorresponding file, or NULL

Definition at line 144 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().

                                                       {
        struct posix_file *file;

        list_for_each_entry ( file, &posix_files, list ) {
                if ( file->fd == fd )
                        return file;
        }
        return NULL;
}
static int posix_find_free_fd ( void  ) [static]

Find an available file descriptor.

Return values:
fdFile descriptor, or negative error number

Definition at line 159 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().

                                       {
        int fd;

        for ( fd = POSIX_FD_MIN ; fd <= POSIX_FD_MAX ; fd++ ) {
                if ( ! posix_fd_to_file ( fd ) )
                        return fd;
        }
        DBG ( "POSIX could not find free file descriptor\n" );
        return -ENFILE;
}
int open ( const char *  uri_string)

Open file.

Parameters:
uri_stringURI string
Return values:
fdFile descriptor, or negative error number

Definition at line 176 of file posix_io.c.

References posix_file::data, DBG, EINPROGRESS, ENOMEM, posix_file::fd, INIT_LIST_HEAD, intf_init(), posix_file::list, list_add, list_empty, posix_file_finished(), posix_file_free(), posix_find_free_fd(), posix_file::rc, rc, ref_init, ref_put, posix_file::refcnt, step(), posix_file::xfer, xfer_open_uri_string(), and zalloc().

Referenced by int22(), peerdist_discovery_reply_values(), and pxenv_file_open().

                                    {
        struct posix_file *file;
        int fd;
        int rc;

        /* Find a free file descriptor to use */
        fd = posix_find_free_fd();
        if ( fd < 0 )
                return fd;

        /* Allocate and initialise structure */
        file = zalloc ( sizeof ( *file ) );
        if ( ! file )
                return -ENOMEM;
        ref_init ( &file->refcnt, posix_file_free );
        file->fd = fd;
        file->rc = -EINPROGRESS;
        intf_init ( &file->xfer, &posix_file_xfer_desc, &file->refcnt );
        INIT_LIST_HEAD ( &file->data );

        /* Open URI on data transfer interface */
        if ( ( rc = xfer_open_uri_string ( &file->xfer, uri_string ) ) != 0 )
                goto err;

        /* Wait for open to succeed or fail */
        while ( list_empty ( &file->data ) ) {
                step();
                if ( file->rc == 0 )
                        break;
                if ( file->rc != -EINPROGRESS ) {
                        rc = file->rc;
                        goto err;
                }
        }

        /* Add to list of open files.  List takes reference ownership. */
        list_add ( &file->list, &posix_files );
        DBG ( "POSIX opened %s as file %d\n", uri_string, fd );
        return fd;

 err:
        posix_file_finished ( file, rc );
        ref_put ( &file->refcnt );
        return rc;
}
int select ( fd_set readfds,
int  wait 
)

Check file descriptors for readiness.

Parameters:
readfdsFile descriptors to check
waitWait until data is ready
Return values:
nreadyNumber of ready file descriptors

Definition at line 229 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().

                                         {
        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;
}
ssize_t read_user ( int  fd,
userptr_t  buffer,
off_t  offset,
size_t  max_len 
)

Read data from file.

Parameters:
bufferData buffer
offsetStarting offset within data buffer
lenMaximum length to read
Return values:
lenActual 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 265 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, len, io_buffer::list, list_del, list_empty, list_for_each_entry, max_len, posix_file::pos, posix_fd_to_file(), posix_file::rc, and step().

Referenced by int22(), and pxenv_file_read().

                                                                             {
        struct posix_file *file;
        struct io_buffer *iobuf;
        size_t len;

        /* Identify file */
        file = posix_fd_to_file ( fd );
        if ( ! file )
                return -EBADF;

        /* 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 );
                }
                file->pos += len;
                assert ( len != 0 );
                return len;
        }

        /* If file has completed, return (after returning all data) */
        if ( file->rc != -EINPROGRESS ) {
                assert ( list_empty ( &file->data ) );
                return file->rc;
        }

        /* No data ready and file still in progress; return -WOULDBLOCK */
        return -EWOULDBLOCK;
}
ssize_t fsize ( int  fd)

Determine file size.

Parameters:
fdFile descriptor
Return values:
sizeFile size, or negative error number

Definition at line 311 of file posix_io.c.

References EBADF, posix_file::filesize, and posix_fd_to_file().

Referenced by int22(), and pxenv_get_file_size().

                         {
        struct posix_file *file;

        /* Identify file */
        file = posix_fd_to_file ( fd );
        if ( ! file )
                return -EBADF;

        return file->filesize;
}
int close ( int  fd)

Close file.

Parameters:
fdFile descriptor
Return values:
rcReturn status code

Definition at line 328 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(), ntp_deliver(), peerdist_discovery_reply_values(), and pxenv_file_close().

                     {
        struct posix_file *file;

        /* Identify file */
        file = posix_fd_to_file ( fd );
        if ( ! file )
                return -EBADF;

        /* Terminate data transfer */
        posix_file_finished ( file, 0 );

        /* Remove from list of open files and drop reference */
        list_del ( &file->list );
        ref_put ( &file->refcnt );
        return 0;
}

Variable Documentation

Initial value:

POSIX file data transfer interface operations.

Definition at line 129 of file posix_io.c.

Initial value:

POSIX file data transfer interface descriptor.

Definition at line 135 of file posix_io.c.