R_IO(3)
π R_IO(3) β Radare2 Input/Output Library API π
okay bestie, welcome to the r_io page from the Library Functions Manual β this is the one that makes radare2 actually talk to files and memory and networks and debuggers, and honestly? it ate. π¦
β¨ NAME β¨
r_io β the Radare2 Input/Output Library API. it's giving "one interface to rule all the backends". π
πΈ SYNOPSIS πΈ
#include <r_io.h>
that's it. that's the vibe check. include the header and you're in. π
π«Ά DESCRIPTION π«Ά
so the r_io library hands you one unified interface for input/output operations in radare2, and it plays nice with a whole bunch of backends: files, memory, network connections, and debuggers. it abstracts away file descriptors, memory mappings, caching, and undo functionality. like, it does the boring plumbing so you don't have to, and that's main character energy fr fr. π₯
Key concepts, and yes you need all of these:
- RIO is the main structure representing an I/O context.
- RIODesc represents an open file or resource descriptor.
- RIOMap defines memory mappings from file offsets to virtual addresses.
- RIOBank groups maps for banked memory architectures.
- Caching allows temporary modifications without altering the underlying data.
no cap, those five are the whole personality of this library. π
π INITIALIZATION π
everyone needs a lil setup moment, and here's yours:
RIO * r_io_new(void)β creates and initializes a new I/O context. it's a fresh start, bestie. β¨void r_io_init(RIO *io)β initializes an existing I/O structure. for when you already have the struct and just need it awake.void r_io_free(RIO *io)β frees an I/O context and all associated resources. clean up after yourself, it's the polite thing to do. π
π FILE OPERATIONS π
the day-to-day. the bread and butter. the way you actually touch bytes:
RIODesc * r_io_open(RIO *io, const char *uri, int perm, int mode)β opens a resource specified by URI with given permissions and mode, and maps it at address0. yes, at zero, automatically, that's the deal. πRIODesc * r_io_open_at(RIO *io, const char *uri, int perm, int mode, ut64 at)β opens a resource and maps it at the specified address. for when address0isn't your era.bool r_io_close(RIO *io)β closes the current descriptor. say bye πbool r_io_read_at(RIO *io, ut64 addr, ut8 *buf, int len)β readslenbytes from virtual addressaddrintobuf.bool r_io_write_at(RIO *io, ut64 addr, const ut8 *buf, int len)β writeslenbytes frombufto virtual addressaddr.ut64 r_io_seek(RIO *io, ut64 offset, int whence)β seeks to the specified offset.whencecan beR_IO_SEEK_SET,R_IO_SEEK_CUR, orR_IO_SEEK_END. pick your direction, girlboss. π§
π¦ MEMORY MAPPING π¦
where files become virtual addresses and everything gets β¨spatialβ¨:
RIOMap * r_io_map_add(RIO *io, int fd, int flags, ut64 delta, ut64 addr, ut64 size)β creates a new memory map from file descriptorfdat virtual addressaddrwith sizesize, starting from file offsetdelta.bool r_io_map_del(RIO *io, ut32 id)β deletes the map with the givenid. gone, reduced to atoms. πRIOMap * r_io_map_get(RIO *io, ut32 id)β retrieves the map with the givenid.RIOMap * r_io_map_get_at(RIO *io, ut64 vaddr)β gets the map covering the virtual addressvaddr. it's giving "which map owns this address" detective work. π
π BANKING π
for the banked memory architecture girlies:
RIOBank * r_io_bank_new(const char *name)β creates a new bank with the givenname.bool r_io_bank_add(RIO *io, RIOBank *bank)β adds a bank to the I/O context.bool r_io_bank_use(RIO *io, ut32 bankid)β switches to the specified bank. switching eras, honestly. π
π CACHING π
temporary modifications, zero commitment. the situationship of I/O:
bool r_io_cache_write_at(RIO *io, ut64 addr, const ut8 *buf, int len)β writes to the cache at the specified address.bool r_io_cache_read_at(RIO *io, ut64 addr, ut8 *buf, int len)β reads from the cache at the specified address.void r_io_cache_commit(RIO *io, ut64 from, ut64 to, bool many)β commits cached changes to the underlying storage. this is the "okay we're official now" moment. π«Ά
β UNDO FUNCTIONALITY β
because sometimes you do a thing and then you're like. no. π
int r_io_undo_init(RIO *io)β initializes undo functionality.void r_io_undo_enable(RIO *io, int seek, int write)β enablesseekand/orwriteundo tracking.void r_io_wundo_new(RIO *io, ut64 off, const ut8 *data, int len)β records a write operation for undo.
π₯ EXAMPLES π₯
here's where it clicks, bestie. real code, real vibes.
Opening and reading a file
RIO *io = r_io_new();
RIODesc *desc = r_io_open(io, "/bin/ls", R_PERM_R, 0);
if (desc) {
ut8 buf[64];
r_io_read_at(io, 0, buf, sizeof(buf));
}
r_io_free(io);
Creating a memory map
RIO *io = r_io_new();
RIODesc *desc = r_io_open_nomap(io, "malloc://1024", R_PERM_RW, 0);
if (desc) {
RIOMap *map = r_io_map_add(io, desc->fd, R_PERM_RW, 0, 0x1000, 1024);
}
r_io_free(io);
Using cache for temporary modifications
RIO *io = r_io_new();
r_io_open(io, "file.bin", R_PERM_RW, 0);
ut8 data[] = {0x90, 0x90}; // NOP NOP
r_io_cache_write_at(io, 0x100, data, 2);
// Changes are cached, not written to file yet
r_io_cache_commit(io, 0x100, 0x102, false);
// Now changes are committed
r_io_free(io);
π SEE ALSO π
go read these next, they're all in the group chat:
π AUTHORS π
The radare2 project team. kings, honestly. π
one last thing bestie: this page shipped with the Debian build, dated September 20, 2025, and it lives under the manual name R_IO(3). that's the footer, and now you know it. slay, go write some bytes. π β¨
π¦ where this page comes from
- alpine 3.24: radare2-doc 6.1.6-r0 Β· GPL-3.0-or-later AND LGPL-2.0-or-later AND LGPL-2.1-or-later
- arch rolling: radare2 6.2.2-1 Β· GPL-3.0-only AND LGPL-3.0-only
- nixos 26.05: radare2 6.1.8
- nixpkgs unstable: radare2 6.2.4
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- ubuntu resolute: radare2 6.0.7+ds-1 Β· LGPL-3.0-only
- ubuntu stonking: radare2 6.1.8+ds-1 Β· LGPL-3.0-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms