2 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
8 * Copyright (c) 2007, The Storage Networking Industry Association.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
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
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
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.
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. */
42 #include <sys/types.h>
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.
56 int ndmp_log_msg_id
= 0;
60 * ************************************************************************
62 * ************************************************************************
68 * Called when dump/restore has completed.
69 * Sends a notify_halt request to the NDMP client.
72 * session (input) - session pointer.
73 * err (input) - UNIX error code.
79 ndmpd_api_done_v2(void *cookie
, int err
)
81 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
82 ndmp_notify_data_halted_request req_v2
;
87 if (session
->ns_data
.dd_state
== NDMP_DATA_STATE_IDLE
||
88 session
->ns_data
.dd_state
== NDMP_DATA_STATE_HALTED
)
91 NDMP_LOG(LOG_DEBUG
, "data.operation: %d",
92 session
->ns_data
.dd_operation
);
94 if (session
->ns_data
.dd_operation
== NDMP_DATA_OP_BACKUP
) {
96 * Send/discard any buffered file history data.
98 ndmpd_file_history_cleanup(session
, (err
== 0 ? TRUE
: FALSE
));
101 * If mover local and successfull backup, write any
102 * remaining buffered data to tape.
104 if (session
->ns_data
.dd_mover
.addr_type
== NDMP_ADDR_LOCAL
&&
106 if (ndmpd_local_write(session
, 0, 0) < 0)
111 session
->ns_data
.dd_state
= NDMP_DATA_STATE_HALTED
;
115 session
->ns_data
.dd_halt_reason
= NDMP_DATA_HALT_SUCCESSFUL
;
118 session
->ns_data
.dd_halt_reason
= NDMP_DATA_HALT_ABORTED
;
121 session
->ns_data
.dd_halt_reason
= NDMP_DATA_HALT_CONNECT_ERROR
;
124 session
->ns_data
.dd_halt_reason
= NDMP_DATA_HALT_INTERNAL_ERROR
;
127 req_v2
.reason
= session
->ns_data
.dd_halt_reason
;
128 req_v2
.text_reason
= "";
130 NDMP_LOG(LOG_DEBUG
, "ndmp_send_request(NDMP_NOTIFY_DATA_HALTED)");
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");
136 if (session
->ns_data
.dd_mover
.addr_type
== NDMP_ADDR_TCP
) {
138 if (session
->ns_mover
.md_sock
!= session
->ns_data
.dd_sock
) {
139 (void) close(session
->ns_data
.dd_sock
);
141 NDMP_LOG(LOG_DEBUG
, "Not closing as used by mover");
144 session
->ns_data
.dd_sock
= -1;
146 ndmpd_mover_error(session
, NDMP_MOVER_HALT_CONNECT_CLOSED
);
154 * Sends a log request to the NDMP client.
157 * cookie (input) - session pointer.
158 * str (input) - null terminated string
159 * format (input) - printf style format.
160 * ... (input) - format arguments.
168 ndmpd_api_log_v2(void *cookie
, char *format
, ...)
170 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
171 ndmp_log_log_request request
;
172 static char buf
[1024];
178 va_start(ap
, format
);
180 /*LINTED variable format specifier */
181 (void) vsnprintf(buf
, sizeof (buf
), format
, ap
);
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");
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.
206 * client_data (input) - session pointer.
207 * data (input) - data to be written.
208 * length (input) - data length.
211 * 0 - data successfully read.
213 * 1 - session terminated or operation aborted.
216 ndmpd_api_read_v2(void *client_data
, char *data
, ulong_t length
)
218 ndmpd_session_t
*session
= (ndmpd_session_t
*)client_data
;
224 * Read the data from the data connection if the mover is remote.
226 if (session
->ns_data
.dd_mover
.addr_type
== NDMP_ADDR_TCP
)
227 return (ndmpd_remote_read(session
, data
, length
));
229 return (ndmpd_local_read(session
, data
, length
));
236 * Seek to the specified position in the data stream and start a
237 * read for the specified amount of data.
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
245 * 0 - seek successful.
249 ndmpd_api_seek_v2(void *cookie
, u_longlong_t offset
, u_longlong_t length
)
251 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
257 session
->ns_data
.dd_read_offset
= offset
;
258 session
->ns_data
.dd_read_length
= length
;
261 * Send a notify_data_read request if the mover is remote.
263 if (session
->ns_data
.dd_mover
.addr_type
== NDMP_ADDR_TCP
) {
264 ndmp_notify_data_read_request request
;
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
;
271 request
.offset
= long_long_to_quad(offset
);
272 request
.length
= long_long_to_quad(length
);
274 if (ndmp_send_request_lock(session
->ns_connection
,
275 NDMP_NOTIFY_DATA_READ
, NDMP_NO_ERR
,
276 (void *)&request
, 0) < 0) {
279 "Sending notify_data_read request");
284 /* Mover is local. */
286 err
= ndmpd_mover_seek(session
, offset
, length
);
288 ndmpd_mover_error(session
, NDMP_MOVER_HALT_INTERNAL_ERROR
);
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.
299 return (ndmp_wait_for_mover(session
));
304 * ndmpd_api_file_recovered_v2
306 * Notify the NDMP client that the specified file was recovered.
309 * cookie (input) - session pointer.
310 * name (input) - name of recovered file.
311 * error (input) - 0 if file successfully recovered.
312 * otherwise, error code indicating why recovery failed.
318 ndmpd_api_file_recovered_v2(void *cookie
, char *name
, int error
)
320 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
321 ndmp_log_file_request_v2 request
;
331 request
.error
= NDMP_NO_ERR
;
334 request
.error
= NDMP_FILE_NOT_FOUND_ERR
;
337 request
.error
= NDMP_PERMISSION_ERR
;
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");
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.
359 * client_data (input) - session pointer.
360 * data (input) - data to be written.
361 * length (input) - data length.
364 * 0 - data successfully written.
368 ndmpd_api_write_v2(void *client_data
, char *data
, ulong_t length
)
370 ndmpd_session_t
*session
= (ndmpd_session_t
*)client_data
;
376 * Write the data to the data connection if the mover is remote.
378 if (session
->ns_data
.dd_mover
.addr_type
== NDMP_ADDR_TCP
)
379 return (ndmpd_remote_write(session
, data
, length
));
381 return (ndmpd_local_write(session
, data
, length
));
386 * ************************************************************************
388 * ************************************************************************
394 * Called when the data module has completed.
395 * Sends a notify_halt request to the NDMP client.
398 * session (input) - session pointer.
399 * err (input) - UNIX error code.
405 ndmpd_api_done_v3(void *cookie
, int err
)
407 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
408 ndmp_data_halt_reason reason
;
412 reason
= NDMP_DATA_HALT_SUCCESSFUL
;
416 reason
= NDMP_DATA_HALT_ABORTED
;
420 reason
= NDMP_DATA_HALT_CONNECT_ERROR
;
424 reason
= NDMP_DATA_HALT_INTERNAL_ERROR
;
427 ndmpd_data_error(session
, reason
);
433 * Sends a log request to the NDMP client.
436 * cookie (input) - session pointer.
437 * format (input) - printf style format.
438 * ... (input) - format arguments.
446 ndmpd_api_log_v3(void *cookie
, ndmp_log_type type
, ulong_t msg_id
,
449 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
450 ndmp_log_message_request_v3 request
;
451 static char buf
[1024];
457 va_start(ap
, format
);
459 /*LINTED variable format specifier */
460 (void) vsnprintf(buf
, sizeof (buf
), format
, ap
);
464 request
.log_type
= type
;
465 request
.message_id
= msg_id
;
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.");
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.
486 * client_data (input) - session pointer.
487 * data (input) - data to be written.
488 * length (input) - data length.
491 * 0 - data successfully written.
495 ndmpd_api_write_v3(void *client_data
, char *data
, ulong_t length
)
497 ndmpd_session_t
*session
= (ndmpd_session_t
*)client_data
;
503 * Write the data to the tape if the mover is local, otherwise,
504 * write the data to the data connection.
506 * The same write function for of v2 can be used in V3
507 * for writing data to the data connection to the mover.
508 * So we don't need ndmpd_remote_write_v3().
510 if (session
->ns_data
.dd_data_addr
.addr_type
== NDMP_ADDR_LOCAL
)
511 return (ndmpd_local_write_v3(session
, data
, length
));
513 return (ndmpd_remote_write(session
, data
, length
));
520 * Callback function called by the backup/recover module.
521 * Reads data from the mover.
522 * If the mover is remote, the data is read from the data connection.
523 * If the mover is local, the data is read from the tape device.
526 * client_data (input) - session pointer.
527 * data (input) - data to be written.
528 * length (input) - data length.
531 * 0 - data successfully read.
533 * 1 - session terminated or operation aborted.
536 ndmpd_api_read_v3(void *client_data
, char *data
, ulong_t length
)
538 ndmpd_session_t
*session
= (ndmpd_session_t
*)client_data
;
544 * Read the data from the data connection if the mover is remote.
546 if (session
->ns_data
.dd_data_addr
.addr_type
== NDMP_ADDR_LOCAL
)
547 return (ndmpd_local_read_v3(session
, data
, length
));
549 return (ndmpd_remote_read_v3(session
, data
, length
));
554 * ndmpd_api_get_name_v3
556 * Return the name entry at the specified index from the
557 * recover file name list.
560 * cookie (input) - NDMP session pointer.
561 * name_index (input) - index of entry to be returned.
564 * Pointer to name entry.
565 * 0 if requested entry does not exist.
568 ndmpd_api_get_name_v3(void *cookie
, ulong_t name_index
)
570 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
575 if (name_index
>= session
->ns_data
.dd_nlist_len
)
578 return (&session
->ns_data
.dd_nlist_v3
[name_index
]);
583 * ndmpd_api_file_recovered_v3
585 * Notify the NDMP client that the specified file was recovered.
588 * cookie (input) - session pointer.
589 * name (input) - name of recovered file.
590 * ssid (input) - selection set id.
591 * error (input) - 0 if file successfully recovered.
592 * otherwise, error code indicating why recovery failed.
599 ndmpd_api_file_recovered_v3(void *cookie
, char *name
, int error
)
601 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
602 ndmp_log_file_request_v3 request
;
611 request
.error
= NDMP_NO_ERR
;
614 request
.error
= NDMP_FILE_NOT_FOUND_ERR
;
617 request
.error
= NDMP_PERMISSION_ERR
;
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");
633 * Seek to the specified position in the data stream and start a
634 * read for the specified amount of data.
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
642 * 0 - seek successful.
643 * 1 - seek needed DMA(client) intervention.
647 ndmpd_api_seek_v3(void *cookie
, u_longlong_t offset
, u_longlong_t length
)
649 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
651 ndmp_notify_data_read_request request
;
656 session
->ns_data
.dd_read_offset
= offset
;
657 session
->ns_data
.dd_read_length
= length
;
660 * Send a notify_data_read request if the mover is remote.
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
;
668 request
.offset
= long_long_to_quad(offset
);
669 request
.length
= long_long_to_quad(length
);
671 if (ndmp_send_request_lock(session
->ns_connection
,
672 NDMP_NOTIFY_DATA_READ
, NDMP_NO_ERR
,
673 (void *)&request
, 0) < 0) {
675 "Sending notify_data_read request");
682 /* Mover is local. */
684 err
= ndmpd_mover_seek(session
, offset
, length
);
686 ndmpd_mover_error(session
, NDMP_MOVER_HALT_INTERNAL_ERROR
);
694 * NDMP client intervention is required to perform the seek.
695 * Wait for the client to either do the seek and send a continue
696 * request or send an abort request.
698 err
= ndmp_wait_for_mover(session
);
701 * If we needed a client intervention, then we should be able to
702 * detect this in DAR.
711 * ************************************************************************
713 * ************************************************************************
719 * Sends a log request to the NDMP client.
720 * No message association is supported now, but can be added later on
724 * cookie (input) - session pointer.
725 * format (input) - printf style format.
726 * ... (input) - format arguments.
734 ndmpd_api_log_v4(void *cookie
, ndmp_log_type type
, ulong_t msg_id
,
737 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
738 ndmp_log_message_request_v4 request
;
739 static char buf
[1024];
745 va_start(ap
, format
);
747 /*LINTED variable format specifier */
748 (void) vsnprintf(buf
, sizeof (buf
), format
, ap
);
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;
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.");
767 * ndmpd_api_file_recovered_v4
769 * Notify the NDMP client that the specified file was recovered.
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.
782 ndmpd_api_file_recovered_v4(void *cookie
, char *name
, int error
)
784 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
785 ndmp_log_file_request_v4 request
;
794 request
.recovery_status
= NDMP_RECOVERY_SUCCESSFUL
;
797 request
.recovery_status
= NDMP_RECOVERY_FAILED_PERMISSION
;
800 request
.recovery_status
= NDMP_RECOVERY_FAILED_NOT_FOUND
;
803 request
.recovery_status
= NDMP_RECOVERY_FAILED_NO_DIRECTORY
;
806 request
.recovery_status
= NDMP_RECOVERY_FAILED_OUT_OF_MEMORY
;
809 request
.recovery_status
= NDMP_RECOVERY_FAILED_IO_ERROR
;
812 request
.recovery_status
= NDMP_RECOVERY_FAILED_FILE_PATH_EXISTS
;
815 request
.recovery_status
= NDMP_RECOVERY_FAILED_UNDEFINED_ERROR
;
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");
830 * ************************************************************************
832 * ************************************************************************
838 * Return the pointer of the environment variable from the variable
839 * array for the spcified environment variable.
842 * cookie (input) - NDMP session pointer.
843 * name (input) - name of variable.
846 * Pointer to variable.
847 * NULL if variable not found.
851 ndmpd_api_find_env(void *cookie
, char *name
)
853 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
860 envp
= session
->ns_data
.dd_env
;
861 for (i
= 0; envp
&& i
< session
->ns_data
.dd_env_len
; envp
++, i
++)
862 if (strcmp(name
, envp
->name
) == NULL
)
872 * Return the value of an environment variable from the variable array.
875 * cookie (input) - NDMP session pointer.
876 * name (input) - name of variable.
879 * Pointer to variable value.
880 * 0 if variable not found.
884 ndmpd_api_get_env(void *cookie
, char *name
)
888 envp
= ndmpd_api_find_env(cookie
, name
);
890 return (envp
->value
);
899 * Adds an environment variable name/value pair to the environment
903 * session (input) - session pointer.
904 * name (input) - variable name.
905 * val (input) - value.
912 ndmpd_api_add_env(void *cookie
, char *name
, char *value
)
914 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
921 session
->ns_data
.dd_env
= realloc((void *)session
->ns_data
.dd_env
,
922 sizeof (ndmp_pval
) * (session
->ns_data
.dd_env_len
+ 1));
924 if (session
->ns_data
.dd_env
== NULL
) {
925 NDMP_LOG(LOG_ERR
, "Out of memory.");
928 namebuf
= strdup(name
);
932 valbuf
= strdup(value
);
933 if (valbuf
== NULL
) {
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
);
951 * Sets an environment variable name/value pair in the environment
952 * variable list. If the variable exists, it gets the new value,
953 * otherwise it's added as a new variable.
956 * session (input) - session pointer.
957 * name (input) - variable name.
958 * val (input) - value.
965 ndmpd_api_set_env(void *cookie
, char *name
, char *value
)
971 envp
= ndmpd_api_find_env(cookie
, name
);
973 rv
= ndmpd_api_add_env(cookie
, name
, value
);
974 } else if (!(valbuf
= strdup(value
))) {
979 envp
->value
= valbuf
;
989 * Return the name entry at the specified index from the
990 * recover file name list.
993 * cookie (input) - NDMP session pointer.
994 * name_index (input) - index of entry to be returned.
997 * Pointer to name entry.
998 * 0 if requested entry does not exist.
1001 ndmpd_api_get_name(void *cookie
, ulong_t name_index
)
1003 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
1005 if (session
== NULL
)
1008 if (name_index
>= session
->ns_data
.dd_nlist_len
)
1011 return (&session
->ns_data
.dd_nlist
[name_index
]);
1016 * ndmpd_api_dispatch
1018 * Process pending NDMP client requests and check registered files for
1019 * data availability.
1022 * cookie (input) - session pointer.
1024 * TRUE block until a request has been processed or
1025 * until a file handler has been called.
1026 * FALSE don't block.
1029 * -1 - abort request received or connection closed.
1033 ndmpd_api_dispatch(void *cookie
, boolean_t block
)
1035 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
1038 if (session
== NULL
)
1042 err
= ndmpd_select(session
, block
, HC_ALL
);
1043 if (err
< 0 || session
->ns_data
.dd_abort
== TRUE
||
1051 * Something was processed.
1052 * Set the block flag to false so that we will return as
1053 * soon as everything available to be processed has been
1062 * ndmpd_api_add_file_handler
1064 * Adds a file handler to the file handler list.
1065 * The file handler list is used by ndmpd_api_dispatch.
1068 * daemon_cookie (input) - session pointer.
1069 * cookie (input) - opaque data to be passed to file hander when called.
1070 * fd (input) - file descriptor.
1071 * mode (input) - bitmask of the following:
1072 * NDMP_SELECT_MODE_READ = watch file for ready for reading
1073 * NDMP_SELECT_MODE_WRITE = watch file for ready for writing
1074 * NDMP_SELECT_MODE_EXCEPTION = watch file for exception
1075 * func (input) - function to call when the file meets one of the
1076 * conditions specified by mode.
1083 ndmpd_api_add_file_handler(void *daemon_cookie
, void *cookie
, int fd
,
1084 ulong_t mode
, ndmpd_file_handler_func_t
*func
)
1086 ndmpd_session_t
*session
= (ndmpd_session_t
*)daemon_cookie
;
1088 return (ndmpd_add_file_handler(session
, cookie
, fd
, mode
, HC_MODULE
,
1094 * ndmpd_api_remove_file_handler
1096 * Removes a file handler from the file handler list.
1099 * cookie (input) - session pointer.
1100 * fd (input) - file descriptor.
1107 ndmpd_api_remove_file_handler(void *cookie
, int fd
)
1109 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
1111 return (ndmpd_remove_file_handler(session
, fd
));