Revert "[fs] Use the Fuchsia-defined open flags"

This reverts commit 2aff2cba029cf0f7e98e6d19f6dc7a663c318227.

Reason for revert: Fuchsia uses upstream Rust, which doesn't pull these constants from our C library, but their own. I'll need to wait a few days for us to update upstream Rust before we can make progress here.

Original change's description:
> [fs] Use the Fuchsia-defined open flags
> 
> This change uses the Fuchsia-defined flags on the wire
> as well as on filesystem servers. Clients interacting
> with filesystems through the POSIX compatibility layer
> can continue using POSIX open flags; they will be translated
> by the RIO layers client-side.
> 
> ZX-1359 #comment In Progress
> 
> Change-Id: I27dfdea2024183d5d59daa1ed7d8886d89d503d0

TBR=kulakowski@google.com,smklein@google.com,swetland@google.com,mcgrathr@google.com,planders@google.com

Change-Id: If93c2da36f92ea28ed013a61c01c6ec521da26cc
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
diff --git a/system/core/devmgr/devhost-rpc-server.c b/system/core/devmgr/devhost-rpc-server.c
index 52d71d9..b80d2c7 100644
--- a/system/core/devmgr/devhost-rpc-server.c
+++ b/system/core/devmgr/devhost-rpc-server.c
@@ -31,8 +31,8 @@
 
 #define MXDEBUG 0
 
-#define CAN_WRITE(ios) (ios->flags & ZX_FS_RIGHT_WRITABLE)
-#define CAN_READ(ios) (ios->flags & ZX_FS_RIGHT_READABLE)
+#define CAN_WRITE(ios) (((03 & ios->flags) == O_RDWR) || ((03 & ios->flags) == O_WRONLY))
+#define CAN_READ(ios) (((03 & ios->flags) == O_RDWR) || ((03 & ios->flags) == O_RDONLY))
 
 devhost_iostate_t* create_devhost_iostate(zx_device_t* dev) {
     devhost_iostate_t* ios;
@@ -56,8 +56,8 @@
 
     // detect pipeline directive and discard all other
     // protocol flags
-    bool pipeline = flags & ZX_FS_FLAG_PIPELINE;
-    flags &= (~ZX_FS_FLAG_PIPELINE);
+    bool pipeline = flags & O_PIPELINE;
+    flags &= (~O_PIPELINE);
 
     newios->flags = flags;
 
@@ -317,7 +317,7 @@
             }
         } else {
             xprintf("devhost_rio_handler() clone dev %p name '%s'\n", dev, dev->name);
-            flags = ios->flags | (flags & ZX_FS_FLAG_PIPELINE);
+            flags = ios->flags | (flags & O_PIPELINE);
         }
         devhost_get_handles(msg->handle[0], dev, path, flags);
         return ERR_DISPATCHER_INDIRECT;
diff --git a/system/core/devmgr/devmgr-devfs.c b/system/core/devmgr/devmgr-devfs.c
index a6efea4..6fb6711 100644
--- a/system/core/devmgr/devmgr-devfs.c
+++ b/system/core/devmgr/devmgr-devfs.c
@@ -464,14 +464,14 @@
     devnode_t* dn = dirdn;
     zx_status_t r = devfs_walk(&dn, path, &path);
 
