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