OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "nacl_io/kernel_handle.h" | 5 #include "nacl_io/kernel_handle.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <pthread.h> | 8 #include <pthread.h> |
9 | 9 |
10 #include "nacl_io/mount.h" | 10 #include "nacl_io/mount.h" |
11 #include "nacl_io/mount_node.h" | 11 #include "nacl_io/mount_node.h" |
| 12 #include "nacl_io/mount_node_socket.h" |
12 #include "nacl_io/osunistd.h" | 13 #include "nacl_io/osunistd.h" |
13 | 14 |
14 #include "sdk_util/auto_lock.h" | 15 #include "sdk_util/auto_lock.h" |
15 | 16 |
16 namespace nacl_io { | 17 namespace nacl_io { |
17 | 18 |
18 // It is only legal to construct a handle while the kernel lock is held. | 19 // It is only legal to construct a handle while the kernel lock is held. |
19 KernelHandle::KernelHandle() | 20 KernelHandle::KernelHandle() |
20 : mount_(NULL), node_(NULL) {} | 21 : mount_(NULL), node_(NULL) {} |
21 | 22 |
22 KernelHandle::KernelHandle(const ScopedMount& mnt, const ScopedMountNode& node) | 23 KernelHandle::KernelHandle(const ScopedMount& mnt, const ScopedMountNode& node) |
23 : mount_(mnt), node_(node) {} | 24 : mount_(mnt), node_(node) {} |
24 | 25 |
25 KernelHandle::~KernelHandle() { | 26 KernelHandle::~KernelHandle() { |
26 // Force release order for cases where mount_ is not ref'd by mounting. | 27 // Force release order for cases where mount_ is not ref'd by mounting. |
27 node_.reset(NULL); | 28 node_.reset(NULL); |
28 mount_.reset(NULL); | 29 mount_.reset(NULL); |
29 } | 30 } |
30 | 31 |
31 // Returns the MountNodeSocket* if this node is a socket. | 32 // Returns the MountNodeSocket* if this node is a socket. |
32 MountNodeSocket* KernelHandle::socket_node() { | 33 MountNodeSocket* KernelHandle::socket_node() { |
33 if (node_.get() && node_->IsaSock()) | 34 if (node_.get() && node_->IsaSock()) |
34 return reinterpret_cast<MountNodeSocket*>(node_.get()); | 35 return reinterpret_cast<MountNodeSocket*>(node_.get()); |
35 return NULL; | 36 return NULL; |
36 } | 37 } |
37 | 38 |
38 Error KernelHandle::Init(int open_flags) { | 39 Error KernelHandle::Init(int open_flags) { |
39 handle_data_.flags = open_flags; | 40 handle_attr_.flags = open_flags; |
40 | 41 |
41 if (open_flags & O_APPEND) { | 42 if (open_flags & O_APPEND) { |
42 Error error = node_->GetSize(&handle_data_.offs); | 43 Error error = node_->GetSize(&handle_attr_.offs); |
43 if (error) | 44 if (error) |
44 return error; | 45 return error; |
45 } | 46 } |
46 | 47 |
47 return 0; | 48 return 0; |
48 } | 49 } |
49 | 50 |
50 Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) { | 51 Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) { |
51 // By default, don't move the offset. | 52 // By default, don't move the offset. |
52 *out_offset = offset; | 53 *out_offset = offset; |
53 size_t base; | 54 size_t base; |
54 size_t node_size; | 55 size_t node_size; |
55 | 56 |
56 AUTO_LOCK(handle_lock_); | 57 AUTO_LOCK(handle_lock_); |
57 Error error = node_->GetSize(&node_size); | 58 Error error = node_->GetSize(&node_size); |
58 if (error) | 59 if (error) |
59 return error; | 60 return error; |
60 | 61 |
61 switch (whence) { | 62 switch (whence) { |
62 default: | 63 default: |
63 return -1; | 64 return -1; |
64 case SEEK_SET: | 65 case SEEK_SET: |
65 base = 0; | 66 base = 0; |
66 break; | 67 break; |
67 case SEEK_CUR: | 68 case SEEK_CUR: |
68 base = handle_data_.offs; | 69 base = handle_attr_.offs; |
69 break; | 70 break; |
70 case SEEK_END: | 71 case SEEK_END: |
71 base = node_size; | 72 base = node_size; |
72 break; | 73 break; |
73 } | 74 } |
74 | 75 |
75 if (base + offset < 0) | 76 if (base + offset < 0) |
76 return EINVAL; | 77 return EINVAL; |
77 | 78 |
78 off_t new_offset = base + offset; | 79 off_t new_offset = base + offset; |
79 | 80 |
80 // Seeking past the end of the file will zero out the space between the old | 81 // Seeking past the end of the file will zero out the space between the old |
81 // end and the new end. | 82 // end and the new end. |
82 if (new_offset > node_size) { | 83 if (new_offset > node_size) { |
83 error = node_->FTruncate(new_offset); | 84 error = node_->FTruncate(new_offset); |
84 if (error) | 85 if (error) |
85 return EINVAL; | 86 return EINVAL; |
86 } | 87 } |
87 | 88 |
88 *out_offset = handle_data_.offs = new_offset; | 89 *out_offset = handle_attr_.offs = new_offset; |
89 return 0; | 90 return 0; |
90 } | 91 } |
91 | 92 |
92 Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) { | 93 Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) { |
93 AUTO_LOCK(handle_lock_); | 94 AUTO_LOCK(handle_lock_); |
94 Error error = node_->Read(handle_data_, buf, nbytes, cnt); | 95 Error error = node_->Read(handle_attr_, buf, nbytes, cnt); |
95 if (0 == error) | 96 if (0 == error) |
96 handle_data_.offs += *cnt; | 97 handle_attr_.offs += *cnt; |
97 return error; | 98 return error; |
98 } | 99 } |
99 | 100 |
100 Error KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) { | 101 Error KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) { |
101 AUTO_LOCK(handle_lock_); | 102 AUTO_LOCK(handle_lock_); |
102 Error error = node_->Write(handle_data_, buf, nbytes, cnt); | 103 Error error = node_->Write(handle_attr_, buf, nbytes, cnt); |
103 if (0 == error) | 104 if (0 == error) |
104 handle_data_.offs += *cnt; | 105 handle_attr_.offs += *cnt; |
105 return error; | 106 return error; |
106 } | 107 } |
107 | 108 |
108 Error KernelHandle::GetDents(struct dirent* pdir, size_t nbytes, int* cnt) { | 109 Error KernelHandle::GetDents(struct dirent* pdir, size_t nbytes, int* cnt) { |
109 AUTO_LOCK(handle_lock_); | 110 AUTO_LOCK(handle_lock_); |
110 Error error = node_->GetDents(handle_data_.offs, pdir, nbytes, cnt); | 111 Error error = node_->GetDents(handle_attr_.offs, pdir, nbytes, cnt); |
111 if (0 == error) | 112 if (0 == error) |
112 handle_data_.offs += *cnt; | 113 handle_attr_.offs += *cnt; |
113 return error; | 114 return error; |
114 } | 115 } |
115 | 116 |
116 Error KernelHandle::Fcntl(int request, int* result, ...) { | 117 Error KernelHandle::Fcntl(int request, int* result, ...) { |
117 va_list ap; | 118 va_list ap; |
118 va_start(ap, result); | 119 va_start(ap, result); |
119 Error rtn = VFcntl(request, result, ap); | 120 Error rtn = VFcntl(request, result, ap); |
120 va_end(ap); | 121 va_end(ap); |
121 return rtn; | 122 return rtn; |
122 } | 123 } |
123 | 124 |
124 Error KernelHandle::VFcntl(int request, int* result, va_list args) { | 125 Error KernelHandle::VFcntl(int request, int* result, va_list args) { |
125 switch (request) { | 126 switch (request) { |
126 case F_GETFL: { | 127 case F_GETFL: { |
127 *result = handle_data_.flags; | 128 *result = handle_attr_.flags; |
128 return 0; | 129 return 0; |
129 } | 130 } |
130 case F_SETFL: { | 131 case F_SETFL: { |
131 AUTO_LOCK(handle_lock_); | 132 AUTO_LOCK(handle_lock_); |
132 int flags = va_arg(args, int); | 133 int flags = va_arg(args, int); |
133 if (!(flags & O_APPEND) && (handle_data_.flags & O_APPEND)) { | 134 if (!(flags & O_APPEND) && (handle_attr_.flags & O_APPEND)) { |
134 // Attempt to clear O_APPEND. | 135 // Attempt to clear O_APPEND. |
135 return EPERM; | 136 return EPERM; |
136 } | 137 } |
137 // Only certain flags are mutable | 138 // Only certain flags are mutable |
138 const int mutable_flags = O_ASYNC | O_NONBLOCK; | 139 const int mutable_flags = O_ASYNC | O_NONBLOCK; |
139 flags &= mutable_flags; | 140 flags &= mutable_flags; |
140 handle_data_.flags &= ~mutable_flags; | 141 handle_attr_.flags &= ~mutable_flags; |
141 handle_data_.flags |= flags; | 142 handle_attr_.flags |= flags; |
142 return 0; | 143 return 0; |
143 } | 144 } |
144 } | 145 } |
145 return ENOSYS; | 146 return ENOSYS; |
146 } | 147 } |
147 | 148 |
| 149 Error KernelHandle::Accept(PP_Resource* new_sock, struct sockaddr* addr, |
| 150 socklen_t* len) { |
| 151 MountNodeSocket* sock = socket_node(); |
| 152 if (!sock) |
| 153 return ENOTSOCK; |
| 154 |
| 155 AUTO_LOCK(handle_lock_); |
| 156 return sock->Accept(handle_attr_, new_sock, addr, len); |
| 157 } |
| 158 |
| 159 Error KernelHandle::Connect(const struct sockaddr* addr, socklen_t len) { |
| 160 MountNodeSocket* sock = socket_node(); |
| 161 if (!sock) |
| 162 return ENOTSOCK; |
| 163 |
| 164 AUTO_LOCK(handle_lock_); |
| 165 return sock->Connect(handle_attr_, addr, len); |
| 166 } |
| 167 |
| 168 Error KernelHandle::Recv(void* buf, size_t len, int flags, int* out_len) { |
| 169 MountNodeSocket* sock = socket_node(); |
| 170 if (!sock) |
| 171 return ENOTSOCK; |
| 172 |
| 173 AUTO_LOCK(handle_lock_); |
| 174 return sock->Recv(handle_attr_, buf, len, flags, out_len); |
| 175 } |
| 176 |
| 177 Error KernelHandle::RecvFrom(void* buf, |
| 178 size_t len, |
| 179 int flags, |
| 180 struct sockaddr* src_addr, |
| 181 socklen_t* addrlen, |
| 182 int* out_len) { |
| 183 MountNodeSocket* sock = socket_node(); |
| 184 if (!sock) |
| 185 return ENOTSOCK; |
| 186 |
| 187 AUTO_LOCK(handle_lock_); |
| 188 return sock->RecvFrom(handle_attr_, buf, len, flags, src_addr, addrlen, |
| 189 out_len); |
| 190 } |
| 191 |
| 192 Error KernelHandle::Send(const void* buf, |
| 193 size_t len, |
| 194 int flags, |
| 195 int* out_len) { |
| 196 MountNodeSocket* sock = socket_node(); |
| 197 if (!sock) |
| 198 return ENOTSOCK; |
| 199 |
| 200 AUTO_LOCK(handle_lock_); |
| 201 return sock->Send(handle_attr_, buf, len, flags, out_len); |
| 202 } |
| 203 |
| 204 Error KernelHandle::SendTo(const void* buf, |
| 205 size_t len, |
| 206 int flags, |
| 207 const struct sockaddr* dest_addr, |
| 208 socklen_t addrlen, |
| 209 int* out_len) { |
| 210 MountNodeSocket* sock = socket_node(); |
| 211 if (!sock) |
| 212 return ENOTSOCK; |
| 213 |
| 214 AUTO_LOCK(handle_lock_); |
| 215 return sock->SendTo(handle_attr_, buf, len, flags, dest_addr, addrlen, |
| 216 out_len); |
| 217 } |
| 218 |
148 } // namespace nacl_io | 219 } // namespace nacl_io |
OLD | NEW |