-    bool pipeline = flags & ZX_FS_FLAG_PIPELINE;
+    bool pipeline = flags & O_PIPELINE;
 
     if (r == ZX_ERR_NEXT) {
         // we only partially matched -- there's more path to walk
         if ((dn->device == NULL) || (dn->device->hrpc == ZX_HANDLE_INVALID)) {
             // no remote to pass this on to
             r = ZX_ERR_NOT_FOUND;
-        } else if (flags & (ZX_FS_FLAG_NOREMOTE | ZX_FS_FLAG_DIRECTORY)) {
+        } else if (flags & (O_NOREMOTE | O_DIRECTORY)) {
             // local requested, but this is remote only
             r = ZX_ERR_NOT_SUPPORTED;
         } else {
@@ -495,7 +495,7 @@
 
     // If we are a local-only node, or we are asked to not go remote,
     // or we are asked to open-as-a-directory, open locally:
-    if ((flags & (ZX_FS_FLAG_NOREMOTE | ZX_FS_FLAG_DIRECTORY)) || devnode_is_local(dn)) {
+    if ((flags & (O_NOREMOTE | O_DIRECTORY)) || devnode_is_local(dn)) {
         if ((r = iostate_create(dn, h)) < 0) {
             goto fail;
         }
@@ -596,7 +596,7 @@
     switch (ZXRIO_OP(msg->op)) {
     case ZXRIO_CLONE:
         msg->data[0] = 0;
-        devfs_open(dn, msg->handle[0], (char*) msg->data, arg | ZX_FS_FLAG_NOREMOTE);
+        devfs_open(dn, msg->handle[0], (char*) msg->data, arg | O_NOREMOTE);
         return ERR_DISPATCHER_INDIRECT;
     case ZXRIO_OPEN:
         if ((len < 1) || (len > 1024)) {
diff --git a/system/core/devmgr/vfs-memory.cpp b/system/core/devmgr/vfs-memory.cpp
index eeb7057..dc39d22 100644
--- a/system/core/devmgr/vfs-memory.cpp
+++ b/system/core/devmgr/vfs-memory.cpp
@@ -104,28 +104,32 @@
 }
 
 zx_status_t VnodeDir::ValidateFlags(uint32_t flags) {
-    if (flags & ZX_FS_RIGHT_WRITABLE) {
+    switch (flags & O_ACCMODE) {
+    case O_WRONLY:
+    case O_RDWR:
         return ZX_ERR_NOT_FILE;
     }
     return ZX_OK;
 }
 
 zx_status_t VnodeFile::ValidateFlags(uint32_t flags) {
-    if (flags & ZX_FS_FLAG_DIRECTORY) {
+    if (flags & O_DIRECTORY) {
         return ZX_ERR_NOT_DIR;
     }
     return ZX_OK;
 }
 
 zx_status_t VnodeVmo::ValidateFlags(uint32_t flags) {
-    if (flags & ZX_FS_FLAG_DIRECTORY) {
+    if (flags & O_DIRECTORY) {
         return ZX_ERR_NOT_DIR;
     }
-    if (flags & ZX_FS_RIGHT_WRITABLE) {
-        return ZX_ERR_ACCESS_DENIED;
+    switch (flags & O_ACCMODE) {
+        case O_WRONLY:
+        case O_RDWR:
+            return ZX_ERR_ACCESS_DENIED;
+        }
+        return ZX_OK;
     }
-    return ZX_OK;
-}
 
 zx_status_t VnodeVmo::Serve(fs::Vfs* vfs, zx::channel channel, uint32_t flags) {
     return ZX_OK;
@@ -818,9 +822,9 @@
         fbl::RefPtr<fs::Vnode> vn;
         fbl::StringPiece pathout;
         ZX_ASSERT(memfs::root_vfs.Open(memfs::global_root, &vn, fbl::StringPiece("/data"), &pathout,
-                                       ZX_FS_RIGHT_READABLE | ZX_FS_FLAG_CREATE, S_IFDIR) == ZX_OK);
+                                       O_CREAT, S_IFDIR) == ZX_OK);
         ZX_ASSERT(memfs::root_vfs.Open(memfs::global_root, &vn, fbl::StringPiece("/volume"), &pathout,
-                                       ZX_FS_RIGHT_READABLE | ZX_FS_FLAG_CREATE, S_IFDIR) == ZX_OK);
+                                       O_CREAT, S_IFDIR) == ZX_OK);
 
         memfs::global_loop.reset(new async::Loop());
         memfs::global_loop->StartThread("root-dispatcher");
diff --git a/system/public/zircon/device/vfs.h b/system/public/zircon/device/vfs.h
index 2a39bfa..8e6b8dc 100644
--- a/system/public/zircon/device/vfs.h
+++ b/system/public/zircon/device/vfs.h
@@ -15,13 +15,12 @@
 #define ZX_FS_RIGHT_WRITABLE      0x00000002
 // The connection can mount and unmount filesystems.
 #define ZX_FS_RIGHT_ADMIN         0x00000004
-#define ZX_FS_RIGHTS              0x0000FFFF
 
 // Flags
 // If the file does not exist, it will be created.
 #define ZX_FS_FLAG_CREATE         0x00010000
-// The file must not exist, otherwise an error will be returned.
-// Ignored without ZX_FS_FLAG_CREATE.
+// The file must not exist, otherwise an error will be returned. Must be used
+// with ZX_FS_FLAG_CREATE.
 #define ZX_FS_FLAG_EXCLUSIVE      0x00020000
 // Truncates the file before using it.
 #define ZX_FS_FLAG_TRUNCATE       0x00040000
diff --git a/system/uapp/blobstore/blobstore-ops.cpp b/system/uapp/blobstore/blobstore-ops.cpp
index 573bde2..9d559a0 100644
--- a/system/uapp/blobstore/blobstore-ops.cpp
+++ b/system/uapp/blobstore/blobstore-ops.cpp
@@ -39,11 +39,13 @@
 }
 
 zx_status_t VnodeBlob::ValidateFlags(uint32_t flags) {
-    if ((flags & ZX_FS_FLAG_DIRECTORY) && !IsDirectory()) {
+    if ((flags & O_DIRECTORY) && !IsDirectory()) {
         return ZX_ERR_NOT_DIR;
     }
 
-    if (flags & ZX_FS_RIGHT_WRITABLE) {
+    switch (flags & O_ACCMODE) {
+    case O_WRONLY:
+    case O_RDWR:
         if (IsDirectory()) {
             return ZX_ERR_NOT_FILE;
         } else if (GetState() != kBlobStateEmpty) {
diff --git a/system/uapp/minfs/host.cpp b/system/uapp/minfs/host.cpp
index ab3457b..3a0e0d0 100644
--- a/system/uapp/minfs/host.cpp
+++ b/system/uapp/minfs/host.cpp
@@ -140,44 +140,6 @@
     return 0;
 }
 
-// Since this is a host-side tool, the client may be bringing
-// their own C library, and we do not have the guarantee that
-// our ZX_FS flags align with the O_* flags.
-uint32_t fdio_flags_to_zxio(uint32_t flags) {
-    uint32_t result = 0;
-    switch (flags & O_ACCMODE) {
-    case O_RDONLY:
-        result |= ZX_FS_RIGHT_READABLE;
-        break;
-    case O_WRONLY:
-        result |= ZX_FS_RIGHT_WRITABLE;
-        break;
-    case O_RDWR:
-        result |= ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE;
-        break;
-    }
-    if (flags & O_PATH) {
-        result |= ZX_FS_FLAG_VNODE_REF_ONLY;
-    }
-    if (flags & O_CREAT) {
-        result |= ZX_FS_FLAG_CREATE;
-    }
-    if (flags & O_EXCL) {
-        result |= ZX_FS_FLAG_EXCLUSIVE;
-    }
-    if (flags & O_TRUNC) {
-        result |= ZX_FS_FLAG_TRUNCATE;
-    }
-    if (flags & O_DIRECTORY) {
-        result |= ZX_FS_FLAG_DIRECTORY;
-    }
-    if (flags & O_APPEND) {
-        result |= ZX_FS_FLAG_APPEND;
-    }
-
-    return result;
-}
-
 int emu_open(const char* path, int flags, mode_t mode) {
     //TODO: fdtab lock
     ZX_DEBUG_ASSERT_MSG(!host_path(path), "'emu_' functions can only operate on target paths");
@@ -190,7 +152,6 @@
         if (fdtab[fd].vn == nullptr) {
             fbl::RefPtr<fs::Vnode> vn_fs;
             fbl::StringPiece str(path + PREFIX_SIZE);
-            flags = fdio_flags_to_zxio(flags);
             zx_status_t status = fake_vfs.Open(fake_root, &vn_fs, str, &str, flags, mode);
             if (status < 0) {
                 STATUS(status);
diff --git a/system/uapp/minfs/minfs-ops.cpp b/system/uapp/minfs/minfs-ops.cpp
index ba3e3c0..9458dc2 100644
--- a/system/uapp/minfs/minfs-ops.cpp
+++ b/system/uapp/minfs/minfs-ops.cpp
@@ -1076,12 +1076,16 @@
 
 zx_status_t VnodeMinfs::ValidateFlags(uint32_t flags) {
     FS_TRACE(MINFS, "VnodeMinfs::ValidateFlags(0x%x) vn=%p(#%u)\n", flags, this, ino_);
-    if ((flags & ZX_FS_FLAG_DIRECTORY) && !IsDirectory()) {
+    if ((flags & O_DIRECTORY) && !IsDirectory()) {
         return ZX_ERR_NOT_DIR;
     }
 
-    if ((flags & ZX_FS_RIGHT_WRITABLE) && IsDirectory()) {
-        return ZX_ERR_NOT_FILE;
+    switch (flags & O_ACCMODE) {
+    case O_WRONLY:
+    case O_RDWR:
+        if (IsDirectory()) {
+            return ZX_ERR_NOT_FILE;
+        }
     }
 
     return ZX_OK;
diff --git a/system/ulib/fdio/namespace.c b/system/ulib/fdio/namespace.c
index a3cb7ee..c4510e4 100644
--- a/system/ulib/fdio/namespace.c
+++ b/system/ulib/fdio/namespace.c
@@ -270,7 +270,7 @@
 // Expects a canonical path (no ..) with no leading
 // slash and no trailing slash
 static zx_status_t mxdir_open(fdio_t* io, const char* path,
-                              uint32_t flags, uint32_t mode,
+                              int32_t flags, uint32_t mode,
                               fdio_t** out) {
     mxdir_t* dir = (mxdir_t*) io;
     mxvn_t* vn = dir->vn;
diff --git a/system/ulib/fdio/null.c b/system/ulib/fdio/null.c
index f468cd6..b0af66c 100644
--- a/system/ulib/fdio/null.c
+++ b/system/ulib/fdio/null.c
@@ -59,7 +59,7 @@
     return ZX_ERR_NOT_SUPPORTED;
 }
 
-zx_status_t fdio_default_open(fdio_t* io, const char* path, uint32_t flags, uint32_t mode, fdio_t** out) {
+zx_status_t fdio_default_open(fdio_t* io, const char* path, int32_t flags, uint32_t mode, fdio_t** out) {
     return ZX_ERR_NOT_SUPPORTED;
 }
 
diff --git a/system/ulib/fdio/private-remoteio.h b/system/ulib/fdio/private-remoteio.h
index 4b556b7..53c045c 100644
--- a/system/ulib/fdio/private-remoteio.h
+++ b/system/ulib/fdio/private-remoteio.h
@@ -25,17 +25,17 @@
 // which needs lower level access to remoteio internals
 
 // open operation directly on remoteio handle
-zx_status_t zxrio_open_handle(zx_handle_t h, const char* path, uint32_t flags,
+zx_status_t zxrio_open_handle(zx_handle_t h, const char* path, int32_t flags,
                               uint32_t mode, fdio_t** out);
 
 // open operation directly on remoteio handle
 // returns new remoteio handle on success
 // fails and discards non-REMOTE protocols
-zx_status_t zxrio_open_handle_raw(zx_handle_t h, const char* path, uint32_t flags,
+zx_status_t zxrio_open_handle_raw(zx_handle_t h, const char* path, int32_t flags,
                                   uint32_t mode, zx_handle_t *out);
 
 // open operation directly on remoteio fdio_t
-zx_status_t zxrio_open(fdio_t* io, const char* path, uint32_t flags,
+zx_status_t zxrio_open(fdio_t* io, const char* path, int32_t flags,
                        uint32_t mode, fdio_t** out);
 
 // misc operation directly on remoteio fdio_t
@@ -51,5 +51,5 @@
                     size_t in_len, void* out_buf, size_t out_len);
 
 zx_status_t zxrio_getobject(zx_handle_t rio_h, uint32_t op, const char* name,
-                            uint32_t flags, uint32_t mode,
+                            int32_t flags, uint32_t mode,
                             zxrio_object_t* info);
diff --git a/system/ulib/fdio/private.h b/system/ulib/fdio/private.h
index 9daf7c4..fd0ce7c 100644
--- a/system/ulib/fdio/private.h
+++ b/system/ulib/fdio/private.h
@@ -40,7 +40,7 @@
     off_t (*seek)(fdio_t* io, off_t offset, int whence);
     zx_status_t (*misc)(fdio_t* io, uint32_t op, int64_t off, uint32_t maxreply, void* data, size_t len);
     zx_status_t (*close)(fdio_t* io);
-    zx_status_t (*open)(fdio_t* io, const char* path, uint32_t flags, uint32_t mode, fdio_t** out);
+    zx_status_t (*open)(fdio_t* io, const char* path, int32_t flags, uint32_t mode, fdio_t** out);
     zx_status_t (*clone)(fdio_t* io, zx_handle_t* out_handles, uint32_t* out_types);
     zx_status_t (*unwrap)(fdio_t* io, zx_handle_t* out_handles, uint32_t* out_types);
     zx_status_t (*shutdown)(fdio_t* io, int how);
@@ -69,7 +69,7 @@
     uint32_t magic;
     atomic_int_fast32_t refcount;
     int32_t dupcount;
-    uint32_t flags;
+    int32_t flags;
 } fdio_t;
 
 // Lifecycle notes:
@@ -115,7 +115,7 @@
 static inline zx_status_t fdio_misc(fdio_t* io, uint32_t op, int64_t off, uint32_t maxreply, void* data, size_t len) {
     return io->ops->misc(io, op, off, maxreply, data, len);
 }
-static inline zx_status_t fdio_open(fdio_t* io, const char* path, uint32_t flags, uint32_t mode, fdio_t** out) {
+static inline zx_status_t fdio_open(fdio_t* io, const char* path, int32_t flags, uint32_t mode, fdio_t** out) {
     return io->ops->open(io, path, flags, mode, out);
 }
 zx_status_t fdio_close(fdio_t* io);
@@ -183,7 +183,7 @@
 off_t fdio_default_seek(fdio_t* io, off_t offset, int whence);
 zx_status_t fdio_default_misc(fdio_t* io, uint32_t op, int64_t off, uint32_t arg, void* data, size_t len);
 zx_status_t fdio_default_close(fdio_t* io);
-zx_status_t fdio_default_open(fdio_t* io, const char* path, uint32_t flags, uint32_t mode, fdio_t** out);
+zx_status_t fdio_default_open(fdio_t* io, const char* path, int32_t flags, uint32_t mode, fdio_t** out);
 zx_status_t fdio_default_clone(fdio_t* io, zx_handle_t* handles, uint32_t* types);
 ssize_t fdio_default_ioctl(fdio_t* io, uint32_t op, const void* in_buf, size_t in_len, void* out_buf, size_t out_len);
 void fdio_default_wait_begin(fdio_t* io, uint32_t events, zx_handle_t* handle, zx_signals_t* _signals);
diff --git a/system/ulib/fdio/remoteio.c b/system/ulib/fdio/remoteio.c
index d246b00..0d50524 100644
--- a/system/ulib/fdio/remoteio.c
+++ b/system/ulib/fdio/remoteio.c
@@ -16,7 +16,6 @@
 
 #include <zircon/device/device.h>
 #include <zircon/device/ioctl.h>
-#include <zircon/device/vfs.h>
 #include <zircon/processargs.h>
 #include <zircon/syscalls.h>
 
@@ -521,7 +520,7 @@
 // This function always consumes the cnxn handle
 // The svc handle is only used to send a message
 static zx_status_t zxrio_connect(zx_handle_t svc, zx_handle_t cnxn,
-                                 uint32_t op, uint32_t flags, uint32_t mode,
+                                 uint32_t op, int32_t flags, uint32_t mode,
                                  const char* name) {
     size_t len = strlen(name);
     if (len >= PATH_MAX) {
@@ -533,7 +532,7 @@
     memset(&msg, 0, ZXRIO_HDR_SZ);
     msg.op = op;
     msg.datalen = len;
-    msg.arg = ZX_FS_FLAG_PIPELINE | flags;
+    msg.arg = O_PIPELINE | flags;
     msg.arg2.mode = mode;
     msg.hcount = 1;
     msg.handle[0] = cnxn;
@@ -571,8 +570,7 @@
         zx_handle_close(h);
         return ZX_ERR_UNAVAILABLE;
     }
-    return zxrio_connect(dir, h, ZXRIO_OPEN, ZX_FS_RIGHT_READABLE |
-                         ZX_FS_RIGHT_WRITABLE, 0755, path);
+    return zxrio_connect(dir, h, ZXRIO_OPEN, O_RDWR, 0755, path);
 }
 
 zx_handle_t fdio_service_clone(zx_handle_t svc) {
@@ -584,8 +582,7 @@
     if ((r = zx_channel_create(0, &cli, &srv)) < 0) {
         return ZX_HANDLE_INVALID;
     }
-    if ((r = zxrio_connect(svc, srv, ZXRIO_CLONE, ZX_FS_RIGHT_READABLE |
-                           ZX_FS_RIGHT_WRITABLE, 0755, "")) < 0) {
+    if ((r = zxrio_connect(svc, srv, ZXRIO_CLONE, O_RDWR, 0755, "")) < 0) {
         zx_handle_close(cli);
         return ZX_HANDLE_INVALID;
     }
@@ -600,8 +597,7 @@
         zx_handle_close(srv);
         return ZX_ERR_INVALID_ARGS;
     }
-    return zxrio_connect(svc, srv, ZXRIO_CLONE, ZX_FS_RIGHT_READABLE |
-                         ZX_FS_RIGHT_WRITABLE, 0755, "");
+    return zxrio_connect(svc, srv, ZXRIO_CLONE, O_RDWR, 0755, "");
 }
 
 zx_status_t zxrio_misc(fdio_t* io, uint32_t op, int64_t off,
@@ -796,7 +792,7 @@
 }
 
 zx_status_t zxrio_getobject(zx_handle_t rio_h, uint32_t op, const char* name,
-                            uint32_t flags, uint32_t mode,
+                            int32_t flags, uint32_t mode,
                             zxrio_object_t* info) {
     if (name == NULL) {
         return ZX_ERR_INVALID_ARGS;
@@ -807,7 +803,7 @@
         return ZX_ERR_BAD_PATH;
     }
 
-    if (flags & ZX_FS_FLAG_PIPELINE) {
+    if (flags & O_PIPELINE) {
         zx_handle_t h0, h1;
         zx_status_t r;
         if ((r = zx_channel_create(0, &h0, &h1)) < 0) {
@@ -837,7 +833,7 @@
     }
 }
 
-zx_status_t zxrio_open_handle(zx_handle_t h, const char* path, uint32_t flags,
+zx_status_t zxrio_open_handle(zx_handle_t h, const char* path, int32_t flags,
                               uint32_t mode, fdio_t** out) {
     zxrio_object_t info;
     zx_status_t r = zxrio_getobject(h, ZXRIO_OPEN, path, flags, mode, &info);
@@ -847,7 +843,7 @@
     return fdio_from_handles(info.type, info.handle, info.hcount, info.extra, info.esize, out);
 }
 
-zx_status_t zxrio_open_handle_raw(zx_handle_t h, const char* path, uint32_t flags,
+zx_status_t zxrio_open_handle_raw(zx_handle_t h, const char* path, int32_t flags,
                                   uint32_t mode, zx_handle_t *out) {
     zxrio_object_t info;
     zx_status_t r = zxrio_getobject(h, ZXRIO_OPEN, path, flags, mode, &info);
@@ -867,7 +863,7 @@
     return ZX_ERR_WRONG_TYPE;
 }
 
-zx_status_t zxrio_open(fdio_t* io, const char* path, uint32_t flags, uint32_t mode, fdio_t** out) {
+zx_status_t zxrio_open(fdio_t* io, const char* path, int32_t flags, uint32_t mode, fdio_t** out) {
     zxrio_t* rio = (void*)io;
     return zxrio_open_handle(rio->h, path, flags, mode, out);
 }
diff --git a/system/ulib/fdio/unistd.c b/system/ulib/fdio/unistd.c
index b3b19b8..f1bafa0 100644
--- a/system/ulib/fdio/unistd.c
+++ b/system/ulib/fdio/unistd.c
@@ -166,72 +166,6 @@
     return io->ops->close(io);
 }
 
-// Verify the O_* flags which align with ZXIO_FS_*.
-static_assert(O_PATH == ZX_FS_FLAG_VNODE_REF_ONLY, "Open Flag mismatch");
-static_assert(O_ADMIN == ZX_FS_RIGHT_ADMIN, "Open Flag mismatch");
-static_assert(O_CREAT == ZX_FS_FLAG_CREATE, "Open Flag mismatch");
-static_assert(O_EXCL == ZX_FS_FLAG_EXCLUSIVE, "Open Flag mismatch");
-static_assert(O_TRUNC == ZX_FS_FLAG_TRUNCATE, "Open Flag mismatch");
-static_assert(O_DIRECTORY == ZX_FS_FLAG_DIRECTORY, "Open Flag mismatch");
-static_assert(O_APPEND == ZX_FS_FLAG_APPEND, "Open Flag mismatch");
-static_assert(O_NOREMOTE == ZX_FS_FLAG_NOREMOTE, "Open Flag mismatch");
-static_assert(O_PIPELINE == ZX_FS_FLAG_PIPELINE, "Open Flag mismatch");
-
-// The mask of "1:1" flags which match between both open flag representations.
-#define ZXIO_FS_MASK (O_PATH | O_ADMIN | O_CREAT | O_EXCL | O_TRUNC | \
-                      O_DIRECTORY | O_APPEND | O_NOREMOTE | O_PIPELINE)
-
-// Verify that the remaining O_* flags don't overlap with the ZXIO mask.
-static_assert(!(O_RDONLY & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_WRONLY & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_RDWR & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_NONBLOCK & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_DSYNC & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_SYNC & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_RSYNC & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_NOFOLLOW & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_CLOEXEC & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_NOCTTY & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_ASYNC & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_DIRECT & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_LARGEFILE & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_NOATIME & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-static_assert(!(O_TMPFILE & ZXIO_FS_MASK), "Unexpected collision with ZXIO_FS_MASK");
-
-static uint32_t fdio_flags_to_zxio(uint32_t flags) {
-    uint32_t result = 0;
-    switch (flags & O_ACCMODE) {
-    case O_RDONLY:
-        result |= ZX_FS_RIGHT_READABLE;
-        break;
-    case O_WRONLY:
-        result |= ZX_FS_RIGHT_WRITABLE;
-        break;
-    case O_RDWR:
-        result |= ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE;
-        break;
-    }
-
-    result |= (flags & ZXIO_FS_MASK);
-    return result;
-}
-
-static uint32_t zxio_flags_to_fdio(uint32_t flags) {
-    uint32_t result = 0;
-    if ((flags & (ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE)) ==
-        (ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE)) {
-        result |= O_RDWR;
-    } else if (flags & ZX_FS_RIGHT_WRITABLE) {
-        result |= O_WRONLY;
-    } else {
-        result |= O_RDONLY;
-    }
-
-    result |= (flags & ZXIO_FS_MASK);
-    return result;
-}
-
-
 // Possibly return an owned fdio_t corresponding to either the root,
 // the cwd, or, for the ...at variants, dirfd. In the absolute path
 // case, *path is also adjusted.
@@ -379,7 +313,7 @@
     }
     flags |= (is_dir ? O_DIRECTORY : 0);
 
-    status = iodir->ops->open(iodir, clean, fdio_flags_to_zxio(flags), mode, io);
+    status = iodir->ops->open(iodir, clean, flags, mode, io);
     fdio_release(iodir);
     return status;
 }
@@ -508,8 +442,7 @@
         clean[1] = 0;
     }
 
-    zx_status_t r = iodir->ops->open(iodir, clean,
-                                     fdio_flags_to_zxio(O_RDONLY | O_DIRECTORY), 0, io);
+    zx_status_t r = iodir->ops->open(iodir, clean, O_RDONLY | O_DIRECTORY, 0, io);
     fdio_release(iodir);
     return r;
 }
@@ -1169,7 +1102,6 @@
             flags = 0;
             r = ZX_OK;
         }
-        flags = zxio_flags_to_fdio(flags);
         if (io->flags & FDIO_FLAG_NONBLOCK) {
             flags |= O_NONBLOCK;
         }
@@ -1193,8 +1125,7 @@
             // support FCNTL but it's still valid to set non-blocking
             r = ZX_OK;
         } else {
-            uint32_t flags = fdio_flags_to_zxio(n & ~O_NONBLOCK);
-            r = io->ops->misc(io, ZXRIO_FCNTL, flags, F_SETFL, NULL, 0);
+            r = io->ops->misc(io, ZXRIO_FCNTL, n & (~O_NONBLOCK), F_SETFL, NULL, 0);
         }
         if (r != ZX_OK) {
             n = STATUS(r);
diff --git a/system/ulib/fs/connection.cpp b/system/ulib/fs/connection.cpp
index 48fadb2..20f3a9c 100644
--- a/system/ulib/fs/connection.cpp
+++ b/system/ulib/fs/connection.cpp
@@ -47,16 +47,16 @@
 void OpenAt(Vfs* vfs, fbl::RefPtr<Vnode> parent,
             zxrio_msg_t* msg, zx::channel channel,
             fbl::StringPiece path, uint32_t flags, uint32_t mode) {
-    // Filter out flags that are invalid when combined with REF_ONLY.
+    // Filter out flags that are invalid when combined with O_PATH
     if (IsPathOnly(flags)) {
-        flags &= ZX_FS_FLAG_VNODE_REF_ONLY | ZX_FS_FLAG_DIRECTORY | ZX_FS_FLAG_PIPELINE;
+        flags &= O_PATH | O_DIRECTORY | O_NOFOLLOW | O_PIPELINE;
     }
 
     // The pipeline directive instructs the VFS layer to open the vnode
     // immediately, rather than describing the VFS object to the caller.
     // We check it early so we can throw away the protocol part of flags.
-    bool pipeline = flags & ZX_FS_FLAG_PIPELINE;
-    uint32_t open_flags = flags & (~ZX_FS_FLAG_PIPELINE);
+    bool pipeline = flags & O_PIPELINE;
+    uint32_t open_flags = flags & (~O_PIPELINE);
     size_t hcount = 0;
 
     fbl::RefPtr<Vnode> vnode;
@@ -66,7 +66,7 @@
     memset(&obj, 0, sizeof(obj));
     if (r != ZX_OK) {
         xprintf("vfs: open: r=%d\n", r);
-    } else if (!(open_flags & ZX_FS_FLAG_NOREMOTE) && vnode->IsRemote()) {
+    } else if (!(open_flags & O_NOREMOTE) && vnode->IsRemote()) {
         // Remote handoff to a remote filesystem node.
         //
         // TODO(smklein): There exists a race between multiple threads
@@ -217,7 +217,7 @@
         zx::channel channel(msg->handle[0]); // take ownership
         if ((len < 1) || (len > PATH_MAX)) {
             WriteErrorReply(fbl::move(channel), ZX_ERR_INVALID_ARGS);
-        } else if ((arg & ZX_FS_RIGHT_ADMIN) && !(flags_ & ZX_FS_RIGHT_ADMIN)) {
+        } else if ((arg & O_ADMIN) && !(flags_ & O_ADMIN)) {
             WriteErrorReply(fbl::move(channel), ZX_ERR_ACCESS_DENIED);
         } else {
             path[len] = 0;
@@ -235,7 +235,7 @@
     }
     case ZXRIO_CLONE: {
         zx::channel channel(msg->handle[0]); // take ownership
-        if (!(arg & ZX_FS_FLAG_PIPELINE)) {
+        if (!(arg & O_PIPELINE)) {
             zxrio_object_t obj;
             memset(&obj, 0, ZXRIO_OBJECT_MINSIZE);
             obj.type = FDIO_PROTOCOL_REMOTE;
@@ -277,7 +277,7 @@
 
         size_t actual;
         zx_status_t status;
-        if (flags_ & ZX_FS_FLAG_APPEND) {
+        if (flags_ & O_APPEND) {
             size_t end;
             status = vnode_->Append(msg->data, len, &end, &actual);
             if (status == ZX_OK) {
@@ -382,10 +382,10 @@
     }
     case ZXRIO_FCNTL: {
         uint32_t cmd = msg->arg;
-        constexpr uint32_t kStatusFlags = ZX_FS_FLAG_APPEND;
+        constexpr uint32_t kStatusFlags = O_APPEND;
         switch (cmd) {
         case F_GETFL:
-            msg->arg2.mode = flags_ & (kStatusFlags | ZX_FS_RIGHTS | ZX_FS_FLAG_VNODE_REF_ONLY);
+            msg->arg2.mode = flags_ & (kStatusFlags | O_ACCMODE);
             return ZX_OK;
         case F_SETFL:
             flags_ = (flags_ & ~kStatusFlags) | (msg->arg2.mode & kStatusFlags);
@@ -439,7 +439,7 @@
         case IOCTL_VFS_MOUNT_FS:
         case IOCTL_VFS_MOUNT_MKDIR_FS:
             // Mounting requires ADMIN privileges
-            if (!(flags_ & ZX_FS_RIGHT_ADMIN)) {
+            if (!(flags_ & O_ADMIN)) {
                 vfs_unmount_handle(msg->handle[0], 0);
                 zx_handle_close(msg->handle[0]);
                 return ZX_ERR_ACCESS_DENIED;
@@ -488,7 +488,7 @@
         case IOCTL_VFS_UNMOUNT_FS:
         case IOCTL_VFS_GET_DEVICE_PATH:
             // Unmounting ioctls require Connection privileges
-            if (!(flags_ & ZX_FS_RIGHT_ADMIN)) {
+            if (!(flags_ & O_ADMIN)) {
                 return ZX_ERR_ACCESS_DENIED;
             }
         // If our permissions validate, fall through to the VFS ioctl
@@ -569,7 +569,7 @@
             return ZX_ERR_INVALID_ARGS;
         }
         zxrio_mmap_data_t* data = reinterpret_cast<zxrio_mmap_data_t*>(msg->data);
-        if ((flags_ & ZX_FS_FLAG_APPEND) && data->flags & FDIO_MMAP_FLAG_WRITE) {
+        if ((flags_ & O_APPEND) && data->flags & FDIO_MMAP_FLAG_WRITE) {
             return ZX_ERR_ACCESS_DENIED;
         } else if (!IsWritable(flags_) && (data->flags & FDIO_MMAP_FLAG_WRITE)) {
             return ZX_ERR_ACCESS_DENIED;
diff --git a/system/ulib/fs/include/fs/connection.h b/system/ulib/fs/include/fs/connection.h
index ac9b31b..871a4ba 100644
--- a/system/ulib/fs/include/fs/connection.h
+++ b/system/ulib/fs/include/fs/connection.h
@@ -34,8 +34,7 @@
     // |vfs| is the VFS which is responsible for dispatching operations to the vnode.
     // |vnode| is the vnode which will handle I/O requests.
     // |channel| is the channel on which the RIO protocol will be served.
-    // |flags| are the file flags passed to |open()|, such as
-    // |ZX_FS_RIGHT_READABLE|.
+    // |flags| are the file flags passed to |open()|, such as |O_RDONLY|.
     Connection(fs::Vfs* vfs, fbl::RefPtr<fs::Vnode> vnode, zx::channel channel,
                uint32_t flags);
 
@@ -72,7 +71,7 @@
     // The object field is |ZX_HANDLE_INVALID| when not actively waiting.
     async::Wait wait_;
 
-    // Open flags such as |ZX_FS_RIGHT_READABLE|, and other bits.
+    // Open flags such as |O_RDONLY|, |O_ADMIN|, and other bits.
     uint32_t flags_;
 
     // Handle to event which allows client to refer to open vnodes in multi-path
diff --git a/system/ulib/fs/include/fs/vfs.h b/system/ulib/fs/include/fs/vfs.h
index 69961d8..72aafdd 100644
--- a/system/ulib/fs/include/fs/vfs.h
+++ b/system/ulib/fs/include/fs/vfs.h
@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include <fcntl.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -33,21 +34,36 @@
 #include <fbl/string_piece.h>
 #include <fbl/unique_ptr.h>
 
+// Ensure O_PATH and O_DIRECTORY are explicitly defined
+// for host-side tools. They are not a part of standard Posix,
+// so they are not guaranteed to exist in an arbitrary host-side
+// C library.
+
+#ifndef O_PATH
+#define O_PATH 010000000
+#endif
+
+#ifndef O_DIRECTORY
+#define O_DIRECTORY 0200000
+#endif
+
 namespace fs {
 
 class Connection;
 class Vnode;
 
 inline constexpr bool IsWritable(uint32_t flags) {
-    return flags & ZX_FS_RIGHT_WRITABLE;
+    uint32_t mode = flags & O_ACCMODE;
+    return mode == O_RDWR || mode == O_WRONLY;
 }
 
 inline constexpr bool IsReadable(uint32_t flags) {
-    return flags & ZX_FS_RIGHT_READABLE;
+    uint32_t mode = flags & O_ACCMODE;
+    return mode == O_RDWR || mode == O_RDONLY;
 }
 
 inline constexpr bool IsPathOnly(uint32_t flags) {
-    return flags & ZX_FS_FLAG_VNODE_REF_ONLY;
+    return flags & O_PATH;
 }
 
 // A storage class for a vdircookie which is passed to Readdir.
diff --git a/system/ulib/fs/include/fs/vnode.h b/system/ulib/fs/include/fs/vnode.h
index b48168e..8b182eb 100644
--- a/system/ulib/fs/include/fs/vnode.h
+++ b/system/ulib/fs/include/fs/vnode.h
@@ -61,8 +61,7 @@
     // all following I/O operations on the opened file will be redirected to the
     // indicated vnode instead of being handled by this instance.
     //
-    // |flags| are the open flags to be validated, such as |ZX_FS_RIGHT_READABLE| and
-    // |ZX_FS_FLAG_DIRECTORY|.
+    // |flags| are the open flags to be validated, such as |O_RDONLY| and |O_DIRECTORY|.
     virtual zx_status_t Open(uint32_t flags, fbl::RefPtr<Vnode>* out_redirect);
 
     // METHODS FOR OPENED NODES
diff --git a/system/ulib/fs/mount.cpp b/system/ulib/fs/mount.cpp
index 53a9210..044da5c 100644
--- a/system/ulib/fs/mount.cpp
+++ b/system/ulib/fs/mount.cpp
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
@@ -93,9 +94,8 @@
 zx_status_t Vfs::MountMkdir(fbl::RefPtr<Vnode> vn, fbl::StringPiece name, MountChannel h,
                             uint32_t flags) {
     fbl::AutoLock lock(&vfs_lock_);
-    zx_status_t r = OpenLocked(vn, &vn, name, &name, ZX_FS_FLAG_CREATE |
-                               ZX_FS_RIGHT_READABLE | ZX_FS_FLAG_DIRECTORY |
-                               ZX_FS_FLAG_NOREMOTE, S_IFDIR);
+    zx_status_t r = OpenLocked(vn, &vn, name, &name,
+                               O_CREAT | O_RDONLY | O_DIRECTORY | O_NOREMOTE, S_IFDIR);
     ZX_DEBUG_ASSERT(r <= ZX_OK); // Should not be accessing remote nodes
     if (r < 0) {
         return r;
diff --git a/system/ulib/fs/pseudo-dir.cpp b/system/ulib/fs/pseudo-dir.cpp
index 4ccb5fa..971e189 100644
--- a/system/ulib/fs/pseudo-dir.cpp
+++ b/system/ulib/fs/pseudo-dir.cpp
@@ -4,6 +4,7 @@
 
 #include <fs/pseudo-dir.h>
 
+#include <fcntl.h>
 #include <sys/stat.h>
 
 #include <fbl/auto_lock.h>
diff --git a/system/ulib/fs/pseudo-file.cpp b/system/ulib/fs/pseudo-file.cpp
index 605fe95..a1f2503 100644
--- a/system/ulib/fs/pseudo-file.cpp
+++ b/system/ulib/fs/pseudo-file.cpp
@@ -4,6 +4,8 @@
 
 #include <fs/pseudo-file.h>
 
+#include <fcntl.h>
+
 namespace fs {
 
 PseudoFile::PseudoFile(ReadHandler read_handler, WriteHandler write_handler)
@@ -14,7 +16,7 @@
 PseudoFile::~PseudoFile() = default;
 
 zx_status_t PseudoFile::ValidateFlags(uint32_t flags) {
-    if (flags & ZX_FS_FLAG_DIRECTORY) {
+    if (flags & O_DIRECTORY) {
         return ZX_ERR_NOT_DIR;
     }
     if (IsReadable(flags) && !read_handler_) {
@@ -168,7 +170,7 @@
 
 UnbufferedPseudoFile::Content::Content(fbl::RefPtr<UnbufferedPseudoFile> file, uint32_t flags)
     : file_(fbl::move(file)), flags_(flags),
-      truncated_since_last_successful_write_(flags_ & (ZX_FS_FLAG_CREATE | ZX_FS_FLAG_TRUNCATE)) {}
+      truncated_since_last_successful_write_(flags_ & (O_CREAT | O_TRUNC)) {}
 
 UnbufferedPseudoFile::Content::~Content() = default;
 
diff --git a/system/ulib/fs/service.cpp b/system/ulib/fs/service.cpp
index 884cb74..6e799a7 100644
--- a/system/ulib/fs/service.cpp
+++ b/system/ulib/fs/service.cpp
@@ -4,6 +4,8 @@
 
 #include <fs/service.h>
 
+#include <fcntl.h>
+
 namespace fs {
 
 Service::Service(Connector connector)
@@ -12,7 +14,7 @@
 Service::~Service() = default;
 
 zx_status_t Service::ValidateFlags(uint32_t flags) {
-    if (flags & ZX_FS_FLAG_DIRECTORY) {
+    if (flags & O_DIRECTORY) {
         return ZX_ERR_NOT_DIR;
     }
     return ZX_OK;
@@ -27,7 +29,7 @@
 }
 
 zx_status_t Service::Serve(Vfs* vfs, zx::channel channel, uint32_t flags) {
-    ZX_DEBUG_ASSERT(!(flags & ZX_FS_FLAG_DIRECTORY)); // checked by Open
+    ZX_DEBUG_ASSERT(!(flags & O_DIRECTORY)); // checked by Open
 
     if (!connector_) {
         return ZX_ERR_NOT_SUPPORTED;
diff --git a/system/ulib/fs/vfs.cpp b/system/ulib/fs/vfs.cpp
index 94d4043..3385d38 100644
--- a/system/ulib/fs/vfs.cpp
+++ b/system/ulib/fs/vfs.cpp
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include <fbl/auto_call.h>
+#include <fcntl.h>
 #include <fdio/remoteio.h>
 #include <fdio/watcher.h>
 #include <stdlib.h>
@@ -68,16 +69,20 @@
 // Validate open flags as much as they can be validated
 // independently of the target node.
 zx_status_t vfs_prevalidate_flags(uint32_t flags) {
-    if (!(flags & ZX_FS_RIGHT_WRITABLE)) {
-        if (flags & ZX_FS_FLAG_TRUNCATE) {
+    switch (flags & O_ACCMODE) {
+    case O_PATH:
+        ZX_DEBUG_ASSERT((flags & (O_TRUNC | O_CREAT | O_RDWR)) == 0);
+        return ZX_OK;
+    case O_RDONLY:
+        if (flags & O_TRUNC) {
             return ZX_ERR_INVALID_ARGS;
         }
-    } else if (!(flags & ZX_FS_RIGHTS)) {
-        if (!IsPathOnly(flags)) {
-            return ZX_ERR_INVALID_ARGS;
-        }
+    case O_WRONLY:
+    case O_RDWR:
+        return ZX_OK;
+    default:
+        return ZX_ERR_INVALID_ARGS;
     }
-    return ZX_OK;
 }
 
 } // namespace
@@ -149,7 +154,7 @@
         return ZX_ERR_INVALID_ARGS;
     }
 
-    if (flags & ZX_FS_FLAG_CREATE) {
+    if (flags & O_CREAT) {
         if (must_be_dir && !S_ISDIR(mode)) {
             return ZX_ERR_INVALID_ARGS;
         } else if (path == ".") {
@@ -158,7 +163,7 @@
             return ZX_ERR_ACCESS_DENIED;
         }
         if ((r = vndir->Create(&vn, path, mode)) < 0) {
-            if ((r == ZX_ERR_ALREADY_EXISTS) && (!(flags & ZX_FS_FLAG_EXCLUSIVE))) {
+            if ((r == ZX_ERR_ALREADY_EXISTS) && (!(flags & O_EXCL))) {
                 goto try_open;
             }
             if (r == ZX_ERR_NOT_SUPPORTED) {
@@ -176,7 +181,7 @@
             return r;
         }
 #ifdef __Fuchsia__
-        if (!(flags & ZX_FS_FLAG_NOREMOTE) && vn->IsRemote()) {
+        if (!(flags & O_NOREMOTE) && vn->IsRemote()) {
             // Opening a mount point: Traverse across remote.
             *pathout = ".";
 
@@ -186,7 +191,7 @@
             }
         }
 
-        flags |= (must_be_dir ? ZX_FS_FLAG_DIRECTORY : 0);
+        flags |= (must_be_dir ? O_DIRECTORY : 0);
 #endif
         if (ReadonlyLocked() && IsWritable(flags)) {
             return ZX_ERR_ACCESS_DENIED;
@@ -194,13 +199,13 @@
         if ((r = vn->ValidateFlags(flags)) != ZX_OK) {
             return r;
         }
-        // VNODE_REF_ONLY requests that we don't actually open the underlying
+        // O_PATH requests that we don't actually open the underlying
         // Vnode.
         if (!IsPathOnly(flags)) {
             if ((r = OpenVnode(flags, &vn)) != ZX_OK) {
                 return r;
             }
-            if ((flags & ZX_FS_FLAG_TRUNCATE) && ((r = vn->Truncate(0)) < 0)) {
+            if ((flags & O_TRUNC) && ((r = vn->Truncate(0)) < 0)) {
                 vn->Close();
                 return r;
             }
@@ -413,7 +418,7 @@
 }
 
 zx_status_t Vfs::ServeDirectory(fbl::RefPtr<fs::Vnode> vn, zx::channel channel) {
-    uint32_t flags = ZX_FS_FLAG_DIRECTORY;
+    uint32_t flags = O_DIRECTORY;
     zx_status_t r;
     if ((r = vn->ValidateFlags(flags)) != ZX_OK) {
         return r;
@@ -426,7 +431,7 @@
         return r;
     }
 
-    return vn->Serve(this, fbl::move(channel), ZX_FS_RIGHT_ADMIN);
+    return vn->Serve(this, fbl::move(channel), O_ADMIN);
 }
 
 void Vfs::RegisterConnection(fbl::unique_ptr<Connection> connection) {
diff --git a/system/ulib/fs/vmo-file.cpp b/system/ulib/fs/vmo-file.cpp
index 3343f98..38b4e11 100644
--- a/system/ulib/fs/vmo-file.cpp
+++ b/system/ulib/fs/vmo-file.cpp
@@ -4,6 +4,7 @@
 
 #include <fs/vmo-file.h>
 
+#include <fcntl.h>
 #include <limits.h>
 #include <string.h>
 
@@ -18,14 +19,19 @@
 
 zx_rights_t GetVmoRightsForAccessMode(uint32_t flags) {
     zx_rights_t rights = ZX_RIGHT_TRANSFER | ZX_RIGHT_DUPLICATE | ZX_RIGHT_MAP;
-    if (flags & ZX_FS_RIGHT_READABLE) {
-        rights |= ZX_RIGHT_READ;
-    }
-    if (flags & ZX_FS_RIGHT_WRITABLE) {
+    switch (flags & O_ACCMODE) {
+    case O_RDONLY:
+        rights |= ZX_RIGHT_READ | ZX_RIGHT_EXECUTE;
+        break;
+    case O_RDWR:
+        rights |= ZX_RIGHT_READ | ZX_RIGHT_WRITE; // no execute
+        break;
+    case O_WRONLY:
         rights |= ZX_RIGHT_WRITE;
-    }
-    if ((flags & ZX_FS_RIGHT_READABLE) & !(flags & ZX_FS_RIGHT_WRITABLE)) {
-        rights |= ZX_RIGHT_EXECUTE;
+        break;
+    default:
+        ZX_DEBUG_ASSERT(false); // checked by the VFS
+        break;
     }
     return rights;
 }
@@ -59,7 +65,7 @@
 VmoFile::~VmoFile() {}
 
 zx_status_t VmoFile::ValidateFlags(uint32_t flags) {
-    if (flags & ZX_FS_FLAG_DIRECTORY) {
+    if (flags & O_DIRECTORY) {
         return ZX_ERR_NOT_DIR;
     }
     if (IsWritable(flags) && !writable_) {
diff --git a/system/ulib/fs/watcher.cpp b/system/ulib/fs/watcher.cpp
index f6d2262..a109b75 100644
--- a/system/ulib/fs/watcher.cpp
+++ b/system/ulib/fs/watcher.cpp
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
diff --git a/system/utest/fs-vnode/pseudo-dir-tests.cpp b/system/utest/fs-vnode/pseudo-dir-tests.cpp
index 7cd7760..ba78097 100644
--- a/system/utest/fs-vnode/pseudo-dir-tests.cpp
+++ b/system/utest/fs-vnode/pseudo-dir-tests.cpp
@@ -65,8 +65,8 @@
 
     // open as directory
     fbl::RefPtr<fs::Vnode> redirect;
-    EXPECT_EQ(ZX_OK, dir->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
-    EXPECT_EQ(ZX_OK, dir->Open(ZX_FS_FLAG_DIRECTORY, &redirect));
+    EXPECT_EQ(ZX_OK, dir->ValidateFlags(O_DIRECTORY));
+    EXPECT_EQ(ZX_OK, dir->Open(O_DIRECTORY, &redirect));
     EXPECT_NULL(redirect);
 
     // get attributes
diff --git a/system/utest/fs-vnode/pseudo-file-tests.cpp b/system/utest/fs-vnode/pseudo-file-tests.cpp
index ea7888e..d016b2a 100644
--- a/system/utest/fs-vnode/pseudo-file-tests.cpp
+++ b/system/utest/fs-vnode/pseudo-file-tests.cpp
@@ -4,6 +4,8 @@
 
 #include <fs/pseudo-file.h>
 
+#include <fcntl.h>
+
 #include <fbl/initializer_list.h>
 #include <fbl/vector.h>
 #include <unittest/unittest.h>
@@ -109,54 +111,54 @@
     // no read handler, no write handler
     {
         auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile());
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_RDWR));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(O_DIRECTORY));
     }
 
     // read handler, no write handler
     {
         auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile(&DummyReader));
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_RDWR));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(O_DIRECTORY));
 
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDONLY, &redirect));
         EXPECT_NONNULL(redirect);
     }
 
     // no read handler, write handler
     {
         auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile(nullptr, &DummyWriter));
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_RDWR));
+        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(O_DIRECTORY));
 
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_NONNULL(redirect);
     }
 
     // read handler, write handler
     {
         auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile(&DummyReader, &DummyWriter));
-        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
+        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(O_DIRECTORY));
 
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDONLY, &redirect));
         EXPECT_NONNULL(redirect);
         redirect.reset();
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDWR));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDWR, &redirect));
         EXPECT_NONNULL(redirect);
         redirect.reset();
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_NONNULL(redirect);
     }
 
@@ -169,51 +171,51 @@
     // no read handler, no write handler
     {
         auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile());
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_RDWR));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(O_DIRECTORY));
     }
 
     // read handler, no write handler
     {
         auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile(&DummyReader));
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_RDWR));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(O_DIRECTORY));
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDONLY, &redirect));
         EXPECT_NONNULL(redirect);
     }
 
     // no read handler, write handler
     {
         auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile(nullptr, &DummyWriter));
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(O_RDWR));
+        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(O_DIRECTORY));
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_NONNULL(redirect);
     }
 
     // read handler, write handler
     {
         auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile(&DummyReader, &DummyWriter));
-        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
+        EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(O_DIRECTORY));
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDONLY, &redirect));
         EXPECT_NONNULL(redirect);
         redirect.reset();
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDWR));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDWR, &redirect));
         EXPECT_NONNULL(redirect);
         redirect.reset();
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_NONNULL(redirect);
     }
 
@@ -230,7 +232,7 @@
         EXPECT_EQ(ZX_OK, file->Getattr(&attr));
         EXPECT_EQ(V_TYPE_FILE, attr.mode);
         EXPECT_EQ(1, attr.nlink);
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_FLAG_VNODE_REF_ONLY));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_PATH));
         vnattr_t path_attr;
         EXPECT_EQ(ZX_OK, file->Getattr(&path_attr));
         EXPECT_BYTES_EQ((uint8_t*) &attr, (uint8_t*) &path_attr, sizeof(attr), "");
@@ -245,8 +247,8 @@
         EXPECT_EQ(1, attr.nlink);
 
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDONLY, &redirect));
         vnattr_t open_attr;
         EXPECT_EQ(ZX_OK, file->Getattr(&open_attr));
         EXPECT_BYTES_EQ((uint8_t*)&attr, (uint8_t*)&open_attr, sizeof(attr), "");
@@ -261,8 +263,8 @@
         EXPECT_EQ(1, attr.nlink);
 
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         vnattr_t open_attr;
         EXPECT_EQ(ZX_OK, file->Getattr(&open_attr));
         EXPECT_BYTES_EQ((uint8_t*)&attr, (uint8_t*)&open_attr, sizeof(attr), "");
@@ -277,8 +279,8 @@
         EXPECT_EQ(1, attr.nlink);
 
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDWR));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDWR, &redirect));
         vnattr_t open_attr;
         EXPECT_EQ(ZX_OK, file->Getattr(&open_attr));
         EXPECT_BYTES_EQ((uint8_t*)&attr, (uint8_t*)&open_attr, sizeof(attr), "");
