1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * BSD 3 Clause License 8 * 9 * Copyright (c) 2007, The Storage Networking Industry Association. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * - Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * - Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in 19 * the documentation and/or other materials provided with the 20 * distribution. 21 * 22 * - Neither the name of The Storage Networking Industry Association (SNIA) 23 * nor the names of its contributors may be used to endorse or promote 24 * products derived from this software without specific prior written 25 * permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 /* Copyright (c) 2007, The Storage Networking Industry Association. */ 40 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ 41 42 #include <sys/types.h> 43 #include <stdlib.h> 44 #include <errno.h> 45 #include <stdarg.h> 46 #include <stdio.h> 47 #include <string.h> 48 #include "ndmpd.h" 49 50 51 /* 52 * Message Id counter. This number is increased by MOD_LOGV3 macro. 53 * MOD_LOGCONTV3 macro uses the number generated by the last MOD_LOGV3. 54 * 55 */ 56 int ndmp_log_msg_id = 0; 57 58 59 /* 60 * ************************************************************************ 61 * NDMP V2 CALLBACKS 62 * ************************************************************************ 63 */ 64 65 /* 66 * ndmpd_api_done_v2 67 * 68 * Called when dump/restore has completed. 69 * Sends a notify_halt request to the NDMP client. 70 * 71 * Parameters: 72 * session (input) - session pointer. 73 * err (input) - UNIX error code. 74 * 75 * Returns: 76 * void 77 */ 78 void 79 ndmpd_api_done_v2(void *cookie, int err) 80 { 81 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 82 ndmp_notify_data_halted_request req_v2; 83 84 if (session == NULL) 85 return; 86 87 if (session->ns_data.dd_state == NDMP_DATA_STATE_IDLE || 88 session->ns_data.dd_state == NDMP_DATA_STATE_HALTED) 89 return; 90 91 NDMP_LOG(LOG_DEBUG, "data.operation: %d", 92 session->ns_data.dd_operation); 93 94 if (session->ns_data.dd_operation == NDMP_DATA_OP_BACKUP) { 95 /* 96 * Send/discard any buffered file history data. 97 */ 98 ndmpd_file_history_cleanup(session, (err == 0 ? TRUE : FALSE)); 99 100 /* 101 * If mover local and successfull backup, write any 102 * remaining buffered data to tape. 103 */ 104 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_LOCAL && 105 err == 0) { 106 if (ndmpd_local_write(session, 0, 0) < 0) 107 err = EIO; 108 } 109 } 110 111 session->ns_data.dd_state = NDMP_DATA_STATE_HALTED; 112 113 switch (err) { 114 case 0: 115 session->ns_data.dd_halt_reason = NDMP_DATA_HALT_SUCCESSFUL; 116 break; 117 case EINTR: 118 session->ns_data.dd_halt_reason = NDMP_DATA_HALT_ABORTED; 119 break; 120 case EIO: 121 session->ns_data.dd_halt_reason = NDMP_DATA_HALT_CONNECT_ERROR; 122 break; 123 default: 124 session->ns_data.dd_halt_reason = NDMP_DATA_HALT_INTERNAL_ERROR; 125 } 126 127 req_v2.reason = session->ns_data.dd_halt_reason; 128 req_v2.text_reason = ""; 129 130 NDMP_LOG(LOG_DEBUG, "ndmp_send_request(NDMP_NOTIFY_DATA_HALTED)"); 131 132 if (ndmp_send_request_lock(session->ns_connection, 133 NDMP_NOTIFY_DATA_HALTED, NDMP_NO_ERR, (void *)&req_v2, 0) < 0) 134 NDMP_LOG(LOG_DEBUG, "Sending notify_data_halted request"); 135 136 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) { 137 138 if (session->ns_mover.md_sock != session->ns_data.dd_sock) { 139 (void) close(session->ns_data.dd_sock); 140 } else { 141 NDMP_LOG(LOG_DEBUG, "Not closing as used by mover"); 142 } 143 144 session->ns_data.dd_sock = -1; 145 } else { 146 ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED); 147 } 148 } 149 150 151 /* 152 * ndmpd_api_log_v2 153 * 154 * Sends a log request to the NDMP client. 155 * 156 * Parameters: 157 * cookie (input) - session pointer. 158 * str (input) - null terminated string 159 * format (input) - printf style format. 160 * ... (input) - format arguments. 161 * 162 * Returns: 163 * 0 - success. 164 * -1 - error. 165 */ 166 /*ARGSUSED*/ 167 int 168 ndmpd_api_log_v2(void *cookie, char *format, ...) 169 { 170 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 171 ndmp_log_log_request request; 172 static char buf[1024]; 173 va_list ap; 174 175 if (session == NULL) 176 return (-1); 177 178 va_start(ap, format); 179 180 /*LINTED variable format specifier */ 181 (void) vsnprintf(buf, sizeof (buf), format, ap); 182 va_end(ap); 183 184 request.entry = buf; 185 186 187 if (ndmp_send_request(session->ns_connection, _NDMP_LOG_LOG, 188 NDMP_NO_ERR, (void *)&request, 0) < 0) { 189 NDMP_LOG(LOG_DEBUG, "Sending log request"); 190 return (-1); 191 } 192 return (0); 193 194 } 195 196 197 /* 198 * ndmpd_api_read_v2 199 * 200 * Callback function called by the backup/recover module. 201 * Reads data from the mover. 202 * If the mover is remote, the data is read from the data connection. 203 * If the mover is local, the data is read from the tape device. 204 * 205 * Parameters: 206 * client_data (input) - session pointer. 207 * data (input) - data to be written. 208 * length (input) - data length. 209 * 210 * Returns: 211 * 0 - data successfully read. 212 * -1 - error. 213 * 1 - session terminated or operation aborted. 214 */ 215 int 216 ndmpd_api_read_v2(void *client_data, char *data, ulong_t length) 217 { 218 ndmpd_session_t *session = (ndmpd_session_t *)client_data; 219 220 if (session == NULL) 221 return (-1); 222 223 /* 224 * Read the data from the data connection if the mover is remote. 225 */ 226 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) 227 return (ndmpd_remote_read(session, data, length)); 228 else 229 return (ndmpd_local_read(session, data, length)); 230 } 231 232 233 /* 234 * ndmpd_api_seek_v2 235 * 236 * Seek to the specified position in the data stream and start a 237 * read for the specified amount of data. 238 * 239 * Parameters: 240 * cookie (input) - session pointer. 241 * offset (input) - stream position to seek to. 242 * length (input) - amount of data that will be read using ndmpd_api_read 243 * 244 * Returns: 245 * 0 - seek successful. 246 * -1 - error. 247 */ 248 int 249 ndmpd_api_seek_v2(void *cookie, u_longlong_t offset, u_longlong_t length) 250 { 251 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 252 int err; 253 254 if (session == NULL) 255 return (-1); 256 257 session->ns_data.dd_read_offset = offset; 258 session->ns_data.dd_read_length = length; 259 260 /* 261 * Send a notify_data_read request if the mover is remote. 262 */ 263 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) { 264 ndmp_notify_data_read_request request; 265 266 session->ns_mover.md_discard_length = 267 session->ns_mover.md_bytes_left_to_read; 268 session->ns_mover.md_bytes_left_to_read = length; 269 session->ns_mover.md_position = offset; 270 271 request.offset = long_long_to_quad(offset); 272 request.length = long_long_to_quad(length); 273 274 if (ndmp_send_request_lock(session->ns_connection, 275 NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR, 276 (void *)&request, 0) < 0) { 277 278 NDMP_LOG(LOG_DEBUG, 279 "Sending notify_data_read request"); 280 return (-1); 281 } 282 return (0); 283 } 284 /* Mover is local. */ 285 286 err = ndmpd_mover_seek(session, offset, length); 287 if (err < 0) { 288 ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 289 return (-1); 290 } 291 if (err == 0) 292 return (0); 293 294 /* 295 * NDMP client intervention is required to perform the seek. 296 * Wait for the client to either do the seek and send a continue 297 * request or send an abort request. 298 */ 299 nlp_ref_nw(session); 300 for (; ; ) { 301 nlp_wait_nw(session); 302 303 if (nlp_event_rv_get(session) < 0) { 304 nlp_unref_nw(session); 305 return (-1); 306 } 307 308 if (session->ns_eof == TRUE) { 309 nlp_unref_nw(session); 310 return (-1); 311 } 312 313 switch (session->ns_mover.md_state) { 314 case NDMP_MOVER_STATE_ACTIVE: 315 /* 316 * There is a bug in the original SDK code which 317 * causes to fall in an infinite loop after the 318 * break. 319 */ 320 nlp_unref_nw(session); 321 break; 322 323 case NDMP_MOVER_STATE_PAUSED: 324 continue; 325 326 default: 327 nlp_unref_nw(session); 328 return (-1); 329 } 330 } 331 } 332 333 334 /* 335 * ndmpd_api_file_recovered_v2 336 * 337 * Notify the NDMP client that the specified file was recovered. 338 * 339 * Parameters: 340 * cookie (input) - session pointer. 341 * name (input) - name of recovered file. 342 * error (input) - 0 if file successfully recovered. 343 * otherwise, error code indicating why recovery failed. 344 * 345 * Returns: 346 * void. 347 */ 348 int 349 ndmpd_api_file_recovered_v2(void *cookie, char *name, int error) 350 { 351 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 352 ndmp_log_file_request_v2 request; 353 354 if (session == NULL) 355 return (-1); 356 357 request.name = name; 358 request.ssid = 0; 359 360 switch (error) { 361 case 0: 362 request.error = NDMP_NO_ERR; 363 break; 364 case ENOENT: 365 request.error = NDMP_FILE_NOT_FOUND_ERR; 366 break; 367 default: 368 request.error = NDMP_PERMISSION_ERR; 369 } 370 371 if (ndmp_send_request(session->ns_connection, NDMP_LOG_FILE, 372 NDMP_NO_ERR, (void *)&request, 0) < 0) { 373 NDMP_LOG(LOG_DEBUG, "Sending log file request"); 374 return (-1); 375 } 376 return (0); 377 } 378 379 380 /* 381 * ndmpd_api_write_v2 382 * 383 * Callback function called by the backup/restore module. 384 * Writes data to the mover. 385 * If the mover is remote, the data is written to the data connection. 386 * If the mover is local, the data is buffered and written to the 387 * tape device after a full record has been buffered. 388 * 389 * Parameters: 390 * client_data (input) - session pointer. 391 * data (input) - data to be written. 392 * length (input) - data length. 393 * 394 * Returns: 395 * 0 - data successfully written. 396 * -1 - error. 397 */ 398 int 399 ndmpd_api_write_v2(void *client_data, char *data, ulong_t length) 400 { 401 ndmpd_session_t *session = (ndmpd_session_t *)client_data; 402 403 if (session == NULL) 404 return (-1); 405 406 /* 407 * Write the data to the data connection if the mover is remote. 408 */ 409 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) 410 return (ndmpd_remote_write(session, data, length)); 411 else 412 return (ndmpd_local_write(session, data, length)); 413 } 414 415 416 /* 417 * ************************************************************************ 418 * NDMP V3 CALLBACKS 419 * ************************************************************************ 420 */ 421 422 /* 423 * ndmpd_api_done_v3 424 * 425 * Called when the data module has completed. 426 * Sends a notify_halt request to the NDMP client. 427 * 428 * Parameters: 429 * session (input) - session pointer. 430 * err (input) - UNIX error code. 431 * 432 * Returns: 433 * void 434 */ 435 void 436 ndmpd_api_done_v3(void *cookie, int err) 437 { 438 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 439 ndmp_data_halt_reason reason; 440 441 switch (err) { 442 case 0: 443 reason = NDMP_DATA_HALT_SUCCESSFUL; 444 break; 445 446 case EINTR: 447 reason = NDMP_DATA_HALT_ABORTED; 448 break; 449 450 case EIO: 451 reason = NDMP_DATA_HALT_CONNECT_ERROR; 452 break; 453 454 default: 455 reason = NDMP_DATA_HALT_INTERNAL_ERROR; 456 } 457 458 ndmpd_data_error(session, reason); 459 } 460 461 /* 462 * ndmpd_api_log_v3 463 * 464 * Sends a log request to the NDMP client. 465 * 466 * Parameters: 467 * cookie (input) - session pointer. 468 * format (input) - printf style format. 469 * ... (input) - format arguments. 470 * 471 * Returns: 472 * 0 - success. 473 * -1 - error. 474 */ 475 /*ARGSUSED*/ 476 int 477 ndmpd_api_log_v3(void *cookie, ndmp_log_type type, ulong_t msg_id, 478 char *format, ...) 479 { 480 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 481 ndmp_log_message_request_v3 request; 482 static char buf[1024]; 483 va_list ap; 484 485 if (session == NULL) 486 return (-1); 487 488 va_start(ap, format); 489 490 /*LINTED variable format specifier */ 491 (void) vsnprintf(buf, sizeof (buf), format, ap); 492 va_end(ap); 493 494 request.entry = buf; 495 request.log_type = type; 496 request.message_id = msg_id; 497 498 if (ndmp_send_request(session->ns_connection, NDMP_LOG_MESSAGE, 499 NDMP_NO_ERR, (void *)&request, 0) < 0) { 500 NDMP_LOG(LOG_DEBUG, "Error sending log message request."); 501 return (-1); 502 } 503 return (0); 504 } 505 506 507 /* 508 * ndmpd_api_write_v3 509 * 510 * Callback function called by the backup/restore module. 511 * Writes data to the mover. 512 * If the mover is remote, the data is written to the data connection. 513 * If the mover is local, the data is buffered and written to the 514 * tape device after a full record has been buffered. 515 * 516 * Parameters: 517 * client_data (input) - session pointer. 518 * data (input) - data to be written. 519 * length (input) - data length. 520 * 521 * Returns: 522 * 0 - data successfully written. 523 * -1 - error. 524 */ 525 int 526 ndmpd_api_write_v3(void *client_data, char *data, ulong_t length) 527 { 528 ndmpd_session_t *session = (ndmpd_session_t *)client_data; 529 530 if (session == NULL) 531 return (-1); 532 533 /* 534 * Write the data to the tape if the mover is local, otherwise, 535 * write the data to the data connection. 536 * 537 * The same write function for of v2 can be used in V3 538 * for writing data to the data connection to the mover. 539 * So we don't need ndmpd_remote_write_v3(). 540 */ 541 if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL) 542 return (ndmpd_local_write_v3(session, data, length)); 543 else 544 return (ndmpd_remote_write(session, data, length)); 545 } 546 547 548 /* 549 * ndmpd_api_read_v3 550 * 551 * Callback function called by the backup/recover module. 552 * Reads data from the mover. 553 * If the mover is remote, the data is read from the data connection. 554 * If the mover is local, the data is read from the tape device. 555 * 556 * Parameters: 557 * client_data (input) - session pointer. 558 * data (input) - data to be written. 559 * length (input) - data length. 560 * 561 * Returns: 562 * 0 - data successfully read. 563 * -1 - error. 564 * 1 - session terminated or operation aborted. 565 */ 566 int 567 ndmpd_api_read_v3(void *client_data, char *data, ulong_t length) 568 { 569 ndmpd_session_t *session = (ndmpd_session_t *)client_data; 570 571 if (session == NULL) 572 return (-1); 573 574 /* 575 * Read the data from the data connection if the mover is remote. 576 */ 577 if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL) 578 return (ndmpd_local_read_v3(session, data, length)); 579 else 580 return (ndmpd_remote_read_v3(session, data, length)); 581 } 582 583 584 /* 585 * ndmpd_api_get_name_v3 586 * 587 * Return the name entry at the specified index from the 588 * recover file name list. 589 * 590 * Parameters: 591 * cookie (input) - NDMP session pointer. 592 * name_index (input) - index of entry to be returned. 593 * 594 * Returns: 595 * Pointer to name entry. 596 * 0 if requested entry does not exist. 597 */ 598 void * 599 ndmpd_api_get_name_v3(void *cookie, ulong_t name_index) 600 { 601 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 602 603 if (session == NULL) 604 return (NULL); 605 606 if (name_index >= session->ns_data.dd_nlist_len) 607 return (NULL); 608 609 return (&session->ns_data.dd_nlist_v3[name_index]); 610 } 611 612 613 /* 614 * ndmpd_api_file_recovered_v3 615 * 616 * Notify the NDMP client that the specified file was recovered. 617 * 618 * Parameters: 619 * cookie (input) - session pointer. 620 * name (input) - name of recovered file. 621 * ssid (input) - selection set id. 622 * error (input) - 0 if file successfully recovered. 623 * otherwise, error code indicating why recovery failed. 624 * 625 * Returns: 626 * 0 - success. 627 * -1 - error. 628 */ 629 int 630 ndmpd_api_file_recovered_v3(void *cookie, char *name, int error) 631 { 632 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 633 ndmp_log_file_request_v3 request; 634 635 if (session == NULL) 636 return (-1); 637 638 request.name = name; 639 640 switch (error) { 641 case 0: 642 request.error = NDMP_NO_ERR; 643 break; 644 case ENOENT: 645 request.error = NDMP_FILE_NOT_FOUND_ERR; 646 break; 647 default: 648 request.error = NDMP_PERMISSION_ERR; 649 } 650 651 if (ndmp_send_request(session->ns_connection, NDMP_LOG_FILE, 652 NDMP_NO_ERR, (void *)&request, 0) < 0) { 653 NDMP_LOG(LOG_DEBUG, "Error sending log file request"); 654 return (-1); 655 } 656 657 return (0); 658 } 659 660 661 /* 662 * ndmpd_api_seek_v3 663 * 664 * Seek to the specified position in the data stream and start a 665 * read for the specified amount of data. 666 * 667 * Parameters: 668 * cookie (input) - session pointer. 669 * offset (input) - stream position to seek to. 670 * length (input) - amount of data that will be read using ndmpd_api_read 671 * 672 * Returns: 673 * 0 - seek successful. 674 * 1 - seek needed DMA(client) intervention. 675 * -1 - error. 676 */ 677 int 678 ndmpd_api_seek_v3(void *cookie, u_longlong_t offset, u_longlong_t length) 679 { 680 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 681 int err; 682 ndmp_notify_data_read_request request; 683 684 if (session == NULL) 685 return (-1); 686 687 session->ns_data.dd_read_offset = offset; 688 session->ns_data.dd_read_length = length; 689 690 /* 691 * Send a notify_data_read request if the mover is remote. 692 */ 693 if (session->ns_data.dd_data_addr.addr_type != NDMP_ADDR_LOCAL) { 694 session->ns_data.dd_discard_length = 695 session->ns_data.dd_bytes_left_to_read; 696 session->ns_data.dd_bytes_left_to_read = length; 697 session->ns_data.dd_position = offset; 698 699 request.offset = long_long_to_quad(offset); 700 request.length = long_long_to_quad(length); 701 702 if (ndmp_send_request_lock(session->ns_connection, 703 NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR, 704 (void *)&request, 0) < 0) { 705 NDMP_LOG(LOG_DEBUG, 706 "Sending notify_data_read request"); 707 return (-1); 708 } 709 710 return (0); 711 } 712 713 /* Mover is local. */ 714 715 err = ndmpd_mover_seek(session, offset, length); 716 if (err < 0) { 717 ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 718 return (-1); 719 } 720 721 if (err == 0) 722 return (0); 723 724 /* 725 * NDMP client intervention is required to perform the seek. 726 * Wait for the client to either do the seek and send a continue 727 * request or send an abort request. 728 */ 729 err = ndmpd_mover_wait_v3(session); 730 731 /* 732 * If we needed a client intervention, then we should be able to 733 * detect this in DAR. 734 */ 735 if (err == 0) 736 err = 1; 737 return (err); 738 } 739 740 741 /* 742 * ************************************************************************ 743 * NDMP V4 CALLBACKS 744 * ************************************************************************ 745 */ 746 747 /* 748 * ndmpd_api_log_v4 749 * 750 * Sends a log request to the NDMP client. 751 * No message association is supported now, but can be added later on 752 * in this function. 753 * 754 * Parameters: 755 * cookie (input) - session pointer. 756 * format (input) - printf style format. 757 * ... (input) - format arguments. 758 * 759 * Returns: 760 * 0 - success. 761 * -1 - error. 762 */ 763 /*ARGSUSED*/ 764 int 765 ndmpd_api_log_v4(void *cookie, ndmp_log_type type, ulong_t msg_id, 766 char *format, ...) 767 { 768 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 769 ndmp_log_message_request_v4 request; 770 static char buf[1024]; 771 va_list ap; 772 773 if (session == NULL) 774 return (-1); 775 776 va_start(ap, format); 777 778 /*LINTED variable format specifier */ 779 (void) vsnprintf(buf, sizeof (buf), format, ap); 780 va_end(ap); 781 782 request.entry = buf; 783 request.log_type = type; 784 request.message_id = msg_id; 785 request.associated_message_valid = NDMP_NO_ASSOCIATED_MESSAGE; 786 request.associated_message_sequence = 0; 787 788 if (ndmp_send_request(session->ns_connection, NDMP_LOG_MESSAGE, 789 NDMP_NO_ERR, (void *)&request, 0) < 0) { 790 NDMP_LOG(LOG_DEBUG, "Error sending log message request."); 791 return (-1); 792 } 793 return (0); 794 } 795 796 797 /* 798 * ndmpd_api_file_recovered_v4 799 * 800 * Notify the NDMP client that the specified file was recovered. 801 * 802 * Parameters: 803 * cookie (input) - session pointer. 804 * name (input) - name of recovered file. 805 * ssid (input) - selection set id. 806 * error (input) - 0 if file successfully recovered. 807 * otherwise, error code indicating why recovery failed. 808 * 809 * Returns: 810 * void. 811 */ 812 int 813 ndmpd_api_file_recovered_v4(void *cookie, char *name, int error) 814 { 815 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 816 ndmp_log_file_request_v4 request; 817 818 if (session == NULL) 819 return (-1); 820 821 request.name = name; 822 823 switch (error) { 824 case 0: 825 request.recovery_status = NDMP_RECOVERY_SUCCESSFUL; 826 break; 827 case EPERM: 828 request.recovery_status = NDMP_RECOVERY_FAILED_PERMISSION; 829 break; 830 case ENOENT: 831 request.recovery_status = NDMP_RECOVERY_FAILED_NOT_FOUND; 832 break; 833 case ENOTDIR: 834 request.recovery_status = NDMP_RECOVERY_FAILED_NO_DIRECTORY; 835 break; 836 case ENOMEM: 837 request.recovery_status = NDMP_RECOVERY_FAILED_OUT_OF_MEMORY; 838 break; 839 case EIO: 840 request.recovery_status = NDMP_RECOVERY_FAILED_IO_ERROR; 841 break; 842 case EEXIST: 843 request.recovery_status = NDMP_RECOVERY_FAILED_FILE_PATH_EXISTS; 844 break; 845 default: 846 request.recovery_status = NDMP_RECOVERY_FAILED_UNDEFINED_ERROR; 847 break; 848 } 849 850 if (ndmp_send_request(session->ns_connection, NDMP_LOG_FILE, 851 NDMP_NO_ERR, (void *)&request, 0) < 0) { 852 NDMP_LOG(LOG_DEBUG, "Error sending log file request"); 853 return (-1); 854 } 855 856 return (0); 857 } 858 859 860 /* 861 * ************************************************************************ 862 * LOCALS 863 * ************************************************************************ 864 */ 865 866 /* 867 * ndmpd_api_find_env 868 * 869 * Return the pointer of the environment variable from the variable 870 * array for the spcified environment variable. 871 * 872 * Parameters: 873 * cookie (input) - NDMP session pointer. 874 * name (input) - name of variable. 875 * 876 * Returns: 877 * Pointer to variable. 878 * NULL if variable not found. 879 * 880 */ 881 ndmp_pval * 882 ndmpd_api_find_env(void *cookie, char *name) 883 { 884 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 885 ulong_t i; 886 ndmp_pval *envp; 887 888 if (session == NULL) 889 return (NULL); 890 891 envp = session->ns_data.dd_env; 892 for (i = 0; envp && i < session->ns_data.dd_env_len; envp++, i++) 893 if (strcmp(name, envp->name) == NULL) 894 return (envp); 895 896 return (NULL); 897 } 898 899 900 /* 901 * ndmpd_api_get_env 902 * 903 * Return the value of an environment variable from the variable array. 904 * 905 * Parameters: 906 * cookie (input) - NDMP session pointer. 907 * name (input) - name of variable. 908 * 909 * Returns: 910 * Pointer to variable value. 911 * 0 if variable not found. 912 * 913 */ 914 char * 915 ndmpd_api_get_env(void *cookie, char *name) 916 { 917 ndmp_pval *envp; 918 919 envp = ndmpd_api_find_env(cookie, name); 920 if (envp) 921 return (envp->value); 922 923 return (NULL); 924 } 925 926 927 /* 928 * ndmpd_api_add_env 929 * 930 * Adds an environment variable name/value pair to the environment 931 * variable list. 932 * 933 * Parameters: 934 * session (input) - session pointer. 935 * name (input) - variable name. 936 * val (input) - value. 937 * 938 * Returns: 939 * 0 - success. 940 * -1 - error. 941 */ 942 int 943 ndmpd_api_add_env(void *cookie, char *name, char *value) 944 { 945 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 946 char *namebuf; 947 char *valbuf; 948 949 if (session == NULL) 950 return (-1); 951 952 session->ns_data.dd_env = realloc((void *)session->ns_data.dd_env, 953 sizeof (ndmp_pval) * (session->ns_data.dd_env_len + 1)); 954 955 if (session->ns_data.dd_env == NULL) { 956 NDMP_LOG(LOG_ERR, "Out of memory."); 957 return (-1); 958 } 959 namebuf = strdup(name); 960 if (namebuf == NULL) 961 return (-1); 962 963 valbuf = strdup(value); 964 if (valbuf == NULL) { 965 free(namebuf); 966 return (-1); 967 } 968 969 (void) mutex_lock(&session->ns_lock); 970 session->ns_data.dd_env[session->ns_data.dd_env_len].name = namebuf; 971 session->ns_data.dd_env[session->ns_data.dd_env_len].value = valbuf; 972 session->ns_data.dd_env_len++; 973 (void) mutex_unlock(&session->ns_lock); 974 975 return (0); 976 } 977 978 979 /* 980 * ndmpd_api_set_env 981 * 982 * Sets an environment variable name/value pair in the environment 983 * variable list. If the variable exists, it gets the new value, 984 * otherwise it's added as a new variable. 985 * 986 * Parameters: 987 * session (input) - session pointer. 988 * name (input) - variable name. 989 * val (input) - value. 990 * 991 * Returns: 992 * 0 - success. 993 * -1 - error. 994 */ 995 int 996 ndmpd_api_set_env(void *cookie, char *name, char *value) 997 { 998 char *valbuf; 999 int rv; 1000 ndmp_pval *envp; 1001 1002 envp = ndmpd_api_find_env(cookie, name); 1003 if (!envp) { 1004 rv = ndmpd_api_add_env(cookie, name, value); 1005 } else if (!(valbuf = strdup(value))) { 1006 rv = -1; 1007 } else { 1008 rv = 0; 1009 free(envp->value); 1010 envp->value = valbuf; 1011 } 1012 1013 return (rv); 1014 } 1015 1016 1017 /* 1018 * ndmpd_api_get_name 1019 * 1020 * Return the name entry at the specified index from the 1021 * recover file name list. 1022 * 1023 * Parameters: 1024 * cookie (input) - NDMP session pointer. 1025 * name_index (input) - index of entry to be returned. 1026 * 1027 * Returns: 1028 * Pointer to name entry. 1029 * 0 if requested entry does not exist. 1030 */ 1031 void * 1032 ndmpd_api_get_name(void *cookie, ulong_t name_index) 1033 { 1034 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 1035 1036 if (session == NULL) 1037 return (NULL); 1038 1039 if (name_index >= session->ns_data.dd_nlist_len) 1040 return (NULL); 1041 1042 return (&session->ns_data.dd_nlist[name_index]); 1043 } 1044 1045 1046 /* 1047 * ndmpd_api_dispatch 1048 * 1049 * Process pending NDMP client requests and check registered files for 1050 * data availability. 1051 * 1052 * Parameters: 1053 * cookie (input) - session pointer. 1054 * block (input) - 1055 * TRUE block until a request has been processed or 1056 * until a file handler has been called. 1057 * FALSE don't block. 1058 * 1059 * Returns: 1060 * -1 - abort request received or connection closed. 1061 * 0 - success. 1062 */ 1063 int 1064 ndmpd_api_dispatch(void *cookie, boolean_t block) 1065 { 1066 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 1067 int err; 1068 1069 if (session == NULL) 1070 return (-1); 1071 1072 for (; ; ) { 1073 err = ndmpd_select(session, block, HC_ALL); 1074 if (err < 0 || session->ns_data.dd_abort == TRUE || 1075 session->ns_eof) 1076 return (-1); 1077 1078 if (err == 0) 1079 return (0); 1080 1081 /* 1082 * Something was processed. 1083 * Set the block flag to false so that we will return as 1084 * soon as everything available to be processed has been 1085 * processed. 1086 */ 1087 block = FALSE; 1088 } 1089 } 1090 1091 1092 /* 1093 * ndmpd_api_add_file_handler 1094 * 1095 * Adds a file handler to the file handler list. 1096 * The file handler list is used by ndmpd_api_dispatch. 1097 * 1098 * Parameters: 1099 * daemon_cookie (input) - session pointer. 1100 * cookie (input) - opaque data to be passed to file hander when called. 1101 * fd (input) - file descriptor. 1102 * mode (input) - bitmask of the following: 1103 * NDMP_SELECT_MODE_READ = watch file for ready for reading 1104 * NDMP_SELECT_MODE_WRITE = watch file for ready for writing 1105 * NDMP_SELECT_MODE_EXCEPTION = watch file for exception 1106 * func (input) - function to call when the file meets one of the 1107 * conditions specified by mode. 1108 * 1109 * Returns: 1110 * 0 - success. 1111 * -1 - error. 1112 */ 1113 int 1114 ndmpd_api_add_file_handler(void *daemon_cookie, void *cookie, int fd, 1115 ulong_t mode, ndmpd_file_handler_func_t *func) 1116 { 1117 ndmpd_session_t *session = (ndmpd_session_t *)daemon_cookie; 1118 1119 return (ndmpd_add_file_handler(session, cookie, fd, mode, HC_MODULE, 1120 func)); 1121 } 1122 1123 1124 /* 1125 * ndmpd_api_remove_file_handler 1126 * 1127 * Removes a file handler from the file handler list. 1128 * 1129 * Parameters: 1130 * cookie (input) - session pointer. 1131 * fd (input) - file descriptor. 1132 * 1133 * Returns: 1134 * 0 - success. 1135 * -1 - error. 1136 */ 1137 int 1138 ndmpd_api_remove_file_handler(void *cookie, int fd) 1139 { 1140 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 1141 1142 return (ndmpd_remove_file_handler(session, fd)); 1143 } 1144