file_sync_service.c revision 20d33f4d99c26afdd0aebf23786958ef34e261e3
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;
4620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    unsigned int uid, gid;
4720d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    unsigned int mode = 0775;
4820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    uint64_t cap = 0;
4920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    uid = getuid();
5020d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    gid = getgid();
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(name[0] != '/') return -1;
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        x = adb_dirstart(x);
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(x == 0) return 0;
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *x = 0;
5820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if (is_on_system(name)) {
5920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fs_config(name, 1, &uid, &gid, &mode, &cap);
6020d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
6120d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        ret = adb_mkdir(name, mode);
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if((ret < 0) && (errno != EEXIST)) {
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D("mkdir(\"%s\") -> %s\n", name, strerror(errno));
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *x = '/';
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return ret;
6620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        } else if(ret == 0) {
6720d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            ret = chown(name, uid, gid);
6820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            if (ret < 0) {
6920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng                *x = '/';
7020d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng                return ret;
7120d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            }
7220d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            selinux_android_restorecon(name);
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *x++ = '/';
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int do_stat(int s, const char *path)
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct stat st;
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.stat.id = ID_STAT;
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(lstat(path, &st)) {
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.mode = 0;
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.size = 0;
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.time = 0;
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.mode = htoll(st.st_mode);
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.size = htoll(st.st_size);
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.stat.time = htoll(st.st_mtime);
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return writex(s, &msg.stat, sizeof(msg.stat));
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int do_list(int s, const char *path)
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DIR *d;
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct dirent *de;
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct stat st;
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int len;
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char tmp[1024 + 256 + 1];
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *fname;
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = strlen(path);
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(tmp, path, len);
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tmp[len] = '/';
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fname = tmp + len + 1;
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.id = ID_DENT;
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    d = opendir(path);
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(d == 0) goto done;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while((de = readdir(d))) {
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int len = strlen(de->d_name);
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* not supposed to be possible, but
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               if it does happen, let's not buffer overrun */
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(len > 256) continue;
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        strcpy(fname, de->d_name);
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(lstat(tmp, &st) == 0) {
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.dent.mode = htoll(st.st_mode);
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.dent.size = htoll(st.st_size);
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.dent.time = htoll(st.st_mtime);
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            msg.dent.namelen = htoll(len);
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(writex(s, &msg.dent, sizeof(msg.dent)) ||
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               writex(s, de->d_name, len)) {
13614e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes                closedir(d);
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return -1;
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    closedir(d);
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdone:
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.id = ID_DONE;
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.mode = 0;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.size = 0;
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.time = 0;
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.dent.namelen = 0;
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return writex(s, &msg.dent, sizeof(msg.dent));
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int fail_message(int s, const char *reason)
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int len = strlen(reason);
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("sync: failure: %s\n", reason);
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.data.id = ID_FAIL;
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.data.size = htoll(len);
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(writex(s, &msg.data, sizeof(msg.data)) ||
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project       writex(s, reason, len)) {
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int fail_errno(int s)
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return fail_message(s, strerror(errno));
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Chengstatic int handle_send_file(int s, char *path, unsigned int uid,
17620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        unsigned int gid, mode_t mode, char *buffer)
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned int timestamp = 0;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0 && errno == ENOENT) {
18420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if(mkdirs(path) != 0) {
18520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            if(fail_errno(s))
18620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng                return -1;
18720d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fd = -1;
18820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        } else {
18920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
19020d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0 && errno == EEXIST) {
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fd = adb_open_mode(path, O_WRONLY, mode);
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0) {
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fail_errno(s))
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fd = -1;
19920d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    } else {
20020d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if(fchown(fd, uid, gid) != 0) {
20120d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fail_errno(s);
20220d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            errno = 0;
20320d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
20420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        /* fchown clears the setuid bit - restore it if present */
20520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if(fchmod(fd, mode) != 0) {
20620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fail_errno(s);
20720d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            errno = 0;
20820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        unsigned int len;
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(readx(s, &msg.data, sizeof(msg.data)))
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(msg.data.id != ID_DATA) {
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(msg.data.id == ID_DONE) {
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                timestamp = ltohl(msg.data.size);
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(s, "invalid data message");
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        len = ltohl(msg.data.size);
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(len > SYNC_DATA_MAX) {
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fail_message(s, "oversize data message");
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(readx(s, buffer, len))
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto fail;
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd < 0)
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(writex(fd, buffer, len)) {
236408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            int saved_errno = errno;
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_close(fd);
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_unlink(path);
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fd = -1;
240408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            errno = saved_errno;
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(fail_errno(s)) return -1;
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd >= 0) {
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct utimbuf u;
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd);
24820d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        selinux_android_restorecon(path);
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        u.actime = timestamp;
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        u.modtime = timestamp;
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        utime(path, &u);
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.status.id = ID_OKAY;
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.status.msglen = 0;
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(writex(s, &msg.status, sizeof(msg.status)))
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail:
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd >= 0)
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd);
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_unlink(path);
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_SYMLINKS
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int handle_send_link(int s, char *path, char *buffer)
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    syncmsg msg;
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned int len;
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ret;
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(readx(s, &msg.data, sizeof(msg.data)))
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(msg.data.id != ID_DATA) {
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fail_message(s, "invalid data message: expected ID_DATA");
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = ltohl(msg.data.size);
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(len > SYNC_DATA_MAX) {
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fail_message(s, "oversize data message");
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(readx(s, buffer, len))
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ret = symlink(buffer, path);
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ret && errno == ENOENT) {
29220d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        if(mkdirs(path) != 0) {
29320d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            fail_errno(s);
29420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng            return -1;
29520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        }
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = symlink(buffer, path);
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ret) {
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fail_errno(s);
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(readx(s, &msg.data, sizeof(msg.data)))
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(msg.data.id == ID_DONE) {
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.status.id = ID_OKAY;
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.status.msglen = 0;
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(writex(s, &msg.status, sizeof(msg.status)))
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fail_message(s, "invalid data message: expected ID_DONE");
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* HAVE_SYMLINKS */
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int do_send(int s, char *path, char *buffer)
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *tmp;
32320d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng    unsigned int mode;
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int is_link, ret;
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    tmp = strrchr(path,',');
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(tmp) {
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *tmp = 0;
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        errno = 0;
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode = strtoul(tmp + 1, NULL, 0);
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef HAVE_SYMLINKS
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        is_link = 0;
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
33420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        is_link = S_ISLNK((mode_t) mode);
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode &= 0777;
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!tmp || errno) {
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mode = 0644;
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        is_link = 0;
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_unlink(path);
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_SYMLINKS
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(is_link)
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = handle_send_link(s, path, buffer);
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else {
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
35320d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        unsigned int uid, gid;
35420d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        uint64_t cap = 0;
35520d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        uid = getuid();
35620d33f4d99c26afdd0aebf23786958ef34e261e3Liang Cheng        gid = getgid();
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