@@ -298,7 +300,7 @@
         EXPECT_EQ(V_TYPE_FILE, attr.mode);
         EXPECT_EQ(1, attr.nlink);
 
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_FLAG_VNODE_REF_ONLY));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_PATH));
         vnattr_t path_attr;
         EXPECT_EQ(ZX_OK, file->Getattr(&path_attr));
         EXPECT_BYTES_EQ((uint8_t*) &attr, (uint8_t*) &path_attr, sizeof(attr), "");
@@ -313,8 +315,8 @@
         EXPECT_EQ(1, attr.nlink);
 
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDONLY, &redirect));
         vnattr_t open_attr;
         EXPECT_EQ(ZX_OK, file->Getattr(&open_attr));
         EXPECT_BYTES_EQ((uint8_t*)&attr, (uint8_t*)&open_attr, sizeof(attr), "");
@@ -329,8 +331,8 @@
         EXPECT_EQ(1, attr.nlink);
 
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         vnattr_t open_attr;
         EXPECT_EQ(ZX_OK, file->Getattr(&open_attr));
         EXPECT_BYTES_EQ((uint8_t*)&attr, (uint8_t*)&open_attr, sizeof(attr), "");
@@ -345,8 +347,8 @@
         EXPECT_EQ(1, attr.nlink);
 
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDWR));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDWR, &redirect));
         vnattr_t open_attr;
         EXPECT_EQ(ZX_OK, file->Getattr(&open_attr));
         EXPECT_BYTES_EQ((uint8_t*)&attr, (uint8_t*)&open_attr, sizeof(attr), "");
