Print this page
4738 tape block number is set at wrong place
Reviewed by: Albert Lee <trisk@nexenta.com>
Approved by: Dan McDonald <danmcd@omniti.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/ndmpd/ndmp/ndmpd_util.c
+++ new/usr/src/cmd/ndmpd/ndmp/ndmpd_util.c
1 1 /*
2 2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 3 */
4 4
5 5 /*
6 6 * BSD 3 Clause License
7 7 *
8 8 * Copyright (c) 2007, The Storage Networking Industry Association.
9 9 *
10 10 * Redistribution and use in source and binary forms, with or without
11 11 * modification, are permitted provided that the following conditions
12 12 * are met:
13 13 * - Redistributions of source code must retain the above copyright
14 14 * notice, this list of conditions and the following disclaimer.
15 15 *
16 16 * - Redistributions in binary form must reproduce the above copyright
17 17 * notice, this list of conditions and the following disclaimer in
18 18 * the documentation and/or other materials provided with the
19 19 * distribution.
20 20 *
21 21 * - Neither the name of The Storage Networking Industry Association (SNIA)
22 22 * nor the names of its contributors may be used to endorse or promote
23 23 * products derived from this software without specific prior written
24 24 * permission.
25 25 *
26 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30 30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 36 * POSSIBILITY OF SUCH DAMAGE.
37 37 */
38 38 /* Copyright (c) 2007, The Storage Networking Industry Association. */
39 39 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
40 40 /* Copyright 2014 Nexenta Systems, Inc. All rights reserved. */
41 41
42 42 #include <sys/types.h>
43 43 #include <assert.h>
44 44 #include <ctype.h>
45 45 #include <errno.h>
46 46 #include <stdio.h>
47 47 #include <stdlib.h>
48 48 #include <unistd.h>
49 49 #include <strings.h>
50 50 #include <time.h>
51 51 #include "ndmpd.h"
52 52 #include <bitmap.h>
53 53 #include <sys/queue.h>
54 54 #include <sys/socket.h>
55 55 #include <netinet/in.h>
56 56 #include <netinet/tcp.h>
57 57 #include <arpa/inet.h>
58 58 #include <sys/socketvar.h>
59 59 #include <net/if.h>
60 60 #include <netdb.h>
61 61 #include <sys/filio.h>
62 62 #include <sys/mtio.h>
63 63 #include <sys/scsi/impl/uscsi.h>
64 64 #include <sys/scsi/scsi.h>
65 65 #include "tlm.h"
66 66
67 67 /*
68 68 * Force to backup all the intermediate directories leading to an object
69 69 * to be backed up in 'dump' format backup.
70 70 */
71 71 boolean_t ndmp_dump_path_node = FALSE;
72 72
73 73
74 74 /*
75 75 * Force to backup all the intermediate directories leading to an object
76 76 * to be backed up in 'tar' format backup.
77 77 */
78 78 boolean_t ndmp_tar_path_node = FALSE;
79 79
80 80
81 81 /*
82 82 * Should the 'st_ctime' be ignored during incremental level backup?
83 83 */
84 84 boolean_t ndmp_ignore_ctime = FALSE;
85 85
86 86 /*
87 87 * Should the 'st_lmtime' be included during incremental level backup?
88 88 */
89 89 boolean_t ndmp_include_lmtime = FALSE;
90 90
91 91 /*
92 92 * Force to send the file history node entries along with the file history
93 93 * dir entries for all directories containing the changed files to the client
94 94 * for incremental backup.
95 95 *
96 96 * Note: This variable is added to support Bakbone Software's Netvault DMA
97 97 * which expects to get the FH ADD NODES for all upper directories which
98 98 * contain the changed files in incremental backup along with the FH ADD DIRS.
99 99 */
100 100 boolean_t ndmp_fhinode = FALSE;
101 101
102 102 /*
103 103 * Maximum permitted sequence number in the token-based backup. The
104 104 * value of this variable can be changed by the administrator and is
105 105 * saved in the NDMP configuration file.
106 106 */
107 107 static int ndmp_max_tok_seq = NDMP_MAX_TOKSEQ;
108 108
109 109 /*
110 110 * Force backup directories in incremental backups. If the
111 111 * directory is not modified itself, it's not backed up by
112 112 * default.
113 113 */
114 114 int ndmp_force_bk_dirs = 0;
115 115
116 116 /*
117 117 * Keeps track of the open SCSI (including tape and robot) devices.
118 118 * When a SCSI device is opened its name must be added to this list and
119 119 * when it's closed its name must be removed from this list. The main
120 120 * purpose of this list is the robot device. If the robot devices are not
121 121 * attached in SASD layer, Local Backup won't see them. If they are
122 122 * attached and we open the robot devices, then wrong commands are sent
123 123 * to robot by SASD since it assumes that the robot is a tape (sequential
124 124 * access) device.
125 125 */
126 126 struct open_list {
127 127 LIST_ENTRY(open_list) ol_q;
128 128 int ol_nref;
129 129 char *ol_devnm;
130 130 int ol_sid;
131 131 int ol_lun;
132 132 int ol_fd;
133 133 ndmp_connection_t *cl_conn;
134 134 };
135 135 LIST_HEAD(ol_head, open_list);
136 136
137 137
138 138 /*
139 139 * Head of the opened SCSI devices list.
140 140 */
141 141 static struct ol_head ol_head;
142 142
143 143 mutex_t ol_mutex = DEFAULTMUTEX;
144 144
145 145
146 146 /*
147 147 * List of things to be exluded from backup.
148 148 */
149 149 static char *exls[] = {
150 150 EXCL_PROC,
151 151 EXCL_TMP,
152 152 NULL, /* reserved for a copy of the "backup.directory" */
153 153 NULL
154 154 };
155 155
156 156
157 157 /*
158 158 * The counter for creating unique names with "ndmp.%d" format.
159 159 */
160 160 #define NDMP_RCF_BASENAME "ndmp."
161 161 static int ndmp_job_cnt = 0;
162 162
163 163 static int scsi_test_unit_ready(int dev_id);
164 164
165 165 /*
166 166 * ndmpd_add_file_handler
167 167 *
168 168 * Adds a file handler to the file handler list.
169 169 * The file handler list is used by ndmpd_api_dispatch.
170 170 *
171 171 * Parameters:
172 172 * session (input) - session pointer.
173 173 * cookie (input) - opaque data to be passed to file hander when called.
174 174 * fd (input) - file descriptor.
175 175 * mode (input) - bitmask of the following:
176 176 * 1 = watch file for ready for reading
177 177 * 2 = watch file for ready for writing
178 178 * 4 = watch file for exception
179 179 * class (input) - handler class. (HC_CLIENT, HC_MOVER, HC_MODULE)
180 180 * func (input) - function to call when the file meets one of the
181 181 * conditions specified by mode.
182 182 *
183 183 * Returns:
184 184 * 0 - success.
185 185 * -1 - error.
186 186 */
187 187 int
188 188 ndmpd_add_file_handler(ndmpd_session_t *session, void *cookie, int fd,
189 189 ulong_t mode, ulong_t class, ndmpd_file_handler_func_t *func)
190 190 {
191 191 ndmpd_file_handler_t *new;
192 192
193 193 new = ndmp_malloc(sizeof (ndmpd_file_handler_t));
194 194 if (new == 0)
195 195 return (-1);
196 196
197 197 new->fh_cookie = cookie;
198 198 new->fh_fd = fd;
199 199 new->fh_mode = mode;
200 200 new->fh_class = class;
201 201 new->fh_func = func;
202 202 new->fh_next = session->ns_file_handler_list;
203 203 session->ns_file_handler_list = new;
204 204 return (0);
205 205 }
206 206
207 207
208 208 /*
209 209 * ndmpd_remove_file_handler
210 210 *
211 211 * Removes a file handler from the file handler list.
212 212 *
213 213 * Parameters:
214 214 * session (input) - session pointer.
215 215 * fd (input) - file descriptor.
216 216 *
217 217 * Returns:
218 218 * 0 - success.
219 219 * -1 - error.
220 220 */
221 221 int
222 222 ndmpd_remove_file_handler(ndmpd_session_t *session, int fd)
223 223 {
224 224 ndmpd_file_handler_t **last;
225 225 ndmpd_file_handler_t *handler;
226 226
227 227 last = &session->ns_file_handler_list;
228 228 while (*last != 0) {
229 229 handler = *last;
230 230
231 231 if (handler->fh_fd == fd) {
232 232 *last = handler->fh_next;
233 233 (void) free(handler);
234 234 return (1);
235 235 }
236 236 last = &handler->fh_next;
237 237 }
238 238
239 239 return (0);
240 240 }
241 241
242 242
243 243 /*
244 244 * ndmp_connection_closed
245 245 *
246 246 * If the connection closed or not.
247 247 *
248 248 * Parameters:
249 249 * fd (input) : file descriptor
250 250 *
251 251 * Returns:
252 252 * 0 - connection is still valid
253 253 * 1 - connection is not valid anymore
254 254 * -1 - Internal kernel error
255 255 */
256 256 int
257 257 ndmp_connection_closed(int fd)
258 258 {
259 259 fd_set fds;
260 260 int closed, ret;
261 261 struct timeval timeout;
262 262
263 263 if (fd < 0) /* We are not using the mover */
264 264 return (-1);
265 265
266 266 timeout.tv_sec = 0;
267 267 timeout.tv_usec = 1000;
268 268
269 269 FD_ZERO(&fds);
270 270 FD_SET(fd, &fds);
271 271 ret = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
272 272
273 273 closed = (ret == -1 && errno == EBADF);
274 274
275 275 return (closed);
276 276 }
277 277
278 278 /*
279 279 * ndmp_check_mover_state
280 280 *
281 281 * Checks the mover connection status and sends an appropriate
282 282 * NDMP message to client based on that.
283 283 *
284 284 * Parameters:
285 285 * ndmpd_session_t *session (input) : session pointer
286 286 *
287 287 * Returns:
288 288 * void.
289 289 */
290 290 void
291 291 ndmp_check_mover_state(ndmpd_session_t *session)
292 292 {
293 293 int moverfd;
294 294 /*
295 295 * NDMPV3 Spec (Three-way restore):
296 296 * Once all of the files have been recovered, NDMP DATA Server closes
297 297 * the connection to the mover on the NDMP TAPE Server. THEN
298 298 * The NDMP client should receive an NDMP_NOTIFY_MOVER_HALTED message
299 299 * with an NDMP_MOVER_CONNECT_CLOSED reason from the NDMP TAPE Server
300 300 */
301 301 moverfd = session->ns_mover.md_sock;
302 302 /* If connection is closed by the peer */
303 303 if (moverfd >= 0 &&
304 304 session->ns_mover.md_mode == NDMP_MOVER_MODE_WRITE) {
305 305 int closed, reason;
306 306
307 307 closed = ndmp_connection_closed(moverfd);
308 308 if (closed) {
309 309 /* Connection closed or internal error */
310 310 if (closed > 0) {
311 311 NDMP_LOG(LOG_DEBUG,
312 312 "ndmp mover: connection closed by peer");
313 313 reason = NDMP_MOVER_HALT_CONNECT_CLOSED;
314 314 } else {
315 315 NDMP_LOG(LOG_DEBUG,
316 316 "ndmp mover: Internal error");
317 317 reason = NDMP_MOVER_HALT_INTERNAL_ERROR;
318 318 }
319 319 ndmpd_mover_error(session, reason);
320 320
321 321 }
322 322 }
323 323 }
324 324
325 325
326 326 /*
327 327 * ndmpd_select
328 328 *
329 329 * Calls select on the the set of file descriptors from the
330 330 * file handler list masked by the fd_class argument.
331 331 * Calls the file handler function for each
332 332 * file descriptor that is ready for I/O.
333 333 *
334 334 * Parameters:
335 335 * session (input) - session pointer.
336 336 * block (input) - if TRUE, ndmpd_select waits until at least one
337 337 * file descriptor is ready for I/O. Otherwise,
338 338 * it returns immediately if no file descriptors are
339 339 * ready for I/O.
340 340 * class_mask (input) - bit mask of handler classes to be examined.
341 341 * Provides for excluding some of the handlers from
342 342 * being called.
343 343 *
344 344 * Returns:
345 345 * -1 - error.
346 346 * 0 - no handlers were called.
347 347 * 1 - at least one handler was called.
348 348 */
349 349 int
350 350 ndmpd_select(ndmpd_session_t *session, boolean_t block, ulong_t class_mask)
351 351 {
352 352 fd_set rfds;
353 353 fd_set wfds;
354 354 fd_set efds;
355 355 int n;
356 356 ndmpd_file_handler_t *handler;
357 357 struct timeval timeout;
358 358 ndmp_lbr_params_t *nlp;
359 359
360 360 if (session->ns_file_handler_list == 0)
361 361 return (0);
362 362
363 363
364 364 /*
365 365 * If select should be blocked, then we poll every ten seconds.
366 366 * The reason is in case of three-way restore we should be able
367 367 * to detect if the other end closed the connection or not.
368 368 * NDMP client(DMA) does not send any information about the connection
369 369 * that was closed in the other end.
370 370 */
371 371
372 372 if (block == TRUE)
373 373 timeout.tv_sec = 10;
374 374 else
375 375 timeout.tv_sec = 0;
376 376 timeout.tv_usec = 0;
377 377
378 378 do {
379 379 /* Create the fd_sets for select. */
380 380 FD_ZERO(&rfds);
381 381 FD_ZERO(&wfds);
382 382 FD_ZERO(&efds);
383 383
384 384 for (handler = session->ns_file_handler_list; handler != 0;
385 385 handler = handler->fh_next) {
386 386 if ((handler->fh_class & class_mask) == 0)
387 387 continue;
388 388
389 389 if (handler->fh_mode & NDMPD_SELECT_MODE_READ)
390 390 FD_SET(handler->fh_fd, &rfds);
391 391 if (handler->fh_mode & NDMPD_SELECT_MODE_WRITE)
392 392 FD_SET(handler->fh_fd, &wfds);
393 393 if (handler->fh_mode & NDMPD_SELECT_MODE_EXCEPTION)
394 394 FD_SET(handler->fh_fd, &efds);
395 395 }
396 396 ndmp_check_mover_state(session);
397 397 n = select(FD_SETSIZE, &rfds, &wfds, &efds, &timeout);
398 398 } while (n == 0 && block == TRUE);
399 399
400 400 if (n < 0) {
401 401 int connection_fd = ndmp_get_fd(session->ns_connection);
402 402
403 403 if (errno == EINTR)
404 404 return (0);
405 405
406 406 NDMP_LOG(LOG_DEBUG, "Select error: %m");
407 407
408 408 nlp = ndmp_get_nlp(session);
409 409 (void) mutex_lock(&nlp->nlp_mtx);
410 410 for (handler = session->ns_file_handler_list; handler != 0;
411 411 handler = handler->fh_next) {
412 412 if ((handler->fh_class & class_mask) == 0)
413 413 continue;
414 414
415 415 if (handler->fh_mode & NDMPD_SELECT_MODE_READ) {
416 416 if (FD_ISSET(handler->fh_fd, &rfds) &&
417 417 connection_fd == handler->fh_fd)
418 418 session->ns_eof = TRUE;
419 419 }
420 420 if (handler->fh_mode & NDMPD_SELECT_MODE_WRITE) {
421 421 if (FD_ISSET(handler->fh_fd, &wfds) &&
422 422 connection_fd == handler->fh_fd)
423 423 session->ns_eof = TRUE;
424 424 }
425 425 if (handler->fh_mode & NDMPD_SELECT_MODE_EXCEPTION) {
426 426 if (FD_ISSET(handler->fh_fd, &efds) &&
427 427 connection_fd == handler->fh_fd)
428 428 session->ns_eof = TRUE;
429 429 }
430 430 }
431 431 (void) cond_broadcast(&nlp->nlp_cv);
432 432 (void) mutex_unlock(&nlp->nlp_mtx);
433 433 return (-1);
434 434 }
435 435 if (n == 0)
436 436 return (0);
437 437
438 438 handler = session->ns_file_handler_list;
439 439 while (handler != 0) {
440 440 ulong_t mode = 0;
441 441
442 442 if ((handler->fh_class & class_mask) == 0) {
443 443 handler = handler->fh_next;
444 444 continue;
445 445 }
446 446 if (handler->fh_mode & NDMPD_SELECT_MODE_READ) {
447 447 if (FD_ISSET(handler->fh_fd, &rfds)) {
448 448 mode |= NDMPD_SELECT_MODE_READ;
449 449 FD_CLR(handler->fh_fd, &rfds);
450 450 }
451 451 }
452 452 if (handler->fh_mode & NDMPD_SELECT_MODE_WRITE) {
453 453 if (FD_ISSET(handler->fh_fd, &wfds)) {
454 454 mode |= NDMPD_SELECT_MODE_WRITE;
455 455 FD_CLR(handler->fh_fd, &wfds);
456 456 }
457 457 }
458 458 if (handler->fh_mode & NDMPD_SELECT_MODE_EXCEPTION) {
459 459 if (FD_ISSET(handler->fh_fd, &efds)) {
460 460 mode |= NDMPD_SELECT_MODE_EXCEPTION;
461 461 FD_CLR(handler->fh_fd, &efds);
462 462 }
463 463 }
464 464 if (mode) {
465 465 (*handler->fh_func) (handler->fh_cookie,
466 466 handler->fh_fd, mode);
467 467
468 468 /*
469 469 * K.L. The list can be modified during the execution
470 470 * of handler->fh_func. Therefore, handler will start
471 471 * from the beginning of the handler list after
472 472 * each execution.
473 473 */
474 474 handler = session->ns_file_handler_list;
475 475 } else
476 476 handler = handler->fh_next;
477 477
478 478 }
479 479
480 480 return (1);
481 481 }
482 482
483 483
484 484 /*
485 485 * ndmpd_save_env
486 486 *
487 487 * Saves a copy of the environment variable list from the data_start_backup
488 488 * request or data_start_recover request.
489 489 *
490 490 * Parameters:
491 491 * session (input) - session pointer.
492 492 * env (input) - environment variable list to be saved.
493 493 * envlen (input) - length of variable array.
494 494 *
495 495 * Returns:
496 496 * error code.
497 497 */
498 498 ndmp_error
499 499 ndmpd_save_env(ndmpd_session_t *session, ndmp_pval *env, ulong_t envlen)
500 500 {
501 501 ulong_t i;
502 502 char *namebuf;
503 503 char *valbuf;
504 504
505 505 session->ns_data.dd_env_len = 0;
506 506
507 507 if (envlen == 0)
508 508 return (NDMP_NO_ERR);
509 509
510 510 session->ns_data.dd_env = ndmp_malloc(sizeof (ndmp_pval) * envlen);
511 511 if (session->ns_data.dd_env == 0)
512 512 return (NDMP_NO_MEM_ERR);
513 513
514 514 for (i = 0; i < envlen; i++) {
515 515 namebuf = strdup(env[i].name);
516 516 if (namebuf == 0)
517 517 return (NDMP_NO_MEM_ERR);
518 518
519 519 valbuf = strdup(env[i].value);
520 520 if (valbuf == 0) {
521 521 free(namebuf);
522 522 return (NDMP_NO_MEM_ERR);
523 523 }
524 524
525 525 NDMP_LOG(LOG_DEBUG, "env(%s): \"%s\"",
526 526 namebuf, valbuf);
527 527
528 528 (void) mutex_lock(&session->ns_lock);
529 529 session->ns_data.dd_env[i].name = namebuf;
530 530 session->ns_data.dd_env[i].value = valbuf;
531 531 session->ns_data.dd_env_len++;
532 532 (void) mutex_unlock(&session->ns_lock);
533 533 }
534 534
535 535 return (NDMP_NO_ERR);
536 536 }
537 537
538 538
539 539 /*
540 540 * ndmpd_free_env
541 541 *
542 542 * Free the previously saved environment variable array.
543 543 *
544 544 * Parameters:
545 545 * session - NDMP session pointer.
546 546 *
547 547 * Returns:
548 548 * void.
549 549 */
550 550 void
551 551 ndmpd_free_env(ndmpd_session_t *session)
552 552 {
553 553 ulong_t i;
554 554 int count = session->ns_data.dd_env_len;
555 555
556 556 (void) mutex_lock(&session->ns_lock);
557 557 session->ns_data.dd_env_len = 0;
558 558 for (i = 0; i < count; i++) {
559 559 free(session->ns_data.dd_env[i].name);
560 560 free(session->ns_data.dd_env[i].value);
561 561 }
562 562
563 563 free((char *)session->ns_data.dd_env);
564 564 session->ns_data.dd_env = 0;
565 565 (void) mutex_unlock(&session->ns_lock);
566 566 }
567 567
568 568
569 569 /*
570 570 * ndmpd_save_nlist_v2
571 571 *
572 572 * Save a copy of list of file names to be restored.
573 573 *
574 574 * Parameters:
575 575 * nlist (input) - name list from data_start_recover request.
576 576 * nlistlen (input) - length of name list.
577 577 *
578 578 * Returns:
579 579 * array of file name pointers.
580 580 *
581 581 * Notes:
582 582 * free_nlist should be called to free the returned list.
583 583 * A null pointer indicates the end of the list.
584 584 */
585 585 ndmp_error
586 586 ndmpd_save_nlist_v2(ndmpd_session_t *session, ndmp_name *nlist,
587 587 ulong_t nlistlen)
588 588 {
589 589 ulong_t i;
590 590 char *namebuf;
591 591 char *destbuf;
592 592
593 593 if (nlistlen == 0)
594 594 return (NDMP_NO_ERR);
595 595
596 596 session->ns_data.dd_nlist_len = 0;
597 597 session->ns_data.dd_nlist = ndmp_malloc(sizeof (ndmp_name)*nlistlen);
598 598 if (session->ns_data.dd_nlist == 0)
599 599 return (NDMP_NO_MEM_ERR);
600 600
601 601 for (i = 0; i < nlistlen; i++) {
602 602 namebuf = ndmp_malloc(strlen(nlist[i].name) + 1);
603 603 if (namebuf == 0)
604 604 return (NDMP_NO_MEM_ERR);
605 605
606 606 destbuf = ndmp_malloc(strlen(nlist[i].dest) + 1);
607 607 if (destbuf == 0) {
608 608 free(namebuf);
609 609 return (NDMP_NO_MEM_ERR);
610 610 }
611 611 (void) strlcpy(namebuf, nlist[i].name,
612 612 strlen(nlist[i].name) + 1);
613 613 (void) strlcpy(destbuf, nlist[i].dest,
614 614 strlen(nlist[i].dest) + 1);
615 615
616 616 session->ns_data.dd_nlist[i].name = namebuf;
617 617 session->ns_data.dd_nlist[i].dest = destbuf;
618 618 session->ns_data.dd_nlist[i].ssid = nlist[i].ssid;
619 619 session->ns_data.dd_nlist[i].fh_info = nlist[i].fh_info;
620 620 session->ns_data.dd_nlist_len++;
621 621 }
622 622
623 623 return (NDMP_NO_ERR);
624 624 }
625 625
626 626
627 627 /*
628 628 * ndmpd_free_nlist_v2
629 629 *
630 630 * Free a list created by ndmpd_save_nlist_v2.
631 631 *
632 632 * Parameters:
633 633 * session (input) - session pointer.
634 634 *
635 635 * Returns:
636 636 * void
637 637 */
638 638 void
639 639 ndmpd_free_nlist_v2(ndmpd_session_t *session)
640 640 {
641 641 ulong_t i;
642 642
643 643 for (i = 0; i < session->ns_data.dd_nlist_len; i++) {
644 644 free(session->ns_data.dd_nlist[i].name);
645 645 free(session->ns_data.dd_nlist[i].dest);
646 646 }
647 647
648 648 if (session->ns_data.dd_nlist != NULL)
649 649 free((char *)session->ns_data.dd_nlist);
650 650 session->ns_data.dd_nlist = 0;
651 651 session->ns_data.dd_nlist_len = 0;
652 652 }
653 653
654 654
655 655 /*
656 656 * ndmpd_free_nlist_v3
657 657 *
658 658 * Free a list created by ndmpd_save_nlist_v3.
659 659 *
660 660 * Parameters:
661 661 * session (input) - session pointer.
662 662 *
663 663 * Returns:
664 664 * void
665 665 */
666 666 void
667 667 ndmpd_free_nlist_v3(ndmpd_session_t *session)
668 668 {
669 669 ulong_t i;
670 670 mem_ndmp_name_v3_t *tp; /* destination entry */
671 671
672 672 tp = session->ns_data.dd_nlist_v3;
673 673 for (i = 0; i < session->ns_data.dd_nlist_len; tp++, i++) {
674 674 NDMP_FREE(tp->nm3_opath);
675 675 NDMP_FREE(tp->nm3_dpath);
676 676 NDMP_FREE(tp->nm3_newnm);
677 677 }
678 678
679 679 NDMP_FREE(session->ns_data.dd_nlist_v3);
680 680 session->ns_data.dd_nlist_len = 0;
681 681 }
682 682
683 683
684 684 /*
685 685 * ndmpd_save_nlist_v3
686 686 *
687 687 * Save a copy of list of file names to be restored.
688 688 *
689 689 * Parameters:
690 690 * nlist (input) - name list from data_start_recover request.
691 691 * nlistlen (input) - length of name list.
692 692 *
693 693 * Returns:
694 694 * array of file name pointers.
695 695 *
696 696 * Notes:
697 697 * free_nlist should be called to free the returned list.
698 698 * A null pointer indicates the end of the list.
699 699 */
700 700 ndmp_error
701 701 ndmpd_save_nlist_v3(ndmpd_session_t *session, ndmp_name_v3 *nlist,
702 702 ulong_t nlistlen)
703 703 {
704 704 ulong_t i;
705 705 ndmp_error rv;
706 706 ndmp_name_v3 *sp; /* source entry */
707 707 mem_ndmp_name_v3_t *tp; /* destination entry */
708 708
709 709 if (nlistlen == 0)
710 710 return (NDMP_ILLEGAL_ARGS_ERR);
711 711
712 712 session->ns_data.dd_nlist_len = 0;
713 713 tp = session->ns_data.dd_nlist_v3 =
714 714 ndmp_malloc(sizeof (mem_ndmp_name_v3_t) * nlistlen);
715 715 if (session->ns_data.dd_nlist_v3 == 0)
716 716 return (NDMP_NO_MEM_ERR);
717 717
718 718 rv = NDMP_NO_ERR;
719 719 sp = nlist;
720 720 for (i = 0; i < nlistlen; tp++, sp++, i++) {
721 721 tp->nm3_opath = strdup(sp->original_path);
722 722 if (!tp->nm3_opath) {
723 723 rv = NDMP_NO_MEM_ERR;
724 724 break;
725 725 }
726 726 if (!*sp->destination_dir) {
727 727 tp->nm3_dpath = NULL;
728 728 /* In V4 destination dir cannot be NULL */
729 729 if (session->ns_protocol_version == NDMPV4) {
730 730 rv = NDMP_ILLEGAL_ARGS_ERR;
731 731 break;
732 732 }
733 733 } else if (!(tp->nm3_dpath = strdup(sp->destination_dir))) {
734 734 rv = NDMP_NO_MEM_ERR;
735 735 break;
736 736 }
737 737 if (!*sp->new_name)
738 738 tp->nm3_newnm = NULL;
739 739 else if (!(tp->nm3_newnm = strdup(sp->new_name))) {
740 740 rv = NDMP_NO_MEM_ERR;
741 741 break;
742 742 }
743 743
744 744 tp->nm3_node = quad_to_long_long(sp->node);
745 745 tp->nm3_fh_info = quad_to_long_long(sp->fh_info);
746 746 tp->nm3_err = NDMP_NO_ERR;
747 747 session->ns_data.dd_nlist_len++;
748 748
749 749 NDMP_LOG(LOG_DEBUG, "orig \"%s\"", tp->nm3_opath);
750 750 NDMP_LOG(LOG_DEBUG, "dest \"%s\"", NDMP_SVAL(tp->nm3_dpath));
751 751 NDMP_LOG(LOG_DEBUG, "name \"%s\"", NDMP_SVAL(tp->nm3_newnm));
752 752 NDMP_LOG(LOG_DEBUG, "node %lld", tp->nm3_node);
753 753 NDMP_LOG(LOG_DEBUG, "fh_info %lld", tp->nm3_fh_info);
754 754 }
755 755
756 756 if (rv != NDMP_NO_ERR)
757 757 ndmpd_free_nlist_v3(session);
758 758
759 759 return (rv);
760 760 }
761 761
762 762
763 763 /*
764 764 * ndmpd_free_nlist
765 765 *
766 766 * Free the recovery list based on the version
767 767 *
768 768 * Parameters:
769 769 * session (input) - session pointer.
770 770 *
771 771 * Returns:
772 772 * void
773 773 */
774 774 void
775 775 ndmpd_free_nlist(ndmpd_session_t *session)
776 776 {
777 777 switch (session->ns_protocol_version) {
778 778 case 1:
779 779 case 2:
780 780 ndmpd_free_nlist_v2(session);
781 781 break;
782 782 case 3:
783 783 case 4:
784 784 ndmpd_free_nlist_v3(session);
785 785 break;
786 786
787 787 default:
788 788 NDMP_LOG(LOG_DEBUG, "Unknown version %d",
789 789 session->ns_protocol_version);
790 790 }
791 791 }
792 792
793 793
794 794 /*
795 795 * fh_cmpv3
796 796 *
797 797 * Comparison function used in sorting the Nlist based on their
798 798 * file history info (offset of the entry on the tape)
799 799 *
800 800 * Parameters:
801 801 * p (input) - pointer to P
802 802 * q (input) - pointer to Q
803 803 *
804 804 * Returns:
805 805 * -1: P < Q
806 806 * 0: P = Q
807 807 * 1: P > Q
808 808 */
809 809 static int
810 810 fh_cmpv3(const void *p,
811 811 const void *q)
812 812 {
813 813 #define FH_INFOV3(p) (((mem_ndmp_name_v3_t *)p)->nm3_fh_info)
814 814
815 815 if (FH_INFOV3(p) < FH_INFOV3(q))
816 816 return (-1);
817 817 else if (FH_INFOV3(p) == FH_INFOV3(q))
818 818 return (0);
819 819 else
820 820 return (1);
821 821
822 822 #undef FH_INFOV3
823 823 }
824 824
825 825
826 826 /*
827 827 * ndmp_sort_nlist_v3
828 828 *
829 829 * Sort the recovery list based on their offset on the tape
830 830 *
831 831 * Parameters:
832 832 * session (input) - session pointer.
833 833 *
834 834 * Returns:
835 835 * void
836 836 */
837 837 void
838 838 ndmp_sort_nlist_v3(ndmpd_session_t *session)
839 839 {
840 840 if (!session || session->ns_data.dd_nlist_len == 0 ||
841 841 !session->ns_data.dd_nlist_v3)
842 842 return;
843 843
844 844 (void) qsort(session->ns_data.dd_nlist_v3,
845 845 session->ns_data.dd_nlist_len,
846 846 sizeof (mem_ndmp_name_v3_t), fh_cmpv3);
847 847 }
848 848
849 849
850 850 /*
851 851 * ndmp_send_reply
852 852 *
853 853 * Send the reply, check for error and print the msg if any error
854 854 * occured when sending the reply.
855 855 *
856 856 * Parameters:
857 857 * connection (input) - connection pointer.
858 858 *
859 859 * Return:
860 860 * void
861 861 */
862 862 void
863 863 ndmp_send_reply(ndmp_connection_t *connection, void *reply, char *msg)
864 864 {
865 865 if (ndmp_send_response(connection, NDMP_NO_ERR, reply) < 0)
866 866 NDMP_LOG(LOG_DEBUG, "%s", msg);
867 867 }
868 868
869 869
870 870 /*
871 871 * ndmp_mtioctl
872 872 *
873 873 * Performs numerous filemark operations.
874 874 *
875 875 * Parameters:
876 876 * fd - file descriptor of the device
877 877 * cmd - filemark or record command
878 878 * count - the number of operations to be performed
879 879 */
880 880 int
881 881 ndmp_mtioctl(int fd, int cmd, int count)
882 882 {
883 883 struct mtop mp;
884 884
885 885 mp.mt_op = cmd;
886 886 mp.mt_count = count;
887 887 if (ioctl(fd, MTIOCTOP, &mp) < 0) {
888 888 NDMP_LOG(LOG_ERR, "Failed to send command to tape: %m.");
889 889 return (-1);
890 890 }
891 891
892 892 return (0);
893 893 }
894 894
895 895
896 896 /*
897 897 * quad_to_long_long
898 898 *
899 899 * Convert type quad to longlong_t
900 900 */
901 901 u_longlong_t
902 902 quad_to_long_long(ndmp_u_quad q)
903 903 {
904 904 u_longlong_t ull;
905 905
906 906 ull = ((u_longlong_t)q.high << 32) + q.low;
907 907 return (ull);
908 908 }
909 909
910 910
911 911 /*
912 912 * long_long_to_quad
913 913 *
914 914 * Convert long long to quad type
915 915 */
916 916 ndmp_u_quad
917 917 long_long_to_quad(u_longlong_t ull)
918 918 {
919 919 ndmp_u_quad q;
920 920
921 921 q.high = (ulong_t)(ull >> 32);
922 922 q.low = (ulong_t)ull;
923 923 return (q);
924 924 }
925 925
926 926 void
927 927 set_socket_options(int sock)
928 928 {
929 929 int val;
930 930
931 931 /* set send buffer size */
932 932 val = atoi((const char *)ndmpd_get_prop_default(NDMP_SOCKET_CSS, "60"));
933 933 if (val <= 0)
934 934 val = 60;
935 935 val <<= 10; /* convert the value from kilobytes to bytes */
936 936 if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &val, sizeof (val)) < 0)
937 937 NDMP_LOG(LOG_ERR, "SO_SNDBUF failed: %m");
938 938
939 939 /* set receive buffer size */
940 940 val = atoi((const char *)ndmpd_get_prop_default(NDMP_SOCKET_CRS, "60"));
941 941 if (val <= 0)
942 942 val = 60;
943 943 val <<= 10; /* convert the value from kilobytes to bytes */
944 944 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &val, sizeof (val)) < 0)
945 945 NDMP_LOG(LOG_ERR, "SO_RCVBUF failed: %m");
946 946
947 947 /* don't wait to group tcp data */
948 948 val = 1;
949 949 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val)) != 0)
950 950 NDMP_LOG(LOG_ERR, "TCP_NODELAY failed: %m");
951 951
952 952 /* tcp keep-alive */
953 953 val = 1;
954 954 if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof (val)) != 0)
955 955 NDMP_LOG(LOG_ERR, "SO_KEEPALIVE failed: %m");
956 956 }
957 957
958 958 /*
959 959 * ndmp_get_max_tok_seq
960 960 *
961 961 * Get the maximum permitted token sequence for token-based
962 962 * backups.
963 963 *
964 964 * Parameters:
965 965 * void
966 966 *
967 967 * Returns:
968 968 * ndmp_max_tok_seq
969 969 */
970 970 int
971 971 ndmp_get_max_tok_seq(void)
972 972 {
973 973 return (ndmp_max_tok_seq);
974 974 }
975 975
976 976 /*
977 977 * ndmp_buffer_get_size
978 978 *
979 979 * Return the NDMP transfer buffer size
980 980 *
981 981 * Parameters:
982 982 * session (input) - session pointer.
983 983 *
984 984 * Returns:
985 985 * buffer size
986 986 */
987 987 long
988 988 ndmp_buffer_get_size(ndmpd_session_t *session)
989 989 {
990 990 long xfer_size;
991 991
992 992 if (session == NULL)
993 993 return (0);
994 994
995 995 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
996 996 xfer_size = atoi(ndmpd_get_prop_default(NDMP_MOVER_RECSIZE,
997 997 "60"));
998 998 if (xfer_size > 0)
999 999 xfer_size *= KILOBYTE;
1000 1000 else
1001 1001 xfer_size = REMOTE_RECORD_SIZE;
1002 1002 NDMP_LOG(LOG_DEBUG, "Remote operation: %d", xfer_size);
1003 1003 } else {
1004 1004 NDMP_LOG(LOG_DEBUG,
1005 1005 "Local operation: %lu", session->ns_mover.md_record_size);
1006 1006 if ((xfer_size = session->ns_mover.md_record_size) == 0)
1007 1007 xfer_size = MAX_RECORD_SIZE;
1008 1008 }
1009 1009
1010 1010 NDMP_LOG(LOG_DEBUG, "xfer_size: %d", xfer_size);
1011 1011 return (xfer_size);
1012 1012 }
1013 1013
1014 1014
1015 1015 /*
1016 1016 * ndmp_lbr_init
1017 1017 *
1018 1018 * Initialize the LBR/NDMP backup parameters
1019 1019 *
1020 1020 * Parameters:
1021 1021 * session (input) - session pointer.
1022 1022 *
1023 1023 * Returns:
1024 1024 * 0: on success
1025 1025 * -1: otherwise
1026 1026 */
1027 1027 int
1028 1028 ndmp_lbr_init(ndmpd_session_t *session)
1029 1029 {
1030 1030 if (session->ns_ndmp_lbr_params != NULL) {
1031 1031 NDMP_LOG(LOG_DEBUG, "ndmp_lbr_params already allocated.");
1032 1032 return (0);
1033 1033 }
1034 1034
1035 1035 session->ns_ndmp_lbr_params = ndmp_malloc(sizeof (ndmp_lbr_params_t));
1036 1036 if (session->ns_ndmp_lbr_params == NULL)
1037 1037 return (-1);
1038 1038
1039 1039 session->ns_ndmp_lbr_params->nlp_bkmap = -1;
1040 1040 session->ns_ndmp_lbr_params->nlp_session = session;
1041 1041 (void) cond_init(&session->ns_ndmp_lbr_params->nlp_cv, 0, NULL);
1042 1042 (void) mutex_init(&session->ns_ndmp_lbr_params->nlp_mtx, 0, NULL);
1043 1043 (void) mutex_init(&session->ns_lock, 0, NULL);
1044 1044 session->ns_nref = 0;
1045 1045 return (0);
1046 1046 }
1047 1047
1048 1048
1049 1049 /*
1050 1050 * ndmp_lbr_cleanup
1051 1051 *
1052 1052 * Deallocate and cleanup all NDMP/LBR parameters
1053 1053 *
1054 1054 * Parameters:
1055 1055 * session (input) - session pointer.
1056 1056 *
1057 1057 * Returns:
1058 1058 * 0: on success
1059 1059 * -1: otherwise
1060 1060 */
1061 1061 void
1062 1062 ndmp_lbr_cleanup(ndmpd_session_t *session)
1063 1063 {
1064 1064 ndmpd_abort_marking_v2(session);
1065 1065 ndmp_stop_buffer_worker(session);
1066 1066 ndmp_waitfor_op(session);
1067 1067 ndmp_free_reader_writer_ipc(session);
1068 1068 if (session->ns_ndmp_lbr_params) {
1069 1069 if (session->ns_ndmp_lbr_params->nlp_bkmap != -1)
1070 1070 (void) dbm_free(session->ns_ndmp_lbr_params->nlp_bkmap);
1071 1071 tlm_release_list(session->ns_ndmp_lbr_params->nlp_exl);
1072 1072 tlm_release_list(session->ns_ndmp_lbr_params->nlp_inc);
1073 1073 (void) cond_destroy(&session->ns_ndmp_lbr_params->nlp_cv);
1074 1074 (void) mutex_destroy(&session->ns_ndmp_lbr_params->nlp_mtx);
1075 1075 }
1076 1076
1077 1077 NDMP_FREE(session->ns_ndmp_lbr_params);
1078 1078 }
1079 1079
1080 1080 /*
1081 1081 * ndmp_wait_for_mover
1082 1082 *
1083 1083 * Wait for a mover to become active. Waiting is interrupted if session is
1084 1084 * aborted or mover gets to unexpected state.
1085 1085 *
1086 1086 * Parameters:
1087 1087 * session (input) - session pointer.
1088 1088 *
1089 1089 * Returns:
1090 1090 * 0 if success, -1 if failure.
1091 1091 */
1092 1092 int
1093 1093 ndmp_wait_for_mover(ndmpd_session_t *session)
1094 1094 {
1095 1095 ndmp_lbr_params_t *nlp;
1096 1096 tlm_cmd_t *lcmd;
1097 1097
1098 1098 if ((nlp = ndmp_get_nlp(session)) == NULL)
1099 1099 return (-1);
1100 1100
1101 1101 (void) mutex_lock(&nlp->nlp_mtx);
1102 1102 while (session->ns_mover.md_state == NDMP_MOVER_STATE_PAUSED) {
1103 1103 if (session->ns_eof) {
1104 1104 NDMP_LOG(LOG_ERR, "EOF detected");
1105 1105 break;
1106 1106 }
1107 1107 if (session->ns_data.dd_abort) {
1108 1108 NDMP_LOG(LOG_DEBUG, "Received data abort");
1109 1109 break;
1110 1110 }
1111 1111 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
1112 1112 /* remote backup/restore error */
1113 1113 if (session->ns_mover.md_sock == -1 &&
1114 1114 session->ns_mover.md_listen_sock == -1) {
1115 1115 NDMP_LOG(LOG_ERR,
1116 1116 "Remote data connection terminated");
1117 1117 break;
1118 1118 }
1119 1119 } else {
1120 1120 /* local backup/restore error */
1121 1121 if ((lcmd = nlp->nlp_cmds.tcs_command) != NULL) {
1122 1122 if (lcmd->tc_reader == TLM_STOP ||
1123 1123 lcmd->tc_reader == TLM_ABORT ||
1124 1124 lcmd->tc_writer == TLM_STOP ||
1125 1125 lcmd->tc_writer == TLM_ABORT) {
1126 1126 NDMP_LOG(LOG_ERR,
|
↓ open down ↓ |
1126 lines elided |
↑ open up ↑ |
1127 1127 "Local data connection terminated");
1128 1128 break;
1129 1129 }
1130 1130 }
1131 1131 }
1132 1132
1133 1133 (void) cond_wait(&nlp->nlp_cv, &nlp->nlp_mtx);
1134 1134 }
1135 1135 (void) mutex_unlock(&nlp->nlp_mtx);
1136 1136
1137 - if (session->ns_mover.md_state == NDMP_MOVER_STATE_ACTIVE) {
1138 - session->ns_tape.td_record_count = 0;
1139 - return (0);
1140 - }
1141 -
1142 - return (-1);
1137 + return ((session->ns_mover.md_state == NDMP_MOVER_STATE_ACTIVE) ?
1138 + 0 : -1);
1143 1139 }
1144 1140
1145 1141 /*
1146 1142 * is_buffer_erroneous
1147 1143 *
1148 1144 * Run a sanity check on the buffer
1149 1145 *
1150 1146 * returns:
1151 1147 * TRUE: if the buffer seems to have error
1152 1148 * FALSE: if the buffer is full and has valid data.
1153 1149 */
1154 1150 boolean_t
1155 1151 is_buffer_erroneous(tlm_buffer_t *buf)
1156 1152 {
1157 1153 boolean_t rv;
1158 1154
1159 1155 rv = (buf == NULL || buf->tb_eot || buf->tb_eof ||
1160 1156 buf->tb_errno != 0);
1161 1157 if (rv) {
1162 1158 if (buf == NULL) {
1163 1159 NDMP_LOG(LOG_DEBUG, "buf == NULL");
1164 1160 } else {
1165 1161 NDMP_LOG(LOG_DEBUG, "eot: %u, eof: %u, errno: %d",
1166 1162 buf->tb_eot, buf->tb_eof, buf->tb_errno);
1167 1163 }
1168 1164 }
1169 1165
1170 1166 return (rv);
1171 1167 }
1172 1168
1173 1169 /*
1174 1170 * ndmp_execute_cdb
1175 1171 *
1176 1172 * Main SCSI CDB execution program, this is used by message handler
1177 1173 * for the NDMP tape/SCSI execute CDB requests. This function uses
1178 1174 * USCSI interface to run the CDB command and sets all the CDB parameters
1179 1175 * in the SCSI query before calling the USCSI ioctl. The result of the
1180 1176 * CDB is returned in two places:
1181 1177 * cmd.uscsi_status The status of CDB execution
1182 1178 * cmd.uscsi_rqstatus The status of sense requests
1183 1179 * reply.error The general errno (ioctl)
1184 1180 *
1185 1181 * Parameters:
1186 1182 * session (input) - session pointer
1187 1183 * adapter_name (input) - name of SCSI adapter
1188 1184 * sid (input) - SCSI target ID
1189 1185 * lun (input) - LUN number
1190 1186 * request (input) - NDMP client CDB request
1191 1187 *
1192 1188 * Returns:
1193 1189 * void
1194 1190 */
1195 1191 /*ARGSUSED*/
1196 1192 void
1197 1193 ndmp_execute_cdb(ndmpd_session_t *session, char *adapter_name, int sid, int lun,
1198 1194 ndmp_execute_cdb_request *request)
1199 1195 {
1200 1196 ndmp_execute_cdb_reply reply;
1201 1197 struct uscsi_cmd cmd;
1202 1198 int fd;
1203 1199 struct open_list *olp;
1204 1200 char rq_buf[255];
1205 1201
1206 1202 (void) memset((void *)&cmd, 0, sizeof (cmd));
1207 1203 (void) memset((void *)&reply, 0, sizeof (reply));
1208 1204 (void) memset((void *)rq_buf, 0, sizeof (rq_buf));
1209 1205
1210 1206 if (request->flags == NDMP_SCSI_DATA_IN) {
1211 1207 cmd.uscsi_flags = USCSI_READ | USCSI_RQENABLE;
1212 1208 if ((cmd.uscsi_bufaddr =
1213 1209 ndmp_malloc(request->datain_len)) == 0) {
1214 1210 reply.error = NDMP_NO_MEM_ERR;
1215 1211 if (ndmp_send_response(session->ns_connection,
1216 1212 NDMP_NO_ERR, (void *)&reply) < 0)
1217 1213 NDMP_LOG(LOG_DEBUG, "error sending"
1218 1214 " scsi_execute_cdb reply.");
1219 1215 return;
1220 1216 }
1221 1217
1222 1218 cmd.uscsi_buflen = request->datain_len;
1223 1219 } else if (request->flags == NDMP_SCSI_DATA_OUT) {
1224 1220 cmd.uscsi_flags = USCSI_WRITE | USCSI_RQENABLE;
1225 1221 cmd.uscsi_bufaddr = request->dataout.dataout_val;
1226 1222 cmd.uscsi_buflen = request->dataout.dataout_len;
1227 1223 } else {
1228 1224 cmd.uscsi_flags = USCSI_RQENABLE;
1229 1225 cmd.uscsi_bufaddr = 0;
1230 1226 cmd.uscsi_buflen = 0;
1231 1227 }
1232 1228 cmd.uscsi_rqlen = sizeof (rq_buf);
1233 1229 cmd.uscsi_rqbuf = rq_buf;
1234 1230
1235 1231 cmd.uscsi_timeout = (request->timeout < 1000) ?
1236 1232 1 : (request->timeout / 1000);
1237 1233
1238 1234 cmd.uscsi_cdb = (caddr_t)request->cdb.cdb_val;
1239 1235 cmd.uscsi_cdblen = request->cdb.cdb_len;
1240 1236
1241 1237 NDMP_LOG(LOG_DEBUG, "cmd: 0x%x, len: %d, flags: %d, datain_len: %d",
1242 1238 request->cdb.cdb_val[0] & 0xff, request->cdb.cdb_len,
1243 1239 request->flags, request->datain_len);
1244 1240 NDMP_LOG(LOG_DEBUG, "dataout_len: %d, timeout: %d",
1245 1241 request->dataout.dataout_len, request->timeout);
1246 1242
1247 1243 if (request->cdb.cdb_len > 12) {
1248 1244 reply.error = NDMP_ILLEGAL_ARGS_ERR;
1249 1245 ndmp_send_reply(session->ns_connection, (void *) &reply,
1250 1246 "sending execute_cdb reply");
1251 1247 if (request->flags == NDMP_SCSI_DATA_IN)
1252 1248 free(cmd.uscsi_bufaddr);
1253 1249 return;
1254 1250 }
1255 1251
1256 1252 reply.error = NDMP_NO_ERR;
1257 1253
1258 1254 if ((olp = ndmp_open_list_find(adapter_name, sid, lun)) != NULL) {
1259 1255 fd = olp->ol_fd;
1260 1256 } else {
1261 1257 reply.error = NDMP_DEV_NOT_OPEN_ERR;
1262 1258 ndmp_send_reply(session->ns_connection, (void *) &reply,
1263 1259 "sending execute_cdb reply");
1264 1260 if (request->flags == NDMP_SCSI_DATA_IN)
1265 1261 free(cmd.uscsi_bufaddr);
1266 1262 return;
1267 1263 }
1268 1264
1269 1265 if (ioctl(fd, USCSICMD, &cmd) < 0) {
1270 1266 if (errno != EIO && errno != 0)
1271 1267 NDMP_LOG(LOG_ERR,
1272 1268 "Failed to send command to device: %m");
1273 1269 NDMP_LOG(LOG_DEBUG, "ioctl(USCSICMD) error: %m");
1274 1270 if (cmd.uscsi_status == 0)
1275 1271 reply.error = NDMP_IO_ERR;
1276 1272 }
1277 1273
1278 1274 reply.status = cmd.uscsi_status;
1279 1275
1280 1276 if (request->flags == NDMP_SCSI_DATA_IN) {
1281 1277 reply.datain.datain_len = cmd.uscsi_buflen;
1282 1278 reply.datain.datain_val = cmd.uscsi_bufaddr;
1283 1279 } else {
1284 1280 reply.dataout_len = request->dataout.dataout_len;
1285 1281 }
1286 1282
1287 1283 reply.ext_sense.ext_sense_len = cmd.uscsi_rqlen - cmd.uscsi_rqresid;
1288 1284 reply.ext_sense.ext_sense_val = rq_buf;
1289 1285
1290 1286 if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
1291 1287 (void *)&reply) < 0)
1292 1288 NDMP_LOG(LOG_DEBUG, "Error sending scsi_execute_cdb reply.");
1293 1289
1294 1290 if (request->flags == NDMP_SCSI_DATA_IN)
1295 1291 free(cmd.uscsi_bufaddr);
1296 1292 }
1297 1293
1298 1294
1299 1295 /*
1300 1296 * ndmp_stop_local_reader
1301 1297 *
1302 1298 * Stops a mover reader thread (for local backup only)
1303 1299 *
1304 1300 * Parameters:
1305 1301 * session (input) - session pointer
1306 1302 * cmds (input) - reader/writer command struct
1307 1303 *
1308 1304 * Returns:
1309 1305 * void
1310 1306 */
1311 1307 void
1312 1308 ndmp_stop_local_reader(ndmpd_session_t *session, tlm_commands_t *cmds)
1313 1309 {
1314 1310 ndmp_lbr_params_t *nlp;
1315 1311
1316 1312 if (session != NULL && session->ns_data.dd_sock == -1) {
1317 1313 /* 2-way restore */
1318 1314 if (cmds != NULL && cmds->tcs_reader_count > 0) {
1319 1315 if ((nlp = ndmp_get_nlp(session)) != NULL) {
1320 1316 (void) mutex_lock(&nlp->nlp_mtx);
1321 1317 cmds->tcs_command->tc_reader = TLM_STOP;
1322 1318 (void) cond_broadcast(&nlp->nlp_cv);
1323 1319 (void) mutex_unlock(&nlp->nlp_mtx);
1324 1320 }
1325 1321 }
1326 1322 }
1327 1323 }
1328 1324
1329 1325
1330 1326 /*
1331 1327 * Stops a mover reader thread (for remote backup only)
1332 1328 *
1333 1329 * Parameters:
1334 1330 * session (input) - session pointer
1335 1331 * cmds (input) - reader/writer command struct
1336 1332 *
1337 1333 * Returns:
1338 1334 * void
1339 1335 */
1340 1336 void
1341 1337 ndmp_stop_remote_reader(ndmpd_session_t *session)
1342 1338 {
1343 1339 if (session != NULL) {
1344 1340 if (session->ns_data.dd_sock >= 0) {
1345 1341 /*
1346 1342 * 3-way restore.
1347 1343 */
1348 1344 NDMP_LOG(LOG_DEBUG,
1349 1345 "data.sock: %d", session->ns_data.dd_sock);
1350 1346 (void) close(session->ns_data.dd_sock);
1351 1347 session->ns_data.dd_sock = -1;
1352 1348 }
1353 1349 }
1354 1350 }
1355 1351
1356 1352
1357 1353 /*
1358 1354 * ndmp_wait_for_reader
1359 1355 *
1360 1356 * Wait for a reader until get done (busy wait)
1361 1357 */
1362 1358 void
1363 1359 ndmp_wait_for_reader(tlm_commands_t *cmds)
1364 1360 {
1365 1361 if (cmds == NULL) {
1366 1362 NDMP_LOG(LOG_DEBUG, "cmds == NULL");
1367 1363 } else {
1368 1364 NDMP_LOG(LOG_DEBUG,
1369 1365 "reader_count: %d", cmds->tcs_reader_count);
1370 1366
1371 1367 while (cmds->tcs_reader_count > 0)
1372 1368 (void) sleep(1);
1373 1369 }
1374 1370 }
1375 1371
1376 1372
1377 1373 /*
1378 1374 * ndmp_open_list_find
1379 1375 *
1380 1376 * Find a specific device in the open list
1381 1377 *
1382 1378 * Parameters:
1383 1379 * dev (input) - device name
1384 1380 * sid (input) - SCSI target ID
1385 1381 * lun (input) - LUN number
1386 1382 *
1387 1383 * Returns:
1388 1384 * pointer to the open list entry
1389 1385 */
1390 1386 struct open_list *
1391 1387 ndmp_open_list_find(char *dev, int sid, int lun)
1392 1388 {
1393 1389 struct ol_head *olhp;
1394 1390 struct open_list *olp;
1395 1391
1396 1392 if (dev == NULL || *dev == '\0') {
1397 1393 NDMP_LOG(LOG_DEBUG, "Invalid argument");
1398 1394 return (NULL);
1399 1395 }
1400 1396
1401 1397 (void) mutex_lock(&ol_mutex);
1402 1398 olhp = &ol_head;
1403 1399 for (olp = LIST_FIRST(olhp); olp != NULL; olp = LIST_NEXT(olp, ol_q))
1404 1400 if (strcmp(olp->ol_devnm, dev) == 0 && olp->ol_sid == sid &&
1405 1401 olp->ol_lun == lun) {
1406 1402 (void) mutex_unlock(&ol_mutex);
1407 1403 return (olp);
1408 1404 }
1409 1405
1410 1406 (void) mutex_unlock(&ol_mutex);
1411 1407 return (NULL);
1412 1408 }
1413 1409
1414 1410
1415 1411 /*
1416 1412 * ndmp_open_list_add
1417 1413 *
1418 1414 * Add a specific device to the open list
1419 1415 *
1420 1416 * Parameters:
1421 1417 * conn (input) - connection pointer
1422 1418 * dev (input) - device name
1423 1419 * sid (input) - SCSI target ID
1424 1420 * lun (input) - LUN number
1425 1421 * fd (input) - the device file descriptor
1426 1422 *
1427 1423 * Returns:
1428 1424 * errno
1429 1425 */
1430 1426 int
1431 1427 ndmp_open_list_add(ndmp_connection_t *conn, char *dev, int sid, int lun, int fd)
1432 1428 {
1433 1429 int err;
1434 1430 struct ol_head *olhp;
1435 1431 struct open_list *olp;
1436 1432
1437 1433 if (dev == NULL || *dev == '\0') {
1438 1434 NDMP_LOG(LOG_DEBUG, "Invalid argument");
1439 1435 return (EINVAL);
1440 1436 }
1441 1437 NDMP_LOG(LOG_DEBUG,
1442 1438 "conn: 0x%08x, dev: %s, sid: %d, lun: %d", conn, dev, sid, lun);
1443 1439
1444 1440 err = 0;
1445 1441 olhp = &ol_head;
1446 1442
1447 1443 if ((olp = ndmp_open_list_find(dev, sid, lun)) != NULL) {
1448 1444 NDMP_LOG(LOG_DEBUG, "already in list");
1449 1445 /*
1450 1446 * The adapter handle can be opened many times by the clients.
1451 1447 * Only when the target is set, we must check and reject the
1452 1448 * open request if the device is already being used by another
1453 1449 * session.
1454 1450 */
1455 1451 if (sid == -1)
1456 1452 olp->ol_nref++;
1457 1453 else
1458 1454 err = EBUSY;
1459 1455 } else if ((olp = ndmp_malloc(sizeof (struct open_list))) == NULL) {
1460 1456 err = ENOMEM;
1461 1457 } else if ((olp->ol_devnm = strdup(dev)) == NULL) {
1462 1458 NDMP_LOG(LOG_ERR, "Out of memory.");
1463 1459 free(olp);
1464 1460 err = ENOMEM;
1465 1461 } else {
1466 1462 olp->cl_conn = conn;
1467 1463 olp->ol_nref = 1;
1468 1464 olp->ol_sid = sid;
1469 1465 olp->ol_lun = lun;
1470 1466 if (fd > 0)
1471 1467 olp->ol_fd = fd;
1472 1468 else
1473 1469 olp->ol_fd = -1;
1474 1470 (void) mutex_lock(&ol_mutex);
1475 1471 LIST_INSERT_HEAD(olhp, olp, ol_q);
1476 1472 (void) mutex_unlock(&ol_mutex);
1477 1473 }
1478 1474
1479 1475 return (err);
1480 1476 }
1481 1477
1482 1478
1483 1479 /*
1484 1480 * ndmp_open_list_del
1485 1481 *
1486 1482 * Delete a specific device from the open list
1487 1483 *
1488 1484 * Parameters:
1489 1485 * dev (input) - device name
1490 1486 * sid (input) - SCSI target ID
1491 1487 * lun (input) - LUN number
1492 1488 *
1493 1489 * Returns:
1494 1490 * errno
1495 1491 */
1496 1492 int
1497 1493 ndmp_open_list_del(char *dev, int sid, int lun)
1498 1494 {
1499 1495 struct open_list *olp;
1500 1496
1501 1497 if (dev == NULL || *dev == '\0') {
1502 1498 NDMP_LOG(LOG_DEBUG, "Invalid argument");
1503 1499 return (EINVAL);
1504 1500 }
1505 1501 if ((olp = ndmp_open_list_find(dev, sid, lun)) == NULL) {
1506 1502 NDMP_LOG(LOG_DEBUG, "%s not found", dev);
1507 1503 return (ENOENT);
1508 1504 }
1509 1505
1510 1506 (void) mutex_lock(&ol_mutex);
1511 1507 if (--olp->ol_nref <= 0) {
1512 1508 NDMP_LOG(LOG_DEBUG,
1513 1509 "Removed dev: %s, sid: %d, lun: %d", dev, sid, lun);
1514 1510 LIST_REMOVE(olp, ol_q);
1515 1511 free(olp->ol_devnm);
1516 1512 free(olp);
1517 1513 }
1518 1514 (void) mutex_unlock(&ol_mutex);
1519 1515
1520 1516 return (0);
1521 1517 }
1522 1518
1523 1519
1524 1520 /*
1525 1521 * ndmp_open_list_release
1526 1522 *
1527 1523 * Close all the resources belonging to this connection.
1528 1524 *
1529 1525 * Parameters:
1530 1526 * ndmp_connection_t *conn : connection identifier
1531 1527 *
1532 1528 * Returns:
1533 1529 * void
1534 1530 */
1535 1531 void
1536 1532 ndmp_open_list_release(ndmp_connection_t *conn)
1537 1533 {
1538 1534 struct ol_head *olhp = &ol_head;
1539 1535 struct open_list *olp;
1540 1536 struct open_list *next;
1541 1537
1542 1538 (void) mutex_lock(&ol_mutex);
1543 1539 olp = LIST_FIRST(olhp);
1544 1540 while (olp != NULL) {
1545 1541 next = LIST_NEXT(olp, ol_q);
1546 1542 NDMP_LOG(LOG_DEBUG, "olp->conn 0x%08x", olp->cl_conn);
1547 1543 if (olp->cl_conn == conn) {
1548 1544 NDMP_LOG(LOG_DEBUG,
1549 1545 "Removed dev: %s, sid: %d, lun: %d",
1550 1546 olp->ol_devnm, olp->ol_sid, olp->ol_lun);
1551 1547 LIST_REMOVE(olp, ol_q);
1552 1548 if (olp->ol_fd > 0)
1553 1549 (void) close(olp->ol_fd);
1554 1550 free(olp->ol_devnm);
1555 1551 free(olp);
1556 1552 }
1557 1553 olp = next;
1558 1554 }
1559 1555 (void) mutex_unlock(&ol_mutex);
1560 1556 }
1561 1557
1562 1558
1563 1559 /*
1564 1560 * ndmp_stop_buffer_worker
1565 1561 *
1566 1562 * Stop all reader and writer threads for a specific buffer.
1567 1563 *
1568 1564 * Parameters:
1569 1565 * session (input) - session pointer
1570 1566 *
1571 1567 * Returns:
1572 1568 * void
1573 1569 */
1574 1570 void
1575 1571 ndmp_stop_buffer_worker(ndmpd_session_t *session)
1576 1572 {
1577 1573 ndmp_lbr_params_t *nlp;
1578 1574 tlm_commands_t *cmds;
1579 1575
1580 1576 session->ns_tape.td_pos = 0;
1581 1577 if ((nlp = ndmp_get_nlp(session)) == NULL) {
1582 1578 NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1583 1579 } else {
1584 1580 cmds = &nlp->nlp_cmds;
1585 1581 if (cmds->tcs_command == NULL) {
1586 1582 NDMP_LOG(LOG_DEBUG, "cmds->tcs_command == NULL");
1587 1583 } else {
1588 1584 cmds->tcs_reader = cmds->tcs_writer = TLM_ABORT;
1589 1585 cmds->tcs_command->tc_reader = TLM_ABORT;
1590 1586 cmds->tcs_command->tc_writer = TLM_ABORT;
1591 1587 while (cmds->tcs_reader_count > 0 ||
1592 1588 cmds->tcs_writer_count > 0) {
1593 1589 NDMP_LOG(LOG_DEBUG,
1594 1590 "trying to stop buffer worker");
1595 1591 (void) sleep(1);
1596 1592 }
1597 1593 }
1598 1594 }
1599 1595 }
1600 1596
1601 1597
1602 1598 /*
1603 1599 * ndmp_stop_reader_thread
1604 1600 *
1605 1601 * Stop only the reader threads of a specific buffer
1606 1602 *
1607 1603 * Parameters:
1608 1604 * session (input) - session pointer
1609 1605 *
1610 1606 * Returns:
1611 1607 * void
1612 1608 */
1613 1609 void
1614 1610 ndmp_stop_reader_thread(ndmpd_session_t *session)
1615 1611 {
1616 1612 ndmp_lbr_params_t *nlp;
1617 1613 tlm_commands_t *cmds;
1618 1614
1619 1615 if ((nlp = ndmp_get_nlp(session)) == NULL) {
1620 1616 NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1621 1617 } else {
1622 1618 cmds = &nlp->nlp_cmds;
1623 1619 if (cmds->tcs_command == NULL) {
1624 1620 NDMP_LOG(LOG_DEBUG, "cmds->tcs_command == NULL");
1625 1621 } else {
1626 1622 cmds->tcs_reader = TLM_ABORT;
1627 1623 cmds->tcs_command->tc_reader = TLM_ABORT;
1628 1624 while (cmds->tcs_reader_count > 0) {
1629 1625 NDMP_LOG(LOG_DEBUG,
1630 1626 "trying to stop reader thread");
1631 1627 (void) sleep(1);
1632 1628 }
1633 1629 }
1634 1630 }
1635 1631 }
1636 1632
1637 1633
1638 1634 /*
1639 1635 * ndmp_stop_reader_thread
1640 1636 *
1641 1637 * Stop only the writer threads of a specific buffer
1642 1638 *
1643 1639 * Parameters:
1644 1640 * session (input) - session pointer
1645 1641 *
1646 1642 * Returns:
1647 1643 * void
1648 1644 */
1649 1645 void
1650 1646 ndmp_stop_writer_thread(ndmpd_session_t *session)
1651 1647 {
1652 1648 ndmp_lbr_params_t *nlp;
1653 1649 tlm_commands_t *cmds;
1654 1650
1655 1651 if ((nlp = ndmp_get_nlp(session)) == NULL) {
1656 1652 NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1657 1653 } else {
1658 1654 cmds = &nlp->nlp_cmds;
1659 1655 if (cmds->tcs_command == NULL) {
1660 1656 NDMP_LOG(LOG_DEBUG, "cmds->tcs_command == NULL");
1661 1657 } else {
1662 1658 (void) mutex_lock(&nlp->nlp_mtx);
1663 1659 cmds->tcs_writer = TLM_ABORT;
1664 1660 cmds->tcs_command->tc_writer = TLM_ABORT;
1665 1661 (void) cond_broadcast(&nlp->nlp_cv);
1666 1662 (void) mutex_unlock(&nlp->nlp_mtx);
1667 1663 while (cmds->tcs_writer_count > 0) {
1668 1664 NDMP_LOG(LOG_DEBUG,
1669 1665 "trying to stop writer thread");
1670 1666 (void) sleep(1);
1671 1667 }
1672 1668 }
1673 1669 }
1674 1670 }
1675 1671
1676 1672
1677 1673 /*
1678 1674 * ndmp_free_reader_writer_ipc
1679 1675 *
1680 1676 * Free and release the reader/writer buffers and the IPC structure
1681 1677 * for reader and writer threads.
1682 1678 *
1683 1679 * Parameters:
1684 1680 * session (input) - session pointer
1685 1681 *
1686 1682 * Returns:
1687 1683 * void
1688 1684 */
1689 1685 void
1690 1686 ndmp_free_reader_writer_ipc(ndmpd_session_t *session)
1691 1687 {
1692 1688 ndmp_lbr_params_t *nlp;
1693 1689 tlm_commands_t *cmds;
1694 1690
1695 1691 if ((nlp = ndmp_get_nlp(session)) != NULL) {
1696 1692 cmds = &nlp->nlp_cmds;
1697 1693 if (cmds->tcs_command != NULL) {
1698 1694 NDMP_LOG(LOG_DEBUG, "cmds->tcs_command->tc_ref: %d",
1699 1695 cmds->tcs_command->tc_ref);
1700 1696 tlm_release_reader_writer_ipc(cmds->tcs_command);
1701 1697 }
1702 1698 }
1703 1699 }
1704 1700
1705 1701
1706 1702 /*
1707 1703 * ndmp_waitfor_op
1708 1704 *
1709 1705 * Wait for a session reference count to drop to zero
1710 1706 *
1711 1707 * Parameters:
1712 1708 * session (input) - session pointer
1713 1709 *
1714 1710 * Returns:
1715 1711 * void
1716 1712 */
1717 1713 void
1718 1714 ndmp_waitfor_op(ndmpd_session_t *session)
1719 1715 {
1720 1716 if (session != NULL) {
1721 1717 while (session->ns_nref > 0) {
1722 1718 (void) sleep(1);
1723 1719 NDMP_LOG(LOG_DEBUG,
1724 1720 "waiting for session nref: %d", session->ns_nref);
1725 1721 }
1726 1722 }
1727 1723 }
1728 1724
1729 1725
1730 1726 /*
1731 1727 * ndmp_session_ref
1732 1728 *
1733 1729 * Increment the reference count of the session
1734 1730 *
1735 1731 * Parameters:
1736 1732 * session (input) - session pointer
1737 1733 *
1738 1734 * Returns:
1739 1735 * void
1740 1736 */
1741 1737 void
1742 1738 ndmp_session_ref(ndmpd_session_t *session)
1743 1739 {
1744 1740 (void) mutex_lock(&session->ns_lock);
1745 1741 session->ns_nref++;
1746 1742 (void) mutex_unlock(&session->ns_lock);
1747 1743 }
1748 1744
1749 1745
1750 1746 /*
1751 1747 * ndmp_session_unref
1752 1748 *
1753 1749 * Decrement the reference count of the session
1754 1750 *
1755 1751 * Parameters:
1756 1752 * session (input) - session pointer
1757 1753 *
1758 1754 * Returns:
1759 1755 * void
1760 1756 */
1761 1757 void
1762 1758 ndmp_session_unref(ndmpd_session_t *session)
1763 1759 {
1764 1760 (void) mutex_lock(&session->ns_lock);
1765 1761 session->ns_nref--;
1766 1762 (void) mutex_unlock(&session->ns_lock);
1767 1763 }
1768 1764
1769 1765
1770 1766 /*
1771 1767 * ndmp_addr2str_v3
1772 1768 *
1773 1769 * Convert the address type to a string
1774 1770 *
1775 1771 * Parameters:
1776 1772 * type (input) - address type
1777 1773 *
1778 1774 * Returns:
1779 1775 * type in string
1780 1776 */
1781 1777 char *
1782 1778 ndmp_addr2str_v3(ndmp_addr_type type)
1783 1779 {
1784 1780 char *rv;
1785 1781
1786 1782 switch (type) {
1787 1783 case NDMP_ADDR_LOCAL:
1788 1784 rv = "Local";
1789 1785 break;
1790 1786 case NDMP_ADDR_TCP:
1791 1787 rv = "TCP";
1792 1788 break;
1793 1789 case NDMP_ADDR_FC:
1794 1790 rv = "FC";
1795 1791 break;
1796 1792 case NDMP_ADDR_IPC:
1797 1793 rv = "IPC";
1798 1794 break;
1799 1795 default:
1800 1796 rv = "Unknown";
1801 1797 }
1802 1798
1803 1799 return (rv);
1804 1800 }
1805 1801
1806 1802
1807 1803 /*
1808 1804 * ndmp_valid_v3addr_type
1809 1805 *
1810 1806 * Make sure that the NDMP address is from any of the
1811 1807 * valid types
1812 1808 *
1813 1809 * Parameters:
1814 1810 * type (input) - address type
1815 1811 *
1816 1812 * Returns:
1817 1813 * 1: valid
1818 1814 * 0: invalid
1819 1815 */
1820 1816 boolean_t
1821 1817 ndmp_valid_v3addr_type(ndmp_addr_type type)
1822 1818 {
1823 1819 boolean_t rv;
1824 1820
1825 1821 switch (type) {
1826 1822 case NDMP_ADDR_LOCAL:
1827 1823 case NDMP_ADDR_TCP:
1828 1824 case NDMP_ADDR_FC:
1829 1825 case NDMP_ADDR_IPC:
1830 1826 rv = TRUE;
1831 1827 break;
1832 1828 default:
1833 1829 rv = FALSE;
1834 1830 }
1835 1831
1836 1832 return (rv);
1837 1833 }
1838 1834
1839 1835
1840 1836 /*
1841 1837 * ndmp_copy_addr_v3
1842 1838 *
1843 1839 * Copy NDMP address from source to destination (V2 and V3 only)
1844 1840 *
1845 1841 * Parameters:
1846 1842 * dst (ouput) - destination address
1847 1843 * src (input) - source address
1848 1844 *
1849 1845 * Returns:
1850 1846 * void
1851 1847 */
1852 1848 void
1853 1849 ndmp_copy_addr_v3(ndmp_addr_v3 *dst, ndmp_addr_v3 *src)
1854 1850 {
1855 1851 dst->addr_type = src->addr_type;
1856 1852 switch (src->addr_type) {
1857 1853 case NDMP_ADDR_LOCAL:
1858 1854 /* nothing */
1859 1855 break;
1860 1856 case NDMP_ADDR_TCP:
1861 1857 dst->tcp_ip_v3 = htonl(src->tcp_ip_v3);
1862 1858 dst->tcp_port_v3 = src->tcp_port_v3;
1863 1859 break;
1864 1860 case NDMP_ADDR_FC:
1865 1861 case NDMP_ADDR_IPC:
1866 1862 default:
1867 1863 break;
1868 1864 }
1869 1865 }
1870 1866
1871 1867
1872 1868 /*
1873 1869 * ndmp_copy_addr_v4
1874 1870 *
1875 1871 * Copy NDMP address from source to destination. V4 has a extra
1876 1872 * environment list inside the address too which needs to be copied.
1877 1873 *
1878 1874 * Parameters:
1879 1875 * dst (ouput) - destination address
1880 1876 * src (input) - source address
1881 1877 *
1882 1878 * Returns:
1883 1879 * void
1884 1880 */
1885 1881 void
1886 1882 ndmp_copy_addr_v4(ndmp_addr_v4 *dst, ndmp_addr_v4 *src)
1887 1883 {
1888 1884 int i;
1889 1885
1890 1886 dst->addr_type = src->addr_type;
1891 1887 dst->tcp_len_v4 = src->tcp_len_v4;
1892 1888 switch (src->addr_type) {
1893 1889 case NDMP_ADDR_LOCAL:
1894 1890 /* nothing */
1895 1891 break;
1896 1892 case NDMP_ADDR_TCP:
1897 1893 dst->tcp_addr_v4 = ndmp_malloc(sizeof (ndmp_tcp_addr_v4) *
1898 1894 src->tcp_len_v4);
1899 1895 if (dst->tcp_addr_v4 == 0)
1900 1896 return;
1901 1897
1902 1898 for (i = 0; i < src->tcp_len_v4; i++) {
1903 1899 dst->tcp_ip_v4(i) = htonl(src->tcp_ip_v4(i));
1904 1900 dst->tcp_port_v4(i) = src->tcp_port_v4(i);
1905 1901 dst->tcp_env_v4(i).addr_env_len = 0; /* Solaris */
1906 1902 dst->tcp_env_v4(i).addr_env_val = 0; /* Solaris */
1907 1903 }
1908 1904 break;
1909 1905 case NDMP_ADDR_FC:
1910 1906 case NDMP_ADDR_IPC:
1911 1907 default:
1912 1908 break;
1913 1909 }
1914 1910 }
1915 1911
1916 1912
1917 1913 /*
1918 1914 * ndmp_connect_sock_v3
1919 1915 *
1920 1916 * Creates a socket and connects to the specified address/port
1921 1917 *
1922 1918 * Parameters:
1923 1919 * addr (input) - IP address
1924 1920 * port (input) - port number
1925 1921 *
1926 1922 * Returns:
1927 1923 * 0: on success
1928 1924 * -1: otherwise
1929 1925 */
1930 1926 int
1931 1927 ndmp_connect_sock_v3(ulong_t addr, ushort_t port)
1932 1928 {
1933 1929 int sock;
1934 1930 struct sockaddr_in sin;
1935 1931
1936 1932 NDMP_LOG(LOG_DEBUG, "addr %s:%d", inet_ntoa(IN_ADDR(addr)), port);
1937 1933
1938 1934 sock = socket(AF_INET, SOCK_STREAM, 0);
1939 1935 if (sock < 0) {
1940 1936 NDMP_LOG(LOG_DEBUG, "Socket error: %m");
1941 1937 return (-1);
1942 1938 }
1943 1939
1944 1940 (void) memset((void *) &sin, 0, sizeof (sin));
1945 1941 sin.sin_family = AF_INET;
1946 1942 sin.sin_addr.s_addr = htonl(addr);
1947 1943 sin.sin_port = htons(port);
1948 1944 if (connect(sock, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
1949 1945 NDMP_LOG(LOG_DEBUG, "Connect error: %m");
1950 1946 (void) close(sock);
1951 1947 return (-1);
1952 1948 }
1953 1949
1954 1950 set_socket_options(sock);
1955 1951 NDMP_LOG(LOG_DEBUG, "sock %d", sock);
1956 1952
1957 1953 return (sock);
1958 1954 }
1959 1955
1960 1956 /*
1961 1957 * ndmp_create_socket
1962 1958 *
1963 1959 * Creates a socket for listening for accepting data connections.
1964 1960 *
1965 1961 * Parameters:
1966 1962 * session (input) - session pointer.
1967 1963 * addr (output) - location to store address of socket.
1968 1964 * port (output) - location to store port of socket.
1969 1965 *
1970 1966 * Returns:
1971 1967 * 0 - success.
1972 1968 * -1 - error.
1973 1969 */
1974 1970 int
1975 1971 ndmp_create_socket(ulong_t *addr, ushort_t *port)
1976 1972 {
1977 1973 char *p;
1978 1974 int length;
1979 1975 int sd;
1980 1976 struct sockaddr_in sin;
1981 1977
1982 1978 /* Try the user's prefered NIC IP address */
1983 1979 p = ndmpd_get_prop(NDMP_MOVER_NIC);
1984 1980
1985 1981 /* Try host's IP address */
1986 1982 if (!p || *p == 0)
1987 1983 p = gethostaddr();
1988 1984
1989 1985 /* Try default NIC's IP address (if DNS failed) */
1990 1986 if (!p)
1991 1987 p = get_default_nic_addr();
1992 1988
1993 1989 /* Fail if no IP can be obtained */
1994 1990 if (!p) {
1995 1991 NDMP_LOG(LOG_ERR, "Undetermined network port.");
1996 1992 return (-1);
1997 1993 }
1998 1994
1999 1995 *addr = inet_addr(p);
2000 1996
2001 1997 sd = socket(AF_INET, SOCK_STREAM, 0);
2002 1998 if (sd < 0) {
2003 1999 NDMP_LOG(LOG_DEBUG, "Socket error: %m");
2004 2000 return (-1);
2005 2001 }
2006 2002 sin.sin_family = AF_INET;
2007 2003 sin.sin_addr.s_addr = INADDR_ANY;
2008 2004 sin.sin_port = 0;
2009 2005 length = sizeof (sin);
2010 2006
2011 2007 if (bind(sd, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
2012 2008 NDMP_LOG(LOG_DEBUG, "Bind error: %m");
2013 2009 (void) close(sd);
2014 2010 sd = -1;
2015 2011 } else if (getsockname(sd, (struct sockaddr *)&sin, &length) < 0) {
2016 2012 NDMP_LOG(LOG_DEBUG, "getsockname error: %m");
2017 2013 (void) close(sd);
2018 2014 sd = -1;
2019 2015 } else if (listen(sd, 5) < 0) {
2020 2016 NDMP_LOG(LOG_DEBUG, "Listen error: %m");
2021 2017 (void) close(sd);
2022 2018 sd = -1;
2023 2019 } else
2024 2020 *port = sin.sin_port;
2025 2021
2026 2022 return (sd);
2027 2023 }
2028 2024
2029 2025
2030 2026 /*
2031 2027 * cctime
2032 2028 *
2033 2029 * Convert the specified time into a string. It's like
2034 2030 * ctime(), but:
2035 2031 * - chops the trailing '\n' of ctime.
2036 2032 * - and returns "the epoch" if time is 0.
2037 2033 *
2038 2034 * Returns:
2039 2035 * "": invalid argument.
2040 2036 * "the epoch": if time is 0.
2041 2037 * string format of the time.
2042 2038 */
2043 2039 char *
2044 2040 cctime(time_t *t)
2045 2041 {
2046 2042 char *bp, *cp;
2047 2043 static char tbuf[BUFSIZ];
2048 2044
2049 2045 if (!t)
2050 2046 return ("");
2051 2047
2052 2048 if (*t == (time_t)0)
2053 2049 return ("the epoch");
2054 2050
2055 2051 if ((bp = ctime_r(t, tbuf, BUFSIZ)) == NULL)
2056 2052 return ("");
2057 2053
2058 2054 cp = strchr(bp, '\n');
2059 2055 if (cp)
2060 2056 *cp = '\0';
2061 2057
2062 2058 return (bp);
2063 2059 }
2064 2060
2065 2061
2066 2062 /*
2067 2063 * ndmp_new_job_name
2068 2064 *
2069 2065 * Create a job name for each backup/restore to keep track
2070 2066 *
2071 2067 * Parameters:
2072 2068 * jname (output) - job name
2073 2069 *
2074 2070 * Returns:
2075 2071 * jname
2076 2072 */
2077 2073 char *
2078 2074 ndmp_new_job_name(char *jname)
2079 2075 {
2080 2076 if (jname != NULL) {
2081 2077 (void) snprintf(jname, TLM_MAX_BACKUP_JOB_NAME, "%s%d",
2082 2078 NDMP_RCF_BASENAME, ndmp_job_cnt++);
2083 2079 NDMP_LOG(LOG_DEBUG, "jname: \"%s\"", jname);
2084 2080 }
2085 2081
2086 2082 return (jname);
2087 2083 }
2088 2084
2089 2085
2090 2086 /*
2091 2087 * fs_is_valid_logvol
2092 2088 *
2093 2089 * Check if the log path exists
2094 2090 *
2095 2091 * Parameters:
2096 2092 * path (input) - log path
2097 2093 *
2098 2094 * Returns:
2099 2095 * FALSE: invalid
2100 2096 * TRUE: valid
2101 2097 */
2102 2098 boolean_t
2103 2099 fs_is_valid_logvol(char *path)
2104 2100 {
2105 2101 struct stat64 st;
2106 2102
2107 2103 if (stat64(path, &st) < 0)
2108 2104 return (FALSE);
2109 2105
2110 2106 return (TRUE);
2111 2107 }
2112 2108
2113 2109
2114 2110 /*
2115 2111 * ndmpd_mk_temp
2116 2112 *
2117 2113 * Make a temporary file using the working directory path and the
2118 2114 * jobname
2119 2115 *
2120 2116 * Parameters:
2121 2117 * buf (output) - the temporary file name path
2122 2118 *
2123 2119 * Returns:
2124 2120 * buf
2125 2121 */
2126 2122 char *
2127 2123 ndmpd_mk_temp(char *buf)
2128 2124 {
2129 2125 char fname[TLM_MAX_BACKUP_JOB_NAME];
2130 2126 const char *dir;
2131 2127 char *rv;
2132 2128
2133 2129 if (!buf)
2134 2130 return (NULL);
2135 2131
2136 2132 dir = ndmpd_get_prop(NDMP_DEBUG_PATH);
2137 2133 if (dir == 0 || *dir == '\0') {
2138 2134 NDMP_LOG(LOG_DEBUG, "NDMP work path not specified");
2139 2135 return (0);
2140 2136 }
2141 2137
2142 2138 if (!fs_is_valid_logvol((char *)dir)) {
2143 2139 NDMP_LOG(LOG_ERR,
2144 2140 "Log file path cannot be on system volumes.");
2145 2141 return (0);
2146 2142 }
2147 2143
2148 2144 dir += strspn(dir, " \t");
2149 2145 if (!*dir) {
2150 2146 NDMP_LOG(LOG_DEBUG, "NDMP work path not specified");
2151 2147 return (0);
2152 2148 }
2153 2149
2154 2150 rv = buf;
2155 2151 (void) ndmp_new_job_name(fname);
2156 2152 (void) tlm_cat_path(buf, (char *)dir, fname);
2157 2153
2158 2154 return (rv);
2159 2155 }
2160 2156
2161 2157
2162 2158 /*
2163 2159 * ndmpd_make_bk_dir_path
2164 2160 *
2165 2161 * Make a directory path for temporary files under the NDMP
2166 2162 * working directory.
2167 2163 *
2168 2164 * Parameters:
2169 2165 * buf (output) - result path
2170 2166 * fname (input) - the file name
2171 2167 *
2172 2168 * Returns:
2173 2169 * buf
2174 2170 */
2175 2171 char *
2176 2172 ndmpd_make_bk_dir_path(char *buf, char *fname)
2177 2173 {
2178 2174 const char *p;
2179 2175 char *name;
2180 2176 char path[PATH_MAX];
2181 2177
2182 2178 if (!buf || !fname || !*fname)
2183 2179 return (NULL);
2184 2180
2185 2181 p = ndmpd_get_prop(NDMP_DEBUG_PATH);
2186 2182 if (p == NULL || *p == '\0' || !fs_is_valid_logvol((char *)p)) {
2187 2183 return (NULL);
2188 2184 }
2189 2185
2190 2186 (void) strlcpy(path, (char *)p, PATH_MAX);
2191 2187 (void) trim_whitespace(path);
2192 2188
2193 2189 if ((name = strrchr(fname, '/')) == 0)
2194 2190 name = fname;
2195 2191
2196 2192 (void) tlm_cat_path(buf, path, name);
2197 2193 return (buf);
2198 2194 }
2199 2195
2200 2196
2201 2197 /*
2202 2198 * ndmp_is_chkpnt_root
2203 2199 *
2204 2200 * Is this a root checkpoint (snapshot) directory.
2205 2201 * Note: a temporary function
2206 2202 */
2207 2203 boolean_t
2208 2204 ndmp_is_chkpnt_root(char *path)
2209 2205 {
2210 2206 struct stat64 st;
2211 2207
2212 2208 if (stat64(path, &st) != 0) {
2213 2209 NDMP_LOG(LOG_DEBUG, "Couldn't stat path \"%s\"", path);
2214 2210 return (TRUE);
2215 2211 }
2216 2212 return (FALSE);
2217 2213 }
2218 2214
2219 2215
2220 2216 /*
2221 2217 * ndmpd_make_exc_list
2222 2218 *
2223 2219 * Make a list of files that should not be backed up.
2224 2220 *
2225 2221 * Parameters:
2226 2222 * void
2227 2223 *
2228 2224 * Returns:
2229 2225 * list - array of character strings
2230 2226 */
2231 2227 char **
2232 2228 ndmpd_make_exc_list(void)
2233 2229 {
2234 2230 char *val, **cpp;
2235 2231 int i, n;
2236 2232
2237 2233 n = sizeof (exls);
2238 2234 if ((cpp = ndmp_malloc(n)) != NULL) {
2239 2235 for (i = 0; exls[i] != NULL; i++)
2240 2236 cpp[i] = exls[i];
2241 2237
2242 2238 /*
2243 2239 * If ndmpd_get_prop returns NULL, the array will be
2244 2240 * null-terminated.
2245 2241 */
2246 2242 val = ndmpd_get_prop(NDMP_DEBUG_PATH);
2247 2243 cpp[i] = val;
2248 2244 }
2249 2245
2250 2246 return (cpp);
2251 2247 }
2252 2248
2253 2249
2254 2250 /*
2255 2251 * ndmp_get_bk_dir_ino
2256 2252 *
2257 2253 * Get the inode number of the backup directory
2258 2254 */
2259 2255 int
2260 2256 ndmp_get_bk_dir_ino(ndmp_lbr_params_t *nlp)
2261 2257 {
2262 2258 int rv;
2263 2259 struct stat64 st;
2264 2260
2265 2261 if (stat64(nlp->nlp_backup_path, &st) != 0) {
2266 2262 rv = -1;
2267 2263 NDMP_LOG(LOG_DEBUG, "Getting inode # of \"%s\"",
2268 2264 nlp->nlp_backup_path);
2269 2265 } else {
2270 2266 rv = 0;
2271 2267 nlp->nlp_bkdirino = st.st_ino;
2272 2268 NDMP_LOG(LOG_DEBUG, "nlp_bkdirino: %lu",
2273 2269 (uint_t)nlp->nlp_bkdirino);
2274 2270 }
2275 2271
2276 2272 return (rv);
2277 2273 }
2278 2274
2279 2275
2280 2276 /*
2281 2277 * ndmp_check_utf8magic
2282 2278 *
2283 2279 * Check if the magic string for exists in the tar header. This
2284 2280 * magic string (which also indicates that the file names are in
2285 2281 * UTF8 format) is used as a crest to indetify our own tapes.
2286 2282 * This checking is always done before all restores except DAR
2287 2283 * restores.
2288 2284 */
2289 2285 boolean_t
2290 2286 ndmp_check_utf8magic(tlm_cmd_t *cmd)
2291 2287 {
2292 2288 char *cp;
2293 2289 int err, len, actual_size;
2294 2290
2295 2291 if (cmd == NULL) {
2296 2292 NDMP_LOG(LOG_DEBUG, "cmd == NULL");
2297 2293 return (FALSE);
2298 2294 }
2299 2295 if (cmd->tc_buffers == NULL) {
2300 2296 NDMP_LOG(LOG_DEBUG, "cmd->tc_buffers == NULL");
2301 2297 return (FALSE);
2302 2298 }
2303 2299
2304 2300 /* wait until the first buffer gets full. */
2305 2301 tlm_buffer_in_buf_wait(cmd->tc_buffers);
2306 2302
2307 2303 err = actual_size = 0;
2308 2304 cp = tlm_get_read_buffer(RECORDSIZE, &err, cmd->tc_buffers,
2309 2305 &actual_size);
2310 2306 if (cp == NULL) {
2311 2307 NDMP_LOG(LOG_DEBUG, "Can't read from buffers, err: %d", err);
2312 2308 return (FALSE);
2313 2309 }
2314 2310 len = strlen(NDMPUTF8MAGIC);
2315 2311 if (actual_size < len) {
2316 2312 NDMP_LOG(LOG_DEBUG, "Not enough data in the buffers");
2317 2313 return (FALSE);
2318 2314 }
2319 2315
2320 2316 return ((strncmp(cp, NDMPUTF8MAGIC, len) == 0) ? TRUE : FALSE);
2321 2317 }
2322 2318
2323 2319
2324 2320 /*
2325 2321 * ndmp_get_cur_bk_time
2326 2322 *
2327 2323 * Get the backup checkpoint time.
2328 2324 */
2329 2325 int
2330 2326 ndmp_get_cur_bk_time(ndmp_lbr_params_t *nlp, time_t *tp, char *jname)
2331 2327 {
2332 2328 int err;
2333 2329
2334 2330 if (!nlp || !nlp->nlp_backup_path || !tp) {
2335 2331 NDMP_LOG(LOG_DEBUG, "Invalid argument");
2336 2332 return (-1);
2337 2333 }
2338 2334
2339 2335 if (!fs_is_chkpnt_enabled(nlp->nlp_backup_path)) {
2340 2336 NDMP_LOG(LOG_DEBUG, "Not a chkpnt volume %s",
2341 2337 nlp->nlp_backup_path);
2342 2338 *tp = time(NULL);
2343 2339 return (0);
2344 2340 }
2345 2341
2346 2342 err = tlm_get_chkpnt_time(nlp->nlp_backup_path, !NLP_ISCHKPNTED(nlp),
2347 2343 tp, jname);
2348 2344 if (err != 0) {
2349 2345 NDMP_LOG(LOG_DEBUG, "Can't checkpoint time");
2350 2346 } else {
2351 2347 NDMP_LOG(LOG_DEBUG, "%s", cctime(tp));
2352 2348 }
2353 2349
2354 2350 return (err);
2355 2351 }
2356 2352
2357 2353
2358 2354 /*
2359 2355 * get_relative_path
2360 2356 */
2361 2357 char *
2362 2358 ndmp_get_relative_path(char *base, char *fullpath)
2363 2359 {
2364 2360 char *p = fullpath;
2365 2361
2366 2362 if (!base || !*base)
2367 2363 return (fullpath);
2368 2364
2369 2365 while (*base) {
2370 2366 if (*base != *p)
2371 2367 break;
2372 2368 p++; base++;
2373 2369 }
2374 2370
2375 2371 if (*p == '/')
2376 2372 p++;
2377 2373
2378 2374 return ((*base) ? fullpath : p);
2379 2375 }
2380 2376
2381 2377
2382 2378 /*
2383 2379 * ndmp_get_nlp
2384 2380 *
2385 2381 * Get NDMP local backup parameters
2386 2382 *
2387 2383 * Parameter:
2388 2384 * session cooke
2389 2385 *
2390 2386 * Returns:
2391 2387 * LBR structure
2392 2388 */
2393 2389 ndmp_lbr_params_t *
2394 2390 ndmp_get_nlp(void *cookie)
2395 2391 {
2396 2392 if (cookie == NULL)
2397 2393 return (NULL);
2398 2394
2399 2395 return (((ndmpd_session_t *)cookie)->ns_ndmp_lbr_params);
2400 2396 }
2401 2397
2402 2398
2403 2399 /*
2404 2400 * is_tape_unit_ready
2405 2401 *
2406 2402 * Check if the tape device is ready or not
2407 2403 */
2408 2404 boolean_t
2409 2405 is_tape_unit_ready(char *adptnm, int dev_id)
2410 2406 {
2411 2407 int try;
2412 2408 int fd = 0;
2413 2409
2414 2410 try = TUR_MAX_TRY;
2415 2411 if (dev_id <= 0) {
2416 2412 if ((fd = open(adptnm, O_RDONLY | O_NDELAY)) < 0)
2417 2413 return (FALSE);
2418 2414 } else {
2419 2415 fd = dev_id;
2420 2416 }
2421 2417 do {
2422 2418 if (scsi_test_unit_ready(fd) >= 0) {
2423 2419 NDMP_LOG(LOG_DEBUG, "Unit is ready");
2424 2420
2425 2421 if (dev_id <= 0)
2426 2422 (void) close(fd);
2427 2423
2428 2424 return (TRUE);
2429 2425 }
2430 2426
2431 2427 NDMP_LOG(LOG_DEBUG, "Unit not ready");
2432 2428 (void) usleep(TUR_WAIT);
2433 2429
2434 2430 } while (--try > 0);
2435 2431
2436 2432 if (dev_id <= 0)
2437 2433 (void) close(fd);
2438 2434
2439 2435 NDMP_LOG(LOG_DEBUG, "Unit didn't get ready");
2440 2436 return (FALSE);
2441 2437 }
2442 2438
2443 2439
2444 2440 /*
2445 2441 * scsi_test_unit_ready
2446 2442 *
2447 2443 * This is for Test Unit Read, without this function, the only
2448 2444 * impact is getting EBUSY's before each operation which we have
2449 2445 * busy waiting loops checking EBUSY error code.
2450 2446 */
2451 2447 static int
2452 2448 scsi_test_unit_ready(int dev_id)
2453 2449 {
2454 2450 struct uscsi_cmd ucmd;
2455 2451 union scsi_cdb cdb;
2456 2452 int retval;
2457 2453
2458 2454 (void) memset(&ucmd, 0, sizeof (struct uscsi_cmd));
2459 2455 (void) memset(&cdb, 0, sizeof (union scsi_cdb));
2460 2456 cdb.scc_cmd = SCMD_TEST_UNIT_READY;
2461 2457 ucmd.uscsi_cdb = (caddr_t)&cdb;
2462 2458 ucmd.uscsi_cdblen = CDB_GROUP0;
2463 2459 ucmd.uscsi_flags |= USCSI_SILENT;
2464 2460 ucmd.uscsi_timeout = 60; /* Allow maximum 1 min */
2465 2461
2466 2462 retval = ioctl(dev_id, USCSICMD, &ucmd);
2467 2463
2468 2464 if (retval != 0 && errno != EIO) {
2469 2465 NDMP_LOG(LOG_ERR,
2470 2466 "Failed to send inquiry request to device: %m.");
2471 2467 NDMP_LOG(LOG_DEBUG, "Inquiry request failed for"
2472 2468 " dev_id:%d err=%d -%m", dev_id, errno);
2473 2469 retval = -errno;
2474 2470 } else
2475 2471 retval = -(ucmd.uscsi_status);
2476 2472
2477 2473 return (retval);
2478 2474 }
2479 2475
2480 2476
2481 2477 /*
2482 2478 * ndmp_load_params
2483 2479 *
2484 2480 * Load the parameters.
2485 2481 *
2486 2482 * Parameter:
2487 2483 * void
2488 2484 *
2489 2485 * Returns:
2490 2486 * void
2491 2487 */
2492 2488 void
2493 2489 ndmp_load_params(void)
2494 2490 {
2495 2491 ndmp_dump_path_node = ndmpd_get_prop_yorn(NDMP_DUMP_PATHNODE_ENV) ?
2496 2492 TRUE : FALSE;
2497 2493 ndmp_tar_path_node = ndmpd_get_prop_yorn(NDMP_TAR_PATHNODE_ENV) ?
2498 2494 TRUE : FALSE;
2499 2495 ndmp_ignore_ctime =
2500 2496 ndmpd_get_prop_yorn(NDMP_IGNCTIME_ENV) ? TRUE : FALSE;
2501 2497 ndmp_include_lmtime = ndmpd_get_prop_yorn(NDMP_INCLMTIME_ENV) ?
2502 2498 TRUE : FALSE;
2503 2499 ndmp_max_tok_seq = atoi(ndmpd_get_prop_default(NDMP_MAXSEQ_ENV, "9"));
2504 2500
2505 2501 ndmp_full_restore_path = ndmpd_get_prop_yorn(NDMP_FULL_RESTORE_PATH) ?
2506 2502 TRUE : FALSE;
2507 2503
2508 2504 ndmp_fhinode = ndmpd_get_prop_yorn(NDMP_FHIST_INCR_ENV) ? TRUE : FALSE;
2509 2505
2510 2506 /* Get the value from ndmp SMF property. */
2511 2507 ndmp_dar_support = ndmpd_get_prop_yorn(NDMP_DAR_SUPPORT);
2512 2508
2513 2509 if ((ndmp_ver = atoi(ndmpd_get_prop(NDMP_VERSION_ENV))) == 0)
2514 2510 ndmp_ver = NDMPVER;
2515 2511 }
2516 2512
2517 2513 /*
2518 2514 * randomize
2519 2515 *
2520 2516 * Randomize the contents of a buffer
2521 2517 *
2522 2518 * Parameter:
2523 2519 * buffer (output) - destination buffer
2524 2520 * size (input) - buffer size
2525 2521 *
2526 2522 * Returns:
2527 2523 * void
2528 2524 */
2529 2525 void
2530 2526 randomize(unsigned char *buffer, int size)
2531 2527 {
2532 2528 /* LINTED improper alignment */
2533 2529 unsigned int *p = (unsigned int *)buffer;
2534 2530 unsigned int dwlen = size / sizeof (unsigned int);
2535 2531 unsigned int remlen = size % sizeof (unsigned int);
2536 2532 unsigned int tmp;
2537 2533 unsigned int i;
2538 2534
2539 2535 for (i = 0; i < dwlen; i++)
2540 2536 *p++ = random();
2541 2537
2542 2538 if (remlen) {
2543 2539 tmp = random();
2544 2540 (void) memcpy(p, &tmp, remlen);
2545 2541 }
2546 2542 }
2547 2543
2548 2544 /*
2549 2545 * ndmpd_get_file_entry_type
2550 2546 *
2551 2547 * Converts the mode to the NDMP file type
2552 2548 *
2553 2549 * Parameter:
2554 2550 * mode (input) - file mode
2555 2551 * ftype (output) - file type
2556 2552 *
2557 2553 * Returns:
2558 2554 * void
2559 2555 */
2560 2556 void
2561 2557 ndmpd_get_file_entry_type(int mode, ndmp_file_type *ftype)
2562 2558 {
2563 2559 switch (mode & S_IFMT) {
2564 2560 case S_IFIFO:
2565 2561 *ftype = NDMP_FILE_FIFO;
2566 2562 break;
2567 2563 case S_IFCHR:
2568 2564 *ftype = NDMP_FILE_CSPEC;
2569 2565 break;
2570 2566 case S_IFDIR:
2571 2567 *ftype = NDMP_FILE_DIR;
2572 2568 break;
2573 2569 case S_IFBLK:
2574 2570 *ftype = NDMP_FILE_BSPEC;
2575 2571 break;
2576 2572 case S_IFREG:
2577 2573 *ftype = NDMP_FILE_REG;
2578 2574 break;
2579 2575 case S_IFLNK:
2580 2576 *ftype = NDMP_FILE_SLINK;
2581 2577 break;
2582 2578 default:
2583 2579 *ftype = NDMP_FILE_SOCK;
2584 2580 break;
2585 2581 }
2586 2582 }
2587 2583
2588 2584 /*
2589 2585 * Set a private data in the plugin context
2590 2586 */
2591 2587 void
2592 2588 ndmp_context_set_specific(ndmp_context_t *nctx, void *ptr)
2593 2589 {
2594 2590 nctx->nc_pldata = ptr;
2595 2591 }
2596 2592
2597 2593 /*
2598 2594 * Get a private data in the plugin context
2599 2595 */
2600 2596 void *
2601 2597 ndmp_context_get_specific(ndmp_context_t *nctx)
2602 2598 {
2603 2599 return (nctx->nc_pldata);
2604 2600 }
2605 2601
2606 2602 ndmpd_backup_type_t
2607 2603 ndmp_get_backup_type(ndmp_context_t *ctx)
2608 2604 {
2609 2605 ndmpd_session_t *session = (ndmpd_session_t *)ctx->nc_ddata;
2610 2606
2611 2607 return (session->ns_butype);
2612 2608 }
|
↓ open down ↓ |
1460 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX