blob: 0e0de23075760db0e1bd1f7a05f5888047b0261d [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fcntl.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include "unistd.h"
// checkfile, checkfileat, and checkfd let us error out if the object
// doesn't exist, which allows the stubs to be a little more 'real'
static int checkfile(const char* path, int err) {
struct stat s;
if (stat(path, &s)) {
return -1;
}
if (err) {
errno = err;
return -1;
} else {
return 0;
}
}
static int checkfileat(int fd, const char* path, int flags, int err) {
struct stat s;
if (fstatat(fd, path, &s, flags)) {
return -1;
}
if (err) {
errno = err;
return -1;
} else {
return 0;
}
}
static int checkfd(int fd, int err) {
fdio_t* io;
if ((io = fd_to_io(fd)) == NULL) {
errno = EBADF;
return -1;
}
fdio_release(io);
if (err) {
errno = err;
return -1;
} else {
return 0;
}
}
// not supported by any filesystems yet
int symlink(const char* existing, const char* new) {
errno = ENOSYS;
return -1;
}
ssize_t readlink(const char* restrict path, char* restrict buf, size_t bufsize) {
// EINVAL = not symlink
return checkfile(path, EINVAL);
}
// creating things we don't have plumbing for yet
int mkfifo(const char *path, mode_t mode) {
errno = ENOSYS;
return -1;
}
int mknod(const char* path, mode_t mode, dev_t dev) {
errno = ENOSYS;
return -1;
}
// no permissions support yet
int chown(const char *path, uid_t owner, gid_t group) {
return checkfile(path, ENOSYS);
}
int fchown(int fd, uid_t owner, gid_t group) {
return checkfd(fd, ENOSYS);
}
int lchown(const char *path, uid_t owner, gid_t group) {
return checkfile(path, ENOSYS);
}
// no permissions support, but treat rwx bits as don't care rather than error
int chmod(const char *path, mode_t mode) {
return checkfile(path, (mode & (~0777)) ? ENOSYS : 0);
}
int fchmod(int fd, mode_t mode) {
return checkfd(fd, (mode & (~0777)) ? ENOSYS : 0);
}
int fchmodat(int fd, const char* path, mode_t mode, int flags) {
if (flags & ~AT_SYMLINK_NOFOLLOW) {
errno = EINVAL;
return -1;
}
return checkfileat(fd, path, flags, (mode & (~0777)) ? ENOSYS : 0);
}
int access(const char* path, int mode) {
return checkfile(path, 0);
}
void sync(void) {
}
// at the moment our unlink works on all fs objects
int rmdir(const char* path) {
return unlink(path);
}
// tty stubbing.
int ttyname_r(int fd, char* name, size_t size) {
if (!isatty(fd)) {
return ENOTTY;
}
return checkfd(fd, ENOSYS);
}