@@ -364,8 +366,8 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDONLY, &redirect));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 0u, 0u, ""));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 0u, "firs"));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 2u, "rst"));
@@ -376,8 +378,8 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDONLY, &redirect));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 2u, "cond"));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 6u, 0u, "second"));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 8u, 0u, "second"));
@@ -386,8 +388,8 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDONLY, &redirect));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 0u, ""));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 2u, ""));
         EXPECT_EQ(ZX_OK, redirect->Close());
@@ -395,7 +397,7 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDONLY, &redirect));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 0u, 0u, ""));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 0u, "null"));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 2u, fbl::StringPiece("ll\0n", 4u)));
@@ -406,7 +408,7 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_ERR_IO, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_ERR_IO, file->Open(O_RDONLY, &redirect));
     }
 
     END_TEST;
@@ -421,8 +423,8 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDONLY, &redirect));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 0u, 0u, ""));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 0u, "seco"));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 2u, ""));
@@ -433,8 +435,8 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_RDONLY, &redirect));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 8u, 0u, "fifth"));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 0u, ""));
         EXPECT_TRUE(CheckRead(redirect, ZX_OK, 12u, 0u, fbl::StringPiece("null\0null", 9u)));
@@ -453,8 +455,8 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "fixx", 4u));
         EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "", 0u));
         EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 2u, "rst", 3u));
