Rizin
unix-like reverse engineering framework and cli tools
file_io.h File Reference

I/O types and functions. More...

Go to the source code of this file.

Classes

union  io_buf
 
struct  file_pair
 

Macros

#define IO_BUFFER_SIZE   8192
 

Functions

void io_init (void)
 Initialize the I/O module. More...
 
void io_write_to_user_abort_pipe (void)
 Write a byte to user_abort_pipe[1]. More...
 
void io_no_sparse (void)
 Disable creation of sparse files when decompressing. More...
 
file_pairio_open_src (const char *src_name)
 Open the source file. More...
 
bool io_open_dest (file_pair *pair)
 Open the destination file. More...
 
void io_close (file_pair *pair, bool success)
 Closes the file descriptors and frees possible allocated memory. More...
 
size_t io_read (file_pair *pair, io_buf *buf, size_t size)
 Reads from the source file to a buffer. More...
 
void io_fix_src_pos (file_pair *pair, size_t rewind_size)
 Fix the position in src_fd. More...
 
bool io_pread (file_pair *pair, io_buf *buf, size_t size, off_t pos)
 Read from source file from given offset to a buffer. More...
 
bool io_write (file_pair *pair, const io_buf *buf, size_t size)
 Writes a buffer to the destination file. More...
 

Detailed Description

I/O types and functions.

Definition in file file_io.h.

Macro Definition Documentation

◆ IO_BUFFER_SIZE

#define IO_BUFFER_SIZE   8192

Definition at line 16 of file file_io.h.

Function Documentation

◆ io_close()

void io_close ( file_pair pair,
bool  success 
)

Closes the file descriptors and frees possible allocated memory.

The success argument determines if source or destination file gets unlinked:

  • false: The destination file is unlinked.
  • true: The source file is unlinked unless writing to stdout or –keep was used.

Definition at line 1052 of file file_io.c.

