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/kernel_api/tracing.h"
27 
28 #define GUEST_O_LARGEFILE 00100000
29 
30 namespace berberis {
31 
32 #if !defined(__i386__) && !defined(__x86_64__)
33 #error Currently open flags conversion is only supported on x86
34 #endif
35 
36 // Glibc doesn't expose __O_SYNC
37 #if !defined(__O_SYNC)
38 
39 #if defined(__BIONIC__)
40 #error __O_SYNC undefined in bionic
41 #endif
42 
43 #define __O_SYNC 04000000
44 
45 #endif
46 
47 // Musl defines an O_SEARCH flag an includes it in O_ACCMODE,
48 // bionic and glibc don't.
49 #ifndef O_SEARCH
50 #define O_SEARCH 0
51 #endif
52 
53 static_assert((O_ACCMODE & ~O_SEARCH) == 00000003);
54 
55 // These flags should have the same value on guest and host architectures.
56 static_assert(O_CREAT == 00000100);
57 static_assert(O_EXCL == 00000200);
58 static_assert(O_NOCTTY == 00000400);
59 static_assert(O_TRUNC == 00001000);
60 static_assert(O_APPEND == 00002000);
61 static_assert(O_NONBLOCK == 00004000);
62 static_assert(O_DSYNC == 00010000);
63 static_assert(FASYNC == 00020000);
64 static_assert(O_NOATIME == 01000000);
65 static_assert(O_DIRECTORY == 0200000);
66 static_assert(O_NOFOLLOW == 00400000);
67 static_assert(O_CLOEXEC == 02000000);
68 static_assert(O_DIRECT == 040000);
69 static_assert(__O_SYNC == 04000000);
70 static_assert(O_SYNC == (O_DSYNC | __O_SYNC));
71 static_assert(O_PATH == 010000000);
72 
73 namespace {
74 
75 const int kCompatibleOpenFlags = O_ACCMODE | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | O_APPEND |
76                                  O_NONBLOCK | O_DSYNC | FASYNC | O_NOATIME | O_DIRECTORY |
77                                  O_NOFOLLOW | O_CLOEXEC | O_DIRECT | __O_SYNC | O_PATH;
78 
79 }  // namespace
80 
81 const char* kGuestCpuinfoPath = "/system/etc/cpuinfo.riscv64.txt";
82 
ToHostOpenFlags(int guest_flags)83 int ToHostOpenFlags(int guest_flags) {
84   const int kIncompatibleGuestOpenFlags = GUEST_O_LARGEFILE;
85 
86   int unknown_guest_flags = guest_flags & ~(kCompatibleOpenFlags | kIncompatibleGuestOpenFlags);
87   if (unknown_guest_flags) {
88     KAPI_TRACE("Unsupported guest open flags: original=0x%x unsupported=0x%x",
89                guest_flags,
90                unknown_guest_flags);
91   }
92 
93   int host_flags = guest_flags & ~kIncompatibleGuestOpenFlags;
94 
95   if (guest_flags & GUEST_O_LARGEFILE) {
96     host_flags |= O_LARGEFILE;
97   }
98 
99   return host_flags;
100 }
101 
ToGuestOpenFlags(int host_flags)102 int ToGuestOpenFlags(int host_flags) {
103   const int kIncompatibleHostOpenFlags = O_LARGEFILE;
104 
105   int unknown_host_flags = host_flags & ~(kCompatibleOpenFlags | kIncompatibleHostOpenFlags);
106   if (unknown_host_flags) {
107     KAPI_TRACE("Unsupported host open flags: original=0x%x unsupported=0x%x",
108                host_flags,
109                unknown_host_flags);
110   }
111 
112   int guest_flags = host_flags & ~kIncompatibleHostOpenFlags;
113 
114   if (host_flags & O_LARGEFILE) {
115     guest_flags |= GUEST_O_LARGEFILE;
116   }
117 
118   return guest_flags;
119 }
120 
121 }  // namespace berberis
122