1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <utime.h>
2520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng#include <unistd.h>
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
2820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng#include <private/android_filesystem_config.h>
2920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng#include <selinux/android.h>
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "sysdeps.h"
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define TRACE_TAG  TRACE_SYNC
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb.h"
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "file_sync_service.h"
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng/* TODO: use fs_config to configure permissions on /data */
3720d33f4d99c26afdd0aebf23786958ef34e261e3Liang Chengstatic bool is_on_system(const char *name) {
3820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    const char *SYSTEM = "/system/";
3920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    return (strncmp(SYSTEM, name, strlen(SYSTEM)) == 0);
4020d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng}
4120d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng
42686bce6390db802bfd2cb4e78f9270596b6decb2Daniel Rosenbergstatic bool is_on_vendor(const char *name) {
43686bce6390db802bfd2cb4e78f9270596b6decb2Daniel Rosenberg    const char *VENDOR = "/vendor/";
44686bce6390db802bfd2cb4e78f9270596b6decb2Daniel Rosenberg    return (strncmp(VENDOR, name, strlen(VENDOR)) == 0);
45686bce6390db802bfd2cb4e78f9270596b6decb2Daniel Rosenberg}
46686bce6390db802bfd2cb4e78f9270596b6decb2Daniel Rosenberg
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int mkdirs(char *name)
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ret;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *x = name + 1;
5172917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich    uid_t uid = -1;
5272917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich    gid_t gid = -1;
5320d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    unsigned int mode = 0775;
5420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    uint64_t cap = 0;
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(name[0] != '/') return -1;
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        x = adb_dirstart(x);
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(x == 0) return 0;
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *x = 0;
62686bce6390db802bfd2cb4e78f9270596b6decb2Daniel Rosenberg        if (is_on_system(name) || is_on_vendor(name)) {
6320d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fs_config(name, 1, &uid, &gid, &mode, &cap);
6420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
6520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        ret = adb_mkdir(name, mode);
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if((ret < 0) && (errno != EEXIST)) {
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D("mkdir(\"%s\") -> %s\n", name, strerror(errno));
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *x = '/';
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return ret;
7020d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        } else if(ret == 0) {
7120d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            ret = chown(name, uid, gid);
7220d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            if (ret < 0) {
7320d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng                *x = '/';
7420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng                return ret;
7520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            }
7627a93650c0df02e4cd3c48bbec8acee8b817a012Stephen Smalley            selinux_android_restorecon(name, 0);
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *x++ = '/';
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int do_stat(int s, const char *path)
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct stat st;
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.stat.id = ID_STAT;
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(lstat(path, &st)) {
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.mode = 0;
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.size = 0;
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.time = 0;
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.mode = htoll(st.st_mode);
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.size = htoll(st.st_size);
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.time = htoll(st.st_mtime);
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return writex(s, &msg.stat, sizeof(msg.stat));
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int do_list(int s, const char *path)
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DIR *d;
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct dirent *de;
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct stat st;
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int len;
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char tmp[1024 + 256 + 1];
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *fname;
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = strlen(path);
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(tmp, path, len);
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tmp[len] = '/';
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fname = tmp + len + 1;
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.id = ID_DENT;
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    d = opendir(path);
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(d == 0) goto done;
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while((de = readdir(d))) {
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int len = strlen(de->d_name);
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* not supposed to be possible, but
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               if it does happen, let's not buffer overrun */
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(len > 256) continue;
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        strcpy(fname, de->d_name);
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(lstat(tmp, &st) == 0) {
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.dent.mode = htoll(st.st_mode);
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.dent.size = htoll(st.st_size);
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.dent.time = htoll(st.st_mtime);
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.dent.namelen = htoll(len);
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(writex(s, &msg.dent, sizeof(msg.dent)) ||
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               writex(s, de->d_name, len)) {
14014e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes                closedir(d);
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return -1;
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    closedir(d);
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdone:
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.id = ID_DONE;
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.mode = 0;
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.size = 0;
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.time = 0;
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.namelen = 0;
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return writex(s, &msg.dent, sizeof(msg.dent));
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int fail_message(int s, const char *reason)
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int len = strlen(reason);
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("sync: failure: %s\n", reason);
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.data.id = ID_FAIL;
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.data.size = htoll(len);
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(writex(s, &msg.data, sizeof(msg.data)) ||
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project       writex(s, reason, len)) {
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int fail_errno(int s)
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return fail_message(s, strerror(errno));
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17972917837e6a1163bd389cf535eb404501a118cf2Nick Kralevichstatic int handle_send_file(int s, char *path, uid_t uid,
18055b6c843a6166fbbf57aa4afba8b2c2b3e87cfeaJP Abgrall        gid_t gid, mode_t mode, char *buffer, bool do_unlink)
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned int timestamp = 0;
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
186fe8d7f4f2e775d46d61f7c2d29a4e852434984daNick Kralevich    fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0 && errno == ENOENT) {
18820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if(mkdirs(path) != 0) {
18920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            if(fail_errno(s))
19020d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng                return -1;
19120d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fd = -1;
19220d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        } else {
193fe8d7f4f2e775d46d61f7c2d29a4e852434984daNick Kralevich            fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
19420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0 && errno == EEXIST) {
197fe8d7f4f2e775d46d61f7c2d29a4e852434984daNick Kralevich        fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode);
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0) {
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fail_errno(s))
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fd = -1;
20320d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    } else {
20420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if(fchown(fd, uid, gid) != 0) {
20520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fail_errno(s);
20620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            errno = 0;
20720d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
20872917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich
20972917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich        /*
21072917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich         * fchown clears the setuid bit - restore it if present.
21172917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich         * Ignore the result of calling fchmod. It's not supported
21272917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich         * by all filesystems. b/12441485
21372917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich         */
21472917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich        fchmod(fd, mode);
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        unsigned int len;
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(readx(s, &msg.data, sizeof(msg.data)))
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(msg.data.id != ID_DATA) {
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(msg.data.id == ID_DONE) {
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                timestamp = ltohl(msg.data.size);
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(s, "invalid data message");
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        len = ltohl(msg.data.size);
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(len > SYNC_DATA_MAX) {
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(s, "oversize data message");
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(readx(s, buffer, len))
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd < 0)
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(writex(fd, buffer, len)) {
242408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            int saved_errno = errno;
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_close(fd);
24455b6c843a6166fbbf57aa4afba8b2c2b3e87cfeaJP Abgrall            if (do_unlink) adb_unlink(path);
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fd = -1;
246408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            errno = saved_errno;
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(fail_errno(s)) return -1;
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd >= 0) {
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct utimbuf u;
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd);
25427a93650c0df02e4cd3c48bbec8acee8b817a012Stephen Smalley        selinux_android_restorecon(path, 0);
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        u.actime = timestamp;
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        u.modtime = timestamp;
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        utime(path, &u);
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.status.id = ID_OKAY;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.status.msglen = 0;
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(writex(s, &msg.status, sizeof(msg.status)))
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail:
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd >= 0)
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd);
26955b6c843a6166fbbf57aa4afba8b2c2b3e87cfeaJP Abgrall    if (do_unlink) adb_unlink(path);
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_SYMLINKS
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int handle_send_link(int s, char *path, char *buffer)
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned int len;
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ret;
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(readx(s, &msg.data, sizeof(msg.data)))
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(msg.data.id != ID_DATA) {
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fail_message(s, "invalid data message: expected ID_DATA");
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = ltohl(msg.data.size);
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(len > SYNC_DATA_MAX) {
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fail_message(s, "oversize data message");
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(readx(s, buffer, len))
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ret = symlink(buffer, path);
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ret && errno == ENOENT) {
29820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if(mkdirs(path) != 0) {
29920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fail_errno(s);
30020d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            return -1;
30120d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = symlink(buffer, path);
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ret) {
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fail_errno(s);
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(readx(s, &msg.data, sizeof(msg.data)))
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(msg.data.id == ID_DONE) {
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.status.id = ID_OKAY;
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.status.msglen = 0;
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(writex(s, &msg.status, sizeof(msg.status)))
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fail_message(s, "invalid data message: expected ID_DONE");
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* HAVE_SYMLINKS */
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int do_send(int s, char *path, char *buffer)
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *tmp;
32920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    unsigned int mode;
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int is_link, ret;
33155b6c843a6166fbbf57aa4afba8b2c2b3e87cfeaJP Abgrall    bool do_unlink;
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tmp = strrchr(path,',');
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(tmp) {
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *tmp = 0;
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        errno = 0;
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode = strtoul(tmp + 1, NULL, 0);
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef HAVE_SYMLINKS
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        is_link = 0;
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
34120d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        is_link = S_ISLNK((mode_t) mode);
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode &= 0777;
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!tmp || errno) {
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode = 0644;
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        is_link = 0;
34855b6c843a6166fbbf57aa4afba8b2c2b3e87cfeaJP Abgrall        do_unlink = true;
3494ce2f838e78592d0b93776b73ca4de855a423ddeJP Abgrall    } else {
3504ce2f838e78592d0b93776b73ca4de855a423ddeJP Abgrall        struct stat st;
3514ce2f838e78592d0b93776b73ca4de855a423ddeJP Abgrall        /* Don't delete files before copying if they are not "regular" */
35255b6c843a6166fbbf57aa4afba8b2c2b3e87cfeaJP Abgrall        do_unlink = lstat(path, &st) || S_ISREG(st.st_mode) || S_ISLNK(st.st_mode);
35355b6c843a6166fbbf57aa4afba8b2c2b3e87cfeaJP Abgrall        if (do_unlink) {
3544ce2f838e78592d0b93776b73ca4de855a423ddeJP Abgrall            adb_unlink(path);
3554ce2f838e78592d0b93776b73ca4de855a423ddeJP Abgrall        }
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_SYMLINKS
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(is_link)
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = handle_send_link(s, path, buffer);
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else {
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
36572917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich        uid_t uid = -1;
36672917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich        gid_t gid = -1;
36720d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        uint64_t cap = 0;
36820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* copy user permission bits to "group" and "other" permissions */
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode |= ((mode >> 3) & 0070);
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode |= ((mode >> 3) & 0007);
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
37320d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        tmp = path;
37420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if(*tmp == '/') {
37520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            tmp++;
37620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
377686bce6390db802bfd2cb4e78f9270596b6decb2Daniel Rosenberg        if (is_on_system(path) || is_on_vendor(path)) {
37820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fs_config(tmp, 0, &uid, &gid, &mode, &cap);
37920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
38055b6c843a6166fbbf57aa4afba8b2c2b3e87cfeaJP Abgrall        ret = handle_send_file(s, path, uid, gid, mode, buffer, do_unlink);
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return ret;
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int do_recv(int s, const char *path, char *buffer)
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd, r;
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
391fe8d7f4f2e775d46d61f7c2d29a4e852434984daNick Kralevich    fd = adb_open(path, O_RDONLY | O_CLOEXEC);
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0) {
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fail_errno(s)) return -1;
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.data.id = ID_DATA;
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        r = adb_read(fd, buffer, SYNC_DATA_MAX);
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(r <= 0) {
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(r == 0) break;
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(errno == EINTR) continue;
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            r = fail_errno(s);
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_close(fd);
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return r;
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.data.size = htoll(r);
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(writex(s, &msg.data, sizeof(msg.data)) ||
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           writex(s, buffer, r)) {
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_close(fd);
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_close(fd);
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.data.id = ID_DONE;
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.data.size = 0;
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(writex(s, &msg.data, sizeof(msg.data))) {
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid file_sync_service(int fd, void *cookie)
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char name[1025];
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned namelen;
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *buffer = malloc(SYNC_DATA_MAX);
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(buffer == 0) goto fail;
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("sync: waiting for command\n");
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(readx(fd, &msg.req, sizeof(msg.req))) {
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(fd, "command read failure");
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        namelen = ltohl(msg.req.namelen);
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(namelen > 1024) {
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(fd, "invalid namelen");
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(readx(fd, name, namelen)) {
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(fd, "filename read failure");
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name[namelen] = 0;
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.req.namelen = 0;
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("sync: '%s' '%s'\n", (char*) &msg.req, name);
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        switch(msg.req.id) {
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ID_STAT:
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(do_stat(fd, name)) goto fail;
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ID_LIST:
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(do_list(fd, name)) goto fail;
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ID_SEND:
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(do_send(fd, name, buffer)) goto fail;
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ID_RECV:
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(do_recv(fd, name, buffer)) goto fail;
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ID_QUIT:
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        default:
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(fd, "unknown command");
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail:
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(buffer != 0) free(buffer);
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("sync: done\n");
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_close(fd);
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
482