1053 {
1054  // Take care of sparseness at the end of the output file.
1055  if (success && pair->dest_try_sparse
1056  && pair->dest_pending_sparse > 0) {
1057  // Seek forward one byte less than the size of the pending
1058  // hole, then write one zero-byte. This way the file grows
1059  // to its correct size. An alternative would be to use
1060  // ftruncate() but that isn't portable enough (e.g. it
1061  // doesn't work with FAT on Linux; FAT isn't that important
1062  // since it doesn't support sparse files anyway, but we don't
1063  // want to create corrupt files on it).
1064  if (lseek(pair->dest_fd, pair->dest_pending_sparse - 1,
1065  SEEK_CUR) == -1) {
1066  message_error(_("%s: Seeking failed when trying "
1067  "to create a sparse file: %s"),
1068  pair->dest_name, strerror(errno));
1069  success = false;
1070  } else {
1071  const uint8_t zero[1] = { '\0' };
1072  if (io_write_buf(pair, zero, 1))
1073  success = false;
1074  }
1075  }
1076 
1077  signals_block();
1078 
1079  // Copy the file attributes. We need to skip this if destination
1080  // file isn't open or it is standard output.
1081  if (success && pair->dest_fd != -1 && pair->dest_fd != STDOUT_FILENO)
1082  io_copy_attrs(pair);
1083 
1084  // Close the destination first. If it fails, we must not remove
1085  // the source file!
1086  if (io_close_dest(pair, success))
1087  success = false;
1088 
1089  // Close the source file, and unlink it if the operation using this
1090  // file pair was successful and we haven't requested to keep the
1091  // source file.
1092  io_close_src(pair, success);
1093 
1094  signals_unblock();
1095 
1096  return;
1097 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep lseek
Definition: sflib.h:113
static void io_copy_attrs(const file_pair *pair)
Copies owner/group and permissions.
Definition: file_io.c:352
static bool io_close_dest(file_pair *pair, bool success)
Closes destination file of the file_pair structure.
Definition: file_io.c:1008
static void io_close_src(file_pair *pair, bool success)
Closes source file of the file_pair structure.
Definition: file_io.c:783
static bool io_write_buf(file_pair *pair, const uint8_t *buf, size_t size)
Definition: file_io.c:1224
void message_error(const char *fmt,...)
Definition: message.c:764
#define _(String)
Definition: opintl.h:53
unsigned char uint8_t
Definition: sftypes.h:31
void signals_unblock(void)
Unblock the signals blocked by signals_block().
Definition: signals.c:135
void signals_block(void)
Definition: signals.c:120
bool dest_try_sparse
Definition: file_io.h:61
char * dest_name
Definition: file_io.h:41
off_t dest_pending_sparse
Definition: file_io.h:66
int dest_fd
File descriptor of the target file.
Definition: file_io.h:47
#define STDOUT_FILENO
Definition: private.h:41
#define SEEK_CUR
Definition: zip.c:80

References _, file_pair::dest_fd, file_pair::dest_name, file_pair::dest_pending_sparse, file_pair::dest_try_sparse, io_close_dest(), io_close_src(), io_copy_attrs(), io_write_buf(), lseek, message_error(), SEEK_CUR, signals_block(), signals_unblock(), and STDOUT_FILENO.

Referenced by coder_run(), and list_file().

◆ io_fix_src_pos()

void io_fix_src_pos ( file_pair pair,
size_t  rewind_size 
)

Fix the position in src_fd.

This is used when –single-thream has been specified and decompression is successful. If the input file descriptor supports seeking, this function fixes the input position to point to the next byte after the decompressed stream.

Parameters
pairFile pair having the source file open for reading
rewind_sizeHow many bytes of extra have been read i.e. how much to seek backwards.

Definition at line 1101 of file file_io.c.

1102 {
1103  assert(rewind_size <= IO_BUFFER_SIZE);
1104 
1105  if (rewind_size > 0) {
1106  // This doesn't need to work on unseekable file descriptors,
1107  // so just ignore possible errors.
1108  (void)lseek(pair->src_fd, -(off_t)(rewind_size), SEEK_CUR);
1109  }
1110 
1111  return;
1112 }
#define IO_BUFFER_SIZE
Definition: file_io.h:16
assert(limit<=UINT32_MAX/2)
int off_t
Definition: sftypes.h:41
int src_fd
File descriptor of the source file.
Definition: file_io.h:44

References assert(), IO_BUFFER_SIZE, lseek, SEEK_CUR, and file_pair::src_fd.

Referenced by coder_normal().

◆ io_init()

void io_init ( void  )

Initialize the I/O module.

Definition at line 95 of file file_io.c.

96 {
97  // Make sure that stdin, stdout, and stderr are connected to
98  // a valid file descriptor. Exit immediately with exit code ERROR
99  // if we cannot make the file descriptors valid. Maybe we should
100  // print an error message, but our stderr could be screwed anyway.
102 
103 #ifndef TUKLIB_DOSLIKE
104  // If fchown() fails setting the owner, we warn about it only if
105  // we are root.
106  warn_fchown = geteuid() == 0;
107 
108  // Create a pipe for the self-pipe trick.
109  if (pipe(user_abort_pipe))
110  message_fatal(_("Error creating a pipe: %s"),
111  strerror(errno));
112 
113  // Make both ends of the pipe non-blocking.
114  for (unsigned i = 0; i < 2; ++i) {
116  if (flags == -1 || fcntl(user_abort_pipe[i], F_SETFL,
117  flags | O_NONBLOCK) == -1)
118  message_fatal(_("Error creating a pipe: %s"),
119  strerror(errno));
120  }
121 #endif
122 
123 #ifdef __DJGPP__
124  // Avoid doing useless things when statting files.
125  // This isn't important but doesn't hurt.
126  _djstat_flags = _STAT_EXEC_EXT | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
127 #endif
128 
129  return;
130 }
lzma_index ** i
Definition: index.h:629
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags fcntl
Definition: sflib.h:79
static bool warn_fchown
Definition: file_io.c:21
static int user_abort_pipe[2]
Definition: file_io.c:87
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname pipe
Definition: sflib.h:73
void message_fatal(const char *fmt,...)
Definition: message.c:777
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
#define F_GETFL
Definition: sftypes.h:506
#define O_NONBLOCK
Definition: sftypes.h:494
#define F_SETFL
Definition: sftypes.h:507
@ E_ERROR
Definition: transport.h:23
void tuklib_open_stdxxx(int err_status)

References _, E_ERROR, F_GETFL, F_SETFL, fcntl, flags, i, message_fatal(), O_NONBLOCK, pipe, tuklib_open_stdxxx(), user_abort_pipe, and warn_fchown.

Referenced by main().

◆ io_no_sparse()

void io_no_sparse ( void  )

Disable creation of sparse files when decompressing.

Definition at line 151 of file file_io.c.

152 {
153  try_sparse = false;
154  return;
155 }
static bool try_sparse
If true, try to create sparse files when decompressing.
Definition: file_io.c:67

References try_sparse.

Referenced by parse_real().

◆ io_open_dest()

bool io_open_dest ( file_pair pair)

Open the destination file.

Definition at line 991 of file file_io.c.

992 {
993  signals_block();
994  const bool ret = io_open_dest_real(pair);
995  signals_unblock();
996  return ret;
997 }
static bool io_open_dest_real(file_pair *pair)
Definition: file_io.c:822

References io_open_dest_real(), signals_block(), and signals_unblock().

Referenced by coder_run().

◆ io_open_src()

file_pair* io_open_src ( const char *  src_name)

Open the source file.

Definition at line 741 of file file_io.c.

742 {
743  if (is_empty_filename(src_name))
744  return NULL;
745 
746  // Since we have only one file open at a time, we can use
747  // a statically allocated structure.
748  static file_pair pair;
749 
750  pair = (file_pair){
751  .src_name = src_name,
752  .dest_name = NULL,
753  .src_fd = -1,
754  .dest_fd = -1,
755  .src_eof = false,
756  .src_has_seen_input = false,
757  .flush_needed = false,
758  .dest_try_sparse = false,
759  .dest_pending_sparse = 0,
760  };
761 
762  // Block the signals, for which we have a custom signal handler, so
763  // that we don't need to worry about EINTR.
764  signals_block();
765  const bool error = io_open_src_real(&pair);
766  signals_unblock();
767 
768 #ifdef ENABLE_SANDBOX
769  if (!error)
770  io_sandbox_enter(pair.src_fd);
771 #endif
772 
773  return error ? NULL : &pair;
774 }
#define NULL
Definition: cris-opc.c:27
static bool io_open_src_real(file_pair *pair)
Opens the source file. Returns false on success, true on error.
Definition: file_io.c:502
const char * src_name
Definition: file_io.h:37
bool is_empty_filename(const char *filename)
Check if filename is empty and print an error message.
Definition: util.c:264
void error(const char *msg)
Definition: untgz.c:593

References error(), io_open_src_real(), is_empty_filename(), NULL, signals_block(), signals_unblock(), file_pair::src_fd, and file_pair::src_name.

Referenced by coder_run(), and list_file().

◆ io_pread()

bool io_pread ( file_pair pair,
io_buf buf,
size_t  size,
off_t  pos 
)

Read from source file from given offset to a buffer.

This is remotely similar to standard pread(). This uses lseek() though, so the read offset is changed on each call.

Parameters
pairSeekable source file
bufDestination buffer
sizeAmount of data to read
posOffset relative to the beginning of the file, from which the data should be read.
Returns
On success, false is returned. On error, error message is printed and true is returned.

Definition at line 1186 of file file_io.c.

1187 {
1188  // Using lseek() and read() is more portable than pread() and
1189  // for us it is as good as real pread().
1190  if (lseek(pair->src_fd, pos, SEEK_SET) != pos) {
1191  message_error(_("%s: Error seeking the file: %s"),
1192  pair->src_name, strerror(errno));
1193  return true;
1194  }
1195 
1196  const size_t amount = io_read(pair, buf, size);
1197  if (amount == SIZE_MAX)
1198  return true;
1199 
1200  if (amount != size) {
1201  message_error(_("%s: Unexpected end of file"),
1202  pair->src_name);
1203  return true;
1204  }
1205 
1206  return false;
1207 }
size_t io_read(file_pair *pair, io_buf *buf, size_t size)
Reads from the source file to a buffer.
Definition: file_io.c:1116
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
#define SIZE_MAX
int pos
Definition: main.c:11
#define SEEK_SET
Definition: zip.c:88

References _, io_read(), lseek, message_error(), pos, SEEK_SET, SIZE_MAX, file_pair::src_fd, and file_pair::src_name.

Referenced by parse_block_header(), parse_check_value(), and parse_indexes().

◆ io_read()

size_t io_read ( file_pair pair,
io_buf buf,
size_t  size 
)

Reads from the source file to a buffer.

Parameters
pairFile pair having the source file open for reading
bufDestination buffer to hold the read data
sizeSize of the buffer; assumed be smaller than SSIZE_MAX
Returns
On success, number of bytes read is returned. On end of file zero is returned and pair->src_eof set to true. On error, SIZE_MAX is returned and error message printed.

Definition at line 1116 of file file_io.c.

1117 {
1118  // We use small buffers here.
1119  assert(size < SSIZE_MAX);
1120 
1121  size_t pos = 0;
1122 
1123  while (pos < size) {
1124  const ssize_t amount = read(
1125  pair->src_fd, buf->u8 + pos, size - pos);
1126 
1127  if (amount == 0) {
1128  pair->src_eof = true;
1129  break;
1130  }
1131 
1132  if (amount == -1) {
1133  if (errno == EINTR) {
1134  if (user_abort)
1135  return SIZE_MAX;
1136 
1137  continue;
1138  }
1139 
1140 #ifndef TUKLIB_DOSLIKE
1141  if (IS_EAGAIN_OR_EWOULDBLOCK(errno)) {
1142  // Disable the flush-timeout if no input has
1143  // been seen since the previous flush and thus
1144  // there would be nothing to flush after the
1145  // timeout expires (avoids busy waiting).
1146  const int timeout = pair->src_has_seen_input
1148  : -1;
1149 
1150  switch (io_wait(pair, timeout, true)) {
1151  case IO_WAIT_MORE:
1152  continue;
1153 
1154  case IO_WAIT_ERROR:
1155  return SIZE_MAX;
1156 
1157  case IO_WAIT_TIMEOUT:
1158  pair->flush_needed = true;
1159  return pos;
1160 
1161  default:
1162  message_bug();
1163  }
1164  }
1165 #endif
1166 
1167  message_error(_("%s: Read error: %s"),
1168  pair->src_name, strerror(errno));
1169 
1170  return SIZE_MAX;
1171  }
1172 
1173  pos += (size_t)(amount);
1174 
1175  if (!pair->src_has_seen_input) {
1176  pair->src_has_seen_input = true;
1178  }
1179  }
1180 
1181  return pos;
1182 }
#define IS_EAGAIN_OR_EWOULDBLOCK(e)
Definition: file_io.c:52
static io_wait_ret io_wait(file_pair *pair, int timeout, bool is_reading)
Waits for input or output to become available or for a signal.
Definition: file_io.c:241
@ IO_WAIT_ERROR
Definition: file_io.c:61
@ IO_WAIT_TIMEOUT
Definition: file_io.c:62
@ IO_WAIT_MORE
Definition: file_io.c:60
void message_bug(void)
Definition: message.c:789
int mytime_get_flush_timeout(void)
Get the number of milliseconds until the next flush.
Definition: mytime.c:74
void mytime_set_flush_time(void)
Store the time of when compressor was flushed.
Definition: mytime.c:66
int size_t
Definition: sftypes.h:40
#define EINTR
Definition: sftypes.h:114
int ssize_t
Definition: sftypes.h:39
volatile sig_atomic_t user_abort
Definition: signals.c:16
bool flush_needed
For –flush-timeout: True when flushing is needed.
Definition: file_io.h:57
bool src_has_seen_input
Definition: file_io.h:54
bool src_eof
True once end of the source file has been detected.
Definition: file_io.h:50
uv_timer_t timeout
Definition: main.c:9
#define SSIZE_MAX
Definition: win.h:28
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115

References _, assert(), EINTR, file_pair::flush_needed, io_wait(), IO_WAIT_ERROR, IO_WAIT_MORE, IO_WAIT_TIMEOUT, IS_EAGAIN_OR_EWOULDBLOCK, message_bug(), message_error(), mytime_get_flush_timeout(), mytime_set_flush_time(), pos, read(), SIZE_MAX, file_pair::src_eof, file_pair::src_fd, file_pair::src_has_seen_input, file_pair::src_name, SSIZE_MAX, timeout, and user_abort.

Referenced by coder_normal(), coder_passthru(), coder_run(), and io_pread().

◆ io_write()

bool io_write ( file_pair pair,
const io_buf buf,
size_t  size 
)

Writes a buffer to the destination file.

Parameters
pairFile pair having the destination file open for writing
bufBuffer containing the data to be written
sizeSize of the buffer; assumed be smaller than SSIZE_MAX
Returns
On success, zero is returned. On error, -1 is returned and error message printed.

Definition at line 1275 of file file_io.c.

1276 {
1278 
1279  if (pair->dest_try_sparse) {
1280  // Check if the block is sparse (contains only zeros). If it
1281  // sparse, we just store the amount and return. We will take
1282  // care of actually skipping over the hole when we hit the
1283  // next data block or close the file.
1284  //
1285  // Since io_close() requires that dest_pending_sparse > 0
1286  // if the file ends with sparse block, we must also return
1287  // if size == 0 to avoid doing the lseek().
1288  if (size == IO_BUFFER_SIZE) {
1289  // Even if the block was sparse, treat it as non-sparse
1290  // if the pending sparse amount is large compared to
1291  // the size of off_t. In practice this only matters
1292  // on 32-bit systems where off_t isn't always 64 bits.
1293  const off_t pending_max
1294  = (off_t)(1) << (sizeof(off_t) * CHAR_BIT - 2);
1295  if (is_sparse(buf) && pair->dest_pending_sparse
1296  < pending_max) {
1297  pair->dest_pending_sparse += (off_t)(size);
1298  return false;
1299  }
1300  } else if (size == 0) {
1301  return false;
1302  }
1303 
1304  // This is not a sparse block. If we have a pending hole,
1305  // skip it now.
1306  if (pair->dest_pending_sparse > 0) {
1307  if (lseek(pair->dest_fd, pair->dest_pending_sparse,
1308  SEEK_CUR) == -1) {
1309  message_error(_("%s: Seeking failed when "
1310  "trying to create a sparse "
1311  "file: %s"), pair->dest_name,
1312  strerror(errno));
1313  return true;
1314  }
1315 
1316  pair->dest_pending_sparse = 0;
1317  }
1318  }
1319 
1320  return io_write_buf(pair, buf->u8, size);
1321 }
#define CHAR_BIT
Definition: readbits.h:99
static bool is_sparse(const io_buf *buf)
Definition: file_io.c:1211

References _, assert(), CHAR_BIT, file_pair::dest_fd, file_pair::dest_name, file_pair::dest_pending_sparse, file_pair::dest_try_sparse, IO_BUFFER_SIZE, io_write_buf(), is_sparse(), lseek, message_error(), and SEEK_CUR.

Referenced by coder_passthru(), and coder_write_output().

◆ io_write_to_user_abort_pipe()

void io_write_to_user_abort_pipe ( void  )

Write a byte to user_abort_pipe[1].

This is called from a signal handler.

Definition at line 135 of file file_io.c.

136 {
137  // If the write() fails, it's probably due to the pipe being full.
138  // Failing in that case is fine. If the reason is something else,
139  // there's not much we can do since this is called in a signal
140  // handler. So ignore the errors and try to avoid warnings with
141  // GCC and glibc when _FORTIFY_SOURCE=2 is used.
142  uint8_t b = '\0';
143  const int ret = write(user_abort_pipe[1], &b, 1);
144  (void)ret;
145  return;
146 }
static static fork write
Definition: sflib.h:33
#define b(i)
Definition: sha256.c:42

References b, user_abort_pipe, and write.

Referenced by signal_handler().