1 /* Id */ 2 3 /* 4 * Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <errno.h> 20 #include <fcntl.h> 21 #include <stdarg.h> 22 #include <unistd.h> 23 24 #include "tmux.h" 25 26 int 27 openat(int fd, const char *path, int flags, ...) 28 { 29 mode_t mode; 30 va_list ap; 31 int dotfd, retval, saved_errno; 32 33 if (flags & O_CREAT) { 34 va_start(ap, flags); 35 mode = va_arg(ap, mode_t); 36 va_end(ap); 37 } else 38 mode = 0; 39 40 dotfd = -1; 41 if (fd != AT_FDCWD) { 42 dotfd = open(".", O_RDONLY); 43 if (dotfd == -1) 44 return (-1); 45 if (fchdir(fd) != 0) 46 return (-1); 47 } 48 49 retval = open(path, flags, mode); 50 51 if (dotfd != -1) { 52 if (fchdir(dotfd) != 0) { 53 saved_errno = errno; 54 close(retval); 55 close(dotfd); 56 errno = saved_errno; 57 return (-1); 58 } 59 close(dotfd); 60 } 61 62 return (retval); 63 } 64