file_sync_service.c revision 72917837e6a1163bd389cf535eb404501a118cf2
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
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int mkdirs(char *name)
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ret;
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *x = name + 1;
4672917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich    uid_t uid = -1;
4772917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich    gid_t gid = -1;
4820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    unsigned int mode = 0775;
4920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    uint64_t cap = 0;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(name[0] != '/') return -1;
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        x = adb_dirstart(x);
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(x == 0) return 0;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *x = 0;
5720d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if (is_on_system(name)) {
5820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fs_config(name, 1, &uid, &gid, &mode, &cap);
5920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
6020d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        ret = adb_mkdir(name, mode);
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if((ret < 0) && (errno != EEXIST)) {
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D("mkdir(\"%s\") -> %s\n", name, strerror(errno));
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *x = '/';
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return ret;
6520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        } else if(ret == 0) {
6620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            ret = chown(name, uid, gid);
6720d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            if (ret < 0) {
6820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng                *x = '/';
6920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng                return ret;
7020d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            }
7120d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            selinux_android_restorecon(name);
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *x++ = '/';
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int do_stat(int s, const char *path)
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct stat st;
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.stat.id = ID_STAT;
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(lstat(path, &st)) {
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.mode = 0;
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.size = 0;
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.time = 0;
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.mode = htoll(st.st_mode);
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.size = htoll(st.st_size);
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.time = htoll(st.st_mtime);
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return writex(s, &msg.stat, sizeof(msg.stat));
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int do_list(int s, const char *path)
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DIR *d;
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct dirent *de;
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct stat st;
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int len;
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char tmp[1024 + 256 + 1];
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *fname;
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = strlen(path);
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(tmp, path, len);
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tmp[len] = '/';
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fname = tmp + len + 1;
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.id = ID_DENT;
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    d = opendir(path);
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(d == 0) goto done;
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while((de = readdir(d))) {
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int len = strlen(de->d_name);
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* not supposed to be possible, but
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               if it does happen, let's not buffer overrun */
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(len > 256) continue;
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        strcpy(fname, de->d_name);
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(lstat(tmp, &st) == 0) {
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.dent.mode = htoll(st.st_mode);
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.dent.size = htoll(st.st_size);
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.dent.time = htoll(st.st_mtime);
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.dent.namelen = htoll(len);
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(writex(s, &msg.dent, sizeof(msg.dent)) ||
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               writex(s, de->d_name, len)) {
13514e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes                closedir(d);
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return -1;
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    closedir(d);
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdone:
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.id = ID_DONE;
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.mode = 0;
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.size = 0;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.time = 0;
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.namelen = 0;
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return writex(s, &msg.dent, sizeof(msg.dent));
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int fail_message(int s, const char *reason)
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int len = strlen(reason);
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("sync: failure: %s\n", reason);
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.data.id = ID_FAIL;
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.data.size = htoll(len);
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(writex(s, &msg.data, sizeof(msg.data)) ||
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project       writex(s, reason, len)) {
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int fail_errno(int s)
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return fail_message(s, strerror(errno));
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17472917837e6a1163bd389cf535eb404501a118cf2Nick Kralevichstatic int handle_send_file(int s, char *path, uid_t uid,
17572917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich        gid_t gid, mode_t mode, char *buffer)
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned int timestamp = 0;
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0 && errno == ENOENT) {
18320d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if(mkdirs(path) != 0) {
18420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            if(fail_errno(s))
18520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng                return -1;
18620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fd = -1;
18720d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        } else {
18820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
18920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0 && errno == EEXIST) {
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fd = adb_open_mode(path, O_WRONLY, mode);
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0) {
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fail_errno(s))
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fd = -1;
19820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    } else {
19920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if(fchown(fd, uid, gid) != 0) {
20020d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fail_errno(s);
20120d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            errno = 0;
20220d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
20372917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich
20472917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich        /*
20572917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich         * fchown clears the setuid bit - restore it if present.
20672917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich         * Ignore the result of calling fchmod. It's not supported
20772917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich         * by all filesystems. b/12441485
20872917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich         */
20972917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich        fchmod(fd, mode);
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        unsigned int len;
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(readx(s, &msg.data, sizeof(msg.data)))
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(msg.data.id != ID_DATA) {
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(msg.data.id == ID_DONE) {
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                timestamp = ltohl(msg.data.size);
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(s, "invalid data message");
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        len = ltohl(msg.data.size);
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(len > SYNC_DATA_MAX) {
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(s, "oversize data message");
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(readx(s, buffer, len))
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd < 0)
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(writex(fd, buffer, len)) {
237408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            int saved_errno = errno;
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_close(fd);
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_unlink(path);
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fd = -1;
241408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            errno = saved_errno;
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(fail_errno(s)) return -1;
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd >= 0) {
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct utimbuf u;
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd);
24920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        selinux_android_restorecon(path);
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        u.actime = timestamp;
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        u.modtime = timestamp;
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        utime(path, &u);
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.status.id = ID_OKAY;
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.status.msglen = 0;
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(writex(s, &msg.status, sizeof(msg.status)))
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail:
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd >= 0)
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd);
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_unlink(path);
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_SYMLINKS
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int handle_send_link(int s, char *path, char *buffer)
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned int len;
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ret;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(readx(s, &msg.data, sizeof(msg.data)))
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(msg.data.id != ID_DATA) {
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fail_message(s, "invalid data message: expected ID_DATA");
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = ltohl(msg.data.size);
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(len > SYNC_DATA_MAX) {
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fail_message(s, "oversize data message");
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(readx(s, buffer, len))
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ret = symlink(buffer, path);
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ret && errno == ENOENT) {
29320d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if(mkdirs(path) != 0) {
29420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fail_errno(s);
29520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            return -1;
29620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = symlink(buffer, path);
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ret) {
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fail_errno(s);
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(readx(s, &msg.data, sizeof(msg.data)))
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(msg.data.id == ID_DONE) {
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.status.id = ID_OKAY;
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.status.msglen = 0;
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(writex(s, &msg.status, sizeof(msg.status)))
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fail_message(s, "invalid data message: expected ID_DONE");
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* HAVE_SYMLINKS */
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int do_send(int s, char *path, char *buffer)
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *tmp;
32420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    unsigned int mode;
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int is_link, ret;
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tmp = strrchr(path,',');
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(tmp) {
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *tmp = 0;
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        errno = 0;
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode = strtoul(tmp + 1, NULL, 0);
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef HAVE_SYMLINKS
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        is_link = 0;
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
33520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        is_link = S_ISLNK((mode_t) mode);
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode &= 0777;
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!tmp || errno) {
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode = 0644;
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        is_link = 0;
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_unlink(path);
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_SYMLINKS
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(is_link)
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = handle_send_link(s, path, buffer);
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else {
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
35472917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich        uid_t uid = -1;
35572917837e6a1163bd389cf535eb404501a118cf2Nick Kralevich        gid_t gid = -1;
35620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        uint64_t cap = 0;
35720d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* copy user permission bits to "group" and "other" permissions */
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode |= ((mode >> 3) & 0070);
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode |= ((mode >> 3) & 0007);
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
36220d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        tmp = path;
36320d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if(*tmp == '/') {
36420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            tmp++;
36520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
36620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if (is_on_system(path)) {
36720d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fs_config(tmp, 0, &uid, &gid, &mode, &cap);
36820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
36920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        ret = handle_send_file(s, path, uid, gid, mode, buffer);
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return ret;
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int do_recv(int s, const char *path, char *buffer)
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd, r;
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = adb_open(path, O_RDONLY);
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0) {
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fail_errno(s)) return -1;
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.data.id = ID_DATA;
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        r = adb_read(fd, buffer, SYNC_DATA_MAX);
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(r <= 0) {
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(r == 0) break;
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(errno == EINTR) continue;
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            r = fail_errno(s);
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_close(fd);
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return r;
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.data.size = htoll(r);
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(writex(s, &msg.data, sizeof(msg.data)) ||
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           writex(s, buffer, r)) {
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_close(fd);
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_close(fd);
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.data.id = ID_DONE;
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.data.size = 0;
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(writex(s, &msg.data, sizeof(msg.data))) {
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid file_sync_service(int fd, void *cookie)
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char name[1025];
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned namelen;
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *buffer = malloc(SYNC_DATA_MAX);
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(buffer == 0) goto fail;
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("sync: waiting for command\n");
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(readx(fd, &msg.req, sizeof(msg.req))) {
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(fd, "command read failure");
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        namelen = ltohl(msg.req.namelen);
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(namelen > 1024) {
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(fd, "invalid namelen");
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(readx(fd, name, namelen)) {
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(fd, "filename read failure");
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name[namelen] = 0;
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.req.namelen = 0;
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("sync: '%s' '%s'\n", (char*) &msg.req, name);
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        switch(msg.req.id) {
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ID_STAT:
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(do_stat(fd, name)) goto fail;
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ID_LIST:
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(do_list(fd, name)) goto fail;
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ID_SEND:
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(do_send(fd, name, buffer)) goto fail;
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ID_RECV:
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(do_recv(fd, name, buffer)) goto fail;
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ID_QUIT:
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        default:
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(fd, "unknown command");
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail:
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(buffer != 0) free(buffer);
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("sync: done\n");
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_close(fd);
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
471