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(session->ns_connection, 275 NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR, 276 (void *)&request, 0) < 0) { 277 NDMP_LOG(LOG_DEBUG, 278 "Sending notify_data_read request"); 279 return (-1); 280 } 281 return (0); 282 } 283 /* Mover is local. */ 284 285 err = ndmpd_mover_seek(session, offset, length); 286 if (err < 0) { 287 ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 288 return (-1); 289 } 290 if (err == 0) 291 return (0); 292 293 /* 294 * NDMP client intervention is required to perform the seek. 295 * Wait for the client to either do the seek and send a continue 296 * request or send an abort request. 297 */ 298 nlp_ref_nw(session); 299 for (; ; ) { 300 nlp_wait_nw(session); 301 302 if (nlp_event_rv_get(session) < 0) { 303 nlp_unref_nw(session); 304 return (-1); 305 } 306 307 if (session->ns_eof == TRUE) { 308 nlp_unref_nw(session); 309 return (-1); 310 } 311 312 switch (session->ns_mover.md_state) { 313 case NDMP_MOVER_STATE_ACTIVE: 314 /* 315 * There is a bug in the original SDK code which 316 * causes to fall in an infinite loop after the 317 * break. 318 */ 319 nlp_unref_nw(session); 320 break; 321 322 case NDMP_MOVER_STATE_PAUSED: 323 continue; 324 325 default: 326 nlp_unref_nw(session); 327 return (-1); 328 } 329 } 330 } 331 332 333 /* 334 * ndmpd_api_file_recovered_v2 335 * 336 * Notify the NDMP client that the specified file was recovered. 337 * 338 * Parameters: 339 * cookie (input) - session pointer. 340 * name (input) - name of recovered file. 341 * error (input) - 0 if file successfully recovered. 342 * otherwise, error code indicating why recovery failed. 343 * 344 * Returns: 345 * void. 346 */ 347 int 348 ndmpd_api_file_recovered_v2(void *cookie, char *name, int error) 349 { 350 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 351 ndmp_log_file_request_v2 request; 352 353 if (session == NULL) 354 return (-1); 355 356 request.name = name; 357 request.ssid = 0; 358 359 switch (error) { 360 case 0: 361 request.error = NDMP_NO_ERR; 362 break; 363 case ENOENT: 364 request.error = NDMP_FILE_NOT_FOUND_ERR; 365 break; 366 default: 367 request.error = NDMP_PERMISSION_ERR; 368 } 369 370 if (ndmp_send_request(session->ns_connection, NDMP_LOG_FILE, 371 NDMP_NO_ERR, (void *)&request, 0) < 0) { 372 NDMP_LOG(LOG_DEBUG, "Sending log file request"); 373 return (-1); 374 } 375 return (0); 376 } 377 378 379 /* 380 * ndmpd_api_write_v2 381 * 382 * Callback function called by the backup/restore module. 383 * Writes data to the mover. 384 * If the mover is remote, the data is written to the data connection. 385 * If the mover is local, the data is buffered and written to the 386 * tape device after a full record has been buffered. 387 * 388 * Parameters: 389 * client_data (input) - session pointer. 390 * data (input) - data to be written. 391 * length (input) - data length. 392 * 393 * Returns: 394 * 0 - data successfully written. 395 * -1 - error. 396 */ 397 int 398 ndmpd_api_write_v2(void *client_data, char *data, ulong_t length) 399 { 400 ndmpd_session_t *session = (ndmpd_session_t *)client_data; 401 402 if (session == NULL) 403 return (-1); 404 405 /* 406 * Write the data to the data connection if the mover is remote. 407 */ 408 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) 409 return (ndmpd_remote_write(session, data, length)); 410 else 411 return (ndmpd_local_write(session, data, length)); 412 } 413 414 415 /* 416 * ************************************************************************ 417 * NDMP V3 CALLBACKS 418 * ************************************************************************ 419 */ 420 421 /* 422 * ndmpd_api_done_v3 423 * 424 * Called when the data module has completed. 425 * Sends a notify_halt request to the NDMP client. 426 * 427 * Parameters: 428 * session (input) - session pointer. 429 * err (input) - UNIX error code. 430 * 431 * Returns: 432 * void 433 */ 434 void 435 ndmpd_api_done_v3(void *cookie, int err) 436 { 437 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 438 ndmp_data_halt_reason reason; 439 440 switch (err) { 441 case 0: 442 reason = NDMP_DATA_HALT_SUCCESSFUL; 443 break; 444 445 case EINTR: 446 reason = NDMP_DATA_HALT_ABORTED; 447 break; 448 449 case EIO: 450 reason = NDMP_DATA_HALT_CONNECT_ERROR; 451 break; 452 453 default: 454 reason = NDMP_DATA_HALT_INTERNAL_ERROR; 455 } 456 457 ndmpd_data_error(session, reason); 458 } 459 460 /* 461 * ndmpd_api_log_v3 462 * 463 * Sends a log request to the NDMP client. 464 * 465 * Parameters: 466 * cookie (input) - session pointer. 467 * format (input) - printf style format. 468 * ... (input) - format arguments. 469 * 470 * Returns: 471 * 0 - success. 472 * -1 - error. 473 */ 474 /*ARGSUSED*/ 475 int 476 ndmpd_api_log_v3(void *cookie, ndmp_log_type type, ulong_t msg_id, 477 char *format, ...) 478 { 479 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 480 ndmp_log_message_request_v3 request; 481 static char buf[1024]; 482 va_list ap; 483 484 if (session == NULL) 485 return (-1); 486 487 va_start(ap, format); 488 489 /*LINTED variable format specifier */ 490 (void) vsnprintf(buf, sizeof (buf), format, ap); 491 va_end(ap); 492 493 request.entry = buf; 494 request.log_type = type; 495 request.message_id = msg_id; 496 497 if (ndmp_send_request(session->ns_connection, NDMP_LOG_MESSAGE, 498 NDMP_NO_ERR, (void *)&request, 0) < 0) { 499 NDMP_LOG(LOG_DEBUG, "Error sending log message request."); 500 return (-1); 501 } 502 return (0); 503 } 504 505 506 /* 507 * ndmpd_api_write_v3 508 * 509 * Callback function called by the backup/restore module. 510 * Writes data to the mover. 511 * If the mover is remote, the data is written to the data connection. 512 * If the mover is local, the data is buffered and written to the 513 * tape device after a full record has been buffered. 514 * 515 * Parameters: 516 * client_data (input) - session pointer. 517 * data (input) - data to be written. 518 * length (input) - data length. 519 * 520 * Returns: 521 * 0 - data successfully written. 522 * -1 - error. 523 */ 524 int 525 ndmpd_api_write_v3(void *client_data, char *data, ulong_t length) 526 { 527 ndmpd_session_t *session = (ndmpd_session_t *)client_data; 528 529 if (session == NULL) 530 return (-1); 531 532 /* 533 * Write the data to the tape if the mover is local, otherwise, 534 * write the data to the data connection. 535 * 536 * The same write function for of v2 can be used in V3 537 * for writing data to the data connection to the mover. 538 * So we don't need ndmpd_remote_write_v3(). 539 */ 540 if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL) 541 return (ndmpd_local_write_v3(session, data, length)); 542 else 543 return (ndmpd_remote_write(session, data, length)); 544 } 545 546 547 /* 548 * ndmpd_api_read_v3 549 * 550 * Callback function called by the backup/recover module. 551 * Reads data from the mover. 552 * If the mover is remote, the data is read from the data connection. 553 * If the mover is local, the data is read from the tape device. 554 * 555 * Parameters: 556 * client_data (input) - session pointer. 557 * data (input) - data to be written. 558 * length (input) - data length. 559 * 560 * Returns: 561 * 0 - data successfully read. 562 * -1 - error. 563 * 1 - session terminated or operation aborted. 564 */ 565 int 566 ndmpd_api_read_v3(void *client_data, char *data, ulong_t length) 567 { 568 ndmpd_session_t *session = (ndmpd_session_t *)client_data; 569 570 if (session == NULL) 571 return (-1); 572 573 /* 574 * Read the data from the data connection if the mover is remote. 575 */ 576 if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL) 577 return (ndmpd_local_read_v3(session, data, length)); 578 else 579 return (ndmpd_remote_read_v3(session, data, length)); 580 } 581 582 583 /* 584 * ndmpd_api_get_name_v3 585 * 586 * Return the name entry at the specified index from the 587 * recover file name list. 588 * 589 * Parameters: 590 * cookie (input) - NDMP session pointer. 591 * name_index (input) - index of entry to be returned. 592 * 593 * Returns: 594 * Pointer to name entry. 595 * 0 if requested entry does not exist. 596 */ 597 void * 598 ndmpd_api_get_name_v3(void *cookie, ulong_t name_index) 599 { 600 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 601 602 if (session == NULL) 603 return (NULL); 604 605 if (name_index >= session->ns_data.dd_nlist_len) 606 return (NULL); 607 608 return (&session->ns_data.dd_nlist_v3[name_index]); 609 } 610 611 612 /* 613 * ndmpd_api_file_recovered_v3 614 * 615 * Notify the NDMP client that the specified file was recovered. 616 * 617 * Parameters: 618 * cookie (input) - session pointer. 619 * name (input) - name of recovered file. 620 * ssid (input) - selection set id. 621 * error (input) - 0 if file successfully recovered. 622 * otherwise, error code indicating why recovery failed. 623 * 624 * Returns: 625 * 0 - success. 626 * -1 - error. 627 */ 628 int 629 ndmpd_api_file_recovered_v3(void *cookie, char *name, int error) 630 { 631 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 632 ndmp_log_file_request_v3 request; 633 634 if (session == NULL) 635 return (-1); 636 637 request.name = name; 638 639 switch (error) { 640 case 0: 641 request.error = NDMP_NO_ERR; 642 break; 643 case ENOENT: 644 request.error = NDMP_FILE_NOT_FOUND_ERR; 645 break; 646 default: 647 request.error = NDMP_PERMISSION_ERR; 648 } 649 650 if (ndmp_send_request(session->ns_connection, NDMP_LOG_FILE, 651 NDMP_NO_ERR, (void *)&request, 0) < 0) { 652 NDMP_LOG(LOG_DEBUG, "Error sending log file request"); 653 return (-1); 654 } 655 656 return (0); 657 } 658 659 660 /* 661 * ndmpd_api_seek_v3 662 * 663 * Seek to the specified position in the data stream and start a 664 * read for the specified amount of data. 665 * 666 * Parameters: 667 * cookie (input) - session pointer. 668 * offset (input) - stream position to seek to. 669 * length (input) - amount of data that will be read using ndmpd_api_read 670 * 671 * Returns: 672 * 0 - seek successful. 673 * 1 - seek needed DMA(client) intervention. 674 * -1 - error. 675 */ 676 int 677 ndmpd_api_seek_v3(void *cookie, u_longlong_t offset, u_longlong_t length) 678 { 679 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 680 int err; 681 ndmp_notify_data_read_request request; 682 683 if (session == NULL) 684 return (-1); 685 686 session->ns_data.dd_read_offset = offset; 687 session->ns_data.dd_read_length = length; 688 689 /* 690 * Send a notify_data_read request if the mover is remote. 691 */ 692 if (session->ns_data.dd_data_addr.addr_type != NDMP_ADDR_LOCAL) { 693 session->ns_data.dd_discard_length = 694 session->ns_data.dd_bytes_left_to_read; 695 session->ns_data.dd_bytes_left_to_read = length; 696 session->ns_data.dd_position = offset; 697 698 request.offset = long_long_to_quad(offset); 699 request.length = long_long_to_quad(length); 700 701 if (ndmp_send_request(session->ns_connection, 702 NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR, 703 (void *)&request, 0) < 0) { 704 NDMP_LOG(LOG_DEBUG, 705 "Sending notify_data_read request"); 706 return (-1); 707 } 708 709 return (0); 710 } 711 712 /* Mover is local. */ 713 714 err = ndmpd_mover_seek(session, offset, length); 715 if (err < 0) { 716 ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 717 return (-1); 718 } 719 720 if (err == 0) 721 return (0); 722 723 /* 724 * NDMP client intervention is required to perform the seek. 725 * Wait for the client to either do the seek and send a continue 726 * request or send an abort request. 727 */ 728 err = ndmpd_mover_wait_v3(session); 729 730 /* 731 * If we needed a client intervention, then we should be able to 732 * detect this in DAR. 733 */ 734 if (err == 0) 735 err = 1; 736 return (err); 737 } 738 739 740 /* 741 * ************************************************************************ 742 * NDMP V4 CALLBACKS 743 * ************************************************************************ 744 */ 745 746 /* 747 * ndmpd_api_log_v4 748 * 749 * Sends a log request to the NDMP client. 750 * No message association is supported now, but can be added later on 751 * in this function. 752 * 753 * Parameters: 754 * cookie (input) - session pointer. 755 * format (input) - printf style format. 756 * ... (input) - format arguments. 757 * 758 * Returns: 759 * 0 - success. 760 * -1 - error. 761 */ 762 /*ARGSUSED*/ 763 int 764 ndmpd_api_log_v4(void *cookie, ndmp_log_type type, ulong_t msg_id, 765 char *format, ...) 766 { 767 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 768 ndmp_log_message_request_v4 request; 769 static char buf[1024]; 770 va_list ap; 771 772 if (session == NULL) 773 return (-1); 774 775 va_start(ap, format); 776 777 /*LINTED variable format specifier */ 778 (void) vsnprintf(buf, sizeof (buf), format, ap); 779 va_end(ap); 780 781 request.entry = buf; 782 request.log_type = type; 783 request.message_id = msg_id; 784 request.associated_message_valid = NDMP_NO_ASSOCIATED_MESSAGE; 785 request.associated_message_sequence = 0; 786 787 if (ndmp_send_request(session->ns_connection, NDMP_LOG_MESSAGE, 788 NDMP_NO_ERR, (void *)&request, 0) < 0) { 789 NDMP_LOG(LOG_DEBUG, "Error sending log message request."); 790 return (-1); 791 } 792 return (0); 793 } 794 795 796 /* 797 * ndmpd_api_file_recovered_v4 798 * 799 * Notify the NDMP client that the specified file was recovered. 800 * 801 * Parameters: 802 * cookie (input) - session pointer. 803 * name (input) - name of recovered file. 804 * ssid (input) - selection set id. 805 * error (input) - 0 if file successfully recovered. 806 * otherwise, error code indicating why recovery failed. 807 * 808 * Returns: 809 * void. 810 */ 811 int 812 ndmpd_api_file_recovered_v4(void *cookie, char *name, int error) 813 { 814 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 815 ndmp_log_file_request_v4 request; 816 817 if (session == NULL) 818 return (-1); 819 820 request.name = name; 821 822 switch (error) { 823 case 0: 824 request.recovery_status = NDMP_RECOVERY_SUCCESSFUL; 825 break; 826 case EPERM: 827 request.recovery_status = NDMP_RECOVERY_FAILED_PERMISSION; 828 break; 829 case ENOENT: 830 request.recovery_status = NDMP_RECOVERY_FAILED_NOT_FOUND; 831 break; 832 case ENOTDIR: 833 request.recovery_status = NDMP_RECOVERY_FAILED_NO_DIRECTORY; 834 break; 835 case ENOMEM: 836 request.recovery_status = NDMP_RECOVERY_FAILED_OUT_OF_MEMORY; 837 break; 838 case EIO: 839 request.recovery_status = NDMP_RECOVERY_FAILED_IO_ERROR; 840 break; 841 case EEXIST: 842 request.recovery_status = NDMP_RECOVERY_FAILED_FILE_PATH_EXISTS; 843 break; 844 default: 845 request.recovery_status = NDMP_RECOVERY_FAILED_UNDEFINED_ERROR; 846 break; 847 } 848 849 if (ndmp_send_request(session->ns_connection, NDMP_LOG_FILE, 850 NDMP_NO_ERR, (void *)&request, 0) < 0) { 851 NDMP_LOG(LOG_DEBUG, "Error sending log file request"); 852 return (-1); 853 } 854 855 return (0); 856 } 857 858 859 /* 860 * ************************************************************************ 861 * LOCALS 862 * ************************************************************************ 863 */ 864 865 /* 866 * ndmpd_api_find_env 867 * 868 * Return the pointer of the environment variable from the variable 869 * array for the spcified environment variable. 870 * 871 * Parameters: 872 * cookie (input) - NDMP session pointer. 873 * name (input) - name of variable. 874 * 875 * Returns: 876 * Pointer to variable. 877 * NULL if variable not found. 878 * 879 */ 880 ndmp_pval * 881 ndmpd_api_find_env(void *cookie, char *name) 882 { 883 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 884 ulong_t i; 885 ndmp_pval *envp; 886 887 if (session == NULL) 888 return (NULL); 889 890 envp = session->ns_data.dd_env; 891 for (i = 0; envp && i < session->ns_data.dd_env_len; envp++, i++) 892 if (strcmp(name, envp->name) == NULL) 893 return (envp); 894 895 return (NULL); 896 } 897 898 899 /* 900 * ndmpd_api_get_env 901 * 902 * Return the value of an environment variable from the variable array. 903 * 904 * Parameters: 905 * cookie (input) - NDMP session pointer. 906 * name (input) - name of variable. 907 * 908 * Returns: 909 * Pointer to variable value. 910 * 0 if variable not found. 911 * 912 */ 913 char * 914 ndmpd_api_get_env(void *cookie, char *name) 915 { 916 ndmp_pval *envp; 917 918 envp = ndmpd_api_find_env(cookie, name); 919 if (envp) 920 return (envp->value); 921 922 return (NULL); 923 } 924 925 926 /* 927 * ndmpd_api_add_env 928 * 929 * Adds an environment variable name/value pair to the environment 930 * variable list. 931 * 932 * Parameters: 933 * session (input) - session pointer. 934 * name (input) - variable name. 935 * val (input) - value. 936 * 937 * Returns: 938 * 0 - success. 939 * -1 - error. 940 */ 941 int 942 ndmpd_api_add_env(void *cookie, char *name, char *value) 943 { 944 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 945 char *namebuf; 946 char *valbuf; 947 948 if (session == NULL) 949 return (-1); 950 951 session->ns_data.dd_env = realloc((void *)session->ns_data.dd_env, 952 sizeof (ndmp_pval) * (session->ns_data.dd_env_len + 1)); 953 954 if (session->ns_data.dd_env == NULL) { 955 NDMP_LOG(LOG_ERR, "Out of memory."); 956 return (-1); 957 } 958 namebuf = strdup(name); 959 if (namebuf == NULL) 960 return (-1); 961 962 valbuf = strdup(value); 963 if (valbuf == NULL) { 964 free(namebuf); 965 return (-1); 966 } 967 968 (void) mutex_lock(&session->ns_lock); 969 session->ns_data.dd_env[session->ns_data.dd_env_len].name = namebuf; 970 session->ns_data.dd_env[session->ns_data.dd_env_len].value = valbuf; 971 session->ns_data.dd_env_len++; 972 (void) mutex_unlock(&session->ns_lock); 973 974 return (0); 975 } 976 977 978 /* 979 * ndmpd_api_set_env 980 * 981 * Sets an environment variable name/value pair in the environment 982 * variable list. If the variable exists, it gets the new value, 983 * otherwise it's added as a new variable. 984 * 985 * Parameters: 986 * session (input) - session pointer. 987 * name (input) - variable name. 988 * val (input) - value. 989 * 990 * Returns: 991 * 0 - success. 992 * -1 - error. 993 */ 994 int 995 ndmpd_api_set_env(void *cookie, char *name, char *value) 996 { 997 char *valbuf; 998 int rv; 999 ndmp_pval *envp; 1000 1001 envp = ndmpd_api_find_env(cookie, name); 1002 if (!envp) { 1003 rv = ndmpd_api_add_env(cookie, name, value); 1004 } else if (!(valbuf = strdup(value))) { 1005 rv = -1; 1006 } else { 1007 rv = 0; 1008 free(envp->value); 1009 envp->value = valbuf; 1010 } 1011 1012 return (rv); 1013 } 1014 1015 1016 /* 1017 * ndmpd_api_get_name 1018 * 1019 * Return the name entry at the specified index from the 1020 * recover file name list. 1021 * 1022 * Parameters: 1023 * cookie (input) - NDMP session pointer. 1024 * name_index (input) - index of entry to be returned. 1025 * 1026 * Returns: 1027 * Pointer to name entry. 1028 * 0 if requested entry does not exist. 1029 */ 1030 void * 1031 ndmpd_api_get_name(void *cookie, ulong_t name_index) 1032 { 1033 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 1034 1035 if (session == NULL) 1036 return (NULL); 1037 1038 if (name_index >= session->ns_data.dd_nlist_len) 1039 return (NULL); 1040 1041 return (&session->ns_data.dd_nlist[name_index]); 1042 } 1043 1044 1045 /* 1046 * ndmpd_api_dispatch 1047 * 1048 * Process pending NDMP client requests and check registered files for 1049 * data availability. 1050 * 1051 * Parameters: 1052 * cookie (input) - session pointer. 1053 * block (input) - 1054 * TRUE block until a request has been processed or 1055 * until a file handler has been called. 1056 * FALSE don't block. 1057 * 1058 * Returns: 1059 * -1 - abort request received or connection closed. 1060 * 0 - success. 1061 */ 1062 int 1063 ndmpd_api_dispatch(void *cookie, boolean_t block) 1064 { 1065 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 1066 int err; 1067 1068 if (session == NULL) 1069 return (-1); 1070 1071 for (; ; ) { 1072 err = ndmpd_select(session, block, HC_ALL); 1073 if (err < 0 || session->ns_data.dd_abort == TRUE || 1074 session->ns_eof) 1075 return (-1); 1076 1077 if (err == 0) 1078 return (0); 1079 1080 /* 1081 * Something was processed. 1082 * Set the block flag to false so that we will return as 1083 * soon as everything available to be processed has been 1084 * processed. 1085 */ 1086 block = FALSE; 1087 } 1088 } 1089 1090 1091 /* 1092 * ndmpd_api_add_file_handler 1093 * 1094 * Adds a file handler to the file handler list. 1095 * The file handler list is used by ndmpd_api_dispatch. 1096 * 1097 * Parameters: 1098 * daemon_cookie (input) - session pointer. 1099 * cookie (input) - opaque data to be passed to file hander when called. 1100 * fd (input) - file descriptor. 1101 * mode (input) - bitmask of the following: 1102 * NDMP_SELECT_MODE_READ = watch file for ready for reading 1103 * NDMP_SELECT_MODE_WRITE = watch file for ready for writing 1104 * NDMP_SELECT_MODE_EXCEPTION = watch file for exception 1105 * func (input) - function to call when the file meets one of the 1106 * conditions specified by mode. 1107 * 1108 * Returns: 1109 * 0 - success. 1110 * -1 - error. 1111 */ 1112 int 1113 ndmpd_api_add_file_handler(void *daemon_cookie, void *cookie, int fd, 1114 ulong_t mode, ndmpd_file_handler_func_t *func) 1115 { 1116 ndmpd_session_t *session = (ndmpd_session_t *)daemon_cookie; 1117 1118 return (ndmpd_add_file_handler(session, cookie, fd, mode, HC_MODULE, 1119 func)); 1120 } 1121 1122 1123 /* 1124 * ndmpd_api_remove_file_handler 1125 * 1126 * Removes a file handler from the file handler list. 1127 * 1128 * Parameters: 1129 * cookie (input) - session pointer. 1130 * fd (input) - file descriptor. 1131 * 1132 * Returns: 1133 * 0 - success. 1134 * -1 - error. 1135 */ 1136 int 1137 ndmpd_api_remove_file_handler(void *cookie, int fd) 1138 { 1139 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 1140 1141 return (ndmpd_remove_file_handler(session, fd)); 1142 } 1143