1 #include "compat.h" 2 #include "backuppcd.h" 3 #include "backuppcd-common.h" 4 #include "libbackuppcd.h" 5 #include "sha1.h" 6 #include "net.h" 7 8 #define BPC_CMD_GET_DATA (BPC_CMD_GET | 0x100) 9 #define BPC_MAX_RDIFF_BLOCKSIZE 8192 10 11 /* 12 * This structure contains all the variables that are needed to keep track of 13 * the state of a transfer (GET). 14 */ 15 struct bpc_transfer { 16 uint64_t filesize; 17 int64_t idealblocknum; 18 uint32_t currblocknum; 19 uint32_t blocksize; 20 uint32_t blockoffset; 21 }; 22 23 /* 24 * This structure is used as a handle for a connection to a BackupPC server. 25 */ 26 struct bpc_conn { 27 struct bpc_fileinfo dent; 28 struct bpc_transfer tinfo; 29 backuppc_cmd_t state; 30 int fd; 31 }; 32 33 /* 34 * These values are used by _bpc_client_read() and _bpc_client_write() to 35 * determine the type of variable to read or write. 36 */ 37 typedef enum { 38 BPC_CDT_END, 39 BPC_CDT_UINT8, 40 BPC_CDT_UINT16, 41 BPC_CDT_UINT32, 42 BPC_CDT_UINT64, 43 BPC_CDT_BYTEARRAY, 44 BPC_CDT_STRING, 45 BPC_CDT_STRING_PTR, 46 BPC_CDT_SINK, 47 } bpc_clntdt_t; 48 49 #ifndef MSG_WAITALL 50 #define MSG_WAITALL 0 51 #endif 52 53 #ifndef BPC_MAXPATH_LEN 54 #define BPC_MAXPATH_LEN 4096 55 #endif 56 57 /* 58 * SYNOPSIS (internal): 59 * static int _bpc_client_read( 60 * const int sockid, 61 * ... 62 * ); 63 * 64 * ARGUMENTS: 65 * const int sockid Socket descriptor to read from 66 * ... List of parameters with the appropriate type 67 * and terminated by a BPC_CDT_END 68 * 69 * RETURN VALUE: 70 * This function returns 0 on failure, 1 on success. 71 * 72 * NOTES: 73 * This function reads a variable number of parameters in various formats 74 * from a socket descriptor and stores them in the pointer given. To 75 * specify a value, use the appropriate value from `bpc_clntdt_t' followed 76 * by a pointer to the memory location to store the actual value (in most 77 * cases) or the size of the memory location and the start of the memory 78 * location (for BYTEARRAY, STRING, STRING_PTR). 79 * 80 * If the pointer at the pointed to location is NULL and the data type is 81 * STRING_PTR (size) bytes will be allocated and (size-1) bytes read. 82 * You are responsible for deallocating allocated memory using free(). 83 * 84 * This is an internal function and not part of the LibBackupPCd API and 85 * therefore subject to change or removal. 86 * 87 * EXAMPLES: 88 * uint8_t val_u8; 89 * char *val_str = NULL; 90 * 91 * // Read a uint8_t into val_u8 92 * if (!_bpc_client_read(sockid, BPC_CDT_UINT8, &val_u8, BPC_CDT_END)) { 93 * return(-1); 94 * } 95 * 96 * // Read 4 bytes and a NIL termination char into newly allocated memory 97 * if (!_bpc_client_read(sockid, BPC_CDT_STRING_PTR, (size_t) 5, &val_str, BPC_CDT_END)) { 98 * return(-1); 99 * } 100 * 101 * if (val_str) { 102 * free(val_str); 103 * } 104 * 105 */ 106 static int _bpc_client_read(const int sockid, ...) { 107 bpc_clntdt_t typeid; 108 char tmpbuf[1024]; 109 va_list ap; 110 uint8_t *u8v; 111 uint16_t *u16v; 112 uint32_t *u32v; 113 uint64_t *u64v; 114 char *cpv, **cppv; 115 void *vpv = NULL, *vpv_s; 116 size_t vpv_len, bytes_to_copy; 117 ssize_t read_ret; 118 119 va_start(ap, sockid); 120 while (1) { 121 typeid = va_arg(ap, bpc_clntdt_t); 122 123 if (typeid == BPC_CDT_END) { 124 break; 125 } 126 127 switch (typeid) { 128 case BPC_CDT_UINT8: 129 u8v = va_arg(ap, uint8_t *); 130 vpv_len = sizeof(*u8v); 131 vpv = u8v; 132 break; 133 case BPC_CDT_UINT16: 134 u16v = va_arg(ap, uint16_t *); 135 vpv_len = sizeof(*u16v); 136 vpv = u16v; 137 break; 138 case BPC_CDT_UINT32: 139 u32v = va_arg(ap, uint32_t *); 140 vpv_len = sizeof(*u32v); 141 vpv = u32v; 142 break; 143 case BPC_CDT_UINT64: 144 u64v = va_arg(ap, uint64_t *); 145 vpv_len = sizeof(*u64v); 146 vpv = u64v; 147 break; 148 case BPC_CDT_BYTEARRAY: 149 vpv_len = va_arg(ap, size_t); 150 vpv = va_arg(ap, void *); 151 break; 152 case BPC_CDT_STRING: 153 vpv_len = va_arg(ap, size_t); 154 vpv_len--; 155 cpv = va_arg(ap, char *); 156 cpv[vpv_len] = '\0'; 157 vpv = cpv; 158 break; 159 case BPC_CDT_STRING_PTR: 160 vpv_len = va_arg(ap, size_t); 161 cppv = va_arg(ap, char **); 162 if (*cppv == NULL) { 163 cpv = *cppv = malloc(vpv_len + 1); 164 cpv[vpv_len] = '\0'; 165 } else { 166 cpv = *cppv; 167 } 168 vpv = cpv; 169 break; 170 case BPC_CDT_SINK: 171 vpv_len = va_arg(ap, size_t); 172 vpv = NULL; 173 break; 174 case BPC_CDT_END: 175 return(0); 176 break; 177 default: 178 return(0); 179 } 180 181 vpv_s = vpv; 182 while (vpv_len) { 183 if (vpv) { 184 read_ret = recv(sockid, vpv, vpv_len, MSG_WAITALL); 185 } else { 186 /* 187 * If we have been given no place to put the 188 * data, we just read it to a buffer and 189 * ignore it (aka, sink it). 190 */ 191 bytes_to_copy = sizeof(tmpbuf); 192 if (vpv_len < bytes_to_copy) { 193 bytes_to_copy = vpv_len; 194 } 195 read_ret = recv(sockid, tmpbuf, bytes_to_copy, MSG_WAITALL); 196 } 197 198 if (read_ret <= 0) { 199 return(0); 200 } 201 202 vpv_len -= read_ret; 203 204 if (vpv) { 205 vpv += read_ret; 206 } 207 } 208 vpv = vpv_s; 209 210 switch (typeid) { 211 case BPC_CDT_UINT16: 212 u16v = vpv; 213 *u16v = ntohs(*u16v); 214 break; 215 case BPC_CDT_UINT32: 216 u32v = vpv; 217 *u32v = ntohl(*u32v); 218 break; 219 case BPC_CDT_UINT64: 220 u64v = vpv; 221 *u64v = ntohll(*u64v); 222 break; 223 default: 224 break; 225 } 226 } 227 va_end(ap); 228 229 return(1); 230 } 231 232 /* 233 * SYNOPSIS (internal): 234 * static int _bpc_client_write( 235 * const int sockid, 236 * ... 237 * ); 238 * 239 * ARGUMENTS: 240 * const int sockid Socket descriptor to write to 241 * ... List of parameters with the appropriate type 242 * and terminated by a BPC_CDT_END 243 * 244 * RETURN VALUE: 245 * This function returns 0 on failure, 1 on success. 246 * 247 * NOTES: 248 * This function writes a variable number of parameters in various formats 249 * to a socket descriptor. To specify a value, use the appropriate value 250 * from `bpc_clntdt_t' followed by a value of the appropriate type (in most 251 * cases), or the size of the data to write followed by the appropriate 252 * value (for BYTEARRAY, STRING, STRING_PTR) 253 * 254 * This is an internal function and not part of the LibBackupPCd API and 255 * therefore subject to change or removal. 256 * 257 * EXAMPLES: 258 * uint8_t val_u8 = 3; 259 * char *val_str = "Joe"; 260 * 261 * // Write 3 in a uint8_t format to the socket 262 * if (!_bpc_client_write(sockid, BPC_CDT_UINT8, val_u8, BPC_CDT_END)) { 263 * return(-1); 264 * } 265 * 266 * // Write 3 bytes from a string to the socket 267 * if (!_bpc_client_write(sockid, BPC_CDT_STRING, (size_t) 3, val_str, BPC_CDT_END)) { 268 * return(-1); 269 * } 270 * 271 */ 272 static int _bpc_client_write(const int sockid, ...) { 273 bpc_clntdt_t typeid; 274 va_list ap; 275 uint8_t u8v; 276 uint16_t u16v; 277 uint32_t u32v; 278 uint64_t u64v; 279 void *vpv; 280 char *cpv; 281 size_t vpv_len; 282 ssize_t write_ret; 283 284 va_start(ap, sockid); 285 while (1) { 286 typeid = va_arg(ap, bpc_clntdt_t); 287 288 if (typeid == BPC_CDT_END) { 289 break; 290 } 291 292 switch (typeid) { 293 case BPC_CDT_UINT8: 294 u8v = va_arg(ap, int); 295 vpv_len = sizeof(u8v); 296 vpv = &u8v; 297 break; 298 case BPC_CDT_UINT16: 299 u16v = va_arg(ap, int); 300 u16v = htons(u16v); 301 vpv_len = sizeof(u16v); 302 vpv = &u16v; 303 break; 304 case BPC_CDT_UINT32: 305 u32v = va_arg(ap, uint32_t); 306 u32v = htonl(u32v); 307 vpv_len = sizeof(u32v); 308 vpv = &u32v; 309 break; 310 case BPC_CDT_UINT64: 311 u64v = va_arg(ap, uint64_t); 312 u64v = htonll(u64v); 313 vpv_len = sizeof(u64v); 314 vpv = &u64v; 315 break; 316 case BPC_CDT_BYTEARRAY: 317 vpv_len = va_arg(ap, size_t); 318 vpv = va_arg(ap, void *); 319 break; 320 case BPC_CDT_STRING: 321 cpv = va_arg(ap, char *); 322 vpv_len = strlen(cpv); 323 vpv = cpv; 324 break; 325 case BPC_CDT_SINK: 326 case BPC_CDT_STRING_PTR: 327 case BPC_CDT_END: 328 return(0); 329 default: 330 return(0); 331 } 332 333 while (vpv_len) { 334 write_ret = send(sockid, vpv, vpv_len, 0); 335 336 if (write_ret < 0) { 337 return(0); 338 } 339 340 vpv_len -= write_ret; 341 vpv += write_ret; 342 } 343 } 344 va_end(ap); 345 346 return(1); 347 } 348 349 /* 350 * SYNOPSIS: 351 * int bpc_auth( 352 * BPC_CONN *handle, 353 * const char *username, 354 * const char *password 355 * ); 356 * 357 * ARGUMENTS: 358 * BPC_CONN *handle Connection handle 359 * const char *username Username to authenticate with 360 * const char *password Password to authenticate with 361 * 362 * RETURN VALUE: 363 * This function returns 0 on failure, 1 on success. 364 * 365 * NOTES: 366 * This function authenticates with the server specified by the handle. 367 * 368 * EXAMPLES: 369 * 370 * // Authenticate with the user "user" and password "pass" 371 * if (!bpc_auth(bpc_handle, "user", "pass")) { 372 * return(-1); 373 * } 374 */ 375 int bpc_auth(BPC_CONN *handle, const char *username, const char *password) { 376 uint8_t cmd_reply; 377 uint8_t status; 378 int sockid; 379 380 if (!handle || !username || !password) { 381 CHECKPOINT; 382 return(0); 383 } 384 385 if (handle->state != BPC_CMD_NONE) { 386 CHECKPOINT; 387 return(0); 388 } 389 390 sockid = handle->fd; 391 392 if (!_bpc_client_write(sockid, 393 BPC_CDT_UINT8, (uint8_t) BPC_CMD_AUTH, 394 BPC_CDT_UINT16, (uint16_t) strlen(username), 395 BPC_CDT_UINT16, (uint16_t) strlen(password), 396 BPC_CDT_STRING, username, 397 BPC_CDT_STRING, password, 398 BPC_CDT_END)) { 399 CHECKPOINT; 400 return(0); 401 } 402 403 if (!_bpc_client_read(sockid, 404 BPC_CDT_UINT8, (uint8_t *) &cmd_reply, 405 BPC_CDT_UINT8, (uint8_t *) &status, 406 BPC_CDT_END)) { 407 CHECKPOINT; 408 return(0); 409 } 410 411 if (cmd_reply != BPC_CMD_AUTH_REPLY) { 412 CHECKPOINT; 413 return(0); 414 } 415 416 if (status != BPC_STATUS_OKAY) { 417 CHECKPOINT; 418 return(0); 419 } 420 421 CHECKPOINT; 422 return(1); 423 } 424 425 /* 426 * SYNOPSIS (internal): 427 * static int _bpc_listget_open( 428 * BPC_CONN *handle, 429 * backuppc_cmd_t sendcmd, 430 * const char *rootpath, 431 * const int recursive, 432 * backuppc_hashid_t hashalgo, 433 * const char *exclpat, 434 * const char *inclpat 435 * ); 436 * 437 * ARGUMENTS: 438 * BPC_CONN *handle Connection handle 439 * backuppc_cmd_t sendcmd Command to send (BPC_CMD_LIST or BPC_CMD_GET) 440 * const char *rootpath Root path to start the GET or LIST from 441 * const int recursive Boolean option to specify whether or not to 442 * recurse into directories 443 * backuppc_hashid_t hashalgo OR'd list of hash algorithms to ask the 444 * server to compute for each file 445 * const char *exclpat <<NOT USED:XXX>> 446 * const char *inclpat <<NOT USED:XXX>> 447 * 448 * RETURN VALUE: 449 * This function returns 0 on failure, 1 on success. 450 * 451 * NOTES: 452 * This function initiates a LIST or GET command (depending on the value of 453 * the `sendcmd' parameter) and updates the internal state to indicate that 454 * it is in the middle of such a command. 455 * 456 * You should then call _bpc_list() to get either the LIST results or the 457 * header of a GET result. 458 * 459 * This is an internal function and not part of the LibBackupPCd API and 460 * therefore subject to change or removal. 461 * 462 * EXAMPLES: 463 * 464 * // List every node under the root directory non-recursively with no 465 * // hashing performed on files. 466 * if (!_bpc_listget_open(bpc_handle, BPC_CMD_LIST, "/", 0, BPC_HASH_NONE, NULL, NULL)) { 467 * return(-1); 468 * } 469 * 470 */ 471 static int _bpc_listget_open(BPC_CONN *handle, backuppc_cmd_t sendcmd, const char *rootpath, const int recursive, backuppc_hashid_t hashalgo, const char *exclpat, const char *inclpat) { 472 uint8_t cmd, cmd_options = 0; 473 int sockid; 474 475 sockid = handle->fd; 476 477 if (sendcmd != BPC_CMD_LIST && sendcmd != BPC_CMD_GET) { 478 CHECKPOINT; 479 return(0); 480 } 481 482 /* 483 * Handle NULL patterns as blank ones. 484 */ 485 if (!exclpat) { 486 exclpat = ""; 487 } 488 if (!inclpat) { 489 inclpat = ""; 490 } 491 492 if (recursive) { 493 cmd_options |= BPC_OPT_RECURSIVE; 494 } 495 496 switch (hashalgo) { 497 case BPC_HASH_NONE: 498 break; 499 case BPC_HASH_MD4: 500 cmd_options |= BPC_OPT_MD4; 501 break; 502 case BPC_HASH_MD5: 503 cmd_options |= BPC_OPT_MD5; 504 break; 505 case BPC_HASH_SHA1: 506 cmd_options |= BPC_OPT_SHA1; 507 break; 508 case BPC_HASH_BPC: 509 cmd_options |= BPC_OPT_BPCHASH; 510 break; 511 } 512 513 if (!_bpc_client_write(sockid, 514 BPC_CDT_UINT8, (uint8_t) sendcmd, 515 BPC_CDT_UINT8, (uint8_t) cmd_options, 516 BPC_CDT_UINT32, (uint32_t) strlen(exclpat), 517 BPC_CDT_UINT32, (uint32_t) strlen(inclpat), 518 BPC_CDT_UINT32, (uint32_t) strlen(rootpath), 519 BPC_CDT_STRING, (char *) rootpath, 520 BPC_CDT_STRING, (char *) exclpat, 521 BPC_CDT_STRING, (char *) inclpat, 522 BPC_CDT_END)) { 523 CHECKPOINT; 524 return(0); 525 } 526 527 if (!_bpc_client_read(sockid, 528 BPC_CDT_UINT8, (uint8_t *) &cmd, 529 BPC_CDT_END)) { 530 CHECKPOINT; 531 return(0); 532 } 533 534 /* 535 * If the server sends us a reply for something other than what we 536 * asked for, something went wrong, abort. 537 */ 538 if (cmd != (sendcmd | 0x80)) { 539 CHECKPOINT; 540 return(0); 541 } 542 543 handle->state = sendcmd; 544 545 handle->dent.owner_group[0] = '\0'; 546 handle->dent.owner_user[0] = '\0'; 547 handle->dent.linkdest[0] = '\0'; 548 handle->dent.name[0] = '\0'; 549 550 memset(&handle->dent.hash_md4, 0, sizeof(handle->dent.hash_md4)); 551 memset(&handle->dent.hash_md5, 0, sizeof(handle->dent.hash_md5)); 552 memset(&handle->dent.hash_sha1, 0, sizeof(handle->dent.hash_sha1)); 553 memset(&handle->dent.hash_bpc, 0, sizeof(handle->dent.hash_bpc)); 554 555 CHECKPOINT; 556 return(1); 557 } 558 559 /* 560 * SYNOPSIS (internal): 561 * static int _bpc_listget_close( 562 * BPC_CONN *handle 563 * ); 564 * 565 * ARGUMENTS: 566 * BPC_CONN *handle Connection handle 567 * 568 * RETURN VALUE: 569 * This function returns 0 on failure, 1 on success. 570 * 571 * NOTES: 572 * This function sets the state of a handle back to NONE after a LIST or GET 573 * request has finished. 574 * 575 * This is an internal function and not part of the LibBackupPCd API and 576 * therefore subject to change or removal. 577 * 578 * EXAMPLES: 579 * 580 * // Terminate an existing LIST or GET command 581 * if (!_bpc_listget_close(bpc_handle)) { 582 * return(-1); 583 * } 584 * 585 */ 586 static int _bpc_listget_close(BPC_CONN *handle) { 587 588 handle->state = BPC_CMD_NONE; 589 590 CHECKPOINT; 591 return(1); 592 } 593 594 /* 595 * SYNOPSIS (internal): 596 * static struct bpc_fileinfo *_bpc_list( 597 * BPC_CONN *handle, 598 * backuppc_cmd_t cmd 599 * ); 600 * 601 * ARGUMENTS: 602 * BPC_CONN *handle Connection handle 603 * backuppc_cmd_t cmd Command to process results from (LIST or GET) 604 * 605 * RETURN VALUE: 606 * This function returns a pointer to a (struct bpc_fileinfo) object. The 607 * contents of this objects may be overwritten with subsequent calls to 608 * _bpc_list() for the same handle. NULL is returned on error or when no 609 * more objects exist in the stream. 610 * 611 * NOTES: 612 * This function gets the contents of a LIST_REPLY or GET_REPLY from the 613 * handle and sets them in the (struct bpc_fileinfo) value that it 614 * returns. If it is processing a GET_REPLY it also initializes the 615 * values in the (struct bpc_transfer) members. 616 * 617 * This is an internal function and not part of the LibBackupPCd API and 618 * therefore subject to change or removal. 619 * 620 * EXAMPLES: 621 * 622 * // Get an item from an open LIST command 623 * struct bpc_fileinfo *fileinfo; 624 * 625 * fileinfo = _bpc_list(bpc_handle, BPC_CMD_LIST); 626 * 627 * if (!fileinfo) { 628 * return(-1); 629 * } 630 * 631 */ 632 static struct bpc_fileinfo *_bpc_list(BPC_CONN *handle, backuppc_cmd_t cmd) { 633 struct bpc_fileinfo *ret; 634 struct bpc_transfer *tinfo; 635 int sockid; 636 637 uint64_t filesize; 638 uint32_t attr_sect_len, blocksize, pathnamelen; 639 uint32_t attr_uid, attr_gid, attr_ctime, attr_mtime, attr_devmajor, attr_devminor; 640 uint32_t attrlen; 641 uint16_t attrid; 642 uint16_t attr_mode; 643 uint8_t filetype; 644 mode_t modeval; 645 646 ret = &handle->dent; 647 tinfo = &handle->tinfo; 648 649 sockid = handle->fd; 650 651 if (!_bpc_client_read(sockid, 652 BPC_CDT_UINT8, (uint8_t *) &filetype, 653 BPC_CDT_END)) { 654 CHECKPOINT; 655 return(NULL); 656 } 657 658 if (filetype == 0xff) { 659 _bpc_listget_close(handle); 660 CHECKPOINT; 661 return(NULL); 662 } 663 664 if (!_bpc_client_read(sockid, 665 BPC_CDT_UINT32, (uint32_t *) &attr_sect_len, 666 BPC_CDT_UINT64, (uint64_t *) &filesize, 667 BPC_CDT_UINT32, (uint32_t *) &blocksize, 668 BPC_CDT_UINT32, (uint32_t *) &pathnamelen, 669 BPC_CDT_END)) { 670 CHECKPOINT; 671 return(NULL); 672 } 673 674 if (pathnamelen >= sizeof(ret->name)) { 675 SPOTVAR_I(pathnamelen); 676 CHECKPOINT; 677 return(NULL); 678 } 679 680 if (!_bpc_client_read(sockid, 681 BPC_CDT_STRING, (size_t) (pathnamelen + 1), &ret->name, 682 BPC_CDT_END)) { 683 CHECKPOINT; 684 return(NULL); 685 } 686 687 attr_uid = 0; 688 attr_gid = 0; 689 attr_mode = 0; 690 attr_ctime = 0; 691 attr_mtime = 0; 692 attr_devmajor = 0; 693 attr_devminor = 0; 694 695 memset(ret->hash_md4, '\0', sizeof(ret->hash_md4)); 696 memset(ret->hash_md5, '\0', sizeof(ret->hash_md5)); 697 memset(ret->hash_bpc, '\0', sizeof(ret->hash_bpc)); 698 memset(ret->hash_sha1, '\0', sizeof(ret->hash_sha1)); 699 700 /* 701 * Read the sent attributes. 702 */ 703 if (attr_sect_len != 0) { 704 while (1) { 705 if (!_bpc_client_read(sockid, 706 BPC_CDT_UINT16, (uint16_t *) &attrid, 707 BPC_CDT_END)) { 708 CHECKPOINT; 709 return(NULL); 710 } 711 712 if (attrid == 0xffff) { 713 break; 714 } 715 716 if (!_bpc_client_read(sockid, 717 BPC_CDT_UINT32, (uint32_t *) &attrlen, 718 BPC_CDT_END)) { 719 CHECKPOINT; 720 return(NULL); 721 } 722 723 switch ((backuppc_attrid_t) attrid) { 724 case BPC_ATTRID_NOP: 725 if (attrlen != 0) { 726 CHECKPOINT; 727 return(NULL); 728 } 729 break; 730 case BPC_ATTRID_MTIME: 731 if (!_bpc_client_read(sockid, 732 BPC_CDT_UINT32, (uint32_t *) &attr_mtime, 733 BPC_CDT_END)) { 734 CHECKPOINT; 735 return(NULL); 736 } 737 break; 738 case BPC_ATTRID_CTIME: 739 if (!_bpc_client_read(sockid, 740 BPC_CDT_UINT32, (uint32_t *) &attr_ctime, 741 BPC_CDT_END)) { 742 CHECKPOINT; 743 return(NULL); 744 } 745 break; 746 case BPC_ATTRID_UID: 747 if (!_bpc_client_read(sockid, 748 BPC_CDT_UINT32, (uint32_t *) &attr_uid, 749 BPC_CDT_END)) { 750 CHECKPOINT; 751 return(NULL); 752 } 753 break; 754 case BPC_ATTRID_GID: 755 if (!_bpc_client_read(sockid, 756 BPC_CDT_UINT32, (uint32_t *) &attr_gid, 757 BPC_CDT_END)) { 758 CHECKPOINT; 759 return(NULL); 760 } 761 break; 762 case BPC_ATTRID_ACL: 763 if (!_bpc_client_read(sockid, 764 BPC_CDT_UINT16, (uint16_t *) &attr_mode, 765 BPC_CDT_END)) { 766 CHECKPOINT; 767 return(NULL); 768 } 769 770 break; 771 case BPC_ATTRID_USER: 772 if (attrlen >= sizeof(ret->owner_user)) { 773 CHECKPOINT; 774 return(NULL); 775 } 776 777 if (!_bpc_client_read(sockid, 778 BPC_CDT_STRING, (size_t) attrlen + 1, (char *) &ret->owner_user, 779 BPC_CDT_END)) { 780 CHECKPOINT; 781 return(NULL); 782 } 783 break; 784 case BPC_ATTRID_GROUP: 785 if (attrlen >= sizeof(ret->owner_group)) { 786 CHECKPOINT; 787 return(NULL); 788 } 789 790 if (!_bpc_client_read(sockid, 791 BPC_CDT_STRING, (size_t) attrlen + 1, (char *) &ret->owner_group, 792 BPC_CDT_END)) { 793 CHECKPOINT; 794 return(NULL); 795 } 796 break; 797 case BPC_ATTRID_SYMLINKDEST: 798 if (attrlen >= sizeof(ret->linkdest)) { 799 CHECKPOINT; 800 return(NULL); 801 } 802 803 if (!_bpc_client_read(sockid, 804 BPC_CDT_STRING, (size_t) attrlen + 1, (char *) &ret->linkdest, 805 BPC_CDT_END)) { 806 CHECKPOINT; 807 return(NULL); 808 } 809 break; 810 case BPC_ATTRID_HRDLINKDEST: 811 if (attrlen >= sizeof(ret->linkdest)) { 812 CHECKPOINT; 813 return(NULL); 814 } 815 816 if (!_bpc_client_read(sockid, 817 BPC_CDT_STRING, (size_t) attrlen + 1, (char *) &ret->linkdest, 818 BPC_CDT_END)) { 819 CHECKPOINT; 820 return(NULL); 821 } 822 break; 823 case BPC_ATTRID_MD4: 824 if (attrlen != sizeof(ret->hash_md4)) { 825 CHECKPOINT; 826 return(NULL); 827 } 828 829 if (!_bpc_client_read(sockid, 830 BPC_CDT_BYTEARRAY, (size_t) sizeof(ret->hash_md4), (void *) &ret->hash_md4, 831 BPC_CDT_END)) { 832 CHECKPOINT; 833 return(NULL); 834 } 835 break; 836 case BPC_ATTRID_MD5: 837 if (attrlen != sizeof(ret->hash_md5)) { 838 CHECKPOINT; 839 return(NULL); 840 } 841 842 if (!_bpc_client_read(sockid, 843 BPC_CDT_BYTEARRAY, (size_t) sizeof(ret->hash_md5), (void *) &ret->hash_md5, 844 BPC_CDT_END)) { 845 CHECKPOINT; 846 return(NULL); 847 } 848 break; 849 case BPC_ATTRID_SHA1: 850 if (attrlen != sizeof(ret->hash_sha1)) { 851 CHECKPOINT; 852 return(NULL); 853 } 854 855 if (!_bpc_client_read(sockid, 856 BPC_CDT_BYTEARRAY, (size_t) sizeof(ret->hash_sha1), (void *) &ret->hash_sha1, 857 BPC_CDT_END)) { 858 CHECKPOINT; 859 return(NULL); 860 } 861 break; 862 case BPC_ATTRID_BPCHASH: 863 if (attrlen != sizeof(ret->hash_bpc)) { 864 CHECKPOINT; 865 return(NULL); 866 } 867 868 if (!_bpc_client_read(sockid, 869 BPC_CDT_BYTEARRAY, (size_t) sizeof(ret->hash_bpc), (void *) &ret->hash_bpc, 870 BPC_CDT_END)) { 871 CHECKPOINT; 872 return(NULL); 873 } 874 break; 875 #ifndef DEBUG 876 default: 877 if (!_bpc_client_read(sockid, 878 BPC_CDT_SINK, (size_t) attrlen, 879 BPC_CDT_END)) { 880 CHECKPOINT; 881 return(NULL); 882 } 883 break; 884 #endif 885 } 886 } 887 } 888 889 /* 890 * Determine the POSIX "mode" value from the ACL attrs. 891 */ 892 modeval = 0; 893 if (attr_mode) { 894 if ((attr_mode & BPC_ACL_XUSR) == BPC_ACL_XUSR) { 895 modeval |= S_IXUSR; 896 } 897 if ((attr_mode & BPC_ACL_WUSR) == BPC_ACL_WUSR) { 898 modeval |= S_IWUSR; 899 } 900 if ((attr_mode & BPC_ACL_RUSR) == BPC_ACL_RUSR) { 901 modeval |= S_IRUSR; 902 } 903 #ifndef _USE_WIN32_ 904 if ((attr_mode & BPC_ACL_XGRP) == BPC_ACL_XGRP) { 905 modeval |= S_IXGRP; 906 } 907 if ((attr_mode & BPC_ACL_WGRP) == BPC_ACL_WGRP) { 908 modeval |= S_IWGRP; 909 } 910 if ((attr_mode & BPC_ACL_RGRP) == BPC_ACL_RGRP) { 911 modeval |= S_IRGRP; 912 } 913 if ((attr_mode & BPC_ACL_XOTH) == BPC_ACL_XOTH) { 914 modeval |= S_IXOTH; 915 } 916 if ((attr_mode & BPC_ACL_WOTH) == BPC_ACL_WOTH) { 917 modeval |= S_IWOTH; 918 } 919 if ((attr_mode & BPC_ACL_ROTH) == BPC_ACL_ROTH) { 920 modeval |= S_IROTH; 921 } 922 if ((attr_mode & BPC_ACL_STCK) == BPC_ACL_STCK) { 923 modeval |= S_ISVTX; 924 } 925 if ((attr_mode & BPC_ACL_SGID) == BPC_ACL_SGID) { 926 modeval |= S_ISGID; 927 } 928 if ((attr_mode & BPC_ACL_SUID) == BPC_ACL_SUID) { 929 modeval |= S_ISUID; 930 } 931 #endif 932 } 933 934 #if 0 935 if (filetype == BPC_FILE_REG) { 936 modeval |= S_IFREG; 937 } 938 #ifndef _USE_WIN32_ 939 if (filetype == BPC_FILE_SYMLINK) { 940 modeval |= S_IFLNK; 941 } 942 if (filetype == BPC_FILE_SOCKET) { 943 modeval |= S_IFSOCK; 944 } 945 #endif 946 if (filetype == BPC_FILE_DIR) { 947 modeval |= S_IFDIR; 948 } 949 if (filetype == BPC_FILE_BDEV) { 950 modeval |= S_IFBLK; 951 } 952 if (filetype == BPC_FILE_CDEV) { 953 modeval |= S_IFCHR; 954 } 955 if (filetype == BPC_FILE_FIFO) { 956 modeval |= S_IFIFO; 957 } 958 #endif 959 960 ret->mode = modeval; 961 ret->type = filetype; 962 ret->size = filesize; 963 ret->uid = attr_uid; 964 ret->gid = attr_gid; 965 ret->mtime = attr_mtime; 966 ret->ctime = attr_ctime; 967 968 if (cmd == BPC_CMD_GET) { 969 tinfo->blocksize = blocksize; 970 tinfo->idealblocknum = -1; 971 tinfo->currblocknum = 0; 972 tinfo->filesize = filesize; 973 tinfo->blockoffset = 0; 974 } 975 976 return(ret); 977 } 978 979 /* 980 * SYNOPSIS: 981 * int bpc_list_open( 982 * BPC_CONN *handle, 983 * const char *rootpath, 984 * const int recursive, 985 * backuppc_hashid_t hashalgo, 986 * const char *exclpat, 987 * const char *inclpat 988 * ); 989 * 990 * ARGUMENTS: 991 * BPC_CONN *handle Connection handle 992 * const char *rootpath Root path to start the GET or LIST from 993 * const int recursive Boolean option to specify whether or not to 994 * recurse into directories 995 * backuppc_hashid_t hashalgo OR'd list of hash algorithms to ask the 996 * server to compute for each file 997 * const char *exclpat <<NOT USED:XXX>> 998 * const char *inclpat <<NOT USED:XXX>> 999 * 1000 * RETURN VALUE: 1001 * This function returns 0 on failure, 1 on success. 1002 * 1003 * NOTES: 1004 * This function initiates a LIST command (by calling _bpc_listget_open()). 1005 * You must not be in the middle of any other command at the time. 1006 * 1007 * You should then call bpc_list() to get the LIST results. 1008 * 1009 * EXAMPLES: 1010 * 1011 * // List every node under the root directory non-recursively with no 1012 * // hashing performed on files. 1013 * if (!bpc_list_open(bpc_handle, "/", 0, BPC_HASH_NONE, NULL, NULL)) { 1014 * return(-1); 1015 * } 1016 * 1017 */ 1018 int bpc_list_open(BPC_CONN *handle, const char *rootpath, const int recursive, backuppc_hashid_t hashalgo, const char *exclpat, const char *inclpat) { 1019 if (!handle) { 1020 return(0); 1021 } 1022 1023 if (handle->state != BPC_CMD_NONE) { 1024 return(0); 1025 } 1026 1027 return(_bpc_listget_open(handle, BPC_CMD_LIST, rootpath, recursive, hashalgo, exclpat, inclpat)); 1028 } 1029 1030 /* 1031 * SYNOPSIS: 1032 * int bpc_list_close( 1033 * BPC_CONN *handle 1034 * ); 1035 * 1036 * ARGUMENTS: 1037 * BPC_CONN *handle Connection handle 1038 * 1039 * RETURN VALUE: 1040 * This function returns 0 on failure, 1 on success. 1041 * 1042 * NOTES: 1043 * This function verifies that a previous operation completed 1044 * sucessfully and that we are now not in the middle of any command. 1045 * 1046 * EXAMPLES: 1047 * 1048 * // Verify that the previous LIST command is complete 1049 * if (!bpc_list_close(bpc_handle)) { 1050 * return(-1); 1051 * } 1052 * 1053 */ 1054 int bpc_list_close(BPC_CONN *handle) { 1055 if (!handle) { 1056 return(0); 1057 } 1058 1059 if (handle->state != BPC_CMD_NONE) { 1060 return(0); 1061 } 1062 1063 return(1); 1064 } 1065 1066 /* 1067 * SYNOPSIS: 1068 * struct bpc_fileinfo *bpc_list( 1069 * BPC_CONN *handle, 1070 * ); 1071 * 1072 * ARGUMENTS: 1073 * BPC_CONN *handle Connection handle 1074 * 1075 * RETURN VALUE: 1076 * This function returns a pointer to a (struct bpc_fileinfo) object. The 1077 * contents of this objects may be overwritten with subsequent calls to 1078 * bpc_list() for the same handle. NULL is returned on error or when no 1079 * more objects exist in the stream. 1080 * 1081 * NOTES: 1082 * This function gets the contents of a LIST_REPLY from the handle and sets 1083 * them in the (struct bpc_fileinfo) value that it returns. 1084 * 1085 * EXAMPLES: 1086 * 1087 * // Get an item from an open LIST command 1088 * struct bpc_fileinfo *fileinfo; 1089 * 1090 * fileinfo = bpc_list(bpc_handle); 1091 * 1092 * if (!fileinfo) { 1093 * return(-1); 1094 * } 1095 * 1096 */ 1097 struct bpc_fileinfo *bpc_list(BPC_CONN *handle) { 1098 if (!handle) { 1099 return(NULL); 1100 } 1101 1102 if (handle->state != BPC_CMD_LIST) { 1103 return(NULL); 1104 } 1105 1106 return(_bpc_list(handle, BPC_CMD_LIST)); 1107 } 1108 1109 /* 1110 * SYNOPSIS: 1111 * int bpc_get_open( 1112 * BPC_CONN *handle, 1113 * const char *rootpath, 1114 * const int recursive, 1115 * backuppc_hashid_t hashalgo, 1116 * const char *exclpat, 1117 * const char *inclpat 1118 * ); 1119 * 1120 * ARGUMENTS: 1121 * BPC_CONN *handle Connection handle 1122 * const char *rootpath Root path to start the GET or LIST from 1123 * const int recursive Boolean option to specify whether or not to 1124 * recurse into directories 1125 * backuppc_hashid_t hashalgo OR'd list of hash algorithms to ask the 1126 * server to compute for each file 1127 * const char *exclpat <<NOT USED:XXX>> 1128 * const char *inclpat <<NOT USED:XXX>> 1129 * 1130 * RETURN VALUE: 1131 * This function returns 0 on failure, 1 on success. 1132 * 1133 * NOTES: 1134 * This function initiates a GET command and updates the internal state to 1135 * indicate that it is in the middle of such a command. 1136 * 1137 * You should then call bpc_get_head() to get the header of the GET result. 1138 * 1139 * EXAMPLES: 1140 * 1141 * // Get every node under "/" non-recursively and do not perform any 1142 * // hashing on the files. 1143 * if (!bpc_get_open(bpc_handle, "/", 0, BPC_HASH_NONE, NULL, NULL)) { 1144 * return(-1); 1145 * } 1146 * 1147 */ 1148 int bpc_get_open(BPC_CONN *handle, const char *rootpath, const int recursive, backuppc_hashid_t hashalgo, const char *exclpat, const char *inclpat) { 1149 int retval; 1150 1151 if (!handle) { 1152 CHECKPOINT; 1153 return(0); 1154 } 1155 1156 if (handle->state != BPC_CMD_NONE) { 1157 CHECKPOINT; 1158 return(0); 1159 } 1160 1161 retval = _bpc_listget_open(handle, BPC_CMD_GET, rootpath, recursive, hashalgo, exclpat, inclpat); 1162 1163 if (retval == 0) { 1164 CHECKPOINT; 1165 return(0); 1166 } 1167 1168 CHECKPOINT; 1169 return(retval); 1170 } 1171 1172 /* 1173 * SYNOPSIS: 1174 * int bpc_get_close( 1175 * BPC_CONN *handle 1176 * ); 1177 * 1178 * ARGUMENTS: 1179 * BPC_CONN *handle Connection handle 1180 * 1181 * RETURN VALUE: 1182 * This function returns 0 on failure, 1 on success. 1183 * 1184 * NOTES: 1185 * This function verifies that a previous operation completed 1186 * sucessfully and that we are now not in the middle of any command. 1187 * 1188 * EXAMPLES: 1189 * 1190 * // Verify that we have terminated a previously existing GET command 1191 * if (!bpc_get_close(bpc_handle)) { 1192 * return(-1); 1193 * } 1194 * 1195 */ 1196 int bpc_get_close(BPC_CONN *handle) { 1197 if (!handle) { 1198 return(0); 1199 } 1200 1201 if (handle->state != BPC_CMD_NONE) { 1202 return(0); 1203 } 1204 1205 return(1); 1206 } 1207 1208 /* 1209 * SYNOPSIS (internal): 1210 * struct bpc_fileinfo *bpc_get_head( 1211 * BPC_CONN *handle, 1212 * ); 1213 * 1214 * ARGUMENTS: 1215 * BPC_CONN *handle Connection handle 1216 * 1217 * RETURN VALUE: 1218 * This function returns a pointer to a (struct bpc_fileinfo) object. The 1219 * contents of this objects may be overwritten with subsequent calls to 1220 * bpc_get_head() for the same handle. NULL is returned on error or when no 1221 * more objects exist in the stream. 1222 * 1223 * NOTES: 1224 * This function gets the header of a GET_REPLY from the handle and sets 1225 * them in the (struct bpc_fileinfo) value that it returns. 1226 * 1227 * You should then call bpc_get() if the header indicates that this 1228 * represents this is a regular file. 1229 * 1230 * EXAMPLES: 1231 * 1232 * // Get an item from an open LIST command 1233 * struct bpc_fileinfo *fileinfo; 1234 * 1235 * fileinfo = bpc_get_head(bpc_handle); 1236 * 1237 * if (!fileinfo) { 1238 * return(-1); 1239 * } 1240 * 1241 */ 1242 struct bpc_fileinfo *bpc_get_head(BPC_CONN *handle) { 1243 uint32_t blocknum; 1244 struct bpc_fileinfo *ret; 1245 1246 if (!handle) { 1247 CHECKPOINT; 1248 return(NULL); 1249 } 1250 1251 if (handle->state != BPC_CMD_GET) { 1252 CHECKPOINT; 1253 return(NULL); 1254 } 1255 1256 /* 1257 * The "GET" operation is the same as the "LIST" operation, except 1258 * data will follow if the type is BPC_FILE_REG. 1259 */ 1260 ret = _bpc_list(handle, BPC_CMD_GET); 1261 1262 if (!ret) { 1263 CHECKPOINT; 1264 return(NULL); 1265 } 1266 1267 if (ret->type != BPC_FILE_REG) { 1268 if (!_bpc_client_read(handle->fd, 1269 BPC_CDT_UINT32, &blocknum, 1270 BPC_CDT_END)) { 1271 CHECKPOINT; 1272 return(NULL); 1273 } 1274 1275 if (blocknum != 0xffffffff) { 1276 CHECKPOINT; 1277 return(NULL); 1278 } 1279 1280 CHECKPOINT; 1281 return(ret); 1282 } 1283 1284 handle->state = BPC_CMD_GET_DATA; 1285 1286 return(ret); 1287 } 1288 1289 /* 1290 * SYNOPSIS: 1291 * ssize_t bpc_get( 1292 * BPC_CONN *handle, 1293 * char *buf, 1294 * size_t count 1295 * ); 1296 * 1297 * ARGUMENTS: 1298 * BPC_CONN *handle Connection handle 1299 * void *buf Pointer to a buffer to return data into 1300 * size_t count Size of buffer 1301 * 1302 * RETURN VALUE: 1303 * This function returns the number of bytes written to the memory pointed to 1304 * by `buf' on success. On error -1 is returned. 1305 * 1306 * NOTES: 1307 * 1308 * EXAMPLES: 1309 * 1310 * // Get an item from an open LIST command 1311 * ssize_t ret; 1312 * char buf[20]; 1313 * 1314 * ret = bpc_get(bpc_handle, buf, sizeof(buf)); 1315 * 1316 * if (ret < 0) { 1317 * return(-1); 1318 * } 1319 * 1320 */ 1321 ssize_t bpc_get(BPC_CONN *handle, void *buf, size_t count) { 1322 struct bpc_transfer *tinfo; 1323 ssize_t recv_ret; 1324 uint32_t bytes_left; 1325 uint32_t sinkbytes = 0; 1326 int sockid; 1327 1328 if (!handle) { 1329 CHECKPOINT; 1330 return(-1); 1331 } 1332 1333 if (handle->state != BPC_CMD_GET_DATA) { 1334 CHECKPOINT; 1335 return(-1); 1336 } 1337 1338 sockid = handle->fd; 1339 1340 tinfo = &handle->tinfo; 1341 1342 if (tinfo->blockoffset == 0) { 1343 if (tinfo->currblocknum == tinfo->idealblocknum || tinfo->idealblocknum == -1) { 1344 if (!_bpc_client_read(sockid, 1345 BPC_CDT_UINT32, &tinfo->currblocknum, 1346 BPC_CDT_END)) { 1347 CHECKPOINT; 1348 return(-1); 1349 } 1350 1351 if (tinfo->currblocknum == 0xffffffff) { 1352 handle->state = BPC_CMD_GET; 1353 CHECKPOINT; 1354 return(0); 1355 } 1356 } 1357 1358 if (tinfo->currblocknum == 0) { 1359 tinfo->idealblocknum = 0; 1360 } else { 1361 tinfo->idealblocknum++; 1362 } 1363 } 1364 1365 bytes_left = tinfo->blocksize - tinfo->blockoffset; 1366 1367 if (count > bytes_left) { 1368 count = bytes_left; 1369 } 1370 1371 if ((tinfo->idealblocknum * tinfo->blocksize + tinfo->blockoffset) > tinfo->filesize) { 1372 count = 0; 1373 sinkbytes = tinfo->blocksize - tinfo->blockoffset; 1374 } else { 1375 if ((tinfo->idealblocknum * tinfo->blocksize + tinfo->blockoffset + count) > tinfo->filesize) { 1376 count = tinfo->filesize - (tinfo->idealblocknum * tinfo->blocksize + tinfo->blockoffset); 1377 sinkbytes = tinfo->blocksize - count; 1378 } 1379 } 1380 1381 if (tinfo->currblocknum != tinfo->idealblocknum) { 1382 memset(buf, '\0', count); 1383 recv_ret = count; 1384 } else { 1385 recv_ret = recv(sockid, buf, count, MSG_WAITALL); 1386 1387 if (sinkbytes) { 1388 if (!_bpc_client_read(sockid, 1389 BPC_CDT_SINK, (ssize_t) sinkbytes, 1390 BPC_CDT_END)) { 1391 CHECKPOINT; 1392 return(-1); 1393 } 1394 } 1395 } 1396 1397 if (recv_ret < 0) { 1398 CHECKPOINT; 1399 return(-1); 1400 } 1401 1402 tinfo->blockoffset += recv_ret + sinkbytes; 1403 1404 if (tinfo->blockoffset == tinfo->blocksize) { 1405 tinfo->blockoffset = 0; 1406 } 1407 1408 CHECKPOINT; 1409 return(recv_ret); 1410 } 1411 1412 int bpc_copy(BPC_CONN *handle, bpc_mode_t mode, int fd) { 1413 char buf[32768]; 1414 ssize_t read_ret, write_ret; 1415 int write_fail_count = 0; 1416 int retval = 1; 1417 1418 while (1) { 1419 read_ret = bpc_get(handle, buf, sizeof(buf)); 1420 1421 if (read_ret == 0) { 1422 break; 1423 } 1424 1425 if (read_ret < 0) { 1426 retval = 0; 1427 break; 1428 } 1429 1430 while (read_ret) { 1431 switch (mode) { 1432 case BPC_MODE_WRITE: 1433 write_ret = write(fd, buf, read_ret); 1434 break; 1435 case BPC_MODE_SEND: 1436 write_ret = send(fd, buf, read_ret, 0); 1437 break; 1438 default: 1439 write_ret = -1; 1440 } 1441 1442 1443 if (write_ret < 0) { 1444 retval = 0; 1445 break; 1446 } 1447 1448 if (write_ret == 0) { 1449 write_fail_count++; 1450 } else { 1451 write_fail_count = 0; 1452 } 1453 1454 if (write_fail_count >= 10) { 1455 retval = 0; 1456 break; 1457 } 1458 1459 read_ret -= write_ret; 1460 } 1461 } 1462 1463 CHECKPOINT; 1464 return(retval); 1465 } 1466 1467 int bpc_rdiffget(BPC_CONN *handle, const char *remote_src, const char *dest) { 1468 backuppc_hashid_t hashalgo = BPC_HASH_MD4; 1469 struct stat stbuf; 1470 uint64_t filesize; 1471 uint32_t blocksize; 1472 uint32_t num_hash_ents, hash_ent, hash_ent_size, hash_list_size; 1473 ssize_t read_ret; 1474 char buf[BPC_MAX_RDIFF_BLOCKSIZE]; 1475 void *hash_handle; 1476 int stat_ret; 1477 int sockid; 1478 int fd; 1479 1480 if (!handle) { 1481 return(0); 1482 } 1483 1484 sockid = handle->fd; 1485 1486 stat_ret = stat(dest, &stbuf); 1487 if (stat_ret < 0) { 1488 filesize = 0xffffffffffffffffLLU; 1489 blocksize = 0; 1490 num_hash_ents = 0; 1491 } else { 1492 filesize = stbuf.st_size; 1493 1494 /* 1495 * Determine the block size: 1496 * 0 bytes to 20 MBytes: 2 KBytes 1497 * 20 MBytes to 1 GByte: 4 KBytes 1498 * 1 GByte to Infinity: 8 KBytes 1499 */ 1500 if (filesize < (20 * 1024 * 1024)) { 1501 blocksize = 2048; 1502 } else if (filesize < (1024 * 1024 * 1024)) { 1503 blocksize = 4096; 1504 } else { 1505 blocksize = BPC_MAX_RDIFF_BLOCKSIZE; 1506 } 1507 1508 if (blocksize > BPC_MAX_RDIFF_BLOCKSIZE) { 1509 blocksize = BPC_MAX_RDIFF_BLOCKSIZE; 1510 } 1511 1512 num_hash_ents = (filesize + blocksize - 1) / blocksize; 1513 } 1514 1515 switch (hashalgo) { 1516 case BPC_HASH_NONE: 1517 break; 1518 case BPC_HASH_MD5: 1519 hash_ent_size = (128 / 8); 1520 hash_handle = NULL; 1521 break; 1522 case BPC_HASH_MD4: 1523 hash_ent_size = (128 / 8); 1524 hash_handle = NULL; 1525 break; 1526 case BPC_HASH_SHA1: 1527 hash_ent_size = (160 / 8); 1528 hash_handle = malloc(sizeof(SHA1_CTX)); 1529 break; 1530 case BPC_HASH_BPC: 1531 hash_ent_size = (128 / 8); 1532 hash_handle = NULL; 1533 break; 1534 } 1535 1536 hash_list_size = num_hash_ents * hash_ent_size; 1537 1538 if (!_bpc_client_write(sockid, 1539 BPC_CDT_UINT8, (uint8_t) BPC_CMD_RDGET, 1540 BPC_CDT_UINT64, (uint64_t) filesize, 1541 BPC_CDT_UINT32, (uint32_t) blocksize, 1542 BPC_CDT_UINT8, (uint8_t) hashalgo, 1543 BPC_CDT_UINT32, (uint32_t) hash_list_size, 1544 BPC_CDT_UINT32, (uint32_t) strlen(remote_src), 1545 BPC_CDT_STRING, (char *) remote_src, 1546 BPC_CDT_END)) { 1547 return(0); 1548 } 1549 1550 fd = open(dest, O_RDONLY); 1551 1552 if (fd < 0) { 1553 return(0); 1554 } 1555 1556 for (hash_ent = 0; hash_ent < num_hash_ents; hash_ent++) { 1557 read_ret = read(fd, buf, blocksize); 1558 if (read_ret < 0) { 1559 read_ret = 0; 1560 } 1561 1562 if (read_ret == 0) { 1563 CHECKPOINT; 1564 } 1565 1566 switch (hashalgo) { 1567 case BPC_HASH_NONE: 1568 break; 1569 case BPC_HASH_SHA1: 1570 SHA1Init(hash_handle); 1571 SHA1Update(hash_handle, buf, read_ret); 1572 // SHA1Final(digest[20], hash_handle); 1573 break; 1574 case BPC_HASH_MD5: 1575 case BPC_HASH_MD4: 1576 case BPC_HASH_BPC: 1577 break; 1578 } 1579 } 1580 1581 close(fd); 1582 1583 if (hash_handle) { 1584 free(hash_handle); 1585 } 1586 1587 return(1); 1588 } 1589 1590 int bpc_copyfile(BPC_CONN *handle, struct bpc_fileinfo *src, const char *dest, int preserve) { 1591 int fd; 1592 int retval = 0; 1593 int sys_ret; 1594 1595 switch (src->type) { 1596 case BPC_FILE_DIR: 1597 backuppc_mkdir(dest); 1598 retval = 1; 1599 break; 1600 case BPC_FILE_SYMLINK: 1601 #ifdef HAVE_SYMLINK 1602 sys_ret = symlink(src->linkdest, dest); 1603 if (sys_ret == 0) { 1604 retval = 1; 1605 } 1606 #endif 1607 break; 1608 case BPC_FILE_HRDLINK: 1609 sys_ret = link(src->linkdest, dest); 1610 if (sys_ret == 0) { 1611 retval = 1; 1612 } 1613 break; 1614 case BPC_FILE_CDEV: 1615 case BPC_FILE_BDEV: 1616 case BPC_FILE_SOCKET: 1617 case BPC_FILE_FIFO: 1618 case BPC_FILE_UNKNOWN: 1619 CHECKPOINT; 1620 return(0); 1621 case BPC_FILE_REG: 1622 /* 1623 * Regular files are handled seperately 1624 */ 1625 break; 1626 } 1627 1628 if (src->type != BPC_FILE_REG) { 1629 if (retval && preserve) { 1630 chmod(dest, src->mode); 1631 #ifdef HAVE_LCHOWN 1632 lchown(dest, src->uid, src->gid); 1633 #else 1634 chown(dest, src->uid, src->gid); 1635 #endif 1636 #ifdef HAVE_UTIME 1637 // utime(...) 1638 #endif 1639 } 1640 CHECKPOINT; 1641 return(retval); 1642 } 1643 1644 1645 /* 1646 * Handle the regular files using either RDIFF or GET. 1647 */ 1648 if (access(dest, F_OK) == 0 && 0 /* XXX: RGET NOT IMPLEMENTED */) { 1649 /* 1650 * Do RDIFF 1651 */ 1652 } else { 1653 /* 1654 * Copy the entire file. 1655 */ 1656 fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600); 1657 1658 if (bpc_copy(handle, BPC_MODE_WRITE, fd)) { 1659 retval = 1; 1660 } 1661 1662 close(fd); 1663 } 1664 if (preserve) { 1665 chmod(dest, src->mode); 1666 chown(dest, src->uid, src->gid); 1667 #ifdef HAVE_UTIME 1668 // utime(...) 1669 #endif 1670 } 1671 1672 CHECKPOINT; 1673 return(retval); 1674 } 1675 1676 /* 1677 * SYNOPSIS: 1678 * BPC_CONN *bpc_connect( 1679 * const char *host, 1680 * const int port, 1681 * const char *username, 1682 * const char *password 1683 * ); 1684 * 1685 * ARGUMENTS: 1686 * const char *host BackupPCd host to connect to 1687 * const int port Port to connect to host on (default if == 0) 1688 * const char *username (optional) Username to authenticate with 1689 * const char *password (optional) Password to authenticate with 1690 * 1691 * RETURN VALUE: 1692 * This function returns NULL on failure, a pointer to a (BPC_CONN) on success. 1693 * 1694 * NOTES: 1695 * 1696 * EXAMPLES: 1697 * 1698 */ 1699 BPC_CONN *bpc_connect(const char *host, const int port, const char *username, const char *password) { 1700 BPC_CONN *ret; 1701 int sockid; 1702 int real_port; 1703 1704 if (port == 0) { 1705 real_port = BPC_TCP_PORT; 1706 } else { 1707 real_port = port; 1708 } 1709 1710 sockid = net_connect_tcp(host, real_port); 1711 1712 if (sockid < 0) { 1713 CHECKPOINT; 1714 return(NULL); 1715 } 1716 1717 ret = malloc(sizeof(*ret)); 1718 1719 if (!ret) { 1720 close(sockid); 1721 1722 CHECKPOINT; 1723 return(NULL); 1724 } 1725 1726 ret->fd = sockid; 1727 ret->state = BPC_CMD_NONE; 1728 1729 if (username && password) { 1730 if (!bpc_auth(ret, username, password)) { 1731 close(ret->fd); 1732 free(ret); 1733 1734 CHECKPOINT; 1735 return(NULL); 1736 } 1737 } 1738 1739 CHECKPOINT; 1740 return(ret); 1741 } 1742 1743 /* 1744 * SYNOPSIS: 1745 * int bpc_disconnect( 1746 * BPC_CONN *handle 1747 * ); 1748 * 1749 * ARGUMENTS: 1750 * BPC_CONN *handle Connection handle 1751 * 1752 * RETURN VALUE: 1753 * This function returns -1 on failure, 0 on success. 1754 * 1755 * NOTES: 1756 * 1757 * EXAMPLES: 1758 * 1759 */ 1760 int bpc_disconnect(BPC_CONN *handle) { 1761 int close_ret; 1762 1763 if (!handle) { 1764 CHECKPOINT; 1765 return(-1); 1766 } 1767 1768 if (handle->fd < 0) { 1769 CHECKPOINT; 1770 return(0); 1771 } 1772 1773 close_ret = net_close(handle->fd); 1774 1775 if (close_ret < 0) { 1776 CHECKPOINT; 1777 return(close_ret); 1778 } 1779 1780 free(handle); 1781 1782 CHECKPOINT; 1783 return(0); 1784 } |