github.com/jurelou/go-magic@v0.0.0-20230518182705-f2995a311800/functions.c (about) 1 #if defined(__cplusplus) 2 extern "C" { 3 #endif 4 5 #include "functions.h" 6 7 int check_fd(int fd); 8 static int safe_dup(int fd); 9 static int safe_close(int fd); 10 static int safe_cloexec(int fd); 11 int override_error_output(void *data); 12 int restore_error_output(void *data); 13 14 inline int 15 check_fd(int fd) 16 { 17 errno = 0; 18 if (fd < 0 || (fcntl(fd, F_GETFD) < 0 && errno == EBADF)) { 19 errno = EBADF; 20 return -EBADF; 21 } 22 23 return 0; 24 } 25 26 static int 27 safe_dup(int fd) 28 { 29 int new_fd; 30 int local_errno; 31 int flags = F_DUPFD; 32 33 #if defined(HAVE_F_DUPFD_CLOEXEC) 34 flags = F_DUPFD_CLOEXEC; 35 #endif 36 37 new_fd = fcntl(fd, flags, fileno(stderr) + 1); 38 if (new_fd < 0 && errno == EINVAL) { 39 new_fd = dup(fd); 40 if (new_fd < 0) { 41 local_errno = errno; 42 goto error; 43 } 44 } 45 if (safe_cloexec(new_fd) < 0) { 46 local_errno = errno; 47 goto error; 48 } 49 50 return new_fd; 51 error: 52 errno = local_errno; 53 return -1; 54 } 55 56 static int 57 safe_close(int fd) 58 { 59 int rv; 60 #if defined(HAVE_POSIX_CLOSE_RESTART) 61 rv = posix_close(fd, 0); 62 #else 63 rv = close(fd); 64 if (rv < 0 && errno == EINTR) 65 errno = EINPROGRESS; 66 #endif 67 68 return rv; 69 } 70 71 static inline int 72 safe_cloexec(int fd) 73 { 74 int local_errno; 75 int flags = fcntl(fd, F_GETFD); 76 77 if (flags < 0) { 78 local_errno = errno; 79 goto error; 80 } 81 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { 82 local_errno = errno; 83 goto error; 84 } 85 86 return 0; 87 error: 88 errno = local_errno; 89 return -1; 90 } 91 92 int 93 override_error_output(void *data) 94 { 95 int local_errno; 96 mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO; 97 save_t *s = data; 98 99 #if defined(HAVE_O_CLOEXEC) 100 mode |= O_CLOEXEC; 101 #endif 102 103 assert(s != NULL && \ 104 "Must be a valid pointer to `save_t' type"); 105 106 s->file.old_fd = -1; 107 s->file.new_fd = -1; 108 s->status = -1; 109 110 fflush(stderr); 111 fgetpos(stderr, &s->file.position); 112 113 s->file.old_fd = safe_dup(fileno(stderr)); 114 if (s->file.old_fd < 0) { 115 local_errno = errno; 116 goto error; 117 } 118 119 s->file.new_fd = open("/dev/null", O_WRONLY | O_APPEND, mode); 120 if (s->file.new_fd < 0) { 121 local_errno = errno; 122 123 if (dup2(s->file.old_fd, fileno(stderr)) < 0) { 124 local_errno = errno; 125 goto error; 126 } 127 128 safe_close(s->file.old_fd); 129 goto error; 130 } 131 if (safe_cloexec(s->file.new_fd) < 0) { 132 local_errno = errno; 133 goto error; 134 } 135 if (dup2(s->file.new_fd, fileno(stderr)) < 0) { 136 local_errno = errno; 137 goto error; 138 } 139 140 safe_close(s->file.new_fd); 141 142 return 0; 143 error: 144 s->status = local_errno; 145 errno = s->status; 146 return -1; 147 } 148 149 int 150 restore_error_output(void *data) 151 { 152 int local_errno; 153 save_t *s = data; 154 155 assert(s != NULL && \ 156 "Must be a valid pointer to `save_t' type"); 157 158 if (s->file.old_fd < 0 && s->status != 0) 159 return -1; 160 161 fflush(stderr); 162 163 if (dup2(s->file.old_fd, fileno(stderr)) < 0) { 164 local_errno = errno; 165 goto error; 166 } 167 168 safe_close(s->file.old_fd); 169 clearerr(stderr); 170 fsetpos(stderr, &s->file.position); 171 172 if (setvbuf(stderr, NULL, _IONBF, 0) != 0) { 173 local_errno = errno; 174 goto error; 175 } 176 177 return 0; 178 error: 179 s->status = local_errno; 180 errno = s->status; 181 return -1; 182 } 183 184 inline magic_t 185 magic_open_wrapper(int flags) 186 { 187 return magic_open(flags); 188 } 189 190 inline void 191 magic_close_wrapper(magic_t magic) 192 { 193 magic_close(magic); 194 } 195 196 inline const char* 197 magic_error_wrapper(magic_t magic) 198 { 199 return magic_error(magic); 200 } 201 202 inline int 203 magic_errno_wrapper(magic_t magic) 204 { 205 return magic_errno(magic); 206 } 207 208 inline const char* 209 magic_getpath_wrapper(void) 210 { 211 return magic_getpath(NULL, 0); 212 } 213 214 inline int 215 magic_getparam_wrapper(magic_t magic, int parameter, void *value) 216 { 217 return magic_getparam(magic, parameter, value); 218 } 219 220 inline int 221 magic_setparam_wrapper(magic_t magic, int parameter, const void *value) 222 { 223 if (*(const int *)value < 0 || *(const size_t *)value > UINT_MAX) { 224 errno = EOVERFLOW; 225 return -EOVERFLOW; 226 } 227 228 if (parameter == MAGIC_PARAM_BYTES_MAX) 229 return magic_setparam(magic, parameter, value); 230 231 if (*(const size_t *)value > USHRT_MAX) { 232 errno = EOVERFLOW; 233 return -EOVERFLOW; 234 } 235 236 return magic_setparam(magic, parameter, value); 237 } 238 239 inline int 240 magic_getflags_wrapper(magic_t magic) 241 { 242 #if defined(HAVE_MAGIC_GETFLAGS) 243 return magic_getflags(magic); 244 #else 245 UNUSED(magic); 246 errno = ENOSYS; 247 return -ENOSYS; 248 #endif 249 } 250 251 inline int 252 magic_setflags_wrapper(magic_t magic, int flags) 253 { 254 if (flags < 0 || flags > 0xfffffff) { 255 errno = EINVAL; 256 return -EINVAL; 257 } 258 259 return magic_setflags(magic, flags); 260 } 261 262 inline int 263 magic_load_wrapper(magic_t magic, const char *magic_file, int flags) 264 { 265 int rv; 266 MAGIC_FUNCTION(magic_load, rv, flags, magic, magic_file); 267 return rv; 268 } 269 270 inline int 271 magic_load_buffers_wrapper(magic_t magic, void **buffers, size_t *sizes, size_t count, int flags) 272 { 273 int rv; 274 MAGIC_FUNCTION(magic_load_buffers, rv, flags, magic, buffers, sizes, count); 275 return rv; 276 } 277 278 inline int 279 magic_compile_wrapper(magic_t magic, const char *magic_file, int flags) 280 { 281 int rv; 282 MAGIC_FUNCTION(magic_compile, rv, flags, magic, magic_file); 283 return rv; 284 } 285 286 inline int 287 magic_check_wrapper(magic_t magic, const char *magic_file, int flags) 288 { 289 int rv; 290 MAGIC_FUNCTION(magic_check, rv, flags, magic, magic_file); 291 return rv; 292 } 293 294 inline const char* 295 magic_file_wrapper(magic_t magic, const char* filename, int flags) 296 { 297 const char *cstring; 298 MAGIC_FUNCTION(magic_file, cstring, flags, magic, filename); 299 return cstring; 300 } 301 302 inline const char* 303 magic_buffer_wrapper(magic_t magic, const void *buffer, size_t size, int flags) 304 { 305 const char *cstring; 306 MAGIC_FUNCTION(magic_buffer, cstring, flags, magic, buffer, size); 307 return cstring; 308 } 309 310 inline const char* 311 magic_descriptor_wrapper(magic_t magic, int fd, int flags) 312 { 313 int local_errno; 314 const char *cstring; 315 316 if (check_fd(fd) < 0) { 317 local_errno = errno; 318 goto error; 319 } 320 321 MAGIC_FUNCTION(magic_descriptor, cstring, flags, magic, fd); 322 return cstring; 323 324 error: 325 errno = local_errno; 326 return NULL; 327 } 328 329 inline int 330 magic_version_wrapper(void) 331 { 332 return magic_version(); 333 } 334 335 #if defined(__cplusplus) 336 } 337 #endif