summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'mountd/Server.c')
-rw-r--r--mountd/Server.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/mountd/Server.c b/mountd/Server.c
new file mode 100644
index 000000000..14b383001
--- /dev/null
+++ b/mountd/Server.c
@@ -0,0 +1,232 @@
1/*
2 * Copyright (C) 2008 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/*
18** mountd server support
19*/
20
21#include "mountd.h"
22
23#include <cutils/properties.h>
24#include <cutils/sockets.h>
25
26#include <pthread.h>
27#include <errno.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <string.h>
32#include <sys/socket.h>
33
34#include <private/android_filesystem_config.h>
35
36
37// current client file descriptor
38static int sFD = -1;
39
40// to synchronize writing to client
41static pthread_mutex_t sWriteMutex = PTHREAD_MUTEX_INITIALIZER;
42
43// path for media that failed to mount before the runtime is connected
44static char* sDeferredUnmountableMediaPath = NULL;
45
46static int Write(const char* message)
47{
48 int result = -1;
49
50 pthread_mutex_lock(&sWriteMutex);
51
52 LOG_SERVER("Write: %s\n", message);
53 if (sFD >= 0)
54 result = write(sFD, message, strlen(message) + 1);
55
56 pthread_mutex_unlock(&sWriteMutex);
57
58 return result;
59}
60
61static int Write2(const char* message, const char* data)
62{
63 int result = -1;
64
65 char* buffer = (char *)alloca(strlen(message) + strlen(data) + 1);
66 if (!buffer)
67 {
68 LOG_ERROR("alloca failed in Write2\n");
69 return -1;
70 }
71
72 strcpy(buffer, message);
73 strcat(buffer, data);
74 return Write(buffer);
75}
76
77static void SendStatus()
78{
79 Write(IsMassStorageConnected() ? MOUNTD_UMS_CONNECTED : MOUNTD_UMS_DISCONNECTED);
80 Write(IsMassStorageEnabled() ? MOUNTD_UMS_ENABLED : MOUNTD_UMS_DISABLED);
81}
82
83static void DoCommand(const char* command)
84{
85 LOG_SERVER("DoCommand %s\n", command);
86
87 if (strcmp(command, MOUNTD_ENABLE_UMS) == 0)
88 {
89 EnableMassStorage(true);
90 Write(MOUNTD_UMS_ENABLED);
91 }
92 else if (strcmp(command, MOUNTD_DISABLE_UMS) == 0)
93 {
94 EnableMassStorage(false);
95 Write(MOUNTD_UMS_DISABLED);
96 }
97 else if (strcmp(command, MOUNTD_SEND_STATUS) == 0)
98 {
99 SendStatus();
100 }
101 else if (strncmp(command, MOUNTD_MOUNT_MEDIA, strlen(MOUNTD_MOUNT_MEDIA)) == 0)
102 {
103 const char* path = command + strlen(MOUNTD_MOUNT_MEDIA);
104 MountMedia(path);
105 }
106 else if (strncmp(command, MOUNTD_EJECT_MEDIA, strlen(MOUNTD_EJECT_MEDIA)) == 0)
107 {
108 const char* path = command + strlen(MOUNTD_EJECT_MEDIA);
109 UnmountMedia(path);
110 }
111 else
112 LOGE("unknown command %s\n", command);
113}
114
115int RunServer()
116{
117 int socket = android_get_control_socket(MOUNTD_SOCKET);
118 if (socket < 0) {
119 LOGE("Obtaining file descriptor for socket '%s' failed: %s",
120 MOUNTD_SOCKET, strerror(errno));
121 return -1;
122 }
123
124 if (listen(socket, 4) < 0) {
125 LOGE("Unable to listen on file descriptor '%d' for socket '%s': %s",
126 socket, MOUNTD_SOCKET, strerror(errno));
127 return -1;
128 }
129
130 while (1)
131 {
132 struct sockaddr addr;
133 socklen_t alen;
134 struct ucred cred;
135 socklen_t size;
136
137 alen = sizeof(addr);
138 sFD = accept(socket, &addr, &alen);
139 if (sFD < 0)
140 continue;
141
142 if (sDeferredUnmountableMediaPath) {
143 NotifyMediaState(sDeferredUnmountableMediaPath, MEDIA_UNMOUNTABLE, false);
144 free(sDeferredUnmountableMediaPath);
145 sDeferredUnmountableMediaPath = NULL;
146 }
147
148 while (1)
149 {
150 char buffer[101];
151 int result = read(sFD, buffer, sizeof(buffer) - 1);
152 if (result > 0)
153 {
154 int start = 0;
155 int i;
156 // command should be zero terminated, but just in case
157 buffer[result] = 0;
158 for (i = 0; i < result; i++)
159 {
160 if (buffer[i] == 0)
161 {
162 DoCommand(buffer + start);
163 start = i + 1;
164 }
165 }
166 }
167 else
168 {
169 close(sFD);
170 sFD = -1;
171 break;
172 }
173 }
174 }
175
176 // should never get here
177 return 0;
178}
179
180void SendMassStorageConnected(boolean connected)
181{
182 Write(connected ? MOUNTD_UMS_CONNECTED : MOUNTD_UMS_DISCONNECTED);
183}
184
185void SendUnmountRequest(const char* path)
186{
187 Write2(MOUNTD_REQUEST_EJECT, path);
188}
189
190void NotifyMediaState(const char* path, MediaState state, boolean readOnly)
191{
192 const char* event = NULL;
193 const char* propertyValue = NULL;
194
195 switch (state) {
196 case MEDIA_REMOVED:
197 event = MOUNTD_MEDIA_REMOVED;
198 propertyValue = EXTERNAL_STORAGE_REMOVED;
199 break;
200 case MEDIA_UNMOUNTED:
201 event = MOUNTD_MEDIA_UNMOUNTED;
202 propertyValue = EXTERNAL_STORAGE_UNMOUNTED;
203 break;
204 case MEDIA_MOUNTED:
205 event = (readOnly ? MOUNTD_MEDIA_MOUNTED_READ_ONLY : MOUNTD_MEDIA_MOUNTED);
206 propertyValue = (readOnly ? EXTERNAL_STORAGE_MOUNTED_READ_ONLY : EXTERNAL_STORAGE_MOUNTED);
207 break;
208 case MEDIA_SHARED:
209 event = MOUNTD_MEDIA_SHARED;
210 propertyValue = EXTERNAL_STORAGE_SHARED;
211 break;
212 case MEDIA_BAD_REMOVAL:
213 event = MOUNTD_MEDIA_BAD_REMOVAL;
214 propertyValue = EXTERNAL_STORAGE_BAD_REMOVAL;
215 break;
216 case MEDIA_UNMOUNTABLE:
217 event = MOUNTD_MEDIA_UNMOUNTABLE;
218 propertyValue = EXTERNAL_STORAGE_UNMOUNTABLE;
219 break;
220 default:
221 LOG_ERROR("unknown MediaState %d in NotifyMediaState\n", state);
222 return;
223 }
224
225 property_set(EXTERNAL_STORAGE_STATE, propertyValue);
226 int result = Write2(event, path);
227 if (result < 0 && state == MEDIA_UNMOUNTABLE) {
228
229 // if we cannot communicate with the runtime, defer this message until the runtime is available
230 sDeferredUnmountableMediaPath = strdup(path);
231 }
232}