Home | History | Annotate | Download | only in adb
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdlib.h>
     18 #include <stdio.h>
     19 #include <string.h>
     20 
     21 #include <sys/stat.h>
     22 #include <sys/types.h>
     23 #include <dirent.h>
     24 #include <utime.h>
     25 
     26 #include <errno.h>
     27 
     28 #include "sysdeps.h"
     29 
     30 #define TRACE_TAG  TRACE_SYNC
     31 #include "adb.h"
     32 #include "file_sync_service.h"
     33 
     34 static int mkdirs(char *name)
     35 {
     36     int ret;
     37     char *x = name + 1;
     38 
     39     if(name[0] != '/') return -1;
     40 
     41     for(;;) {
     42         x = adb_dirstart(x);
     43         if(x == 0) return 0;
     44         *x = 0;
     45         ret = adb_mkdir(name, 0775);
     46         if((ret < 0) && (errno != EEXIST)) {
     47             D("mkdir(\"%s\") -> %s\n", name, strerror(errno));
     48             *x = '/';
     49             return ret;
     50         }
     51         *x++ = '/';
     52     }
     53     return 0;
     54 }
     55 
     56 static int do_stat(int s, const char *path)
     57 {
     58     syncmsg msg;
     59     struct stat st;
     60 
     61     msg.stat.id = ID_STAT;
     62 
     63     if(lstat(path, &st)) {
     64         msg.stat.mode = 0;
     65         msg.stat.size = 0;
     66         msg.stat.time = 0;
     67     } else {
     68         msg.stat.mode = htoll(st.st_mode);
     69         msg.stat.size = htoll(st.st_size);
     70         msg.stat.time = htoll(st.st_mtime);
     71     }
     72 
     73     return writex(s, &msg.stat, sizeof(msg.stat));
     74 }
     75 
     76 static int do_list(int s, const char *path)
     77 {
     78     DIR *d;
     79     struct dirent *de;
     80     struct stat st;
     81     syncmsg msg;
     82     int len;
     83 
     84     char tmp[1024 + 256 + 1];
     85     char *fname;
     86 
     87     len = strlen(path);
     88     memcpy(tmp, path, len);
     89     tmp[len] = '/';
     90     fname = tmp + len + 1;
     91 
     92     msg.dent.id = ID_DENT;
     93 
     94     d = opendir(path);
     95     if(d == 0) goto done;
     96 
     97     while((de = readdir(d))) {
     98         int len = strlen(de->d_name);
     99 
    100             /* not supposed to be possible, but
    101                if it does happen, let's not buffer overrun */
    102         if(len > 256) continue;
    103 
    104         strcpy(fname, de->d_name);
    105         if(lstat(tmp, &st) == 0) {
    106             msg.dent.mode = htoll(st.st_mode);
    107             msg.dent.size = htoll(st.st_size);
    108             msg.dent.time = htoll(st.st_mtime);
    109             msg.dent.namelen = htoll(len);
    110 
    111             if(writex(s, &msg.dent, sizeof(msg.dent)) ||
    112                writex(s, de->d_name, len)) {
    113                 return -1;
    114             }
    115         }
    116     }
    117 
    118     closedir(d);
    119 
    120 done:
    121     msg.dent.id = ID_DONE;
    122     msg.dent.mode = 0;
    123     msg.dent.size = 0;
    124     msg.dent.time = 0;
    125     msg.dent.namelen = 0;
    126     return writex(s, &msg.dent, sizeof(msg.dent));
    127 }
    128 
    129 static int fail_message(int s, const char *reason)
    130 {
    131     syncmsg msg;
    132     int len = strlen(reason);
    133 
    134     D("sync: failure: %s\n", reason);
    135 
    136     msg.data.id = ID_FAIL;
    137     msg.data.size = htoll(len);
    138     if(writex(s, &msg.data, sizeof(msg.data)) ||
    139        writex(s, reason, len)) {
    140         return -1;
    141     } else {
    142         return 0;
    143     }
    144 }
    145 
    146 static int fail_errno(int s)
    147 {
    148     return fail_message(s, strerror(errno));
    149 }
    150 
    151 static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
    152 {
    153     syncmsg msg;
    154     unsigned int timestamp = 0;
    155     int fd;
    156 
    157     fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
    158     if(fd < 0 && errno == ENOENT) {
    159         mkdirs(path);
    160         fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
    161     }
    162     if(fd < 0 && errno == EEXIST) {
    163         fd = adb_open_mode(path, O_WRONLY, mode);
    164     }
    165     if(fd < 0) {
    166         if(fail_errno(s))
    167             return -1;
    168         fd = -1;
    169     }
    170 
    171     for(;;) {
    172         unsigned int len;
    173 
    174         if(readx(s, &msg.data, sizeof(msg.data)))
    175             goto fail;
    176 
    177         if(msg.data.id != ID_DATA) {
    178             if(msg.data.id == ID_DONE) {
    179                 timestamp = ltohl(msg.data.size);
    180                 break;
    181             }
    182             fail_message(s, "invalid data message");
    183             goto fail;
    184         }
    185         len = ltohl(msg.data.size);
    186         if(len > SYNC_DATA_MAX) {
    187             fail_message(s, "oversize data message");
    188             goto fail;
    189         }
    190         if(readx(s, buffer, len))
    191             goto fail;
    192 
    193         if(fd < 0)
    194             continue;
    195         if(writex(fd, buffer, len)) {
    196             int saved_errno = errno;
    197             adb_close(fd);
    198             adb_unlink(path);
    199             fd = -1;
    200             errno = saved_errno;
    201             if(fail_errno(s)) return -1;
    202         }
    203     }
    204 
    205     if(fd >= 0) {
    206         struct utimbuf u;
    207         adb_close(fd);
    208         u.actime = timestamp;
    209         u.modtime = timestamp;
    210         utime(path, &u);
    211 
    212         msg.status.id = ID_OKAY;
    213         msg.status.msglen = 0;
    214         if(writex(s, &msg.status, sizeof(msg.status)))
    215             return -1;
    216     }
    217     return 0;
    218 
    219 fail:
    220     if(fd >= 0)
    221         adb_close(fd);
    222     adb_unlink(path);
    223     return -1;
    224 }
    225 
    226 #ifdef HAVE_SYMLINKS
    227 static int handle_send_link(int s, char *path, char *buffer)
    228 {
    229     syncmsg msg;
    230     unsigned int len;
    231     int ret;
    232 
    233     if(readx(s, &msg.data, sizeof(msg.data)))
    234         return -1;
    235 
    236     if(msg.data.id != ID_DATA) {
    237         fail_message(s, "invalid data message: expected ID_DATA");
    238         return -1;
    239     }
    240 
    241     len = ltohl(msg.data.size);
    242     if(len > SYNC_DATA_MAX) {
    243         fail_message(s, "oversize data message");
    244         return -1;
    245     }
    246     if(readx(s, buffer, len))
    247         return -1;
    248 
    249     ret = symlink(buffer, path);
    250     if(ret && errno == ENOENT) {
    251         mkdirs(path);
    252         ret = symlink(buffer, path);
    253     }
    254     if(ret) {
    255         fail_errno(s);
    256         return -1;
    257     }
    258 
    259     if(readx(s, &msg.data, sizeof(msg.data)))
    260         return -1;
    261 
    262     if(msg.data.id == ID_DONE) {
    263         msg.status.id = ID_OKAY;
    264         msg.status.msglen = 0;
    265         if(writex(s, &msg.status, sizeof(msg.status)))
    266             return -1;
    267     } else {
    268         fail_message(s, "invalid data message: expected ID_DONE");
    269         return -1;
    270     }
    271 
    272     return 0;
    273 }
    274 #endif /* HAVE_SYMLINKS */
    275 
    276 static int do_send(int s, char *path, char *buffer)
    277 {
    278     char *tmp;
    279     mode_t mode;
    280     int is_link, ret;
    281 
    282     tmp = strrchr(path,',');
    283     if(tmp) {
    284         *tmp = 0;
    285         errno = 0;
    286         mode = strtoul(tmp + 1, NULL, 0);
    287 #ifndef HAVE_SYMLINKS
    288         is_link = 0;
    289 #else
    290         is_link = S_ISLNK(mode);
    291 #endif
    292         mode &= 0777;
    293     }
    294     if(!tmp || errno) {
    295         mode = 0644;
    296         is_link = 0;
    297     }
    298 
    299     adb_unlink(path);
    300 
    301 
    302 #ifdef HAVE_SYMLINKS
    303     if(is_link)
    304         ret = handle_send_link(s, path, buffer);
    305     else {
    306 #else
    307     {
    308 #endif
    309         /* copy user permission bits to "group" and "other" permissions */
    310         mode |= ((mode >> 3) & 0070);
    311         mode |= ((mode >> 3) & 0007);
    312 
    313         ret = handle_send_file(s, path, mode, buffer);
    314     }
    315 
    316     return ret;
    317 }
    318 
    319 static int do_recv(int s, const char *path, char *buffer)
    320 {
    321     syncmsg msg;
    322     int fd, r;
    323 
    324     fd = adb_open(path, O_RDONLY);
    325     if(fd < 0) {
    326         if(fail_errno(s)) return -1;
    327         return 0;
    328     }
    329 
    330     msg.data.id = ID_DATA;
    331     for(;;) {
    332         r = adb_read(fd, buffer, SYNC_DATA_MAX);
    333         if(r <= 0) {
    334             if(r == 0) break;
    335             if(errno == EINTR) continue;
    336             r = fail_errno(s);
    337             adb_close(fd);
    338             return r;
    339         }
    340         msg.data.size = htoll(r);
    341         if(writex(s, &msg.data, sizeof(msg.data)) ||
    342            writex(s, buffer, r)) {
    343             adb_close(fd);
    344             return -1;
    345         }
    346     }
    347 
    348     adb_close(fd);
    349 
    350     msg.data.id = ID_DONE;
    351     msg.data.size = 0;
    352     if(writex(s, &msg.data, sizeof(msg.data))) {
    353         return -1;
    354     }
    355 
    356     return 0;
    357 }
    358 
    359 void file_sync_service(int fd, void *cookie)
    360 {
    361     syncmsg msg;
    362     char name[1025];
    363     unsigned namelen;
    364 
    365     char *buffer = malloc(SYNC_DATA_MAX);
    366     if(buffer == 0) goto fail;
    367 
    368     for(;;) {
    369         D("sync: waiting for command\n");
    370 
    371         if(readx(fd, &msg.req, sizeof(msg.req))) {
    372             fail_message(fd, "command read failure");
    373             break;
    374         }
    375         namelen = ltohl(msg.req.namelen);
    376         if(namelen > 1024) {
    377             fail_message(fd, "invalid namelen");
    378             break;
    379         }
    380         if(readx(fd, name, namelen)) {
    381             fail_message(fd, "filename read failure");
    382             break;
    383         }
    384         name[namelen] = 0;
    385 
    386         msg.req.namelen = 0;
    387         D("sync: '%s' '%s'\n", (char*) &msg.req, name);
    388 
    389         switch(msg.req.id) {
    390         case ID_STAT:
    391             if(do_stat(fd, name)) goto fail;
    392             break;
    393         case ID_LIST:
    394             if(do_list(fd, name)) goto fail;
    395             break;
    396         case ID_SEND:
    397             if(do_send(fd, name, buffer)) goto fail;
    398             break;
    399         case ID_RECV:
    400             if(do_recv(fd, name, buffer)) goto fail;
    401             break;
    402         case ID_QUIT:
    403             goto fail;
    404         default:
    405             fail_message(fd, "unknown command");
    406             goto fail;
    407         }
    408     }
    409 
    410 fail:
    411     if(buffer != 0) free(buffer);
    412     D("sync: done\n");
    413     adb_close(fd);
    414 }
    415