• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_DIRECTORY 00040000
29 #define GUEST_O_NOFOLLOW 00100000
30 #define GUEST_O_DIRECT 00200000
31 #define GUEST_O_LARGEFILE 00400000
32 
33 namespace berberis {
34 
35 #if !defined(__i386__) && !defined(__x86_64__)
36 #error Currently open flags conversion is only supported on x86
37 #endif
38 
39 // Glibc doesn't expose __O_SYNC
40 #if !defined(__O_SYNC)
41 
42 #if defined(__BIONIC__)
43 #error __O_SYNC undefined in bionic
44 #endif
45 
46 #define __O_SYNC 04000000
47 
48 #endif
49 
50 // Musl defines an O_SEARCH flag an includes it in O_ACCMODE,
51 // bionic and glibc don't.
52 #ifndef O_SEARCH
53 #define O_SEARCH 0
54 #endif
55 
56 static_assert((O_ACCMODE & ~O_SEARCH) == 00000003);
57 
58 // These flags should have the same value on all architectures.
59 static_assert(O_CREAT == 00000100);
60 static_assert(O_EXCL == 00000200);
61 static_assert(O_NOCTTY == 00000400);
62 static_assert(O_TRUNC == 00001000);
63 static_assert(O_APPEND == 00002000);
64 static_assert(O_NONBLOCK == 00004000);
65 static_assert(O_DSYNC == 00010000);
66 static_assert(FASYNC == 00020000);
67 static_assert(O_NOATIME == 01000000);
68 static_assert(O_CLOEXEC == 02000000);
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_CLOEXEC | __O_SYNC |
77                                  O_PATH;
78 
79 }  // namespace
80 
ToHostOpenFlags(int guest_flags)81 int ToHostOpenFlags(int guest_flags) {
82   const int kIncompatibleGuestOpenFlags =
83       GUEST_O_DIRECTORY | GUEST_O_NOFOLLOW | GUEST_O_DIRECT | GUEST_O_LARGEFILE;
84 
85   int unknown_guest_flags = guest_flags & ~(kCompatibleOpenFlags | kIncompatibleGuestOpenFlags);
86   if (unknown_guest_flags) {
87     KAPI_TRACE("Unsupported guest open flags: original=0x%x unsupported=0x%x",
88                guest_flags,
89                unknown_guest_flags);
90   }
91 
92   int host_flags = guest_flags & ~kIncompatibleGuestOpenFlags;
93 
94   if (guest_flags & GUEST_O_DIRECTORY) {
95     host_flags |= O_DIRECTORY;
96   }
97   if (guest_flags & GUEST_O_NOFOLLOW) {
98     host_flags |= O_NOFOLLOW;
99   }
100   if (guest_flags & GUEST_O_DIRECT) {
101     host_flags |= O_DIRECT;
102   }
103   if (guest_flags & GUEST_O_LARGEFILE) {
104     host_flags |= O_LARGEFILE;
105   }
106 
107   return host_flags;
108 }
109 
ToGuestOpenFlags(int host_flags)110 int ToGuestOpenFlags(int host_flags) {
111   const int kIncompatibleHostOpenFlags = O_DIRECTORY | O_NOFOLLOW | O_DIRECT | O_LARGEFILE;
112 
113   int unknown_host_flags = host_flags & ~(kCompatibleOpenFlags | kIncompatibleHostOpenFlags);
114   if (unknown_host_flags) {
115     KAPI_TRACE("Unsupported host open flags: original=0x%x unsupported=0x%x",
116                host_flags,
117                unknown_host_flags);
118   }
119 
120   int guest_flags = host_flags & ~kIncompatibleHostOpenFlags;
121 
122   if (host_flags & O_DIRECTORY) {
123     guest_flags |= GUEST_O_DIRECTORY;
124   }
125   if (host_flags & O_NOFOLLOW) {
126     guest_flags |= GUEST_O_NOFOLLOW;
127   }
128   if (host_flags & O_DIRECT) {
129     guest_flags |= GUEST_O_DIRECT;
130   }
131   if (host_flags & O_LARGEFILE) {
132     guest_flags |= GUEST_O_LARGEFILE;
133   }
134 
135   return guest_flags;
136 }
137 
138 }  // namespace berberis
139