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. More...
 
static void posix_file_free (struct refcnt *refcnt)
 Free open file. More...
 
static void posix_file_finished (struct posix_file *file, int rc)
 Terminate file data transfer. More...
 
static int posix_file_xfer_deliver (struct posix_file *file, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Handle deliver_iob() event. More...
 
static struct posix_fileposix_fd_to_file (int fd)
 Identify file by file descriptor. More...
 
static int posix_find_free_fd (void)
 Find an available file descriptor. More...
 
int open (const char *uri_string)
 Open file. More...
 
int select (fd_set *readfds, int wait)
 Check file descriptors for readiness. More...
 
ssize_t read_user (int fd, userptr_t buffer, off_t offset, size_t max_len)
 Read data from file. More...
 
ssize_t fsize (int fd)
 Determine file size. More...
 
int close (int fd)
 Close file. More...
 

Variables

static struct interface_operation posix_file_xfer_operations []
 POSIX file data transfer interface operations. More...
 
static struct interface_descriptor posix_file_xfer_desc
 POSIX file data transfer interface descriptor. More...
 

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()

static LIST_HEAD ( posix_files  )
static

List of open files.

◆ posix_file_free()

static 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 =
78  container_of ( refcnt, struct posix_file, refcnt );
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 }
An open file.
Definition: posix_io.c:46
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
A reference counter.
Definition: refcnt.h:26
unsigned long tmp
Definition: linux_pci.h:53
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
#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:458
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:40
struct list_head data
Received data queue.
Definition: posix_io.c:65
A persistent I/O buffer.
Definition: iobuf.h:33

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()

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.

95  {
96  intf_shutdown ( &file->xfer, rc );
97  file->rc = rc;
98 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct interface xfer
Data transfer interface.
Definition: posix_io.c:59
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:278
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()

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.

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 }
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition: xfer.h:47
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
int meta(WINDOW *, bool)
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:40
struct list_head data
Received data queue.
Definition: posix_io.c:65
size_t pos
Current seek position.
Definition: posix_io.c:61
size_t filesize
File size.
Definition: posix_io.c:63

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()

static 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 }
struct list_head list
List of open files.
Definition: posix_io.c:50
An open file.
Definition: posix_io.c:46
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
int fd
File descriptor.
Definition: posix_io.c:52
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

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().

◆ posix_find_free_fd()

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.

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 POSIX_FD_MAX
Maximum file descriptor that will ever be allocated.
Definition: posix_io.h:19
#define POSIX_FD_MIN
Minimum file descriptor that will ever be allocated.
Definition: posix_io.h:16
int fd
File descriptor.
Definition: posix_io.c:52
#define ENFILE
Too many open files in system.
Definition: errno.h:493
static struct posix_file * posix_fd_to_file(int fd)
Identify file by file descriptor.
Definition: posix_io.c:144
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498

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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct list_head list
List of open files.
Definition: posix_io.c:50
struct interface xfer
Data transfer interface.
Definition: posix_io.c:59
An open file.
Definition: posix_io.c:46
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
struct refcnt refcnt
Reference count for this object.
Definition: posix_io.c:48
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
#define ENOMEM
Not enough space.
Definition: errno.h:534
#define EINPROGRESS
Operation in progress.
Definition: errno.h:418
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
int fd
File descriptor.
Definition: posix_io.c:52
static void posix_file_finished(struct posix_file *file, int rc)
Terminate file data transfer.
Definition: posix_io.c:95
static void posix_file_free(struct refcnt *refcnt)
Free open file.
Definition: posix_io.c:76
static struct interface_descriptor posix_file_xfer_desc
POSIX file data transfer interface descriptor.
Definition: posix_io.c:135
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
struct list_head data
Received data queue.
Definition: posix_io.c:65
void step(void)
Single-step a single process.
Definition: process.c:98
static int posix_find_free_fd(void)
Find an available file descriptor.
Definition: posix_io.c:159
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:203
int xfer_open_uri_string(struct interface *intf, const char *uri_string)
Open URI string.
Definition: open.c:115
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
int rc
Overall status.
Definition: posix_io.c:57

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 }
An open file.
Definition: posix_io.c:46
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
#define EBADF
Bad file descriptor.
Definition: errno.h:328
#define EINPROGRESS
Operation in progress.
Definition: errno.h:418
#define POSIX_FD_MAX
Maximum file descriptor that will ever be allocated.
Definition: posix_io.h:19
#define POSIX_FD_MIN
Minimum file descriptor that will ever be allocated.
Definition: posix_io.h:16
int fd
File descriptor.
Definition: posix_io.c:52
static struct posix_file * posix_fd_to_file(int fd)
Identify file by file descriptor.
Definition: posix_io.c:144
struct list_head data
Received data queue.
Definition: posix_io.c:65
void step(void)
Single-step a single process.
Definition: process.c:98
int rc
Overall status.
Definition: posix_io.c:57

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_user()

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.

