15 Ports and the Filesystem
Ports are represented as Racket values with the types scheme_input_port_type and scheme_output_port_type. The function scheme_read takes an input port value and returns the next S-expression from the port. The function scheme_write takes an output port and a value and writes the value to the port. Other standard low-level port functions are also provided, such as scheme_getc.
File ports are created with scheme_make_file_input_port and scheme_make_file_output_port; these functions take a FILE * file pointer and return a Scheme port. Strings are read or written with scheme_make_byte_string_input_port, which takes a nul-terminated byte string, and scheme_make_byte_string_output_port, which takes no arguments. The contents of a string output port are obtained with scheme_get_byte_string_output.
Custom ports, with arbitrary read/write handlers, are created with scheme_make_input_port and scheme_make_output_port.
When opening a file for any reason using a name provided from Racket, use scheme_expand_filename to normalize the filename and resolve relative paths.
|
|
|
|
|
|
|
|
If rarely_block is 0, the write blocks until all len bytes are written, possibly to an internal buffer. If rarely_block is 2, the write never blocks, and written bytes are not buffered. If rarely_block is 1, the write blocks only until at least one byte is written (without buffering) or until part of an internal buffer is flushed.
Supplying 0 for len corresponds to a buffer-flush request. If rarely_block is 2, the flush request is non-blocking, and if rarely_block is 0, it is blocking. (A rarely_block of 1 is the same as 0 in this case.)
The result is -1 if no bytes are written from str and unflushed bytes remain in the internal buffer. Otherwise, the return value is the number of written characters.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If only_avail is 0, then the function blocks until size bytes are read or an end-of-file is reached. If only_avail is 1, the function blocks only until at least one byte is read. If only_avail is 2, the function never blocks. If only_avail is -1, the function blocks only until at least one byte is read but also allows breaks (with the guarantee that bytes are read or a break is raised, but not both).
If peek is non-zero, then the port is peeked instead of read. The peek_skip argument indicates a portion of the input stream to skip as a non-negative, exact integer (fixnum or bignum). In this case, an only_avail value of 1 means to continue the skip until at least one byte can be returned, even if it means multiple blocking reads to skip bytes.
If peek is zero, then peek_skip should be either NULL (which means zero) or the fixnum zero.
|
|
|
Use scheme_get_byte followed by scheme_ungetc only when your program will certainly call scheme_get_byte again to consume the byte. Otherwise, use scheme_peek_byte, because some a port may implement peeking and getting differently.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If must_close is non-zero, the new port will be registered with the current custodian, and close_fun is guaranteed to be called before the port is garbage-collected.
Although the return type of scheme_make_input_port is Scheme_Input_Port*, it can be cast into a Scheme_Object*.
The functions are as follows.
intptr_t
get_bytes_fun
(
Scheme_Input_Port* port,
char* buffer,
intptr_t offset,
intptr_t size,
int nonblock,
Scheme_Object* unless)
Reads bytes into buffer, starting from offset, up to size bytes (i.e., buffer is at least offset plus size long). If nonblock is 0, then the function can block indefinitely, but it should return when at least one byte of data is available. If nonblock is 1, the function should never block. If nonblock is 2, a port in unbuffered mode should return only bytes previously forced to be buffered; other ports should treat a nonblock of 2 like 1. If nonblock is -1, the function can block, but should enable breaks while blocking. The function should return 0 if no bytes are ready in non-blocking mode. It should return EOF if an end-of-file is reached (and no bytes were read into buffer). Otherwise, the function should return the number of read bytes. The function can raise an exception to report an error.The unless argument will be non-NULL only when nonblocking is non-zero (except as noted below), and only if the port supports progress events. If unless is non-NULL and SCHEME_CDR(unless) is non-NULL, the latter is a progress event specific to the port. The get_bytes_fun function should return SCHEME_UNLESS_READY instead of reading bytes if the event in unless becomes ready before bytes can be read. In particular, get_bytes_fun should check the event in unless before taking any action, and it should check the event in unless after any operation that may allow Racket thread swaps. If the read must block, then it should unblock if the event in unless becomes ready.
If scheme_progress_evt_via_get is used for progress_evt_fun, then unless can be non-NULL even when nonblocking is 0. In all modes, get_bytes_fun must call scheme_unless_ready to check unless_evt. Furthermore, after any potentially thread-swapping operation, get_bytes_fun must call scheme_wait_input_allowed, because another thread may be attempting to commit, and unless_evt must be checked after scheme_wait_input_allowed returns. To block, the port should use scheme_block_until_unless instead of scheme_block_until. Finally, in blocking mode, get_bytes_fun must return after immediately reading data, without allowing a Racket thread swap.
intptr_t
peek_bytes_fun
(
Scheme_Input_Port* port,
char* buffer,
intptr_t offset,
intptr_t size,
Scheme_Object* skip,
int nonblock,
Scheme_Object* unless_evt)
Can be NULL to use a default implementation of peeking that uses get_bytes_fun. Otherwise, the protocol is the same as for get_bytes_fun, except that an extra skip argument indicates the number of input elements to skip (but skip does not apply to buffer). The skip value will be a non-negative exact integer, either a fixnum or a bignum.
Scheme_Object*
progress_evt_fun
(
Scheme_Input_Port* port)
Called to obtain a progress event for the port, such as for port-progress-evt. This function can be NULL if the port does not support progress events. Use scheme_progress_evt_via_get to obtain a default implementation, in which case peeked_read_fun should be scheme_peeked_read_via_get, and get_bytes_fun and peek_bytes_fun should handle unless as described above.
int
peeked_read_fun
(
Scheme_Input_Port* port,
intptr_t amount,
Scheme_Object* unless_evt,
Scheme_Object* target_ch)
Called to commit previously peeked bytes, just like the sixth argument to make-input-port. Use scheme_peeked_read_via_get for the default implementation of commits when progress_evt_fun is scheme_progress_evt_via_get.The peeked_read_fun function must call scheme_port_count_lines on a successful commit to adjust the port’s position. If line counting is enabled for the port and if line counting uses the default implementation, peeked_read_fun should supply a non-NULL byte-string argument to scheme_port_count_lines, so that character and line counts can be tracked correctly.
int
char_ready_fun
(
Scheme_Input_Port* port)
Returns 1 when a non-blocking get_bytes_fun will return bytes or an EOF.
void
close_fun
(
Scheme_Input_Port* port)
Called to close the port. The port is not considered closed until the function returns.
void
need_wakeup_fun
(
Scheme_Input_Port* port,
void* fds)
Called when the port is blocked on a read; need_wakeup_fun should set appropriate bits in fds to specify which file descriptor(s) it is blocked on. The fds argument is conceptually an array of three fd_set structs (one for read, one for write, one for exceptions), but manipulate this array using scheme_get_fdset to get a particular element of the array, and use MZ_FD_XXX instead of FD_XXX to manipulate a single “fd_set”. On Windows, the first “fd_set” can also contain OS-level semaphores or other handles via scheme_add_fd_handle.
|
If must_close is non-zero, the new port will be registered with the current custodian, and close_fun is guaranteed to be called before the port is garbage-collected.
Although the return type of scheme_make_output_port is Scheme_Output_Port*, it can be cast into a Scheme_Object*.
The functions are as follows.
intptr_t
write_bytes_evt_fun
(
Scheme_Output_Port* port,
const char* buffer,
intptr_t offset,
intptr_t size)
Returns an event that writes up to size bytes atomically when event is chosen in a synchronization. Supply NULL if bytes cannot be written atomically, or supply scheme_write_evt_via_write to use the default implementation in terms of write_bytes_fun (with rarely_block as 2).
intptr_t
write_bytes_fun
(
Scheme_Output_Port* port,
const char* buffer,
intptr_t offset,
intptr_t size,
int rarely_block,
int enable_break)
Write bytes from buffer, starting from offset, up to size bytes (i.e., buffer is at least offset plus size long). If rarely_block is 0, then the function can block indefinitely, and it can buffer output. If rarely_block is 2, the function should never block, and it should not buffer output. If rarely_block is 1, the function should not buffer data, and it should block only until writing at least one byte, either from buffer or an internal buffer. The function should return the number of bytes from buffer that were written; when rarely_block is non-zero and bytes remain in an internal buffer, it should return -1. The size argument can be 0 when rarely_block is 0 for a blocking flush, and it can be 0 if rarely_block is 2 for a non-blocking flush. If enable_break is true, then it should enable breaks while blocking. The function can raise an exception to report an error.
int
char_ready_fun
(
Scheme_Output_Port* port)
Returns 1 when a non-blocking write_bytes_fun will write at least one byte or flush at least one byte from the port’s internal buffer.
void
close_fun
(
Scheme_Output_Port* port)
Called to close the port. The port is not considered closed until the function returns. This function is allowed to block (usually to flush a buffer) unless scheme_close_should_force_port_closed returns a non-zero result, in which case the function must return without blocking.
void
need_wakeup_fun
(
Scheme_Output_Port* port,
void* fds)
Called when the port is blocked on a write; need_wakeup_fun should set appropriate bits in fds to specify which file descriptor(s) it is blocked on. The fds argument is conceptually an array of three fd_set structs (one for read, one for write, one for exceptions), but manipulate this array using scheme_get_fdset to get a particular element of the array, and use MZ_FD_XXX instead of FD_XXX to manipulate a single “fd_set”. On Windows, the first “fd_set” can also contain OS-level semaphores or other handles via scheme_add_fd_handle.
int
write_special_evt_fun
(
Scheme_Output_Port* port,
Scheme_Object* v)
Returns an event that writes v atomically when event is chosen in a synchronization. Supply NULL if specials cannot be written atomically (or at all), or supply scheme_write_special_evt_via_write_special to use the default implementation in terms of write_special_fun (with non_block as 1).
int
write_special_fun
(
Scheme_Output_Port* port,
Scheme_Object* v,
int non_block)
Called to write the special value v for write-special (when non_block is 0) or write-special-avail* (when non_block is 1). If NULL is supplied instead of a function pointer, then write-special and write-special-avail* produce an error for this port.
|
Scheme_Object*
location_fun
(
Scheme_Port* port)
Returns three values: a positive exact integer or #f for a line number, a non-negative exact integer or #f for a column (which must be #f if and only if the line number is #f), and a positive exact integer or #f for a character position.
|
void
count_lines_fun
(
Scheme_Port* port)
|
The got argument indicates the number of bytes read from or written to port. The buffer argument is used only when line counting is enabled, and it represents specific bytes read or written for the purposes of character and line coutning. The buffer argument can be NULL, in which case got non-newline characters are assumed. The offset argument indicates a starting offset into buffer, so "buffer" must be at least offset plus got bytes long.
|
|
|
|
|
|
The name object is used for the port’s name. Specify a non-zero value for regfile only if the file descriptor corresponds to a regular file (which implies that reading never blocks, for example).
On Windows, win_textmode can be non-zero to make trigger auto-conversion (at the byte level) of CRLF combinations to LF.
Closing the resulting port closes the file descriptor.
Instead of calling both scheme_make_fd_input_port and scheme_make_fd_output_port on the same file descriptor, call scheme_make_fd_output_port with a non-zero last argument. Otherwise, closing one of the ports causes the file descriptor used by the other to be closed as well.
|
The name object is used for the port’s name. Specify a non-zero value for regfile only if the file descriptor corresponds to a regular file (which implies that reading never blocks, for example).
On Windows, win_textmode can be non-zero to make trigger auto-conversion (at the byte level) of CRLF combinations to LF.
Closing the resulting port closes the file descriptor.
If read_too is non-zero, the function produces multiple values (see Multiple Values) instead of a single port. The first result is an input port for fd, and the second is an output port for fd. These ports are connected in that the file descriptor is closed only when both of the ports are closed.
|
|
The mode argument is one of the following:
MZFD_CREATE_READ (= 1) —
creates or finds a semaphore to reflect whether fd is ready for reading. MZFD_CREATE_WRITE (= 2) —
creates or finds a semaphore to reflect whether fd is ready for writing. MZFD_CHECK_READ (= 3) —
finds a semaphore to reflect whether fd is ready for reading; the result is NULL if no semaphore was previously created for fd in read mode or if such a semaphore has been posted or removed. MZFD_CHECK_WRITE (= 4) —
like MZFD_CREATE_READ, but for write mode. MZFD_REMOVE (= 5) —
removes all recorded semaphores for fd (unregistering a poll with the operating system) and returns NULL. MZFD_CREATE_VNODE (= 6) —
creates or finds a semaphore to reflect whether fd changes; on some platforms, MZFD_CREATE_VNODE is the same as MZFD_CREATE_READ; on other platforms, only one or the other can be used on a given file descriptor. MZFD_CHECK_VNODE (= 7) —
like MZFD_CHECK_READ, but to find a semaphore recorded via MZFD_CREATE_VNODE. MZFD_REMOVE_VNODE (= 8) —
like MZFD_REMOVE, but to remove a semaphore recorded via MZFD_CREATE_VNODE.
|
|
|
|
|
|
|
|
|
|
|
If guards is not 0, then scheme_security_check_file (see Security Guards) is called with name, where, and checks (which implies that where should never be NULL unless guards is 0). Normally, guards should be SCHEME_GUARD_FILE_EXISTS at a minimum. Note that a failed access check will result in an exception.
|
|
|
|
|
|
|
|
|
|
The directory path is written into buf, of length buflen, if it fits. Otherwise, a new (collectable) string is allocated for the directory path. If actlen is not NULL, *actlen is set to the length of the current directory path. If noexn is no 0, then an exception is raised if the operation fails.
|
If noexn is not 0, then an exception is raised if the operation fails.
|
|
|
|