@@ -463,23 +465,23 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "second", 6u));
         EXPECT_EQ(ZX_OK, redirect->Close());
     }
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_EQ(ZX_OK, redirect->Close());
     }
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "thxrxxx", 7u, 7u));
         EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 2u, "i", 1u));
         EXPECT_EQ(ZX_OK, redirect->Truncate(4u));
@@ -489,8 +491,8 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "null", 4u));
         EXPECT_EQ(ZX_OK, redirect->Truncate(5u));
         EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "null", 9u, 4u));
@@ -499,8 +501,8 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_EQ(ZX_ERR_NO_SPACE, redirect->Truncate(11u));
         EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "too-long", 8u, 8u));
         EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "-off-the-end", 10u, 2u));
@@ -510,8 +512,8 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_EQ(ZX_ERR_IO, redirect->Close());
     }
 
@@ -534,8 +536,8 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "first", 5u));
         EXPECT_TRUE(CheckWrite(redirect, ZX_ERR_NO_SPACE, 2u, "xxx", 0u));
         EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "second", 6u));
@@ -544,8 +546,8 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "", 0u));
         EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "third", 5u, 5u));
         EXPECT_TRUE(CheckAppend(redirect, ZX_OK, fbl::StringPiece("null\0null", 9u), 9u, 9u));
