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