1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "berberis/kernel_api/open_emulation.h"
18
19 // Documentation says that to get access to the constants used below one
20 // must include these three files. In reality it looks as if all constants
21 // are defined by <fcntl.h>, but we include all three as described in docs.
22 #include <fcntl.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25
26 #include "berberis/base/tracing.h"
27
28 namespace berberis {
29
30 #if !defined(__x86_64__)
31 #error Currently open flags conversion is only supported on x86_64
32 #endif
33
34 // Glibc doesn't support O_LARGEFILE and defines it to 0. Here we need
35 // kernel's definition for x86_64.
36 #if (O_LARGEFILE == 0)
37 #undef O_LARGEFILE
38 #define O_LARGEFILE 00100000
39 #endif
40
41 // Glibc doesn't expose __O_SYNC
42 #if !defined(__O_SYNC)
43
44 #if defined(__BIONIC__)
45 #error __O_SYNC undefined in bionic
46 #endif
47
48 #define __O_SYNC 04000000
49
50 #endif
51
52 // Musl defines an O_SEARCH flag an includes it in O_ACCMODE,
53 // bionic and glibc don't.
54 #ifndef O_SEARCH
55 #define O_SEARCH 0
56 #endif
57
58 static_assert((O_ACCMODE & ~O_SEARCH) == 00000003);
59
60 // These flags should have the same value on guest and host architectures.
61 static_assert(O_CREAT == 00000100);
62 static_assert(O_EXCL == 00000200);
63 static_assert(O_NOCTTY == 00000400);
64 static_assert(O_TRUNC == 00001000);
65 static_assert(O_APPEND == 00002000);
66 static_assert(O_NONBLOCK == 00004000);
67 static_assert(O_DSYNC == 00010000);
68 static_assert(FASYNC == 00020000);
69 static_assert(O_NOATIME == 01000000);
70 static_assert(O_DIRECTORY == 0200000);
71 static_assert(O_NOFOLLOW == 00400000);
72 static_assert(O_CLOEXEC == 02000000);
73 static_assert(O_DIRECT == 040000);
74 static_assert(__O_SYNC == 04000000);
75 static_assert(O_SYNC == (O_DSYNC | __O_SYNC));
76 static_assert(O_PATH == 010000000);
77 static_assert(O_LARGEFILE == 00100000);
78
79 namespace {
80
81 const int kCompatibleOpenFlags =
82 O_ACCMODE | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | O_APPEND | O_NONBLOCK | O_DSYNC | FASYNC |
83 O_NOATIME | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC | O_DIRECT | __O_SYNC | O_PATH | O_LARGEFILE;
84
85 } // namespace
86
87 const char* kGuestCpuinfoPath = "/system/etc/cpuinfo.riscv64.txt";
88
ToHostOpenFlags(int guest_flags)89 int ToHostOpenFlags(int guest_flags) {
90 int unknown_guest_flags = guest_flags & ~kCompatibleOpenFlags;
91 if (unknown_guest_flags) {
92 TRACE("Unrecognized guest open flags: original=0x%x unsupported=0x%x. Passing to host as is.",
93 guest_flags,
94 unknown_guest_flags);
95 }
96
97 return guest_flags;
98 }
99
ToGuestOpenFlags(int host_flags)100 int ToGuestOpenFlags(int host_flags) {
101 int unknown_host_flags = host_flags & ~kCompatibleOpenFlags;
102 if (unknown_host_flags) {
103 TRACE("Unrecognized host open flags: original=0x%x unsupported=0x%x. Passing to guest as is.",
104 host_flags,
105 unknown_host_flags);
106 }
107
108 return host_flags;
109 }
110
111 } // namespace berberis
112