| // Copyright 2019 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. | 
 |  | 
 | #ifndef LIB_VFS_CPP_FLAGS_H_ | 
 | #define LIB_VFS_CPP_FLAGS_H_ | 
 |  | 
 | #include <fuchsia/io/cpp/fidl.h> | 
 |  | 
 | namespace vfs { | 
 |  | 
 | class Flags { | 
 |  public: | 
 |   Flags() = delete; | 
 |  | 
 |   static bool IsReadable(fuchsia::io::OpenFlags flags) { | 
 |     return (flags & fuchsia::io::OpenFlags::RIGHT_READABLE) != fuchsia::io::OpenFlags(); | 
 |   } | 
 |  | 
 |   static bool IsWritable(fuchsia::io::OpenFlags flags) { | 
 |     return (flags & fuchsia::io::OpenFlags::RIGHT_WRITABLE) != fuchsia::io::OpenFlags(); | 
 |   } | 
 |  | 
 |   static bool IsExecutable(fuchsia::io::OpenFlags flags) { | 
 |     return (flags & fuchsia::io::OpenFlags::RIGHT_EXECUTABLE) != fuchsia::io::OpenFlags(); | 
 |   } | 
 |  | 
 |   static bool IsDirectory(fuchsia::io::OpenFlags flags) { | 
 |     return (flags & fuchsia::io::OpenFlags::DIRECTORY) != fuchsia::io::OpenFlags(); | 
 |   } | 
 |  | 
 |   static bool IsNotDirectory(fuchsia::io::OpenFlags flags) { | 
 |     return (flags & fuchsia::io::OpenFlags::NOT_DIRECTORY) != fuchsia::io::OpenFlags(); | 
 |   } | 
 |  | 
 |   static bool ShouldDescribe(fuchsia::io::OpenFlags flags) { | 
 |     return (flags & fuchsia::io::OpenFlags::DESCRIBE) != fuchsia::io::OpenFlags(); | 
 |   } | 
 |  | 
 |   static bool IsNodeReference(fuchsia::io::OpenFlags flags) { | 
 |     return (flags & fuchsia::io::OpenFlags::NODE_REFERENCE) != fuchsia::io::OpenFlags(); | 
 |   } | 
 |  | 
 |   static bool ShouldCloneWithSameRights(fuchsia::io::OpenFlags flags) { | 
 |     return (flags & fuchsia::io::OpenFlags::CLONE_SAME_RIGHTS) != fuchsia::io::OpenFlags(); | 
 |   } | 
 |  | 
 |   static bool IsPosixWritable(fuchsia::io::OpenFlags flags) { | 
 |     return (flags & fuchsia::io::OpenFlags::POSIX_WRITABLE) != fuchsia::io::OpenFlags(); | 
 |   } | 
 |  | 
 |   static bool IsPosixExecutable(fuchsia::io::OpenFlags flags) { | 
 |     return (flags & fuchsia::io::OpenFlags::POSIX_EXECUTABLE) != fuchsia::io::OpenFlags(); | 
 |   } | 
 |  | 
 |   // All known rights. | 
 |   static constexpr fuchsia::io::OpenFlags kFsRights = fuchsia::io::OPEN_RIGHTS; | 
 |  | 
 |   // Flags which can be modified by FIDL File::SetFlags. | 
 |   static constexpr fuchsia::io::OpenFlags kSettableStatusFlags = fuchsia::io::OpenFlags::APPEND; | 
 |  | 
 |   // All flags which indicate state of the connection (excluding rights). | 
 |   static constexpr fuchsia::io::OpenFlags kStatusFlags = | 
 |       kSettableStatusFlags | fuchsia::io::OpenFlags::NODE_REFERENCE; | 
 |  | 
 |   // Returns true if the rights flags in |flags_a| does not exceed | 
 |   // those in |flags_b|. | 
 |   static bool StricterOrSameRights(fuchsia::io::OpenFlags flags_a, fuchsia::io::OpenFlags flags_b) { | 
 |     fuchsia::io::OpenFlags rights_a = flags_a & kFsRights; | 
 |     fuchsia::io::OpenFlags rights_b = flags_b & kFsRights; | 
 |     return (rights_a & ~rights_b) == fuchsia::io::OpenFlags(); | 
 |   } | 
 |  | 
 |   // Perform basic flags validation relevant to Directory::Open and Node::Clone. | 
 |   // Returns false if the flags combination is invalid. | 
 |   static bool InputPrecondition(fuchsia::io::OpenFlags flags) { | 
 |     // Reject if OPEN_FLAG_DIRECTORY and OPEN_FLAG_NOT_DIRECTORY are both specified. | 
 |     if (Flags::IsDirectory(flags) && Flags::IsNotDirectory(flags)) { | 
 |       return false; | 
 |     } | 
 |  | 
 |     // Explicitly reject NODE_REFERENCE together with any invalid flags. | 
 |     if (Flags::IsNodeReference(flags)) { | 
 |       if ((flags & ~fuchsia::io::OPEN_FLAGS_ALLOWED_WITH_NODE_REFERENCE) != | 
 |           fuchsia::io::OpenFlags()) { | 
 |         return false; | 
 |       } | 
 |     } | 
 |  | 
 |     return true; | 
 |   } | 
 | }; | 
 |  | 
 | }  // namespace vfs | 
 |  | 
 | #endif  // LIB_VFS_CPP_FLAGS_H_ |