1 /* 2 * file related system call shims and definitions 3 * 4 * Copyright (c) 2013 Stacey D. Son 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef BSD_FILE_H 21 #define BSD_FILE_H 22 23 #include "qemu/path.h" 24 25 extern struct iovec *lock_iovec(int type, abi_ulong target_addr, int count, 26 int copy); 27 extern void unlock_iovec(struct iovec *vec, abi_ulong target_addr, int count, 28 int copy); 29 30 ssize_t safe_read(int fd, void *buf, size_t nbytes); 31 ssize_t safe_pread(int fd, void *buf, size_t nbytes, off_t offset); 32 ssize_t safe_readv(int fd, const struct iovec *iov, int iovcnt); 33 ssize_t safe_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset); 34 35 ssize_t safe_write(int fd, void *buf, size_t nbytes); 36 ssize_t safe_pwrite(int fd, void *buf, size_t nbytes, off_t offset); 37 ssize_t safe_writev(int fd, const struct iovec *iov, int iovcnt); 38 ssize_t safe_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset); 39 40 /* read(2) */ 41 static abi_long do_bsd_read(abi_long arg1, abi_long arg2, abi_long arg3) 42 { 43 abi_long ret; 44 void *p; 45 46 p = lock_user(VERIFY_WRITE, arg2, arg3, 0); 47 if (p == NULL) { 48 return -TARGET_EFAULT; 49 } 50 ret = get_errno(safe_read(arg1, p, arg3)); 51 unlock_user(p, arg2, ret); 52 53 return ret; 54 } 55 56 /* pread(2) */ 57 static abi_long do_bsd_pread(void *cpu_env, abi_long arg1, 58 abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) 59 { 60 abi_long ret; 61 void *p; 62 63 p = lock_user(VERIFY_WRITE, arg2, arg3, 0); 64 if (p == NULL) { 65 return -TARGET_EFAULT; 66 } 67 if (regpairs_aligned(cpu_env) != 0) { 68 arg4 = arg5; 69 arg5 = arg6; 70 } 71 ret = get_errno(safe_pread(arg1, p, arg3, target_arg64(arg4, arg5))); 72 unlock_user(p, arg2, ret); 73 74 return ret; 75 } 76 77 /* readv(2) */ 78 static abi_long do_bsd_readv(abi_long arg1, abi_long arg2, abi_long arg3) 79 { 80 abi_long ret; 81 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); 82 83 if (vec != NULL) { 84 ret = get_errno(safe_readv(arg1, vec, arg3)); 85 unlock_iovec(vec, arg2, arg3, 1); 86 } else { 87 ret = -host_to_target_errno(errno); 88 } 89 90 return ret; 91 } 92 93 /* preadv(2) */ 94 static abi_long do_bsd_preadv(void *cpu_env, abi_long arg1, 95 abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) 96 { 97 abi_long ret; 98 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 1); 99 100 if (vec != NULL) { 101 if (regpairs_aligned(cpu_env) != 0) { 102 arg4 = arg5; 103 arg5 = arg6; 104 } 105 ret = get_errno(safe_preadv(arg1, vec, arg3, target_arg64(arg4, arg5))); 106 unlock_iovec(vec, arg2, arg3, 0); 107 } else { 108 ret = -host_to_target_errno(errno); 109 } 110 111 return ret; 112 } 113 114 /* write(2) */ 115 static abi_long do_bsd_write(abi_long arg1, abi_long arg2, abi_long arg3) 116 { 117 abi_long nbytes, ret; 118 void *p; 119 120 /* nbytes < 0 implies that it was larger than SIZE_MAX. */ 121 nbytes = arg3; 122 if (nbytes < 0) { 123 return -TARGET_EINVAL; 124 } 125 p = lock_user(VERIFY_READ, arg2, nbytes, 1); 126 if (p == NULL) { 127 return -TARGET_EFAULT; 128 } 129 ret = get_errno(safe_write(arg1, p, arg3)); 130 unlock_user(p, arg2, 0); 131 132 return ret; 133 } 134 135 /* pwrite(2) */ 136 static abi_long do_bsd_pwrite(void *cpu_env, abi_long arg1, 137 abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) 138 { 139 abi_long ret; 140 void *p; 141 142 p = lock_user(VERIFY_READ, arg2, arg3, 1); 143 if (p == NULL) { 144 return -TARGET_EFAULT; 145 } 146 if (regpairs_aligned(cpu_env) != 0) { 147 arg4 = arg5; 148 arg5 = arg6; 149 } 150 ret = get_errno(safe_pwrite(arg1, p, arg3, target_arg64(arg4, arg5))); 151 unlock_user(p, arg2, 0); 152 153 return ret; 154 } 155 156 /* writev(2) */ 157 static abi_long do_bsd_writev(abi_long arg1, abi_long arg2, abi_long arg3) 158 { 159 abi_long ret; 160 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); 161 162 if (vec != NULL) { 163 ret = get_errno(safe_writev(arg1, vec, arg3)); 164 unlock_iovec(vec, arg2, arg3, 0); 165 } else { 166 ret = -host_to_target_errno(errno); 167 } 168 169 return ret; 170 } 171 172 /* pwritev(2) */ 173 static abi_long do_bsd_pwritev(void *cpu_env, abi_long arg1, 174 abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) 175 { 176 abi_long ret; 177 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); 178 179 if (vec != NULL) { 180 if (regpairs_aligned(cpu_env) != 0) { 181 arg4 = arg5; 182 arg5 = arg6; 183 } 184 ret = get_errno(safe_pwritev(arg1, vec, arg3, target_arg64(arg4, arg5))); 185 unlock_iovec(vec, arg2, arg3, 0); 186 } else { 187 ret = -host_to_target_errno(errno); 188 } 189 190 return ret; 191 } 192 193 #endif /* BSD_FILE_H */ 194