@@ -554,45 +556,45 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE | ZX_FS_FLAG_TRUNCATE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE | ZX_FS_FLAG_TRUNCATE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY | O_TRUNC));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY | O_TRUNC, &redirect));
         EXPECT_EQ(ZX_OK, redirect->Close());
     }
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE | ZX_FS_FLAG_CREATE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE | ZX_FS_FLAG_CREATE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY | O_CREAT));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY | O_CREAT, &redirect));
         EXPECT_EQ(ZX_OK, redirect->Close());
     }
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_EQ(ZX_OK, redirect->Truncate(0u));
         EXPECT_EQ(ZX_OK, redirect->Close());
     }
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "fourth", 6u, 6u));
         EXPECT_EQ(ZX_OK, redirect->Close());
     }
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_EQ(ZX_OK, redirect->Close());
     }
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "fifth", 5u, 5u));
         EXPECT_EQ(ZX_ERR_INVALID_ARGS, redirect->Truncate(10u));
         EXPECT_EQ(ZX_OK, redirect->Truncate(0u));
@@ -601,8 +603,8 @@
 
     {
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file->ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file->Open(O_WRONLY, &redirect));
         EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "a long string", 13u));
         EXPECT_EQ(ZX_OK, redirect->Truncate(0u));
         EXPECT_EQ(ZX_ERR_IO, redirect->Close());
