tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

fdio.c (3117B)


      1 /* Copyright (c) 2003-2004, Roger Dingledine
      2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      4 /* See LICENSE for licensing information */
      5 
      6 /**
      7 * \file fdio.c
      8 *
      9 * \brief Low-level compatibility wrappers for fd-based IO.
     10 **/
     11 
     12 #include "orconfig.h"
     13 
     14 #ifdef HAVE_UNISTD_H
     15 #include <unistd.h>
     16 #endif
     17 #ifdef HAVE_FCNTL_H
     18 #include <fcntl.h>
     19 #endif
     20 #ifdef _WIN32
     21 #include <windows.h>
     22 #endif
     23 #ifdef HAVE_SYS_TYPES_H
     24 #include <sys/types.h>
     25 #endif
     26 
     27 #include "lib/fdio/fdio.h"
     28 #include "lib/cc/torint.h"
     29 #include "lib/err/torerr.h"
     30 
     31 #include <stdlib.h>
     32 #include <stdio.h>
     33 
     34 /* Some old versions of Unix didn't define constants for these values,
     35 * and instead expect you to say 0, 1, or 2. */
     36 
     37 /** @cond */
     38 #ifndef SEEK_SET
     39 #define SEEK_SET 0
     40 #endif
     41 #ifndef SEEK_CUR
     42 #define SEEK_CUR 1
     43 #endif
     44 #ifndef SEEK_END
     45 #define SEEK_END 2
     46 #endif
     47 /** @endcond */
     48 
     49 /** Return the position of <b>fd</b> with respect to the start of the file. */
     50 off_t
     51 tor_fd_getpos(int fd)
     52 {
     53 #ifdef _WIN32
     54  return (off_t) _lseeki64(fd, 0, SEEK_CUR);
     55 #else
     56  return (off_t) lseek(fd, 0, SEEK_CUR);
     57 #endif
     58 }
     59 
     60 /** Move <b>fd</b> to the end of the file. Return -1 on error, 0 on success.
     61 * If the file is a pipe, do nothing and succeed.
     62 **/
     63 int
     64 tor_fd_seekend(int fd)
     65 {
     66 #ifdef _WIN32
     67  return _lseeki64(fd, 0, SEEK_END) < 0 ? -1 : 0;
     68 #else
     69  off_t rc = lseek(fd, 0, SEEK_END) < 0 ? -1 : 0;
     70 #ifdef ESPIPE
     71  /* If we get an error and ESPIPE, then it's a pipe or a socket of a fifo:
     72   * no need to worry. */
     73  if (rc < 0 && errno == ESPIPE)
     74    rc = 0;
     75 #endif /* defined(ESPIPE) */
     76  return (rc < 0) ? -1 : 0;
     77 #endif /* defined(_WIN32) */
     78 }
     79 
     80 /** Move <b>fd</b> to position <b>pos</b> in the file. Return -1 on error, 0
     81 * on success. */
     82 int
     83 tor_fd_setpos(int fd, off_t pos)
     84 {
     85 #ifdef _WIN32
     86  return _lseeki64(fd, pos, SEEK_SET) < 0 ? -1 : 0;
     87 #else
     88  return lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0;
     89 #endif
     90 }
     91 
     92 /** Replacement for ftruncate(fd, 0): move to the front of the file and remove
     93 * all the rest of the file. Return -1 on error, 0 on success. */
     94 int
     95 tor_ftruncate(int fd)
     96 {
     97  /* Rumor has it that some versions of ftruncate do not move the file pointer.
     98   */
     99  if (tor_fd_setpos(fd, 0) < 0)
    100    return -1;
    101 
    102 #ifdef _WIN32
    103  return _chsize(fd, 0);
    104 #else
    105  return ftruncate(fd, 0);
    106 #endif
    107 }
    108 
    109 /** Minimal version of write_all, for use by logging. */
    110 int
    111 write_all_to_fd_minimal(int fd, const char *buf, size_t count)
    112 {
    113  size_t written = 0;
    114  raw_assert(count < SSIZE_MAX);
    115 
    116  while (written < count) {
    117    ssize_t result = write(fd, buf+written, count-written);
    118    if (result<0)
    119      return -1;
    120    written += result;
    121  }
    122  return 0;
    123 }
    124 
    125 #if defined(HAVE_PIPE2) && defined(O_CLOEXEC)
    126 int
    127 tor_pipe_cloexec(int pipefd[2])
    128 {
    129  return pipe2(pipefd, O_CLOEXEC);
    130 }
    131 #elif defined(HAVE_PIPE) && defined(FD_CLOEXEC)
    132 int
    133 tor_pipe_cloexec(int pipefd[2])
    134 {
    135  if (pipe(pipefd)) {
    136    return -1;
    137  }
    138  if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC)) {
    139    return -1;
    140  }
    141  if (fcntl(pipefd[1], F_SETFD, FD_CLOEXEC)) {
    142    return -1;
    143  }
    144  return 0;
    145 }
    146 #else
    147 /* Intentionally leave symbol undefined. */
    148 #endif