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