diff --git a/system/utest/fs-vnode/service-tests.cpp b/system/utest/fs-vnode/service-tests.cpp
index 649f196..e13edd0 100644
--- a/system/utest/fs-vnode/service-tests.cpp
+++ b/system/utest/fs-vnode/service-tests.cpp
@@ -24,10 +24,10 @@
 
     // open
     fbl::RefPtr<fs::Vnode> redirect;
-    EXPECT_EQ(ZX_OK, svc->ValidateFlags(ZX_FS_RIGHT_READABLE));
-    EXPECT_EQ(ZX_OK, svc->Open(ZX_FS_RIGHT_READABLE, &redirect));
+    EXPECT_EQ(ZX_OK, svc->ValidateFlags(O_RDONLY));
+    EXPECT_EQ(ZX_OK, svc->Open(O_RDONLY, &redirect));
     EXPECT_NULL(redirect);
-    EXPECT_EQ(ZX_ERR_NOT_DIR, svc->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
+    EXPECT_EQ(ZX_ERR_NOT_DIR, svc->ValidateFlags(O_DIRECTORY));
 
     // get attr
     vnattr_t attr;
@@ -42,12 +42,12 @@
 
     // serve, the connector will return success the first time
     fs::Vfs vfs;
-    EXPECT_EQ(ZX_OK, svc->Serve(&vfs, fbl::move(c1), ZX_FS_RIGHT_READABLE));
+    EXPECT_EQ(ZX_OK, svc->Serve(&vfs, fbl::move(c1), O_RDONLY));
     EXPECT_EQ(hc1, bound_channel.get());
 
     // the connector will return failure because bound_channel is still valid
     // we test that the error is propagated back up through Serve
-    EXPECT_EQ(ZX_ERR_IO, svc->Serve(&vfs, fbl::move(c2), ZX_FS_RIGHT_READABLE));
+    EXPECT_EQ(ZX_ERR_IO, svc->Serve(&vfs, fbl::move(c2), O_RDONLY));
     EXPECT_EQ(hc1, bound_channel.get());
 
     END_TEST;
diff --git a/system/utest/fs-vnode/vmo-file-tests.cpp b/system/utest/fs-vnode/vmo-file-tests.cpp
index fb4d471..76509e8 100644
--- a/system/utest/fs-vnode/vmo-file-tests.cpp
+++ b/system/utest/fs-vnode/vmo-file-tests.cpp
@@ -4,6 +4,7 @@
 
 #include <fs/vmo-file.h>
 
+#include <fcntl.h>
 #include <limits.h>
 
 #include <zircon/syscalls.h>
@@ -126,15 +127,14 @@
     {
         fs::VmoFile file(abc, 0u, 0u);
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file.ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file.Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file.ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file.Open(O_RDONLY, &redirect));
         EXPECT_NULL(redirect);
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED,
-                  file.ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file.ValidateFlags(O_RDWR));
         EXPECT_NULL(redirect);
-        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file.ValidateFlags(ZX_FS_RIGHT_WRITABLE));
+        EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file.ValidateFlags(O_WRONLY));
         EXPECT_NULL(redirect);
-        EXPECT_EQ(ZX_ERR_NOT_DIR, file.ValidateFlags(ZX_FS_FLAG_DIRECTORY));
+        EXPECT_EQ(ZX_ERR_NOT_DIR, file.ValidateFlags(O_DIRECTORY));
         EXPECT_NULL(redirect);
     }
 
