iPXE
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 (int fd, void *buf, 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()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ LIST_HEAD()

LIST_HEAD ( posix_files )
static

List of open files.

◆ posix_file_free()

void posix_file_free ( struct refcnt * refcnt)
static

Free open file.

Parameters
refcntReference counter

Definition at line 76 of file posix_io.c.

76 {
77 struct posix_file *file =
79 struct io_buffer *iobuf;
80 struct io_buffer *tmp;
81
82 list_for_each_entry_safe ( iobuf, tmp, &file->data, list ) {
83 list_del ( &iobuf->list );
84 free_iob ( iobuf );
85 }
86 free ( file );
87}
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
A persistent I/O buffer.
Definition iobuf.h:38
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:45
An open file.
Definition posix_io.c:46
struct list_head data
Received data queue.
Definition posix_io.c:65
A reference counter.
Definition refcnt.h:27

References container_of, posix_file::data, free, free_iob(), io_buffer::list, list_del, list_for_each_entry_safe, and tmp.

Referenced by open().

◆ posix_file_finished()

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.

95 {
96 intf_shutdown ( &file->xfer, rc );
97 file->rc = rc;
98}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
struct interface xfer
Data transfer interface.
Definition posix_io.c:59
int rc
Overall status.
Definition posix_io.c:57

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

Referenced by close(), and open().

◆ posix_file_xfer_deliver()

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.

110 {
111
112 /* Keep track of file position solely for the filesize */
113 if ( meta->flags & XFER_FL_ABS_OFFSET )
114 file->pos = 0;
115 file->pos += meta->offset;
116 if ( file->filesize < file->pos )
117 file->filesize = file->pos;
118
119 if ( iob_len ( iobuf ) ) {
120 list_add_tail ( &iobuf->list, &file->data );
121 } else {
122 free_iob ( iobuf );
123 }
124
125 return 0;
126}
uint8_t meta
Metadata flags.
Definition ena.h:3
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
size_t filesize
File size.
Definition posix_io.c:63
size_t pos
Current seek position.
Definition posix_io.c:61
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition xfer.h:48

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

◆ posix_fd_to_file()

struct posix_file * posix_fd_to_file ( int fd)
static

Identify file by file descriptor.

Parameters
fdFile descriptor
Return values
fileCorresponding file, or NULL

Definition at line 144 of file posix_io.c.

144 {
145 struct posix_file *file;
146
147 list_for_each_entry ( file, &posix_files, list ) {
148 if ( file->fd == fd )
149 return file;
150 }
151 return NULL;
152}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
int fd
File descriptor.
Definition posix_io.c:52
struct list_head list
List of open files.
Definition posix_io.c:50

References posix_file::fd, posix_file::list, list_for_each_entry, and NULL.

Referenced by close(), fsize(), posix_find_free_fd(), read(), and select().

◆ posix_find_free_fd()

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.

159 {
160 int fd;
161
162 for ( fd = POSIX_FD_MIN ; fd <= POSIX_FD_MAX ; fd++ ) {
163 if ( ! posix_fd_to_file ( fd ) )
164 return fd;
165 }
166 DBG ( "POSIX could not find free file descriptor\n" );
167 return -ENFILE;
168}
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define ENFILE
Too many open files in system.
Definition errno.h:494
static struct posix_file * posix_fd_to_file(int fd)
Identify file by file descriptor.
Definition posix_io.c:144
#define POSIX_FD_MAX
Maximum file descriptor that will ever be allocated.
Definition posix_io.h:18
#define POSIX_FD_MIN
Minimum file descriptor that will ever be allocated.
Definition posix_io.h:15

References DBG, ENFILE, posix_file::fd, POSIX_FD_MAX, POSIX_FD_MIN, and posix_fd_to_file().

Referenced by open().

◆ open()

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.

176 {
177 struct posix_file *file;
178 int fd;
179 int rc;
180
181 /* Find a free file descriptor to use */
183 if ( fd < 0 )
184 return fd;
185
186 /* Allocate and initialise structure */
187 file = zalloc ( sizeof ( *file ) );
188 if ( ! file )
189 return -ENOMEM;
190 ref_init ( &file->refcnt, posix_file_free );
191 file->fd = fd;
192 file->rc = -EINPROGRESS;
193 intf_init ( &file->xfer, &posix_file_xfer_desc, &file->refcnt );
194 INIT_LIST_HEAD ( &file->data );
195
196 /* Open URI on data transfer interface */
197 if ( ( rc = xfer_open_uri_string ( &file->xfer, uri_string ) ) != 0 )
198 goto err;
199
200 /* Wait for open to succeed or fail */
201 while ( list_empty ( &file->data ) ) {
202 step();
203 if ( file->rc == 0 )
204 break;
205 if ( file->rc != -EINPROGRESS ) {
206 rc = file->rc;
207 goto err;
208 }
209 }
210
211 /* Add to list of open files. List takes reference ownership. */
212 list_add ( &file->list, &posix_files );
213 DBG ( "POSIX opened %s as file %d\n", uri_string, fd );
214 return fd;
215
216 err:
217 posix_file_finished ( file, rc );
218 ref_put ( &file->refcnt );
219 return rc;
220}
#define ENOMEM
Not enough space.
Definition errno.h:535
#define EINPROGRESS
Operation in progress.
Definition errno.h:419
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
int xfer_open_uri_string(struct interface *intf, const char *uri_string)
Open URI string.
Definition open.c:116
static int posix_find_free_fd(void)
Find an available file descriptor.
Definition posix_io.c:159
static struct interface_descriptor posix_file_xfer_desc
POSIX file data transfer interface descriptor.
Definition posix_io.c:135
static void posix_file_free(struct refcnt *refcnt)
Free open file.
Definition posix_io.c:76
static void posix_file_finished(struct posix_file *file, int rc)
Terminate file data transfer.
Definition posix_io.c:95
void step(void)
Single-step a single process.
Definition process.c:99
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
struct refcnt refcnt
Reference count for this object.
Definition posix_io.c:48

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_file_xfer_desc, 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(), pxenv_file_open(), vmbus_open(), and xve_update_state().

◆ select()

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.

229 {
230 struct posix_file *file;
231 int fd;
232
233 do {
234 for ( fd = POSIX_FD_MIN ; fd <= POSIX_FD_MAX ; fd++ ) {
235 if ( ! FD_ISSET ( fd, readfds ) )
236 continue;
237 file = posix_fd_to_file ( fd );
238 if ( ! file )
239 return -EBADF;
240 if ( ( list_empty ( &file->data ) ) &&
241 ( file->rc == -EINPROGRESS ) )
242 continue;
243 /* Data is available or status has changed */
244 FD_ZERO ( readfds );
245 FD_SET ( fd, readfds );
246 return 1;
247 }
248 step();
249 } while ( wait );
250
251 return 0;
252}
#define EBADF
Bad file descriptor.
Definition errno.h:329

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(), pxenv_file_select(), and show_menu().

◆ read()

ssize_t read ( int fd,
void * buf,
size_t max_len )

Read data from file.

Parameters
bufData buffer
max_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 264 of file posix_io.c.

264 {
265 struct posix_file *file;
266 struct io_buffer *iobuf;
267 size_t len;
268
269 /* Identify file */
270 file = posix_fd_to_file ( fd );
271 if ( ! file )
272 return -EBADF;
273
274 /* Try to fetch more data if none available */
275 if ( list_empty ( &file->data ) )
276 step();
277
278 /* Dequeue at most one received I/O buffer into user buffer */
279 list_for_each_entry ( iobuf, &file->data, list ) {
280 len = iob_len ( iobuf );
281 if ( len > max_len )
282 len = max_len;
283 memcpy ( buf, iobuf->data, len );
284 iob_pull ( iobuf, len );
285 if ( ! iob_len ( iobuf ) ) {
286 list_del ( &iobuf->list );
287 free_iob ( iobuf );
288 }
289 file->pos += len;
290 assert ( len != 0 );
291 return len;
292 }
293
294 /* If file has completed, return (after returning all data) */
295 if ( file->rc != -EINPROGRESS ) {
296 assert ( list_empty ( &file->data ) );
297 return file->rc;
298 }
299
300 /* No data ready and file still in progress; return -WOULDBLOCK */
301 return -EWOULDBLOCK;
302}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
ring len
Length.
Definition dwmac.h:226
#define EWOULDBLOCK
Operation would block.
Definition errno.h:680
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define iob_pull(iobuf, len)
Definition iobuf.h:107
void * data
Start of data.
Definition iobuf.h:53

References assert, 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, memcpy(), posix_file::pos, posix_fd_to_file(), posix_file::rc, and step().

◆ fsize()

ssize_t fsize ( int fd)

Determine file size.

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

Definition at line 310 of file posix_io.c.

310 {
311 struct posix_file *file;
312
313 /* Identify file */
314 file = posix_fd_to_file ( fd );
315 if ( ! file )
316 return -EBADF;
317
318 return file->filesize;
319}

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

Referenced by int22(), and pxenv_get_file_size().

◆ close()

int close ( int fd)

Close file.

Parameters
fdFile descriptor
Return values
rcReturn status code

Definition at line 327 of file posix_io.c.

327 {
328 struct posix_file *file;
329
330 /* Identify file */
331 file = posix_fd_to_file ( fd );
332 if ( ! file )
333 return -EBADF;
334
335 /* Terminate data transfer */
336 posix_file_finished ( file, 0 );
337
338 /* Remove from list of open files and drop reference */
339 list_del ( &file->list );
340 ref_put ( &file->refcnt );
341 return 0;
342}

References EBADF, posix_file::fd, posix_file::list, list_del, posix_fd_to_file(), posix_file_finished(), ref_put, and posix_file::refcnt.

Variable Documentation

◆ posix_file_xfer_operations

struct interface_operation posix_file_xfer_operations[]
static
Initial value:
= {
}
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
static int posix_file_xfer_deliver(struct posix_file *file, struct io_buffer *iobuf, struct xfer_metadata *meta)
Handle deliver_iob() event.
Definition posix_io.c:108
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195

POSIX file data transfer interface operations.

Definition at line 129 of file posix_io.c.

◆ posix_file_xfer_desc

struct interface_descriptor posix_file_xfer_desc
static
Initial value:
=
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static struct interface_operation posix_file_xfer_operations[]
POSIX file data transfer interface operations.
Definition posix_io.c:129

POSIX file data transfer interface descriptor.

Definition at line 135 of file posix_io.c.

Referenced by open().