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