• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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 <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <dirent.h>
24 #include <utime.h>
25 
26 #include <errno.h>
27 
28 #include "sysdeps.h"
29 
30 #define TRACE_TAG  TRACE_SYNC
31 #include "adb.h"
32 #include "file_sync_service.h"
33 
mkdirs(char * name)34 static int mkdirs(char *name)
35 {
36     int ret;
37     char *x = name + 1;
38 
39     if(name[0] != '/') return -1;
40 
41     for(;;) {
42         x = adb_dirstart(x);
43         if(x == 0) return 0;
44         *x = 0;
45         ret = adb_mkdir(name, 0775);
46         if((ret < 0) && (errno != EEXIST)) {
47             D("mkdir(\"%s\") -> %s\n", name, strerror(errno));
48             *x = '/';
49             return ret;
50         }
51         *x++ = '/';
52     }
53     return 0;
54 }
55 
do_stat(int s,const char * path)56 static int do_stat(int s, const char *path)
57 {
58     syncmsg msg;
59     struct stat st;
60 
61     msg.stat.id = ID_STAT;
62 
63     if(lstat(path, &st)) {
64         msg.stat.mode = 0;
65         msg.stat.size = 0;
66         msg.stat.time = 0;
67     } else {
68         msg.stat.mode = htoll(st.st_mode);
69         msg.stat.size = htoll(st.st_size);
70         msg.stat.time = htoll(st.st_mtime);
71     }
72 
73     return writex(s, &msg.stat, sizeof(msg.stat));
74 }
75 
do_list(int s,const char * path)76 static int do_list(int s, const char *path)
77 {
78     DIR *d;
79     struct dirent *de;
80     struct stat st;
81     syncmsg msg;
82     int len;
83 
84     char tmp[1024 + 256 + 1];
85     char *fname;
86 
87     len = strlen(path);
88     memcpy(tmp, path, len);
89     tmp[len] = '/';
90     fname = tmp + len + 1;
91 
92     msg.dent.id = ID_DENT;
93 
94     d = opendir(path);
95     if(d == 0) goto done;
96 
97     while((de = readdir(d))) {
98         int len = strlen(de->d_name);
99 
100             /* not supposed to be possible, but
101                if it does happen, let's not buffer overrun */
102         if(len > 256) continue;
103 
104         strcpy(fname, de->d_name);
105         if(lstat(tmp, &st) == 0) {
106             msg.dent.mode = htoll(st.st_mode);
107             msg.dent.size = htoll(st.st_size);
108             msg.dent.time = htoll(st.st_mtime);
109             msg.dent.namelen = htoll(len);
110 
111             if(writex(s, &msg.dent, sizeof(msg.dent)) ||
112                writex(s, de->d_name, len)) {
113                 return -1;
114             }
115         }
116     }
117 
118     closedir(d);
119 
120 done:
121     msg.dent.id = ID_DONE;
122     msg.dent.mode = 0;
123     msg.dent.size = 0;
124     msg.dent.time = 0;
125     msg.dent.namelen = 0;
126     return writex(s, &msg.dent, sizeof(msg.dent));
127 }
128 
fail_message(int s,const char * reason)129 static int fail_message(int s, const char *reason)
130 {
131     syncmsg msg;
132     int len = strlen(reason);
133 
134     D("sync: failure: %s\n", reason);
135 
136     msg.data.id = ID_FAIL;
137     msg.data.size = htoll(len);
138     if(writex(s, &msg.data, sizeof(msg.data)) ||
139        writex(s, reason, len)) {
140         return -1;
141     } else {
142         return 0;
143     }
144 }
145 
fail_errno(int s)146 static int fail_errno(int s)
147 {
148     return fail_message(s, strerror(errno));
149 }
150 
handle_send_file(int s,char * path,mode_t mode,char * buffer)151 static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
152 {
153     syncmsg msg;
154     unsigned int timestamp = 0;
155     int fd;
156 
157     fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
158     if(fd < 0 && errno == ENOENT) {
159         mkdirs(path);
160         fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
161     }
162     if(fd < 0 && errno == EEXIST) {
163         fd = adb_open_mode(path, O_WRONLY, mode);
164     }
165     if(fd < 0) {
166         if(fail_errno(s))
167             return -1;
168         fd = -1;
169     }
170 
171     for(;;) {
172         unsigned int len;
173 
174         if(readx(s, &msg.data, sizeof(msg.data)))
175             goto fail;
176 
177         if(msg.data.id != ID_DATA) {
178             if(msg.data.id == ID_DONE) {
179                 timestamp = ltohl(msg.data.size);
180                 break;
181             }
182             fail_message(s, "invalid data message");
183             goto fail;
184         }
185         len = ltohl(msg.data.size);
186         if(len > SYNC_DATA_MAX) {
187             fail_message(s, "oversize data message");
188             goto fail;
189         }
190         if(readx(s, buffer, len))
191             goto fail;
192 
193         if(fd < 0)
194             continue;
195         if(writex(fd, buffer, len)) {
196             int saved_errno = errno;
197             adb_close(fd);
198             adb_unlink(path);
199             fd = -1;
200             errno = saved_errno;
201             if(fail_errno(s)) return -1;
202         }
203     }
204 
205     if(fd >= 0) {
206         struct utimbuf u;
207         adb_close(fd);
208         u.actime = timestamp;
209         u.modtime = timestamp;
210         utime(path, &u);
211 
212         msg.status.id = ID_OKAY;
213         msg.status.msglen = 0;
214         if(writex(s, &msg.status, sizeof(msg.status)))
215             return -1;
216     }
217     return 0;
218 
219 fail:
220     if(fd >= 0)
221         adb_close(fd);
222     adb_unlink(path);
223     return -1;
224 }
225 
226 #ifdef HAVE_SYMLINKS
handle_send_link(int s,char * path,char * buffer)227 static int handle_send_link(int s, char *path, char *buffer)
228 {
229     syncmsg msg;
230     unsigned int len;
231     int ret;
232 
233     if(readx(s, &msg.data, sizeof(msg.data)))
234         return -1;
235 
236     if(msg.data.id != ID_DATA) {
237         fail_message(s, "invalid data message: expected ID_DATA");
238         return -1;
239     }
240 
241     len = ltohl(msg.data.size);
242     if(len > SYNC_DATA_MAX) {
243         fail_message(s, "oversize data message");
244         return -1;
245     }
246     if(readx(s, buffer, len))
247         return -1;
248 
249     ret = symlink(buffer, path);
250     if(ret && errno == ENOENT) {
251         mkdirs(path);
252         ret = symlink(buffer, path);
253     }
254     if(ret) {
255         fail_errno(s);
256         return -1;
257     }
258 
259     if(readx(s, &msg.data, sizeof(msg.data)))
260         return -1;
261 
262     if(msg.data.id == ID_DONE) {
263         msg.status.id = ID_OKAY;
264         msg.status.msglen = 0;
265         if(writex(s, &msg.status, sizeof(msg.status)))
266             return -1;
267     } else {
268         fail_message(s, "invalid data message: expected ID_DONE");
269         return -1;
270     }
271 
272     return 0;
273 }
274 #endif /* HAVE_SYMLINKS */
275 
do_send(int s,char * path,char * buffer)276 static int do_send(int s, char *path, char *buffer)
277 {
278     char *tmp;
279     mode_t mode;
280     int is_link, ret;
281 
282     tmp = strrchr(path,',');
283     if(tmp) {
284         *tmp = 0;
285         errno = 0;
286         mode = strtoul(tmp + 1, NULL, 0);
287 #ifndef HAVE_SYMLINKS
288         is_link = 0;
289 #else
290         is_link = S_ISLNK(mode);
291 #endif
292         mode &= 0777;
293     }
294     if(!tmp || errno) {
295         mode = 0644;
296         is_link = 0;
297     }
298 
299     adb_unlink(path);
300 
301 
302 #ifdef HAVE_SYMLINKS
303     if(is_link)
304         ret = handle_send_link(s, path, buffer);
305     else {
306 #else
307     {
308 #endif
309         /* copy user permission bits to "group" and "other" permissions */
310         mode |= ((mode >> 3) & 0070);
311         mode |= ((mode >> 3) & 0007);
312 
313         ret = handle_send_file(s, path, mode, buffer);
314     }
315 
316     return ret;
317 }
318 
319 static int do_recv(int s, const char *path, char *buffer)
320 {
321     syncmsg msg;
322     int fd, r;
323 
324     fd = adb_open(path, O_RDONLY);
325     if(fd < 0) {
326         if(fail_errno(s)) return -1;
327         return 0;
328     }
329 
330     msg.data.id = ID_DATA;
331     for(;;) {
332         r = adb_read(fd, buffer, SYNC_DATA_MAX);
333         if(r <= 0) {
334             if(r == 0) break;
335             if(errno == EINTR) continue;
336             r = fail_errno(s);
337             adb_close(fd);
338             return r;
339         }
340         msg.data.size = htoll(r);
341         if(writex(s, &msg.data, sizeof(msg.data)) ||
342            writex(s, buffer, r)) {
343             adb_close(fd);
344             return -1;
345         }
346     }
347 
348     adb_close(fd);
349 
350     msg.data.id = ID_DONE;
351     msg.data.size = 0;
352     if(writex(s, &msg.data, sizeof(msg.data))) {
353         return -1;
354     }
355 
356     return 0;
357 }
358 
359 void file_sync_service(int fd, void *cookie)
360 {
361     syncmsg msg;
362     char name[1025];
363     unsigned namelen;
364 
365     char *buffer = malloc(SYNC_DATA_MAX);
366     if(buffer == 0) goto fail;
367 
368     for(;;) {
369         D("sync: waiting for command\n");
370 
371         if(readx(fd, &msg.req, sizeof(msg.req))) {
372             fail_message(fd, "command read failure");
373             break;
374         }
375         namelen = ltohl(msg.req.namelen);
376         if(namelen > 1024) {
377             fail_message(fd, "invalid namelen");
378             break;
379         }
380         if(readx(fd, name, namelen)) {
381             fail_message(fd, "filename read failure");
382             break;
383         }
384         name[namelen] = 0;
385 
386         msg.req.namelen = 0;
387         D("sync: '%s' '%s'\n", (char*) &msg.req, name);
388 
389         switch(msg.req.id) {
390         case ID_STAT:
391             if(do_stat(fd, name)) goto fail;
392             break;
393         case ID_LIST:
394             if(do_list(fd, name)) goto fail;
395             break;
396         case ID_SEND:
397             if(do_send(fd, name, buffer)) goto fail;
398             break;
399         case ID_RECV:
400             if(do_recv(fd, name, buffer)) goto fail;
401             break;
402         case ID_QUIT:
403             goto fail;
404         default:
405             fail_message(fd, "unknown command");
406             goto fail;
407         }
408     }
409 
410 fail:
411     if(buffer != 0) free(buffer);
412     D("sync: done\n");
413     adb_close(fd);
414 }
415