1f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat/*
2f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Copyright (C) 2007 The Android Open Source Project
3f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
4f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * you may not use this file except in compliance with the License.
6f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * You may obtain a copy of the License at
7f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
8f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
10f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Unless required by applicable law or agreed to in writing, software
11f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * See the License for the specific language governing permissions and
14f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * limitations under the License.
15f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat */
16f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
1749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <stdlib.h>
18f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <stdio.h>
1949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <string.h>
2049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
2149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <sys/stat.h>
2249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <sys/types.h>
2349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <dirent.h>
2449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <utime.h>
2549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
2649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <errno.h>
27a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
28a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "sysdeps.h"
29a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
30a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#define TRACE_TAG  TRACE_SYNC
31a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "adb.h"
32a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "file_sync_service.h"
332a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat
34f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatstatic int mkdirs(char *name)
35f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat{
36f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    int ret;
37f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    char *x = name + 1;
38f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
39f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if(name[0] != '/') return -1;
40a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
41a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    for(;;) {
42bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat        x = adb_dirstart(x);
43586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        if(x == 0) return 0;
44f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        *x = 0;
45a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        ret = adb_mkdir(name, 0775);
46a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if((ret < 0) && (errno != EEXIST)) {
4749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            D("mkdir(\"%s\") -> %s\n", name, strerror(errno));
483bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            *x = '/';
493bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return ret;
503bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
513bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        *x++ = '/';
523bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
533bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    return 0;
543bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat}
553bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
563bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatstatic int do_stat(int s, const char *path)
573bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat{
583bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    syncmsg msg;
593bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    struct stat st;
603bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
613bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    msg.stat.id = ID_STAT;
623bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
633bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if(lstat(path, &st)) {
6452c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat        msg.stat.mode = 0;
653bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        msg.stat.size = 0;
663bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        msg.stat.time = 0;
673bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    } else {
683bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        msg.stat.mode = htoll(st.st_mode);
693bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        msg.stat.size = htoll(st.st_size);
703bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        msg.stat.time = htoll(st.st_mtime);
713bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
723bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
733bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    return writex(s, &msg.stat, sizeof(msg.stat));
743bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat}
753bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
76a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatstatic int do_list(int s, const char *path)
77a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat{
78a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    DIR *d;
79a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    struct dirent *de;
80a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    struct stat st;
81a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    syncmsg msg;
82a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int len;
83a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
84a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char tmp[1024 + 256 + 1];
85a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char *fname;
86a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
87a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    len = strlen(path);
88a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    memcpy(tmp, path, len);
89a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    tmp[len] = '/';
90a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    fname = tmp + len + 1;
91a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
92a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    msg.dent.id = ID_DENT;
93a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
94a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    d = opendir(path);
95a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(d == 0) goto done;
96a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
97a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    while((de = readdir(d))) {
98a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        int len = strlen(de->d_name);
99a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
10049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            /* not supposed to be possible, but
101a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat               if it does happen, let's not buffer overrun */
102a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if(len > 256) continue;
103d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
104f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        strcpy(fname, de->d_name);
105f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        if(lstat(tmp, &st) == 0) {
106f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            msg.dent.mode = htoll(st.st_mode);
107a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            msg.dent.size = htoll(st.st_size);
108f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            msg.dent.time = htoll(st.st_mtime);
109f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            msg.dent.namelen = htoll(len);
110f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
111f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            if(writex(s, &msg.dent, sizeof(msg.dent)) ||
112f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat               writex(s, de->d_name, len)) {
113f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                return -1;
114f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            }
115cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat        }
116cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    }
117cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat
118cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    closedir(d);
119cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat
12097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehatdone:
121cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    msg.dent.id = ID_DONE;
122cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    msg.dent.mode = 0;
123cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    msg.dent.size = 0;
124cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    msg.dent.time = 0;
125cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    msg.dent.namelen = 0;
126cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    return writex(s, &msg.dent, sizeof(msg.dent));
127cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat}
128cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat
12997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehatstatic int fail_message(int s, const char *reason)
130cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat{
131cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    syncmsg msg;
132cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    int len = strlen(reason);
133cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat
134d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    D("sync: failure: %s\n", reason);
135d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
136d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    msg.data.id = ID_FAIL;
137d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    msg.data.size = htoll(len);
138a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(writex(s, &msg.data, sizeof(msg.data)) ||
139a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat       writex(s, reason, len)) {
140a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
141a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
142a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return 0;
143a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
144a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
145a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
146a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatstatic int fail_errno(int s)
147a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat{
148fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    return fail_message(s, strerror(errno));
149f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
150f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
151f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatstatic int handle_send_file(int s, char *path, mode_t mode, char *buffer)
152f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat{
153f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    syncmsg msg;
154a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    unsigned int timestamp = 0;
155a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
156a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
157a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
15897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    if(fd < 0 && errno == ENOENT) {
159a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mkdirs(path);
160a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
161a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
162f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if(fd < 0 && errno == EEXIST) {
163a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        fd = adb_open_mode(path, O_WRONLY, mode);
16497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    }
165a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(fd < 0) {
166a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if(fail_errno(s))
167a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return -1;
168a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        fd = -1;
169a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
170a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
171a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    for(;;) {
172a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        unsigned int len;
173f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
17449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        if(readx(s, &msg.data, sizeof(msg.data)))
175dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat            goto fail;
176dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
177dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat        if(msg.data.id != ID_DATA) {
178dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat            if(msg.data.id == ID_DONE) {
179dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat                timestamp = ltohl(msg.data.size);
180dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat                break;
181dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat            }
182dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat            fail_message(s, "invalid data message");
183dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat            goto fail;
184dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat        }
185dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat        len = ltohl(msg.data.size);
186a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if(len > SYNC_DATA_MAX) {
18749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            fail_message(s, "oversize data message");
188a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            goto fail;
189a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
19049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        if(readx(s, buffer, len))
191a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            goto fail;
192a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
193a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if(fd < 0)
194a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            continue;
195a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if(writex(fd, buffer, len)) {
196a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            adb_close(fd);
19797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            adb_unlink(path);
198a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            fd = -1;
199a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if(fail_errno(s)) return -1;
200a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
201a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
202a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
203a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(fd >= 0) {
204a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        struct utimbuf u;
205a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        adb_close(fd);
206a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        u.actime = timestamp;
207a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        u.modtime = timestamp;
208a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        utime(path, &u);
209a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
210a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        msg.status.id = ID_OKAY;
211d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        msg.status.msglen = 0;
21297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        if(writex(s, &msg.status, sizeof(msg.status)))
213d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            return -1;
2142a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    }
215a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
216a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
21797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehatfail:
218a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(fd >= 0)
219a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        adb_close(fd);
220a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    adb_unlink(path);
221a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return -1;
222a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
223a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
224fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat#ifdef HAVE_SYMLINKS
22597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehatstatic int handle_send_link(int s, char *path, char *buffer)
226a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat{
227a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    syncmsg msg;
228a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    unsigned int len;
2292a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    int ret;
230a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
231a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(readx(s, &msg.data, sizeof(msg.data)))
232a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
233a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
234a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(msg.data.id != ID_DATA) {
235a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        fail_message(s, "invalid data message: expected ID_DATA");
236a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
237a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
238a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
239a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    len = ltohl(msg.data.size);
240a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(len > SYNC_DATA_MAX) {
241a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        fail_message(s, "oversize data message");
242a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
24397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    }
244a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(readx(s, buffer, len))
24549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
24649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
247a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    ret = symlink(buffer, path);
248a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(ret && errno == ENOENT) {
249a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mkdirs(path);
250a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        ret = symlink(buffer, path);
251a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
252a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(ret) {
253a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        fail_errno(s);
254dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat        return -1;
255a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
256dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
257a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(readx(s, &msg.data, sizeof(msg.data)))
258a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
259a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
260a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(msg.data.id == ID_DONE) {
261a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        msg.status.id = ID_OKAY;
262a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        msg.status.msglen = 0;
263a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if(writex(s, &msg.status, sizeof(msg.status)))
264a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return -1;
265a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
266a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        fail_message(s, "invalid data message: expected ID_DONE");
267a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
268a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
269a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
270a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
271a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
272a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif /* HAVE_SYMLINKS */
273a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
274a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatstatic int do_send(int s, char *path, char *buffer)
275a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat{
276a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char *tmp;
27749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    mode_t mode;
27849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int is_link, ret;
27949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
280a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    tmp = strrchr(path,',');
28197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    if(tmp) {
282a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *tmp = 0;
283a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = 0;
284a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mode = strtoul(tmp + 1, NULL, 0);
285a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifndef HAVE_SYMLINKS
286a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        is_link = 0;
287a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#else
288a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        is_link = S_ISLNK(mode);
28997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat#endif
29049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        mode &= 0777;
29149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
29249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if(!tmp || errno) {
293a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mode = 0644;
294a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        is_link = 0;
295dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    }
296a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
297a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    adb_unlink(path);
298a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
29997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat
300a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef HAVE_SYMLINKS
301a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(is_link)
302bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat        ret = handle_send_link(s, path, buffer);
303bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat    else {
3043bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat#else
305a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    {
30697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat#endif
307a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        /* copy user permission bits to "group" and "other" permissions */
308a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mode |= ((mode >> 3) & 0070);
309eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        mode |= ((mode >> 3) & 0007);
310eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
31197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        ret = handle_send_file(s, path, mode, buffer);
312eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
313eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
314a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return ret;
315a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
3163bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
3173bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatstatic int do_recv(int s, const char *path, char *buffer)
3183bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat{
3193bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    syncmsg msg;
320a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd, r;
3213bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
32297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    fd = adb_open(path, O_RDONLY);
3233bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if(fd < 0) {
324a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if(fail_errno(s)) return -1;
325a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return 0;
32697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    }
3273bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
328cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    msg.data.id = ID_DATA;
329cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    for(;;) {
3303bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        r = adb_read(fd, buffer, SYNC_DATA_MAX);
33197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        if(r <= 0) {
3323bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            if(r == 0) break;
3333bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            if(errno == EINTR) continue;
3343bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            r = fail_errno(s);
3353bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            adb_close(fd);
3363bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return r;
3373bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
3383bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        msg.data.size = htoll(r);
3393bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if(writex(s, &msg.data, sizeof(msg.data)) ||
3403bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat           writex(s, buffer, r)) {
3413bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            adb_close(fd);
34297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            return -1;
3433bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
3443bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
3453bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
3463bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    adb_close(fd);
3473bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
3483bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    msg.data.id = ID_DONE;
3493bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    msg.data.size = 0;
350a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if(writex(s, &msg.data, sizeof(msg.data))) {
351a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
35297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    }
35349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
354a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
355eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat}
356a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
357a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid file_sync_service(int fd, void *cookie)
3583bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat{
3593bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    syncmsg msg;
3603bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    char name[1025];
3613bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    unsigned namelen;
36252c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat
36352c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat    char *buffer = malloc(SYNC_DATA_MAX);
36452c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat    if(buffer == 0) goto fail;
36552c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat
36652c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat    for(;;) {
36797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        D("sync: waiting for command\n");
36852c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat
36952c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat        if(readx(fd, &msg.req, sizeof(msg.req))) {
37052c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat            fail_message(fd, "command read failure");
37152c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat            break;
3723bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
3733bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        namelen = ltohl(msg.req.namelen);
3743bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if(namelen > 1024) {
3753bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            fail_message(fd, "invalid namelen");
3763bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            break;
37797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        }
3783bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if(readx(fd, name, namelen)) {
3793bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            fail_message(fd, "filename read failure");
3803bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            break;
38197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        }
3823bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        name[namelen] = 0;
3833bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
3843bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        msg.req.namelen = 0;
3853bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        D("sync: '%s' '%s'\n", (char*) &msg.req, name);
386a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
3873bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        switch(msg.req.id) {
38897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        case ID_STAT:
3893bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            if(do_stat(fd, name)) goto fail;
3903bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            break;
3913bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        case ID_LIST:
39297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            if(do_list(fd, name)) goto fail;
3933bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            break;
3943bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        case ID_SEND:
3953bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            if(do_send(fd, name, buffer)) goto fail;
3963bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            break;
3973bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        case ID_RECV:
3983bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            if(do_recv(fd, name, buffer)) goto fail;
3993bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            break;
4003bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        case ID_QUIT:
4013bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            goto fail;
4023bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        default:
40397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            fail_message(fd, "unknown command");
4043bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            goto fail;
405a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
406a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
407a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
4083bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatfail:
4093bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if(buffer != 0) free(buffer);
4103bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    D("sync: done\n");
4113bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    adb_close(fd);
4123bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat}
41397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat