1 /* 2 * Copyright (c) 2020 Yubico AB. All rights reserved. 3 * Use of this source code is governed by a BSD-style 4 * license that can be found in the LICENSE file. 5 */ 6 7 #include <sys/stat.h> 8 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <poll.h> 12 #include <unistd.h> 13 14 #include "fido.h" 15 16 #ifdef __NetBSD__ 17 #define ppoll pollts 18 #endif 19 20 int 21 fido_hid_unix_open(const char *path) 22 { 23 int fd; 24 struct stat st; 25 26 if ((fd = open(path, O_RDWR)) == -1) { 27 if (errno != ENOENT && errno != ENXIO) 28 fido_log_error(errno, "%s: open %s", __func__, path); 29 return (-1); 30 } 31 32 if (fstat(fd, &st) == -1) { 33 fido_log_error(errno, "%s: fstat %s", __func__, path); 34 if (close(fd) == -1) 35 fido_log_error(errno, "%s: close", __func__); 36 return (-1); 37 } 38 39 if (S_ISCHR(st.st_mode) == 0) { 40 fido_log_debug("%s: S_ISCHR %s", __func__, path); 41 if (close(fd) == -1) 42 fido_log_error(errno, "%s: close", __func__); 43 return (-1); 44 } 45 46 return (fd); 47 } 48 49 int 50 fido_hid_unix_wait(int fd, int ms, const fido_sigset_t *sigmask) 51 { 52 struct timespec ts; 53 struct pollfd pfd; 54 int r; 55 56 memset(&pfd, 0, sizeof(pfd)); 57 pfd.events = POLLIN; 58 pfd.fd = fd; 59 60 #ifdef FIDO_FUZZ 61 if (ms < 0) 62 return (0); 63 #endif 64 if (ms > -1) { 65 ts.tv_sec = ms / 1000; 66 ts.tv_nsec = (ms % 1000) * 1000000; 67 } 68 69 if ((r = ppoll(&pfd, 1, ms > -1 ? &ts : NULL, sigmask)) < 1) { 70 if (r == -1) 71 fido_log_error(errno, "%s: ppoll", __func__); 72 return (-1); 73 } 74 75 return (0); 76 } 77