1 /* 2 * 9p utilities 3 * 4 * Copyright IBM, Corp. 2017 5 * 6 * Authors: 7 * Greg Kurz <groug@kaod.org> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #ifndef QEMU_9P_UTIL_H 14 #define QEMU_9P_UTIL_H 15 16 #ifdef O_PATH 17 #define O_PATH_9P_UTIL O_PATH 18 #else 19 #define O_PATH_9P_UTIL 0 20 #endif 21 22 static inline void close_preserve_errno(int fd) 23 { 24 int serrno = errno; 25 close(fd); 26 errno = serrno; 27 } 28 29 static inline int openat_dir(int dirfd, const char *name) 30 { 31 return openat(dirfd, name, 32 O_DIRECTORY | O_RDONLY | O_NOFOLLOW | O_PATH_9P_UTIL); 33 } 34 35 static inline int openat_file(int dirfd, const char *name, int flags, 36 mode_t mode) 37 { 38 int fd, serrno, ret; 39 40 fd = openat(dirfd, name, flags | O_NOFOLLOW | O_NOCTTY | O_NONBLOCK, 41 mode); 42 if (fd == -1) { 43 return -1; 44 } 45 46 serrno = errno; 47 /* O_NONBLOCK was only needed to open the file. Let's drop it. We don't 48 * do that with O_PATH since fcntl(F_SETFL) isn't supported, and openat() 49 * ignored it anyway. 50 */ 51 if (!(flags & O_PATH_9P_UTIL)) { 52 ret = fcntl(fd, F_SETFL, flags); 53 assert(!ret); 54 } 55 errno = serrno; 56 return fd; 57 } 58 59 ssize_t fgetxattrat_nofollow(int dirfd, const char *path, const char *name, 60 void *value, size_t size); 61 int fsetxattrat_nofollow(int dirfd, const char *path, const char *name, 62 void *value, size_t size, int flags); 63 64 #endif 65