@@ -142,16 +142,16 @@
     {
         fs::VmoFile file(abc, 0u, 0u, true);
         fbl::RefPtr<fs::Vnode> redirect;
-        EXPECT_EQ(ZX_OK, file.ValidateFlags(ZX_FS_RIGHT_READABLE));
-        EXPECT_EQ(ZX_OK, file.Open(ZX_FS_RIGHT_READABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file.ValidateFlags(O_RDONLY));
+        EXPECT_EQ(ZX_OK, file.Open(O_RDONLY, &redirect));
         EXPECT_NULL(redirect);
-        EXPECT_EQ(ZX_OK, file.ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file.Open(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file.ValidateFlags(O_RDWR));
+        EXPECT_EQ(ZX_OK, file.Open(O_RDWR, &redirect));
         EXPECT_NULL(redirect);
-        EXPECT_EQ(ZX_OK, file.ValidateFlags(ZX_FS_RIGHT_WRITABLE));
-        EXPECT_EQ(ZX_OK, file.Open(ZX_FS_RIGHT_WRITABLE, &redirect));
+        EXPECT_EQ(ZX_OK, file.ValidateFlags(O_WRONLY));
+        EXPECT_EQ(ZX_OK, file.Open(O_WRONLY, &redirect));
         EXPECT_NULL(redirect);
-        EXPECT_EQ(ZX_ERR_NOT_DIR, file.ValidateFlags(ZX_FS_FLAG_DIRECTORY));
+        EXPECT_EQ(ZX_ERR_NOT_DIR, file.ValidateFlags(O_DIRECTORY));
         EXPECT_NULL(redirect);
     }
 
@@ -373,8 +373,7 @@
         zx_off_t info[2];
         uint32_t info_size;
         fs::VmoFile file(abc, PAGE_1 - 5u, 23u, false, fs::VmoFile::VmoSharing::NONE);
-        EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, file.GetHandles(ZX_FS_RIGHT_READABLE,
-                                                        vmo.reset_and_get_address(),
+        EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, file.GetHandles(O_RDONLY, vmo.reset_and_get_address(),
                                                         &handle_count, &type, info, &info_size));
     }
 
@@ -389,7 +388,7 @@
         zx_off_t info[2];
         uint32_t info_size;
         fs::VmoFile file(abc, PAGE_1 - 5u, 23u, false, fs::VmoFile::VmoSharing::DUPLICATE);
-        EXPECT_EQ(ZX_OK, file.GetHandles(ZX_FS_RIGHT_READABLE, vmo.reset_and_get_address(),
+        EXPECT_EQ(ZX_OK, file.GetHandles(O_RDONLY, vmo.reset_and_get_address(),
                                          &handle_count, &type, info, &info_size));
         EXPECT_NE(abc.get(), vmo.get());
         EXPECT_EQ(GetKoid(abc.get()), GetKoid(vmo.get()));
@@ -417,8 +416,7 @@
         zx_off_t info[2];
         uint32_t info_size;
         fs::VmoFile file(abc, PAGE_1 - 5u, 23u, true, fs::VmoFile::VmoSharing::DUPLICATE);
-        EXPECT_EQ(ZX_OK, file.GetHandles(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE,
-                                         vmo.reset_and_get_address(),
+        EXPECT_EQ(ZX_OK, file.GetHandles(O_RDWR, vmo.reset_and_get_address(),
                                          &handle_count, &type, info, &info_size));
         EXPECT_NE(abc.get(), vmo.get());
         EXPECT_EQ(GetKoid(abc.get()), GetKoid(vmo.get()));
@@ -453,7 +451,7 @@
         zx_off_t info[2];
         uint32_t info_size;
         fs::VmoFile file(abc, PAGE_1 - 5u, 23u, true, fs::VmoFile::VmoSharing::DUPLICATE);
-        EXPECT_EQ(ZX_OK, file.GetHandles(ZX_FS_RIGHT_WRITABLE, vmo.reset_and_get_address(),
+        EXPECT_EQ(ZX_OK, file.GetHandles(O_WRONLY, vmo.reset_and_get_address(),
                                          &handle_count, &type, info, &info_size));
         EXPECT_NE(abc.get(), vmo.get());
         EXPECT_EQ(GetKoid(abc.get()), GetKoid(vmo.get()));
@@ -485,7 +483,7 @@
         zx_off_t info[2];
         uint32_t info_size;
         fs::VmoFile file(abc, PAGE_2 - 5u, 23u, false, fs::VmoFile::VmoSharing::CLONE_COW);
-        EXPECT_EQ(ZX_OK, file.GetHandles(ZX_FS_RIGHT_READABLE, vmo.reset_and_get_address(),
+        EXPECT_EQ(ZX_OK, file.GetHandles(O_RDONLY, vmo.reset_and_get_address(),
                                          &handle_count, &type, info, &info_size));
         EXPECT_NE(abc.get(), vmo.get());
         EXPECT_NE(GetKoid(abc.get()), GetKoid(vmo.get()));
@@ -513,8 +511,7 @@
         zx_off_t info[2];
         uint32_t info_size;
         fs::VmoFile file(abc, PAGE_2 - 5u, 23u, true, fs::VmoFile::VmoSharing::CLONE_COW);
-        EXPECT_EQ(ZX_OK, file.GetHandles(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE,
-                                         vmo.reset_and_get_address(),
+        EXPECT_EQ(ZX_OK, file.GetHandles(O_RDWR, vmo.reset_and_get_address(),
                                          &handle_count, &type, info, &info_size));
         EXPECT_NE(abc.get(), vmo.get());
         EXPECT_NE(GetKoid(abc.get()), GetKoid(vmo.get()));
@@ -548,7 +545,7 @@
         zx_off_t info[2];
         uint32_t info_size;
         fs::VmoFile file(abc, PAGE_2 - 5u, 23u, true, fs::VmoFile::VmoSharing::CLONE_COW);
-        EXPECT_EQ(ZX_OK, file.GetHandles(ZX_FS_RIGHT_WRITABLE, vmo.reset_and_get_address(),
+        EXPECT_EQ(ZX_OK, file.GetHandles(O_WRONLY, vmo.reset_and_get_address(),
                                          &handle_count, &type, info, &info_size));
         EXPECT_NE(abc.get(), vmo.get());
         EXPECT_NE(GetKoid(abc.get()), GetKoid(vmo.get()));
diff --git a/system/utest/fs/test-access.cpp b/system/utest/fs/test-access.cpp
index 45a4d03..de12375 100644
--- a/system/utest/fs/test-access.cpp
+++ b/system/utest/fs/test-access.cpp
@@ -89,10 +89,16 @@
 
     const char* filename = "::foobar";
 
+    // No creation with "RDWR + WRONLY"
+    ASSERT_LT(open(filename, O_RDWR | O_WRONLY | O_CREAT, 0644), 0);
+
     int fd = open(filename, O_RDWR | O_CREAT, 0644);
     ASSERT_GT(fd, 0);
     ASSERT_EQ(close(fd), 0);
 
+    // No re-opening with "RDWR + WRONLY"
+    ASSERT_LT(open(filename, O_RDWR | O_WRONLY, 0644), 0);
+
     // No read-only truncation
     ASSERT_LT(open(filename, O_RDONLY | O_TRUNC | O_CREAT, 0644), 0);
 
diff --git a/third_party/ulib/musl/include/fcntl.h b/third_party/ulib/musl/include/fcntl.h
index eb9f5b0..32b8091 100644
--- a/third_party/ulib/musl/include/fcntl.h
+++ b/third_party/ulib/musl/include/fcntl.h
@@ -42,35 +42,31 @@
 #define O_WRONLY            01
 #define O_RDWR              02
 
-// Flags which align with ZXIO_FS_*
-// system/ulib/fdio/unistd.c asserts that these flags are aligned
-// with the ZXIO_FS_* versions.
-#define O_CREAT     0x00010000
-#define O_EXCL      0x00020000
-#define O_TRUNC     0x00040000
-#define O_DIRECTORY 0x00080000
-#define O_APPEND    0x00100000
-#define O_PATH      0x00400000
+#define O_CREAT           0100
+#define O_EXCL            0200
+#define O_NOCTTY          0400
+#define O_TRUNC          01000
+#define O_APPEND         02000
+#define O_NONBLOCK       04000
+#define O_DSYNC         010000
+#define O_SYNC        04010000
+#define O_RSYNC       04010000
+#define O_DIRECTORY    0200000
+#define O_NOFOLLOW     0400000
+#define O_CLOEXEC     02000000
+
+#define O_ASYNC         020000
+#define O_DIRECT        040000
+#define O_LARGEFILE    0100000
+#define O_NOATIME     01000000
+#define O_PATH       010000000
+#define O_TMPFILE    020200000
+
 #ifdef _ALL_SOURCE
-#define O_NOREMOTE  0x00200000
-#define O_ADMIN     0x00000004
-#define O_PIPELINE  0x80000000
+#define O_NOREMOTE  0100000000
+#define O_ADMIN     0200000000
+#define O_PIPELINE 02000000000
 #endif
-
-// Flags which do not align with ZXIO_FS_*
-#define O_NONBLOCK  0x00000010
-#define O_DSYNC     0x00000020
-#define O_SYNC      (0x00000040 | O_DSYNC)
-#define O_RSYNC     O_SYNC
-#define O_NOFOLLOW  0x00000080
-#define O_CLOEXEC   0x00000100
-#define O_NOCTTY    0x00000200
-#define O_ASYNC     0x00000400
-#define O_DIRECT    0x00000800
-#define O_LARGEFILE 0x00001000
-#define O_NOATIME   0x00002000
-#define O_TMPFILE   0x00004000
-
 // clang-format on
 
 #define O_NDELAY O_NONBLOCK