Print this page
NEX-2911 NDMP logging should use syslog and is too chatty
NEX-559 NDMP cannot backup/restore a file which spans multiple tapes
   1 /*
   2  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.

   3  */
   4 
   5 /*
   6  * BSD 3 Clause License
   7  *
   8  * Copyright (c) 2007, The Storage Networking Industry Association.
   9  *
  10  * Redistribution and use in source and binary forms, with or without
  11  * modification, are permitted provided that the following conditions
  12  * are met:
  13  *      - Redistributions of source code must retain the above copyright
  14  *        notice, this list of conditions and the following disclaimer.
  15  *
  16  *      - Redistributions in binary form must reproduce the above copyright
  17  *        notice, this list of conditions and the following disclaimer in
  18  *        the documentation and/or other materials provided with the
  19  *        distribution.
  20  *
  21  *      - Neither the name of The Storage Networking Industry Association (SNIA)
  22  *        nor the names of its contributors may be used to endorse or promote
  23  *        products derived from this software without specific prior written
  24  *        permission.
  25  *
  26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36  * POSSIBILITY OF SUCH DAMAGE.
  37  */
  38 /* Copyright (c) 2007, The Storage Networking Industry Association. */
  39 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
  40 /* Copyright 2014 Nexenta Systems, Inc. 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  * ************************************************************************


  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  *


 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  *


 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          */


 322 
 323         if (session == NULL)
 324                 return (-1);
 325 
 326         request.name = name;
 327         request.ssid = 0;
 328 
 329         switch (error) {
 330         case 0:
 331                 request.error = NDMP_NO_ERR;
 332                 break;
 333         case ENOENT:
 334                 request.error = NDMP_FILE_NOT_FOUND_ERR;
 335                 break;
 336         default:
 337                 request.error = NDMP_PERMISSION_ERR;
 338         }
 339 
 340         if (ndmp_send_request_lock(session->ns_connection, NDMP_LOG_FILE,
 341             NDMP_NO_ERR, (void *)&request, 0) < 0) {
 342                 NDMP_LOG(LOG_DEBUG, "Sending log file request");
 343                 return (-1);
 344         }
 345         return (0);
 346 }
 347 
 348 
 349 /*
 350  * ndmpd_api_write_v2
 351  *
 352  * Callback function called by the backup/restore module.
 353  * Writes data to the mover.
 354  * If the mover is remote, the data is written to the data connection.
 355  * If the mover is local, the data is buffered and written to the
 356  * tape device after a full record has been buffered.
 357  *
 358  * Parameters:
 359  *   client_data (input) - session pointer.
 360  *   data       (input) - data to be written.
 361  *   length     (input) - data length.
 362  *


 449         ndmpd_session_t *session = (ndmpd_session_t *)cookie;
 450         ndmp_log_message_request_v3 request;
 451         static char buf[1024];
 452         va_list ap;
 453 
 454         if (session == NULL)
 455                 return (-1);
 456 
 457         va_start(ap, format);
 458 
 459         /*LINTED variable format specifier */
 460         (void) vsnprintf(buf, sizeof (buf), format, ap);
 461         va_end(ap);
 462 
 463         request.entry = buf;
 464         request.log_type = type;
 465         request.message_id = msg_id;
 466 
 467         if (ndmp_send_request(session->ns_connection, NDMP_LOG_MESSAGE,
 468             NDMP_NO_ERR, (void *)&request, 0) < 0) {
 469                 NDMP_LOG(LOG_DEBUG, "Error sending log message request.");
 470                 return (-1);
 471         }
 472         return (0);
 473 }
 474 
 475 
 476 /*
 477  * ndmpd_api_write_v3
 478  *
 479  * Callback function called by the backup/restore module.
 480  * Writes data to the mover.
 481  * If the mover is remote, the data is written to the data connection.
 482  * If the mover is local, the data is buffered and written to the
 483  * tape device after a full record has been buffered.
 484  *
 485  * Parameters:
 486  *   client_data (input) - session pointer.
 487  *   data       (input) - data to be written.
 488  *   length     (input) - data length.
 489  *


 602         ndmp_log_file_request_v3 request;
 603 
 604         if (session == NULL)
 605                 return (-1);
 606 
 607         request.name  = name;
 608 
 609         switch (error) {
 610         case 0:
 611                 request.error = NDMP_NO_ERR;
 612                 break;
 613         case ENOENT:
 614                 request.error = NDMP_FILE_NOT_FOUND_ERR;
 615                 break;
 616         default:
 617                 request.error = NDMP_PERMISSION_ERR;
 618         }
 619 
 620         if (ndmp_send_request_lock(session->ns_connection, NDMP_LOG_FILE,
 621             NDMP_NO_ERR, (void *)&request, 0) < 0) {
 622                 NDMP_LOG(LOG_DEBUG, "Error sending log file request");
 623                 return (-1);
 624         }
 625 
 626         return (0);
 627 }
 628 
 629 
 630 /*
 631  * ndmpd_api_seek_v3
 632  *
 633  * Seek to the specified position in the data stream and start a
 634  * read for the specified amount of data.
 635  *
 636  * Parameters:
 637  *   cookie (input) - session pointer.
 638  *   offset (input) - stream position to seek to.
 639  *   length (input) - amount of data that will be read using ndmpd_api_read
 640  *
 641  * Returns:
 642  *   0 - seek successful.


 654                 return (-1);
 655 
 656         session->ns_data.dd_read_offset = offset;
 657         session->ns_data.dd_read_length = length;
 658 
 659         /*
 660          * Send a notify_data_read request if the mover is remote.
 661          */
 662         if (session->ns_data.dd_data_addr.addr_type != NDMP_ADDR_LOCAL) {
 663                 session->ns_data.dd_discard_length =
 664                     session->ns_data.dd_bytes_left_to_read;
 665                 session->ns_data.dd_bytes_left_to_read = length;
 666                 session->ns_data.dd_position = offset;
 667 
 668                 request.offset = long_long_to_quad(offset);
 669                 request.length = long_long_to_quad(length);
 670 
 671                 if (ndmp_send_request_lock(session->ns_connection,
 672                     NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR,
 673                     (void *)&request, 0) < 0) {
 674                         NDMP_LOG(LOG_DEBUG,
 675                             "Sending notify_data_read request");
 676                         return (-1);
 677                 }
 678 
 679                 return (0);
 680         }
 681 
 682         /* Mover is local. */
 683 
 684         err = ndmpd_mover_seek(session, offset, length);
 685         if (err < 0) {
 686                 ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR);
 687                 return (-1);
 688         }
 689 
 690         if (err == 0)
 691                 return (0);
 692 
 693         /*
 694          * NDMP client intervention is required to perform the seek.


 739         static char buf[1024];
 740         va_list ap;
 741 
 742         if (session == NULL)
 743                 return (-1);
 744 
 745         va_start(ap, format);
 746 
 747         /*LINTED variable format specifier */
 748         (void) vsnprintf(buf, sizeof (buf), format, ap);
 749         va_end(ap);
 750 
 751         request.entry = buf;
 752         request.log_type = type;
 753         request.message_id = msg_id;
 754         request.associated_message_valid = NDMP_NO_ASSOCIATED_MESSAGE;
 755         request.associated_message_sequence = 0;
 756 
 757         if (ndmp_send_request(session->ns_connection, NDMP_LOG_MESSAGE,
 758             NDMP_NO_ERR, (void *)&request, 0) < 0) {
 759                 NDMP_LOG(LOG_DEBUG, "Error sending log message request.");
 760                 return (-1);
 761         }
 762         return (0);
 763 }
 764 
 765 
 766 /*
 767  * ndmpd_api_file_recovered_v4
 768  *
 769  * Notify the NDMP client that the specified file was recovered.
 770  *
 771  * Parameters:
 772  *   cookie (input) - session pointer.
 773  *   name   (input) - name of recovered file.
 774  *   ssid   (input) - selection set id.
 775  *   error  (input) - 0 if file successfully recovered.
 776  *                  otherwise, error code indicating why recovery failed.
 777  *
 778  * Returns:
 779  *   void.


 801                 break;
 802         case ENOTDIR:
 803                 request.recovery_status = NDMP_RECOVERY_FAILED_NO_DIRECTORY;
 804                 break;
 805         case ENOMEM:
 806                 request.recovery_status = NDMP_RECOVERY_FAILED_OUT_OF_MEMORY;
 807                 break;
 808         case EIO:
 809                 request.recovery_status = NDMP_RECOVERY_FAILED_IO_ERROR;
 810                 break;
 811         case EEXIST:
 812                 request.recovery_status = NDMP_RECOVERY_FAILED_FILE_PATH_EXISTS;
 813                 break;
 814         default:
 815                 request.recovery_status = NDMP_RECOVERY_FAILED_UNDEFINED_ERROR;
 816                 break;
 817         }
 818 
 819         if (ndmp_send_request_lock(session->ns_connection, NDMP_LOG_FILE,
 820             NDMP_NO_ERR, (void *)&request, 0) < 0) {
 821                 NDMP_LOG(LOG_DEBUG, "Error sending log file request");
 822                 return (-1);
 823         }
 824 
 825         return (0);
 826 }
 827 
 828 
 829 /*
 830  * ************************************************************************
 831  * LOCALS
 832  * ************************************************************************
 833  */
 834 
 835 /*
 836  * ndmpd_api_find_env
 837  *
 838  * Return the pointer of the environment variable from the variable
 839  * array for the spcified environment variable.
 840  *
 841  * Parameters:


 905  *   val     (input) - value.
 906  *
 907  * Returns:
 908  *   0 - success.
 909  *  -1 - error.
 910  */
 911 int
 912 ndmpd_api_add_env(void *cookie, char *name, char *value)
 913 {
 914         ndmpd_session_t *session = (ndmpd_session_t *)cookie;
 915         char *namebuf;
 916         char *valbuf;
 917 
 918         if (session == NULL)
 919                 return (-1);
 920 
 921         session->ns_data.dd_env = realloc((void *)session->ns_data.dd_env,
 922             sizeof (ndmp_pval) * (session->ns_data.dd_env_len + 1));
 923 
 924         if (session->ns_data.dd_env == NULL) {
 925                 NDMP_LOG(LOG_ERR, "Out of memory.");
 926                 return (-1);
 927         }
 928         namebuf = strdup(name);
 929         if (namebuf == NULL)
 930                 return (-1);
 931 
 932         valbuf = strdup(value);
 933         if (valbuf == NULL) {
 934                 free(namebuf);
 935                 return (-1);
 936         }
 937 
 938         (void) mutex_lock(&session->ns_lock);
 939         session->ns_data.dd_env[session->ns_data.dd_env_len].name = namebuf;
 940         session->ns_data.dd_env[session->ns_data.dd_env_len].value = valbuf;
 941         session->ns_data.dd_env_len++;
 942         (void) mutex_unlock(&session->ns_lock);
 943 
 944         return (0);
 945 }


   1 /*
   2  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
   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 /* Copyright 2014 Nexenta Systems, Inc. All rights reserved. */
  42 
  43 #include <sys/types.h>
  44 #include <syslog.h>
  45 #include <stdlib.h>
  46 #include <errno.h>
  47 #include <stdarg.h>
  48 #include <stdio.h>
  49 #include <string.h>
  50 #include "ndmpd.h"
  51 
  52 
  53 /*
  54  * Message Id counter.  This number is increased by MOD_LOGV3 macro.
  55  * MOD_LOGCONTV3 macro uses the number generated by the last MOD_LOGV3.
  56  *
  57  */
  58 int ndmp_log_msg_id = 0;
  59 
  60 
  61 /*
  62  * ************************************************************************
  63  * NDMP V2 CALLBACKS
  64  * ************************************************************************


  73  * Parameters:
  74  *   session (input) - session pointer.
  75  *   err     (input) - UNIX error code.
  76  *
  77  * Returns:
  78  *   void
  79  */
  80 void
  81 ndmpd_api_done_v2(void *cookie, int err)
  82 {
  83         ndmpd_session_t *session = (ndmpd_session_t *)cookie;
  84         ndmp_notify_data_halted_request req_v2;
  85 
  86         if (session == NULL)
  87                 return;
  88 
  89         if (session->ns_data.dd_state == NDMP_DATA_STATE_IDLE ||
  90             session->ns_data.dd_state == NDMP_DATA_STATE_HALTED)
  91                 return;
  92 
  93         syslog(LOG_DEBUG, "data.operation: %d",
  94             session->ns_data.dd_operation);
  95 
  96         if (session->ns_data.dd_operation == NDMP_DATA_OP_BACKUP) {
  97                 /*
  98                  * Send/discard any buffered file history data.
  99                  */
 100                 ndmpd_file_history_cleanup(session, (err == 0 ? TRUE : FALSE));
 101 
 102                 /*
 103                  * If mover local and successfull backup, write any
 104                  * remaining buffered data to tape.
 105                  */
 106                 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_LOCAL &&
 107                     err == 0) {
 108                         if (ndmpd_local_write(session, 0, 0) < 0)
 109                                 err = EIO;
 110                 }
 111         }
 112 
 113         session->ns_data.dd_state = NDMP_DATA_STATE_HALTED;
 114 
 115         switch (err) {
 116         case 0:
 117                 session->ns_data.dd_halt_reason = NDMP_DATA_HALT_SUCCESSFUL;
 118                 break;
 119         case EINTR:
 120                 session->ns_data.dd_halt_reason = NDMP_DATA_HALT_ABORTED;
 121                 break;
 122         case EIO:
 123                 session->ns_data.dd_halt_reason = NDMP_DATA_HALT_CONNECT_ERROR;
 124                 break;
 125         default:
 126                 session->ns_data.dd_halt_reason = NDMP_DATA_HALT_INTERNAL_ERROR;
 127         }
 128 
 129         req_v2.reason = session->ns_data.dd_halt_reason;
 130         req_v2.text_reason = "";
 131 
 132         syslog(LOG_DEBUG, "ndmp_send_request(NDMP_NOTIFY_DATA_HALTED)");
 133 
 134         if (ndmp_send_request_lock(session->ns_connection,
 135             NDMP_NOTIFY_DATA_HALTED, NDMP_NO_ERR, (void *)&req_v2, 0) < 0)
 136                 syslog(LOG_DEBUG, "Sending notify_data_halted request");
 137 
 138         if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
 139 
 140                 if (session->ns_mover.md_sock != session->ns_data.dd_sock) {
 141                         (void) close(session->ns_data.dd_sock);
 142                 } else {
 143                         syslog(LOG_DEBUG, "Not closing as used by mover");
 144                 }
 145 
 146                 session->ns_data.dd_sock = -1;
 147         } else {
 148                 ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED);
 149         }
 150 }
 151 
 152 
 153 /*
 154  * ndmpd_api_log_v2
 155  *
 156  * Sends a log request to the NDMP client.
 157  *
 158  * Parameters:
 159  *   cookie (input) - session pointer.
 160  *   str    (input) - null terminated string
 161  *   format (input) - printf style format.
 162  *   ...    (input) - format arguments.
 163  *


 171 {
 172         ndmpd_session_t *session = (ndmpd_session_t *)cookie;
 173         ndmp_log_log_request request;
 174         static char buf[1024];
 175         va_list ap;
 176 
 177         if (session == NULL)
 178                 return (-1);
 179 
 180         va_start(ap, format);
 181 
 182         /*LINTED variable format specifier */
 183         (void) vsnprintf(buf, sizeof (buf), format, ap);
 184         va_end(ap);
 185 
 186         request.entry = buf;
 187 
 188 
 189         if (ndmp_send_request(session->ns_connection, _NDMP_LOG_LOG,
 190             NDMP_NO_ERR, (void *)&request, 0) < 0) {
 191                 syslog(LOG_ERR, "Sending log request");
 192                 return (-1);
 193         }
 194         return (0);
 195 
 196 }
 197 
 198 
 199 /*
 200  * ndmpd_api_read_v2
 201  *
 202  * Callback function called by the backup/recover module.
 203  * Reads data from the mover.
 204  * If the mover is remote, the data is read from the data connection.
 205  * If the mover is local, the data is read from the tape device.
 206  *
 207  * Parameters:
 208  *   client_data (input) - session pointer.
 209  *   data       (input) - data to be written.
 210  *   length     (input) - data length.
 211  *


 260         session->ns_data.dd_read_length = length;
 261 
 262         /*
 263          * Send a notify_data_read request if the mover is remote.
 264          */
 265         if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
 266                 ndmp_notify_data_read_request request;
 267 
 268                 session->ns_mover.md_discard_length =
 269                     session->ns_mover.md_bytes_left_to_read;
 270                 session->ns_mover.md_bytes_left_to_read = length;
 271                 session->ns_mover.md_position = offset;
 272 
 273                 request.offset = long_long_to_quad(offset);
 274                 request.length = long_long_to_quad(length);
 275 
 276                 if (ndmp_send_request_lock(session->ns_connection,
 277                     NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR,
 278                     (void *)&request, 0) < 0) {
 279 
 280                         syslog(LOG_ERR,
 281                             "Sending notify_data_read request");
 282                         return (-1);
 283                 }
 284                 return (0);
 285         }
 286         /* Mover is local. */
 287 
 288         err = ndmpd_mover_seek(session, offset, length);
 289         if (err < 0) {
 290                 ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR);
 291                 return (-1);
 292         }
 293         if (err == 0)
 294                 return (0);
 295 
 296         /*
 297          * NDMP client intervention is required to perform the seek.
 298          * Wait for the client to either do the seek and send a continue
 299          * request or send an abort request.
 300          */


 324 
 325         if (session == NULL)
 326                 return (-1);
 327 
 328         request.name = name;
 329         request.ssid = 0;
 330 
 331         switch (error) {
 332         case 0:
 333                 request.error = NDMP_NO_ERR;
 334                 break;
 335         case ENOENT:
 336                 request.error = NDMP_FILE_NOT_FOUND_ERR;
 337                 break;
 338         default:
 339                 request.error = NDMP_PERMISSION_ERR;
 340         }
 341 
 342         if (ndmp_send_request_lock(session->ns_connection, NDMP_LOG_FILE,
 343             NDMP_NO_ERR, (void *)&request, 0) < 0) {
 344                 syslog(LOG_ERR, "Sending log file request");
 345                 return (-1);
 346         }
 347         return (0);
 348 }
 349 
 350 
 351 /*
 352  * ndmpd_api_write_v2
 353  *
 354  * Callback function called by the backup/restore module.
 355  * Writes data to the mover.
 356  * If the mover is remote, the data is written to the data connection.
 357  * If the mover is local, the data is buffered and written to the
 358  * tape device after a full record has been buffered.
 359  *
 360  * Parameters:
 361  *   client_data (input) - session pointer.
 362  *   data       (input) - data to be written.
 363  *   length     (input) - data length.
 364  *


 451         ndmpd_session_t *session = (ndmpd_session_t *)cookie;
 452         ndmp_log_message_request_v3 request;
 453         static char buf[1024];
 454         va_list ap;
 455 
 456         if (session == NULL)
 457                 return (-1);
 458 
 459         va_start(ap, format);
 460 
 461         /*LINTED variable format specifier */
 462         (void) vsnprintf(buf, sizeof (buf), format, ap);
 463         va_end(ap);
 464 
 465         request.entry = buf;
 466         request.log_type = type;
 467         request.message_id = msg_id;
 468 
 469         if (ndmp_send_request(session->ns_connection, NDMP_LOG_MESSAGE,
 470             NDMP_NO_ERR, (void *)&request, 0) < 0) {
 471                 syslog(LOG_ERR, "Error sending log message request.");
 472                 return (-1);
 473         }
 474         return (0);
 475 }
 476 
 477 
 478 /*
 479  * ndmpd_api_write_v3
 480  *
 481  * Callback function called by the backup/restore module.
 482  * Writes data to the mover.
 483  * If the mover is remote, the data is written to the data connection.
 484  * If the mover is local, the data is buffered and written to the
 485  * tape device after a full record has been buffered.
 486  *
 487  * Parameters:
 488  *   client_data (input) - session pointer.
 489  *   data       (input) - data to be written.
 490  *   length     (input) - data length.
 491  *


 604         ndmp_log_file_request_v3 request;
 605 
 606         if (session == NULL)
 607                 return (-1);
 608 
 609         request.name  = name;
 610 
 611         switch (error) {
 612         case 0:
 613                 request.error = NDMP_NO_ERR;
 614                 break;
 615         case ENOENT:
 616                 request.error = NDMP_FILE_NOT_FOUND_ERR;
 617                 break;
 618         default:
 619                 request.error = NDMP_PERMISSION_ERR;
 620         }
 621 
 622         if (ndmp_send_request_lock(session->ns_connection, NDMP_LOG_FILE,
 623             NDMP_NO_ERR, (void *)&request, 0) < 0) {
 624                 syslog(LOG_ERR, "Error sending log file request");
 625                 return (-1);
 626         }
 627 
 628         return (0);
 629 }
 630 
 631 
 632 /*
 633  * ndmpd_api_seek_v3
 634  *
 635  * Seek to the specified position in the data stream and start a
 636  * read for the specified amount of data.
 637  *
 638  * Parameters:
 639  *   cookie (input) - session pointer.
 640  *   offset (input) - stream position to seek to.
 641  *   length (input) - amount of data that will be read using ndmpd_api_read
 642  *
 643  * Returns:
 644  *   0 - seek successful.


 656                 return (-1);
 657 
 658         session->ns_data.dd_read_offset = offset;
 659         session->ns_data.dd_read_length = length;
 660 
 661         /*
 662          * Send a notify_data_read request if the mover is remote.
 663          */
 664         if (session->ns_data.dd_data_addr.addr_type != NDMP_ADDR_LOCAL) {
 665                 session->ns_data.dd_discard_length =
 666                     session->ns_data.dd_bytes_left_to_read;
 667                 session->ns_data.dd_bytes_left_to_read = length;
 668                 session->ns_data.dd_position = offset;
 669 
 670                 request.offset = long_long_to_quad(offset);
 671                 request.length = long_long_to_quad(length);
 672 
 673                 if (ndmp_send_request_lock(session->ns_connection,
 674                     NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR,
 675                     (void *)&request, 0) < 0) {
 676                         syslog(LOG_ERR,
 677                             "Sending notify_data_read request");
 678                         return (-1);
 679                 }
 680 
 681                 return (0);
 682         }
 683 
 684         /* Mover is local. */
 685 
 686         err = ndmpd_mover_seek(session, offset, length);
 687         if (err < 0) {
 688                 ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR);
 689                 return (-1);
 690         }
 691 
 692         if (err == 0)
 693                 return (0);
 694 
 695         /*
 696          * NDMP client intervention is required to perform the seek.


 741         static char buf[1024];
 742         va_list ap;
 743 
 744         if (session == NULL)
 745                 return (-1);
 746 
 747         va_start(ap, format);
 748 
 749         /*LINTED variable format specifier */
 750         (void) vsnprintf(buf, sizeof (buf), format, ap);
 751         va_end(ap);
 752 
 753         request.entry = buf;
 754         request.log_type = type;
 755         request.message_id = msg_id;
 756         request.associated_message_valid = NDMP_NO_ASSOCIATED_MESSAGE;
 757         request.associated_message_sequence = 0;
 758 
 759         if (ndmp_send_request(session->ns_connection, NDMP_LOG_MESSAGE,
 760             NDMP_NO_ERR, (void *)&request, 0) < 0) {
 761                 syslog(LOG_ERR, "Error sending log message request.");
 762                 return (-1);
 763         }
 764         return (0);
 765 }
 766 
 767 
 768 /*
 769  * ndmpd_api_file_recovered_v4
 770  *
 771  * Notify the NDMP client that the specified file was recovered.
 772  *
 773  * Parameters:
 774  *   cookie (input) - session pointer.
 775  *   name   (input) - name of recovered file.
 776  *   ssid   (input) - selection set id.
 777  *   error  (input) - 0 if file successfully recovered.
 778  *                  otherwise, error code indicating why recovery failed.
 779  *
 780  * Returns:
 781  *   void.


 803                 break;
 804         case ENOTDIR:
 805                 request.recovery_status = NDMP_RECOVERY_FAILED_NO_DIRECTORY;
 806                 break;
 807         case ENOMEM:
 808                 request.recovery_status = NDMP_RECOVERY_FAILED_OUT_OF_MEMORY;
 809                 break;
 810         case EIO:
 811                 request.recovery_status = NDMP_RECOVERY_FAILED_IO_ERROR;
 812                 break;
 813         case EEXIST:
 814                 request.recovery_status = NDMP_RECOVERY_FAILED_FILE_PATH_EXISTS;
 815                 break;
 816         default:
 817                 request.recovery_status = NDMP_RECOVERY_FAILED_UNDEFINED_ERROR;
 818                 break;
 819         }
 820 
 821         if (ndmp_send_request_lock(session->ns_connection, NDMP_LOG_FILE,
 822             NDMP_NO_ERR, (void *)&request, 0) < 0) {
 823                 syslog(LOG_ERR, "Error sending log file request");
 824                 return (-1);
 825         }
 826 
 827         return (0);
 828 }
 829 
 830 
 831 /*
 832  * ************************************************************************
 833  * LOCALS
 834  * ************************************************************************
 835  */
 836 
 837 /*
 838  * ndmpd_api_find_env
 839  *
 840  * Return the pointer of the environment variable from the variable
 841  * array for the spcified environment variable.
 842  *
 843  * Parameters:


 907  *   val     (input) - value.
 908  *
 909  * Returns:
 910  *   0 - success.
 911  *  -1 - error.
 912  */
 913 int
 914 ndmpd_api_add_env(void *cookie, char *name, char *value)
 915 {
 916         ndmpd_session_t *session = (ndmpd_session_t *)cookie;
 917         char *namebuf;
 918         char *valbuf;
 919 
 920         if (session == NULL)
 921                 return (-1);
 922 
 923         session->ns_data.dd_env = realloc((void *)session->ns_data.dd_env,
 924             sizeof (ndmp_pval) * (session->ns_data.dd_env_len + 1));
 925 
 926         if (session->ns_data.dd_env == NULL) {
 927                 syslog(LOG_ERR, "Out of memory.");
 928                 return (-1);
 929         }
 930         namebuf = strdup(name);
 931         if (namebuf == NULL)
 932                 return (-1);
 933 
 934         valbuf = strdup(value);
 935         if (valbuf == NULL) {
 936                 free(namebuf);
 937                 return (-1);
 938         }
 939 
 940         (void) mutex_lock(&session->ns_lock);
 941         session->ns_data.dd_env[session->ns_data.dd_env_len].name = namebuf;
 942         session->ns_data.dd_env[session->ns_data.dd_env_len].value = valbuf;
 943         session->ns_data.dd_env_len++;
 944         (void) mutex_unlock(&session->ns_lock);
 945 
 946         return (0);
 947 }