265  {
266  struct posix_file *file;
267  struct io_buffer *iobuf;
268  size_t len;
269 
270  /* Identify file */
271  file = posix_fd_to_file ( fd );
272  if ( ! file )
273  return -EBADF;
274 
275  /* Try to fetch more data if none available */
276  if ( list_empty ( &file->data ) )
277  step();
278 
279  /* Dequeue at most one received I/O buffer into user buffer */
280  list_for_each_entry ( iobuf, &file->data, list ) {
281  len = iob_len ( iobuf );
282  if ( len > max_len )
283  len = max_len;
284  copy_to_user ( buffer, offset, iobuf->data, len );
285  iob_pull ( iobuf, len );
286  if ( ! iob_len ( iobuf ) ) {
287  list_del ( &iobuf->list );
288  free_iob ( iobuf );
289  }
290  file->pos += len;
291  assert ( len != 0 );
292  return len;
293  }
294 
295  /* If file has completed, return (after returning all data) */
296  if ( file->rc != -EINPROGRESS ) {
297  assert ( list_empty ( &file->data ) );
298  return file->rc;
299  }
300 
301  /* No data ready and file still in progress; return -WOULDBLOCK */
302  return -EWOULDBLOCK;
303 }
#define iob_pull(iobuf, len)
Definition: iobuf.h:102
An open file.
Definition: posix_io.c:46
uint16_t max_len
Maximum length (in bytes)
Definition: ntlm.h:18
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition: netvsc.h:16
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define EWOULDBLOCK
Operation would block.
Definition: errno.h:679
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
#define EBADF
Bad file descriptor.
Definition: errno.h:328
#define EINPROGRESS
Operation in progress.
Definition: errno.h:418
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
static __always_inline void copy_to_user(userptr_t dest, off_t dest_off, const void *src, size_t len)
Copy data to user buffer.
Definition: uaccess.h:324
static struct posix_file * posix_fd_to_file(int fd)
Identify file by file descriptor.
Definition: posix_io.c:144
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:40
uint32_t len
Length.
Definition: ena.h:14
struct list_head data
Received data queue.
Definition: posix_io.c:65
void * data
Start of data.
Definition: iobuf.h:48
void step(void)
Single-step a single process.
Definition: process.c:98
size_t pos
Current seek position.
Definition: posix_io.c:61
int rc
Overall status.
Definition: posix_io.c:57
A persistent I/O buffer.
Definition: iobuf.h:33

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

Referenced by int22(), pxenv_file_read(), and read().

◆ fsize()

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.

311  {
312  struct posix_file *file;
313 
314  /* Identify file */
315  file = posix_fd_to_file ( fd );
316  if ( ! file )
317  return -EBADF;
318 
319  return file->filesize;
320 }
An open file.
Definition: posix_io.c:46
#define EBADF
Bad file descriptor.
Definition: errno.h:328
int fd
File descriptor.
Definition: posix_io.c:52
static struct posix_file * posix_fd_to_file(int fd)
Identify file by file descriptor.
Definition: posix_io.c:144
size_t filesize
File size.
Definition: posix_io.c:63

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 328 of file posix_io.c.

328  {
329  struct posix_file *file;
330 
331  /* Identify file */
332  file = posix_fd_to_file ( fd );
333  if ( ! file )
334  return -EBADF;
335 
336  /* Terminate data transfer */
337  posix_file_finished ( file, 0 );
338 
339  /* Remove from list of open files and drop reference */
340  list_del ( &file->list );
341  ref_put ( &file->refcnt );
342  return 0;
343 }
struct list_head list
List of open files.
Definition: posix_io.c:50
An open file.
Definition: posix_io.c:46
struct refcnt refcnt
Reference count for this object.
Definition: posix_io.c:48
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define EBADF
Bad file descriptor.
Definition: errno.h:328
int fd
File descriptor.
Definition: posix_io.c:52
static void posix_file_finished(struct posix_file *file, int rc)
Terminate file data transfer.
Definition: posix_io.c:95
static struct posix_file * posix_fd_to_file(int fd)
Identify file by file descriptor.
Definition: posix_io.c:144
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106

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:249
An open file.
Definition: posix_io.c:46
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
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
static void posix_file_finished(struct posix_file *file, int rc)
Terminate file data transfer.
Definition: posix_io.c:95
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:194

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:
=
struct interface xfer
Data transfer interface.
Definition: posix_io.c:59
An open file.
Definition: posix_io.c:46
static struct interface_operation posix_file_xfer_operations[]
POSIX file data transfer interface operations.
Definition: posix_io.c:129
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:80

POSIX file data transfer interface descriptor.

Definition at line 135 of file posix_io.c.

Referenced by open().