cloudabi_file.c revision 285834
1285307Sed/*- 2285307Sed * Copyright (c) 2015 Nuxi, https://nuxi.nl/ 3285307Sed * 4285307Sed * Redistribution and use in source and binary forms, with or without 5285307Sed * modification, are permitted provided that the following conditions 6285307Sed * are met: 7285307Sed * 1. Redistributions of source code must retain the above copyright 8285307Sed * notice, this list of conditions and the following disclaimer. 9285307Sed * 2. Redistributions in binary form must reproduce the above copyright 10285307Sed * notice, this list of conditions and the following disclaimer in the 11285307Sed * documentation and/or other materials provided with the distribution. 12285307Sed * 13285307Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14285307Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15285307Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16285307Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17285307Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18285307Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19285307Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20285307Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21285307Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22285307Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23285307Sed * SUCH DAMAGE. 24285307Sed */ 25285307Sed 26285307Sed#include <sys/cdefs.h> 27285307Sed__FBSDID("$FreeBSD: head/sys/compat/cloudabi/cloudabi_file.c 285834 2015-07-24 07:46:02Z ed $"); 28285307Sed 29285596Sed#include <sys/param.h> 30285596Sed#include <sys/fcntl.h> 31285834Sed#include <sys/kernel.h> 32285834Sed#include <sys/malloc.h> 33285834Sed#include <sys/namei.h> 34285596Sed#include <sys/syscallsubr.h> 35285596Sed 36285307Sed#include <compat/cloudabi/cloudabi_proto.h> 37285596Sed#include <compat/cloudabi/cloudabi_syscalldefs.h> 38285307Sed 39285834Sedstatic MALLOC_DEFINE(M_CLOUDABI_PATH, "cloudabipath", "CloudABI pathnames"); 40285834Sed 41285834Sed/* 42285834Sed * Copying pathnames from userspace to kernelspace. 43285834Sed * 44285834Sed * Unlike most operating systems, CloudABI doesn't use null-terminated 45285834Sed * pathname strings. Processes always pass pathnames to the kernel by 46285834Sed * providing a base pointer and a length. This has a couple of reasons: 47285834Sed * 48285834Sed * - It makes it easier to use CloudABI in combination with programming 49285834Sed * languages other than C, that may use non-null terminated strings. 50285834Sed * - It allows for calling system calls on individual components of the 51285834Sed * pathname without modifying the input string. 52285834Sed * 53285834Sed * The function below copies in pathname strings and null-terminates it. 54285834Sed * It also ensure that the string itself does not contain any null 55285834Sed * bytes. 56285834Sed * 57285834Sed * TODO(ed): Add an abstraction to vfs_lookup.c that allows us to pass 58285834Sed * in unterminated pathname strings, so we can do away with 59285834Sed * the copying. 60285834Sed */ 61285834Sed 62285834Sedstatic int 63285834Sedcopyin_path(const char *uaddr, size_t len, char **result) 64285834Sed{ 65285834Sed char *buf; 66285834Sed int error; 67285834Sed 68285834Sed if (len >= PATH_MAX) 69285834Sed return (ENAMETOOLONG); 70285834Sed buf = malloc(len + 1, M_CLOUDABI_PATH, M_WAITOK); 71285834Sed error = copyin(uaddr, buf, len); 72285834Sed if (error != 0) { 73285834Sed free(buf, M_CLOUDABI_PATH); 74285834Sed return (error); 75285834Sed } 76285834Sed if (memchr(buf, '\0', len) != NULL) { 77285834Sed free(buf, M_CLOUDABI_PATH); 78285834Sed return (EINVAL); 79285834Sed } 80285834Sed buf[len] = '\0'; 81285834Sed *result = buf; 82285834Sed return (0); 83285834Sed} 84285834Sed 85285834Sedstatic void 86285834Sedcloudabi_freestr(char *buf) 87285834Sed{ 88285834Sed 89285834Sed free(buf, M_CLOUDABI_PATH); 90285834Sed} 91285834Sed 92285307Sedint 93285307Sedcloudabi_sys_file_advise(struct thread *td, 94285307Sed struct cloudabi_sys_file_advise_args *uap) 95285307Sed{ 96285596Sed int advice; 97285307Sed 98285596Sed switch (uap->advice) { 99285596Sed case CLOUDABI_ADVICE_DONTNEED: 100285596Sed advice = POSIX_FADV_DONTNEED; 101285596Sed break; 102285596Sed case CLOUDABI_ADVICE_NOREUSE: 103285596Sed advice = POSIX_FADV_NOREUSE; 104285596Sed break; 105285596Sed case CLOUDABI_ADVICE_NORMAL: 106285596Sed advice = POSIX_FADV_NORMAL; 107285596Sed break; 108285596Sed case CLOUDABI_ADVICE_RANDOM: 109285596Sed advice = POSIX_FADV_RANDOM; 110285596Sed break; 111285596Sed case CLOUDABI_ADVICE_SEQUENTIAL: 112285596Sed advice = POSIX_FADV_SEQUENTIAL; 113285596Sed break; 114285596Sed case CLOUDABI_ADVICE_WILLNEED: 115285596Sed advice = POSIX_FADV_WILLNEED; 116285596Sed break; 117285596Sed default: 118285596Sed return (EINVAL); 119285596Sed } 120285596Sed 121285596Sed return (kern_posix_fadvise(td, uap->fd, uap->offset, uap->len, advice)); 122285307Sed} 123285307Sed 124285307Sedint 125285307Sedcloudabi_sys_file_allocate(struct thread *td, 126285307Sed struct cloudabi_sys_file_allocate_args *uap) 127285307Sed{ 128285307Sed 129285596Sed return (kern_posix_fallocate(td, uap->fd, uap->offset, uap->len)); 130285307Sed} 131285307Sed 132285307Sedint 133285307Sedcloudabi_sys_file_create(struct thread *td, 134285307Sed struct cloudabi_sys_file_create_args *uap) 135285307Sed{ 136285307Sed 137285307Sed /* Not implemented. */ 138285307Sed return (ENOSYS); 139285307Sed} 140285307Sed 141285307Sedint 142285307Sedcloudabi_sys_file_link(struct thread *td, 143285307Sed struct cloudabi_sys_file_link_args *uap) 144285307Sed{ 145285834Sed char *path1, *path2; 146285834Sed int error; 147285307Sed 148285834Sed error = copyin_path(uap->path1, uap->path1len, &path1); 149285834Sed if (error != 0) 150285834Sed return (error); 151285834Sed error = copyin_path(uap->path2, uap->path2len, &path2); 152285834Sed if (error != 0) { 153285834Sed cloudabi_freestr(path1); 154285834Sed return (error); 155285834Sed } 156285834Sed 157285834Sed error = kern_linkat(td, uap->fd1, uap->fd2, path1, path2, 158285834Sed UIO_SYSSPACE, (uap->fd1 & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0 ? 159285834Sed FOLLOW : NOFOLLOW); 160285834Sed cloudabi_freestr(path1); 161285834Sed cloudabi_freestr(path2); 162285834Sed return (error); 163285307Sed} 164285307Sed 165285307Sedint 166285307Sedcloudabi_sys_file_open(struct thread *td, 167285307Sed struct cloudabi_sys_file_open_args *uap) 168285307Sed{ 169285307Sed 170285307Sed /* Not implemented. */ 171285307Sed return (ENOSYS); 172285307Sed} 173285307Sed 174285307Sedint 175285307Sedcloudabi_sys_file_readdir(struct thread *td, 176285307Sed struct cloudabi_sys_file_readdir_args *uap) 177285307Sed{ 178285307Sed 179285307Sed /* Not implemented. */ 180285307Sed return (ENOSYS); 181285307Sed} 182285307Sed 183285307Sedint 184285307Sedcloudabi_sys_file_readlink(struct thread *td, 185285307Sed struct cloudabi_sys_file_readlink_args *uap) 186285307Sed{ 187285834Sed char *path; 188285834Sed int error; 189285307Sed 190285834Sed error = copyin_path(uap->path, uap->pathlen, &path); 191285834Sed if (error != 0) 192285834Sed return (error); 193285834Sed 194285834Sed error = kern_readlinkat(td, uap->fd, path, UIO_SYSSPACE, 195285834Sed uap->buf, UIO_USERSPACE, uap->bufsize); 196285834Sed cloudabi_freestr(path); 197285834Sed return (error); 198285307Sed} 199285307Sed 200285307Sedint 201285307Sedcloudabi_sys_file_rename(struct thread *td, 202285307Sed struct cloudabi_sys_file_rename_args *uap) 203285307Sed{ 204285834Sed char *old, *new; 205285834Sed int error; 206285307Sed 207285834Sed error = copyin_path(uap->old, uap->oldlen, &old); 208285834Sed if (error != 0) 209285834Sed return (error); 210285834Sed error = copyin_path(uap->new, uap->newlen, &new); 211285834Sed if (error != 0) { 212285834Sed cloudabi_freestr(old); 213285834Sed return (error); 214285834Sed } 215285834Sed 216285834Sed error = kern_renameat(td, uap->oldfd, old, uap->newfd, new, 217285834Sed UIO_SYSSPACE); 218285834Sed cloudabi_freestr(old); 219285834Sed cloudabi_freestr(new); 220285834Sed return (error); 221285307Sed} 222285307Sed 223285307Sedint 224285307Sedcloudabi_sys_file_stat_fget(struct thread *td, 225285307Sed struct cloudabi_sys_file_stat_fget_args *uap) 226285307Sed{ 227285307Sed 228285307Sed /* Not implemented. */ 229285307Sed return (ENOSYS); 230285307Sed} 231285307Sed 232285307Sedint 233285307Sedcloudabi_sys_file_stat_fput(struct thread *td, 234285307Sed struct cloudabi_sys_file_stat_fput_args *uap) 235285307Sed{ 236285307Sed 237285307Sed /* Not implemented. */ 238285307Sed return (ENOSYS); 239285307Sed} 240285307Sed 241285307Sedint 242285307Sedcloudabi_sys_file_stat_get(struct thread *td, 243285307Sed struct cloudabi_sys_file_stat_get_args *uap) 244285307Sed{ 245285307Sed 246285307Sed /* Not implemented. */ 247285307Sed return (ENOSYS); 248285307Sed} 249285307Sed 250285307Sedint 251285307Sedcloudabi_sys_file_stat_put(struct thread *td, 252285307Sed struct cloudabi_sys_file_stat_put_args *uap) 253285307Sed{ 254285307Sed 255285307Sed /* Not implemented. */ 256285307Sed return (ENOSYS); 257285307Sed} 258285307Sed 259285307Sedint 260285307Sedcloudabi_sys_file_symlink(struct thread *td, 261285307Sed struct cloudabi_sys_file_symlink_args *uap) 262285307Sed{ 263285834Sed char *path1, *path2; 264285834Sed int error; 265285307Sed 266285834Sed error = copyin_path(uap->path1, uap->path1len, &path1); 267285834Sed if (error != 0) 268285834Sed return (error); 269285834Sed error = copyin_path(uap->path2, uap->path2len, &path2); 270285834Sed if (error != 0) { 271285834Sed cloudabi_freestr(path1); 272285834Sed return (error); 273285834Sed } 274285834Sed 275285834Sed error = kern_symlinkat(td, path1, uap->fd, path2, UIO_SYSSPACE); 276285834Sed cloudabi_freestr(path1); 277285834Sed cloudabi_freestr(path2); 278285834Sed return (error); 279285307Sed} 280285307Sed 281285307Sedint 282285307Sedcloudabi_sys_file_unlink(struct thread *td, 283285307Sed struct cloudabi_sys_file_unlink_args *uap) 284285307Sed{ 285285834Sed char *path; 286285834Sed int error; 287285307Sed 288285834Sed error = copyin_path(uap->path, uap->pathlen, &path); 289285834Sed if (error != 0) 290285834Sed return (error); 291285834Sed 292285834Sed if (uap->flag & CLOUDABI_UNLINK_REMOVEDIR) 293285834Sed error = kern_rmdirat(td, uap->fd, path, UIO_SYSSPACE); 294285834Sed else 295285834Sed error = kern_unlinkat(td, uap->fd, path, UIO_SYSSPACE, 0); 296285834Sed cloudabi_freestr(path); 297285834Sed return (error); 298285307Sed} 299