1 /*
2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 */
4
5 /*
6 * BSD 3 Clause License
7 *
8 * Copyright (c) 2007, The Storage Networking Industry Association.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * - Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * - Neither the name of The Storage Networking Industry Association (SNIA)
22 * nor the names of its contributors may be used to endorse or promote
23 * products derived from this software without specific prior written
24 * permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38 /* Copyright (c) 2007, The Storage Networking Industry Association. */
39 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
40 #include <sys/stat.h>
41 #include <sys/types.h>
42 #include <sys/time.h>
43 #include <ctype.h>
44 #include <sys/socket.h>
45 #include <sys/acl.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 #include <errno.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <time.h>
52 #include <cstack.h>
53 #include "ndmp.h"
54 #include "ndmpd.h"
55 #include <bitmap.h>
56 #include <traverse.h>
57
58
59 /*
60 * Maximum length of the string-representation of u_longlong_t type.
61 */
62 #define QUAD_DECIMAL_LEN 20
63
64
65 /* Is Y=yes or T=true */
66 #define IS_YORT(c) (strchr("YT", toupper(c)))
67
68 /* Is F=file format (vs D=node-dir format) */
69 #define IS_F(c) (toupper(c) == 'F')
70
71 /*
72 * If path is defined.
73 */
74 #define ISDEFINED(cp) ((cp) && *(cp))
75 #define SHOULD_LBRBK(bpp) (!((bpp)->bp_opr & TLM_OP_CHOOSE_ARCHIVE))
76
77 /*
78 * Component boundary means end of path or on a '/'. At this
79 * point both paths should be on component boundary.
80 */
81 #define COMPBNDRY(p) (!*(p) || (*p) == '/')
82
83 typedef struct bk_param_v3 {
84 ndmpd_session_t *bp_session;
85 ndmp_lbr_params_t *bp_nlp;
86 tlm_job_stats_t *bp_js;
87 tlm_cmd_t *bp_lcmd;
88 tlm_commands_t *bp_cmds;
89 tlm_acls_t *bp_tlmacl;
90 int bp_opr;
91 char *bp_tmp;
92 char *bp_chkpnm;
93 char **bp_excls;
94 char *bp_unchkpnm;
95 } bk_param_v3_t;
96
97
98 /*
99 * Multiple destination restore mode
100 */
101 #define MULTIPLE_DEST_DIRS 128
102
103 int multiple_dest_restore = 0;
104
105 /*
106 * Plug-in module ops
107 */
108 ndmp_plugin_t *ndmp_pl;
109
110 /*
111 * NDMP exclusion list
112 */
113 char **ndmp_excl_list = NULL;
114
115 /*
116 * split_env
117 *
118 * Splits the string into list of sections separated by the
119 * sep character.
120 *
121 * Parameters:
122 * envp (input) - the environment variable that should be broken
123 * sep (input) - the separator character
124 *
125 * Returns:
126 * Array of character pointers: On success. The array is allocated
127 * as well as all its entries. They all should be freed by the
128 * caller.
129 * NULL: on error
130 */
131 static char **
split_env(char * envp,char sep)132 split_env(char *envp, char sep)
133 {
134 char *bp, *cp, *ep;
135 char *save;
136 char **cpp;
137 int n;
138
139 if (!envp)
140 return (NULL);
141
142 while (isspace(*envp))
143 envp++;
144
145 if (!*envp)
146 return (NULL);
147
148 bp = save = strdup(envp);
149 if (!bp)
150 return (NULL);
151
152 /*
153 * Since the env variable is not empty, it contains at least one
154 * component
155 */
156 n = 1;
157 while ((cp = strchr(bp, sep))) {
158 if (cp > save && *(cp-1) != '\\')
159 n++;
160
161 bp = cp + 1;
162 }
163
164 n++; /* for the terminating NULL pointer */
165 cpp = ndmp_malloc(sizeof (char *) * n);
166 if (!cpp) {
167 free(save);
168 return (NULL);
169 }
170
171 (void) memset(cpp, 0, n * sizeof (char *));
172 n = 0;
173 cp = bp = ep = save;
174 while (*cp)
175 if (*cp == sep) {
176 *ep = '\0';
177 if (strlen(bp) > 0) {
178 cpp[n] = strdup(bp);
179 if (!cpp[n++]) {
180 tlm_release_list(cpp);
181 cpp = NULL;
182 break;
183 }
184 }
185 ep = bp = ++cp;
186 } else if (*cp == '\\') {
187 ++cp;
188 if (*cp == 'n') { /* "\n" */
189 *ep++ = '\n';
190 cp++;
191 } else if (*cp == 't') { /* "\t" */
192 *ep++ = '\t';
193 cp++;
194 } else
195 *ep++ = *cp++;
196 } else
197 *ep++ = *cp++;
198
199 *ep = '\0';
200 if (cpp) {
201 if (strlen(bp) > 0) {
202 cpp[n] = strdup(bp);
203 if (!cpp[n++]) {
204 tlm_release_list(cpp);
205 cpp = NULL;
206 } else
207 cpp[n] = NULL;
208 }
209
210 if (n == 0 && cpp != NULL) {
211 tlm_release_list(cpp);
212 cpp = NULL;
213 }
214 }
215
216 free(save);
217 return (cpp);
218 }
219
220
221 /*
222 * prl
223 *
224 * Print the array of character pointers passed to it. This is
225 * used for debugging purpose.
226 *
227 * Parameters:
228 * lpp (input) - pointer to the array of strings
229 *
230 * Returns:
231 * void
232 */
233 static void
prl(char ** lpp)234 prl(char **lpp)
235 {
236 if (!lpp) {
237 NDMP_LOG(LOG_DEBUG, "empty");
238 return;
239 }
240
241 while (*lpp)
242 NDMP_LOG(LOG_DEBUG, "\"%s\"", *lpp++);
243 }
244
245
246 /*
247 * inlist
248 *
249 * Looks through all the strings of the array to see if the ent
250 * matches any of the strings. The strings are patterns.
251 *
252 * Parameters:
253 * lpp (input) - pointer to the array of strings
254 * ent (input) - the entry to be matched
255 *
256 * Returns:
257 * TRUE: if there is a match
258 * FALSE: invalid argument or no match
259 */
260 static boolean_t
inlist(char ** lpp,char * ent)261 inlist(char **lpp, char *ent)
262 {
263 if (!lpp || !ent) {
264 NDMP_LOG(LOG_DEBUG, "empty list");
265 return (FALSE);
266 }
267
268 while (*lpp) {
269 /*
270 * Fixing the sync_sort NDMPV3 problem, it sends the inclusion
271 * like "./" which we should skip the "./"
272 */
273 char *pattern = *lpp;
274 if (strncmp(pattern, "./", 2) == 0)
275 pattern += 2;
276
277 NDMP_LOG(LOG_DEBUG, "pattern %s, ent %s", pattern, ent);
278
279 if (match(pattern, ent)) {
280 NDMP_LOG(LOG_DEBUG, "match(%s,%s)", pattern, ent);
281 return (TRUE);
282 }
283 lpp++;
284 }
285
286 NDMP_LOG(LOG_DEBUG, "no match");
287 return (FALSE);
288 }
289
290
291 /*
292 * inexl
293 *
294 * Checks if the entry is in the list. This is used for exclusion
295 * list. If the exclusion list is empty, FALSE should be returned
296 * showing that nothing should be excluded by default.
297 *
298 * Parameters:
299 * lpp (input) - pointer to the array of strings
300 * ent (input) - the entry to be matched
301 *
302 * Returns:
303 * TRUE: if there is a match
304 * FALSE: invalid argument or no match
305 *
306 */
307 static boolean_t
inexl(char ** lpp,char * ent)308 inexl(char **lpp, char *ent)
309 {
310 if (!lpp || !ent)
311 return (FALSE);
312
313 return (inlist(lpp, ent));
314 }
315
316
317 /*
318 * ininc
319 *
320 * Checks if the entry is in the list. This is used for inclusion
321 * list. If the inclusion list is empty, TRUE should be returned
322 * showing that everything should be included by default.
323 *
324 * Parameters:
325 * lpp (input) - pointer to the array of strings
326 * ent (input) - the entry to be matched
327 *
328 * Returns:
329 * TRUE: if there is a match or the list is empty
330 * FALSE: no match
331 */
332 static boolean_t
ininc(char ** lpp,char * ent)333 ininc(char **lpp, char *ent)
334 {
335 if (!lpp || !ent || !*ent)
336 return (TRUE);
337
338 return (inlist(lpp, ent));
339 }
340
341
342 /*
343 * setupsels
344 *
345 * Set up the selection list for Local B/R functions. A new array of
346 * "char *" is created and the pointers point to the original paths of
347 * the Nlist.
348 *
349 * Parameters:
350 * session (input) - pointer to the session
351 * params (input) - pointer to the parameters structure
352 * nlp (input) - pointer to the nlp structure
353 * index(input) - If not zero is the DAR entry position
354 *
355 * Returns:
356 * list pointer: on success
357 * NULL: on error
358 */
359 /*ARGSUSED*/
360 char **
setupsels(ndmpd_session_t * session,ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp,int index)361 setupsels(ndmpd_session_t *session, ndmpd_module_params_t *params,
362 ndmp_lbr_params_t *nlp, int index)
363 {
364 char **lpp, **save;
365 int i, n;
366 int len;
367 int start, end;
368 mem_ndmp_name_v3_t *ep;
369
370 n = session->ns_data.dd_nlist_len;
371
372 save = lpp = ndmp_malloc(sizeof (char *) * (n + 1));
373 if (!lpp) {
374 MOD_LOGV3(params, NDMP_LOG_ERROR, "Insufficient memory.\n");
375 return (NULL);
376 }
377
378 if (index) { /* DAR, just one entry */
379 /*
380 * We have to setup a list of strings that will not match any
381 * file. One DAR entry will be added in the right position later
382 * in this function.
383 * When the match is called from tar_getdir the
384 * location of the selection that matches the entry is
385 * important
386 */
387 for (i = 0; i < n; ++i)
388 *(lpp+i) = " ";
389 n = 1;
390 start = index-1;
391 end = start+1;
392 lpp += start; /* Next selection entry will be in lpp[start] */
393 } else {
394 start = 0;
395 end = n;
396 }
397
398 for (i = start; i < end; i++) {
399 ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params, i);
400 if (!ep)
401 continue;
402
403 /*
404 * Check for clients that send original path as "."(like
405 * CA products). In this situation opath is something like
406 * "/v1/." and we should change it to "/v1/"
407 */
408 len = strlen(ep->nm3_opath);
409 if (len > 1 && ep->nm3_opath[len-2] == '/' &&
410 ep->nm3_opath[len-1] == '.') {
411 ep->nm3_opath[len-1] = '\0';
412 NDMP_LOG(LOG_DEBUG,
413 "nm3_opath changed from %s. to %s",
414 ep->nm3_opath, ep->nm3_opath);
415 }
416 *lpp++ = ep->nm3_opath;
417 }
418
419 /* list termination indicator is a null pointer */
420 *lpp = NULL;
421
422 return (save);
423 }
424
425
426 /*
427 * mkrsp
428 *
429 * Make Restore Path.
430 * It gets a path, a selection (with which the path has matched) a new
431 * name and makes a new name for the path.
432 * All the components of the path and the selection are skipped as long
433 * as they are the same. If either of the path or selection are not on
434 * a component boundary, the match was reported falsefully and no new name
435 * is generated(Except the situation in which both path and selection
436 * end with trailing '/' and selection is the prefix of the path).
437 * Otherwise, the remaining of the path is appended to the
438 * new name. The result is saved in the buffer passed.
439 *
440 * Parameters:
441 * bp (output) - pointer to the result buffer
442 * pp (input) - pointer to the path
443 * sp (input) - pointer to the selection
444 * np (input) - pointer to the new name
445 *
446 * Returns:
447 * pointer to the bp: on success
448 * NULL: otherwise
449 */
450 char *
mkrsp(char * bp,char * pp,char * sp,char * np)451 mkrsp(char *bp, char *pp, char *sp, char *np)
452 {
453 if (!bp || !pp)
454 return (NULL);
455
456
457 pp += strspn(pp, "/");
458 if (sp) {
459 sp += strspn(sp, "/");
460
461 /* skip as much as match */
462 while (*sp && *pp && *sp == *pp) {
463 sp++;
464 pp++;
465 }
466
467 if (!COMPBNDRY(pp) || !COMPBNDRY(sp))
468 /* An exception to the boundary rule */
469 /* (!(!*sp && (*(pp - 1)) == '/')) */
470 if (*sp || (*(pp - 1)) != '/')
471 return (NULL);
472
473 /* if pp shorter than sp, it should not be restored */
474 if (!*pp && *sp) {
475 sp += strspn(sp, "/");
476 if (strlen(sp) > 0)
477 return (NULL);
478 }
479 }
480
481 if (np)
482 np += strspn(np, "/");
483 else
484 np = "";
485
486 if (!tlm_cat_path(bp, np, pp)) {
487 NDMP_LOG(LOG_ERR, "Restore path too long %s/%s.", np, pp);
488 return (NULL);
489 }
490
491 return (bp);
492 }
493
494
495 /*
496 * mknewname
497 *
498 * This is used as callback for creating the restore path. This function
499 * can handle both single destination and multiple restore paths.
500 *
501 * Make up the restore destination path for a particular file/directory, path,
502 * based on nm3_opath and nm3_dpath. path should have matched nm3_opath
503 * in some way.
504 */
505 char *
mknewname(struct rs_name_maker * rnp,char * buf,int idx,char * path)506 mknewname(struct rs_name_maker *rnp, char *buf, int idx, char *path)
507 {
508 char *rv;
509 ndmp_lbr_params_t *nlp;
510 mem_ndmp_name_v3_t *ep;
511
512 rv = NULL;
513 if (!buf) {
514 NDMP_LOG(LOG_DEBUG, "buf is NULL");
515 } else if (!path) {
516 NDMP_LOG(LOG_DEBUG, "path is NULL");
517 } else if ((nlp = rnp->rn_nlp) == 0) {
518 NDMP_LOG(LOG_DEBUG, "rnp->rn_nlp is NULL");
519 } else if (!nlp->nlp_params) {
520 NDMP_LOG(LOG_DEBUG, "nlp->nlp_params is NULL");
521 } else
522 if (!ndmp_full_restore_path) {
523 if (idx < 0 || idx >= (int)nlp->nlp_nfiles) {
524 NDMP_LOG(LOG_DEBUG,
525 "Invalid idx %d range (0, %d)",
526 idx, nlp->nlp_nfiles);
527 } else if (!(ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(
528 nlp->nlp_params, idx))) {
529 NDMP_LOG(LOG_DEBUG,
530 "nlist entry %d is NULL", idx);
531 } else {
532 rv = mkrsp(buf, path, ep->nm3_opath,
533 ep->nm3_dpath);
534
535 NDMP_LOG(LOG_DEBUG,
536 "idx %d org \"%s\" dst \"%s\"",
537 idx, ep->nm3_opath, ep->nm3_dpath);
538 if (rv) {
539 NDMP_LOG(LOG_DEBUG,
540 "path \"%s\": \"%s\"", path, rv);
541 } else {
542 NDMP_LOG(LOG_DEBUG,
543 "path \"%s\": NULL", path);
544 }
545 }
546 } else {
547 if (!tlm_cat_path(buf, nlp->nlp_restore_path, path)) {
548 NDMP_LOG(LOG_ERR, "Path too long %s/%s.",
549 nlp->nlp_restore_path, path);
550 rv = NULL;
551 } else {
552 rv = buf;
553 NDMP_LOG(LOG_DEBUG,
554 "path \"%s\": \"%s\"", path, rv);
555 }
556 }
557
558 return (rv);
559 }
560
561
562 /*
563 * chopslash
564 *
565 * Remove the slash from the end of the given path
566 */
567 static void
chopslash(char * cp)568 chopslash(char *cp)
569 {
570 int ln;
571
572 if (!cp || !*cp)
573 return;
574
575 ln = strlen(cp);
576 cp += ln - 1; /* end of the string */
577 while (ln > 0 && *cp == '/') {
578 *cp-- = '\0';
579 ln--;
580 }
581 }
582
583
584 /*
585 * joinpath
586 *
587 * Join two given paths
588 */
589 static char *
joinpath(char * bp,char * pp,char * np)590 joinpath(char *bp, char *pp, char *np)
591 {
592 if (pp && *pp) {
593 if (np && *np)
594 (void) tlm_cat_path(bp, pp, np);
595 else
596 (void) strlcpy(bp, pp, TLM_MAX_PATH_NAME);
597 } else {
598 if (np && *np)
599 (void) strlcpy(bp, np, TLM_MAX_PATH_NAME);
600 else
601 bp = NULL;
602 }
603
604 return (bp);
605 }
606
607
608 /*
609 * voliswr
610 *
611 * Is the volume writable?
612 */
613 static int
voliswr(char * path)614 voliswr(char *path)
615 {
616 int rv;
617
618 if (!path)
619 return (0);
620
621 rv = !fs_is_rdonly(path) && !fs_is_chkpntvol(path);
622 NDMP_LOG(LOG_DEBUG, "%d path \"%s\"", rv, path);
623 return (rv);
624
625 }
626
627
628 /*
629 * is_valid_backup_dir_v3
630 *
631 * Checks the validity of the backup path. Backup path should
632 * have the following characteristics to be valid:
633 * 1) It should be an absolute path.
634 * 2) It should be a directory.
635 * 3) It should not be checkpoint root directory
636 * 4) If the file system is read-only, the backup path
637 * should be a checkpointed path. Checkpoint cannot
638 * be created on a read-only file system.
639 *
640 * Parameters:
641 * params (input) - pointer to the parameters structure.
642 * bkpath (input) - the backup path
643 *
644 * Returns:
645 * TRUE: if everything's OK
646 * FALSE: otherwise.
647 */
648 static boolean_t
is_valid_backup_dir_v3(ndmpd_module_params_t * params,char * bkpath)649 is_valid_backup_dir_v3(ndmpd_module_params_t *params, char *bkpath)
650 {
651 char *msg;
652 struct stat64 st;
653
654 if (*bkpath != '/') {
655 MOD_LOGV3(params, NDMP_LOG_ERROR,
656 "Relative backup path not allowed \"%s\".\n", bkpath);
657 return (FALSE);
658 }
659 if (stat64(bkpath, &st) < 0) {
660 msg = strerror(errno);
661 MOD_LOGV3(params, NDMP_LOG_ERROR, "\"%s\" %s.\n",
662 bkpath, msg);
663 return (FALSE);
664 }
665 if (!S_ISDIR(st.st_mode)) {
666 /* only directories can be specified as the backup path */
667 MOD_LOGV3(params, NDMP_LOG_ERROR,
668 "\"%s\" is not a directory.\n", bkpath);
669 return (FALSE);
670 }
671 if (fs_is_rdonly(bkpath) && !fs_is_chkpntvol(bkpath) &&
672 fs_is_chkpnt_enabled(bkpath)) {
673 /* it is not a chkpnted path */
674 MOD_LOGV3(params, NDMP_LOG_ERROR,
675 "\"%s\" is not a checkpointed path.\n", bkpath);
676 return (FALSE);
677 }
678
679 return (TRUE);
680 }
681
682
683 /*
684 * log_date_token_v3
685 *
686 * Log the token sequence number and also the date of the
687 * last backup for token-based backup in the system log
688 * and also send them as normal log to the client.
689 *
690 * Parameters:
691 * params (input) - pointer to the parameters structure
692 * nlp (input) - pointer to the nlp structure
693 *
694 * Returns:
695 * void
696 */
697 static void
log_date_token_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)698 log_date_token_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
699 {
700 MOD_LOGV3(params, NDMP_LOG_NORMAL, "Token sequence counter: %d.\n",
701 nlp->nlp_tokseq);
702
703 MOD_LOGV3(params, NDMP_LOG_NORMAL, "Date of the last backup: %s.\n",
704 cctime(&nlp->nlp_tokdate));
705
706 if (nlp->nlp_dmpnm) {
707 MOD_LOGV3(params, NDMP_LOG_NORMAL,
708 "Backup date log file name: \"%s\".\n", nlp->nlp_dmpnm);
709 }
710 }
711
712
713 /*
714 * log_lbr_bk_v3
715 *
716 * Log the backup level and data of the backup for LBR-type
717 * backup in the system log and also send them as normal log
718 * to the client.
719 *
720 * Parameters:
721 * params (input) - pointer to the parameters structure
722 * nlp (input) - pointer to the nlp structure
723 *
724 * Returns:
725 * void
726 */
727 static void
log_lbr_bk_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)728 log_lbr_bk_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
729 {
730 MOD_LOGV3(params, NDMP_LOG_NORMAL,
731 "Date of this level '%c': %s.\n", nlp->nlp_clevel,
732 cctime(&nlp->nlp_cdate));
733
734 if (nlp->nlp_dmpnm) {
735 MOD_LOGV3(params, NDMP_LOG_NORMAL,
736 "Backup date log file name: \"%s\".\n", nlp->nlp_dmpnm);
737 }
738 }
739
740
741 /*
742 * log_level_v3
743 *
744 * Log the backup level and date of the last and the current
745 * backup for level-type backup in the system log and also
746 * send them as normal log to the client.
747 *
748 * Parameters:
749 * params (input) - pointer to the parameters structure
750 * nlp (input) - pointer to the nlp structure
751 *
752 * Returns:
753 * void
754 */
755 static void
log_level_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)756 log_level_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
757 {
758 MOD_LOGV3(params, NDMP_LOG_NORMAL,
759 "Date of the last level '%u': %s.\n", nlp->nlp_llevel,
760 cctime(&nlp->nlp_ldate));
761
762 MOD_LOGV3(params, NDMP_LOG_NORMAL,
763 "Date of this level '%u': %s.\n", nlp->nlp_clevel,
764 cctime(&nlp->nlp_cdate));
765
766 MOD_LOGV3(params, NDMP_LOG_NORMAL, "Update: %s.\n",
767 NDMP_TORF(NLP_ISSET(nlp, NLPF_UPDATE)));
768 }
769
770
771 /*
772 * log_bk_params_v3
773 *
774 * Dispatcher function which calls the appropriate function
775 * for logging the backup date and level in the system log
776 * and also send them as normal log message to the client.
777 *
778 * Parameters:
779 * session (input) - pointer to the session
780 * params (input) - pointer to the parameters structure
781 * nlp (input) - pointer to the nlp structure
782 *
783 * Returns:
784 * void
785 */
786 static void
log_bk_params_v3(ndmpd_session_t * session,ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)787 log_bk_params_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
788 ndmp_lbr_params_t *nlp)
789 {
790 MOD_LOGV3(params, NDMP_LOG_NORMAL, "Backing up \"%s\".\n",
791 nlp->nlp_backup_path);
792
793 if (session->ns_mover.md_data_addr.addr_type == NDMP_ADDR_LOCAL)
794 MOD_LOGV3(params, NDMP_LOG_NORMAL,
795 "Tape record size: %d.\n",
796 session->ns_mover.md_record_size);
797
798 MOD_LOGV3(params, NDMP_LOG_NORMAL, "File history: %c.\n",
799 NDMP_YORN(NLP_ISSET(nlp, NLPF_FH)));
800
801 if (NLP_ISSET(nlp, NLPF_TOKENBK))
802 log_date_token_v3(params, nlp);
803 else if (NLP_ISSET(nlp, NLPF_LBRBK))
804 log_lbr_bk_v3(params, nlp);
805 else if (NLP_ISSET(nlp, NLPF_LEVELBK))
806 log_level_v3(params, nlp);
807 else {
808 MOD_LOGV3(params, NDMP_LOG_ERROR,
809 "Internal error: backup level not defined for \"%s\".\n",
810 nlp->nlp_backup_path);
811 }
812 }
813
814
815 /*
816 * get_update_env_v3
817 *
818 * Is the UPDATE environment variable specified? If it is
819 * the corresponding flag is set in the flags field of the
820 * nlp structure, otherwise the flag is cleared.
821 *
822 * Parameters:
823 * params (input) - pointer to the parameters structure
824 * nlp (input) - pointer to the nlp structure
825 *
826 * Returns:
827 * void
828 */
829 static void
get_update_env_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)830 get_update_env_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
831 {
832 char *envp;
833
834 envp = MOD_GETENV(params, "UPDATE");
835 if (!envp) {
836 NLP_SET(nlp, NLPF_UPDATE);
837 NDMP_LOG(LOG_DEBUG,
838 "env(UPDATE) not defined, default to TRUE");
839 } else {
840 NDMP_LOG(LOG_DEBUG, "env(UPDATE): \"%s\"", envp);
841 if (IS_YORT(*envp))
842 NLP_SET(nlp, NLPF_UPDATE);
843 else
844 NLP_UNSET(nlp, NLPF_UPDATE);
845 }
846 }
847
848
849 /*
850 * get_hist_env_v3
851 *
852 * Is backup history requested? If it is, the corresponding
853 * flag is set in the flags field of the nlp structure, otherwise
854 * the flag is cleared.
855 *
856 * Parameters:
857 * params (input) - pointer to the parameters structure
858 * nlp (input) - pointer to the nlp structure
859 *
860 * Returns:
861 * void
862 */
863 static void
get_hist_env_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)864 get_hist_env_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
865 {
866 char *envp;
867
868 envp = MOD_GETENV(params, "HIST");
869 if (!envp) {
870 NDMP_LOG(LOG_DEBUG, "env(HIST) not defined");
871 NLP_UNSET(nlp, NLPF_FH);
872 } else {
873 NDMP_LOG(LOG_DEBUG, "env(HIST): \"%s\"", envp);
874 if (IS_YORT(*envp) || IS_F(*envp))
875 NLP_SET(nlp, NLPF_FH);
876 else
877 NLP_UNSET(nlp, NLPF_FH);
878
879 /* Force file format if specified */
880 if (IS_F(*envp)) {
881 params->mp_file_history_path_func =
882 ndmpd_api_file_history_file_v3;
883 params->mp_file_history_dir_func = 0;
884 params->mp_file_history_node_func = 0;
885 }
886 }
887 }
888
889
890 /*
891 * get_exc_env_v3
892 *
893 * Gets the EXCLUDE environment variable and breaks it
894 * into strings. The separator of the EXCLUDE environment
895 * variable is the ',' character.
896 *
897 * Parameters:
898 * params (input) - pointer to the parameters structure
899 * nlp (input) - pointer to the nlp structure
900 *
901 * Returns:
902 * void
903 */
904 static void
get_exc_env_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)905 get_exc_env_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
906 {
907 char *envp;
908
909 envp = MOD_GETENV(params, "EXCLUDE");
910 if (!envp) {
911 NDMP_LOG(LOG_DEBUG, "env(EXCLUDE) not defined");
912 nlp->nlp_exl = NULL;
913 } else {
914 NDMP_LOG(LOG_DEBUG, "env(EXCLUDE): \"%s\"", envp);
915 nlp->nlp_exl = split_env(envp, ',');
916 prl(nlp->nlp_exl);
917 }
918 }
919
920
921 /*
922 * get_inc_env_v3
923 *
924 * Gets the FILES environment variable that shows which files
925 * should be backed up, and breaks it into strings. The
926 * separator of the FILES environment variable is the space
927 * character.
928 *
929 * Parameters:
930 * params (input) - pointer to the parameters structure
931 * nlp (input) - pointer to the nlp structure
932 *
933 * Returns:
934 * void
935 */
936 static void
get_inc_env_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)937 get_inc_env_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
938 {
939 char *envp;
940
941 envp = MOD_GETENV(params, "FILES");
942 if (!envp) {
943 NDMP_LOG(LOG_DEBUG, "env(FILES) not defined");
944 nlp->nlp_inc = NULL;
945 } else {
946 NDMP_LOG(LOG_DEBUG, "env(FILES): \"%s\"", envp);
947 nlp->nlp_inc = split_env(envp, ' ');
948 prl(nlp->nlp_inc);
949 }
950 }
951
952
953 /*
954 * get_direct_env_v3
955 *
956 * Gets the DIRECT environment variable that shows if the fh_info should
957 * be sent to the client or not.
958 *
959 * Parameters:
960 * params (input) - pointer to the parameters structure
961 * nlp (input) - pointer to the nlp structure
962 *
963 * Returns:
964 * void
965 */
966 static void
get_direct_env_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)967 get_direct_env_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
968 {
969 char *envp;
970
971 /*
972 * We should send the fh_info to the DMA, unless it is specified
973 * in the request that we should not send fh_info.
974 * At the moment we do not support DAR on directories, so if the user
975 * needs to restore a directory they should disable the DAR.
976 */
977 if (params->mp_operation == NDMP_DATA_OP_RECOVER && !ndmp_dar_support) {
978 NDMP_LOG(LOG_DEBUG, "Direct Access Restore Disabled");
979 NLP_UNSET(nlp, NLPF_DIRECT);
980 MOD_LOGV3(params, NDMP_LOG_NORMAL,
981 "DAR is disabled. Running Restore without DAR");
982 return;
983 }
984
985 /*
986 * Regardless of whether DIRECT is defined at backup time we send
987 * back the fh_info, for some clients do not use get_backup_attrs.
988 * If operation is restore we have to unset the DIRECT, for
989 * some clients do not set the MOVER window.
990 */
991 if (params->mp_operation == NDMP_DATA_OP_BACKUP) {
992 NDMP_LOG(LOG_DEBUG, "backup default env(DIRECT): YES");
993 NLP_SET(nlp, NLPF_DIRECT);
994 } else {
995
996 envp = MOD_GETENV(params, "DIRECT");
997 if (!envp) {
998 NDMP_LOG(LOG_DEBUG, "env(DIRECT) not defined");
999 NLP_UNSET(nlp, NLPF_DIRECT);
1000 } else {
1001 NDMP_LOG(LOG_DEBUG, "env(DIRECT): \"%s\"", envp);
1002 if (IS_YORT(*envp)) {
1003 NLP_SET(nlp, NLPF_DIRECT);
1004 NDMP_LOG(LOG_DEBUG,
1005 "Direct Access Restore Enabled");
1006 } else {
1007 NLP_UNSET(nlp, NLPF_DIRECT);
1008 NDMP_LOG(LOG_DEBUG,
1009 "Direct Access Restore Disabled");
1010 }
1011 }
1012 }
1013
1014 if (NLP_ISSET(nlp, NLPF_DIRECT)) {
1015 if (params->mp_operation == NDMP_DATA_OP_BACKUP)
1016 MOD_LOGV3(params, NDMP_LOG_NORMAL,
1017 "Direct Access Restore information is supported");
1018 else
1019 MOD_LOGV3(params, NDMP_LOG_NORMAL,
1020 "Running Restore with Direct Access Restore");
1021 } else {
1022 if (params->mp_operation == NDMP_DATA_OP_BACKUP)
1023 MOD_LOGV3(params, NDMP_LOG_NORMAL,
1024 "Direct Access Restore is not supported");
1025 else
1026 MOD_LOGV3(params, NDMP_LOG_NORMAL,
1027 "Running Restore without Direct Access Restore");
1028 }
1029 }
1030
1031
1032 /*
1033 * get_date_token_v3
1034 *
1035 * Parse the token passed as the argument. Evaluate it and
1036 * issue any warning or error if needed. Save the date and
1037 * token sequence in the nlp structure fields. The sequence
1038 * number in the token should be less than hard-limit. If
1039 * it's between soft and hard limit, a warning is issued.
1040 * There is a configurable limit which should be less than
1041 * the soft-limit saved in ndmp_max_tok_seq variable.
1042 *
1043 * The NLPF_TOKENBK flag is set in the nlp flags field to
1044 * show that the backup type is token-based.
1045 *
1046 * Parameters:
1047 * params (input) - pointer to the parameters structure
1048 * nlp (input) - pointer to the nlp structure
1049 * basedate (input) - the value of the BASE_DATE environment
1050 * variable.
1051 *
1052 * Returns:
1053 * NDMP_NO_ERR: on success
1054 * != NDMP_NO_ERR: Otherwise
1055 *
1056 */
1057 static ndmp_error
get_date_token_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp,char * basedate)1058 get_date_token_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp,
1059 char *basedate)
1060 {
1061 char *endp;
1062 uint_t seq;
1063 ndmp_error rv;
1064 time_t tstamp;
1065 u_longlong_t tok;
1066
1067 if (!params || !nlp || !basedate || !*basedate)
1068 return (NDMP_ILLEGAL_ARGS_ERR);
1069
1070 if (MOD_GETENV(params, "LEVEL")) {
1071 MOD_LOGV3(params, NDMP_LOG_WARNING,
1072 "Both BASE_DATE and LEVEL environment variables "
1073 "defined.\n");
1074 MOD_LOGCONTV3(params, NDMP_LOG_WARNING,
1075 "BASE_DATE is being used for this backup.\n");
1076 }
1077
1078 tok = strtoll(basedate, &endp, 10);
1079 if (endp == basedate) {
1080 MOD_LOGV3(params, NDMP_LOG_ERROR,
1081 "Invalid BASE_DATE environment variable: \"%s\".\n",
1082 basedate);
1083 return (NDMP_ILLEGAL_ARGS_ERR);
1084 }
1085
1086 tstamp = tok & 0xffffffff;
1087 seq = (tok >> 32) & 0xffffffff;
1088 NDMP_LOG(LOG_DEBUG, "basedate \"%s\" %lld seq %u tstamp %u",
1089 basedate, tok, seq, tstamp);
1090
1091 if ((int)seq > ndmp_get_max_tok_seq()) {
1092 rv = NDMP_ILLEGAL_ARGS_ERR;
1093 MOD_LOGV3(params, NDMP_LOG_ERROR,
1094 "The sequence counter of the token exceeds the "
1095 "maximum permitted value.\n");
1096 MOD_LOGCONTV3(params, NDMP_LOG_ERROR,
1097 "Token sequence: %u, maxiumum value: %u.\n",
1098 seq, ndmp_get_max_tok_seq());
1099 } else if (seq >= NDMP_TOKSEQ_HLIMIT) {
1100 rv = NDMP_ILLEGAL_ARGS_ERR;
1101 MOD_LOGV3(params, NDMP_LOG_ERROR,
1102 "The sequence counter the of token exceeds the "
1103 "hard-limit.\n");
1104 MOD_LOGCONTV3(params, NDMP_LOG_ERROR,
1105 "Token sequence: %u, hard-limit: %u.\n",
1106 seq, NDMP_TOKSEQ_HLIMIT);
1107 } else {
1108 rv = NDMP_NO_ERR;
1109 /*
1110 * Issue a warning if the seq is equal to the maximum
1111 * permitted seq number or equal to the soft-limit.
1112 */
1113 if (seq == NDMP_TOKSEQ_SLIMIT) {
1114 MOD_LOGV3(params, NDMP_LOG_WARNING,
1115 "The sequence counter of the token has reached "
1116 "the soft-limit.\n");
1117 MOD_LOGCONTV3(params, NDMP_LOG_WARNING,
1118 "Token sequence: %u, soft-limit: %u.\n",
1119 seq, NDMP_TOKSEQ_SLIMIT);
1120 } else if ((int)seq == ndmp_get_max_tok_seq()) {
1121 MOD_LOGV3(params, NDMP_LOG_WARNING,
1122 "The sequence counter of the token has reached "
1123 "the maximum permitted value.\n");
1124 MOD_LOGCONTV3(params, NDMP_LOG_WARNING,
1125 "Token sequence: %u, maxiumum value: %u.\n",
1126 seq, ndmp_get_max_tok_seq());
1127 }
1128
1129 /*
1130 * The current seq is equal to the seq field of the
1131 * token. It will be increased after successful backup
1132 * before setting the DUMP_DATE environment variable.
1133 */
1134 nlp->nlp_dmpnm = MOD_GETENV(params, "DMP_NAME");
1135 NLP_SET(nlp, NLPF_TOKENBK);
1136 NLP_UNSET(nlp, NLPF_LEVELBK);
1137 NLP_UNSET(nlp, NLPF_LBRBK);
1138 nlp->nlp_tokseq = seq;
1139 nlp->nlp_tokdate = tstamp;
1140 /*
1141 * The value of nlp_cdate will be set to the checkpoint
1142 * creation time after it is created.
1143 */
1144 }
1145
1146 return (rv);
1147 }
1148
1149
1150 /*
1151 * get_lbr_bk_v3
1152 *
1153 * Sets the level fields of the nlp structures for
1154 * LBR-type backup. The NLPF_LBRBK flag of the
1155 * nlp flags is also set to show the backup type.
1156 *
1157 * Parameters:
1158 * params (input) - pointer to the parameters structure
1159 * nlp (input) - pointer to the nlp structure
1160 * type (input) - the backup level: 'F', 'A', 'I', 'D' or
1161 * their lower-case values.
1162 *
1163 * Returns:
1164 * NDMP_NO_ERR: on success
1165 * != NDMP_NO_ERR: Otherwise
1166 */
1167 static ndmp_error
get_lbr_bk_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp,char * type)1168 get_lbr_bk_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp, char *type)
1169 {
1170 if (!params || !nlp || !type || !*type)
1171 return (NDMP_ILLEGAL_ARGS_ERR);
1172
1173 NLP_SET(nlp, NLPF_LBRBK);
1174 NLP_UNSET(nlp, NLPF_TOKENBK);
1175 NLP_UNSET(nlp, NLPF_LEVELBK);
1176 nlp->nlp_dmpnm = MOD_GETENV(params, "DMP_NAME");
1177 nlp->nlp_llevel = toupper(*type);
1178 nlp->nlp_ldate = (time_t)0;
1179 nlp->nlp_clevel = nlp->nlp_llevel;
1180 (void) time(&nlp->nlp_cdate);
1181
1182 return (NDMP_NO_ERR);
1183 }
1184
1185
1186 /*
1187 * get_backup_level_v3
1188 *
1189 * Gets the backup level from the environment variables. If
1190 * BASE_DATE is specified, it will be used, otherwise LEVEL
1191 * will be used. If neither is specified, LEVEL = '0' is
1192 * assumed.
1193 *
1194 * Parameters:
1195 * params (input) - pointer to the parameters structure
1196 * nlp (input) - pointer to the nlp structure
1197 *
1198 * Returns:
1199 * NDMP_NO_ERR: on success
1200 * != NDMP_NO_ERR: Otherwise
1201 */
1202 static ndmp_error
get_backup_level_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)1203 get_backup_level_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
1204 {
1205 char *envp;
1206 ndmp_error rv;
1207
1208 /*
1209 * If the BASE_DATE env variable is specified use it, otherwise
1210 * look to see if LEVEL is specified. If LEVEL is not
1211 * specified either, backup level '0' must be made. Level backup
1212 * does not clear the archive bit.
1213 *
1214 * If LEVEL environment varaible is specified, values for
1215 * 'F', 'D', 'I' and 'A' (for 'Full', 'Differential',
1216 * 'Incremental', and 'Archive' is checked first. Then
1217 * level '0' to '9' will be checked.
1218 *
1219 * LEVEL environment variable can hold only one character.
1220 * If its length is longer than 1, an error is returned.
1221 */
1222 envp = MOD_GETENV(params, "BASE_DATE");
1223 if (envp)
1224 return (get_date_token_v3(params, nlp, envp));
1225
1226
1227 envp = MOD_GETENV(params, "LEVEL");
1228 if (!envp) {
1229 NDMP_LOG(LOG_DEBUG, "env(LEVEL) not defined, default to 0");
1230 NLP_SET(nlp, NLPF_LEVELBK);
1231 NLP_UNSET(nlp, NLPF_LBRBK);
1232 NLP_UNSET(nlp, NLPF_TOKENBK);
1233 nlp->nlp_llevel = 0;
1234 nlp->nlp_ldate = 0;
1235 nlp->nlp_clevel = 0;
1236 /*
1237 * The value of nlp_cdate will be set to the checkpoint
1238 * creation time after it is created.
1239 */
1240 return (NDMP_NO_ERR);
1241 }
1242
1243 if (*(envp+1) != '\0') {
1244 MOD_LOGV3(params, NDMP_LOG_ERROR,
1245 "Invalid backup level \"%s\".\n", envp);
1246 return (NDMP_ILLEGAL_ARGS_ERR);
1247 }
1248
1249 if (IS_LBR_BKTYPE(*envp))
1250 return (get_lbr_bk_v3(params, nlp, envp));
1251
1252 if (!isdigit(*envp)) {
1253 MOD_LOGV3(params, NDMP_LOG_ERROR,
1254 "Invalid backup level \"%s\".\n", envp);
1255 return (NDMP_ILLEGAL_ARGS_ERR);
1256 }
1257
1258 NLP_SET(nlp, NLPF_LEVELBK);
1259 NLP_UNSET(nlp, NLPF_LBRBK);
1260 NLP_UNSET(nlp, NLPF_TOKENBK);
1261 nlp->nlp_llevel = *envp - '0';
1262 nlp->nlp_ldate = 0;
1263 nlp->nlp_clevel = nlp->nlp_llevel;
1264 /*
1265 * The value of nlp_cdate will be set to the checkpoint
1266 * creation time after it is created.
1267 */
1268 if (ndmpd_get_dumptime(nlp->nlp_backup_path, &nlp->nlp_llevel,
1269 &nlp->nlp_ldate) < 0) {
1270 MOD_LOGV3(params, NDMP_LOG_ERROR,
1271 "Getting dumpdates for %s level '%c'.\n",
1272 nlp->nlp_backup_path, *envp);
1273 return (NDMP_NO_MEM_ERR);
1274 } else {
1275 get_update_env_v3(params, nlp);
1276 rv = NDMP_NO_ERR;
1277 }
1278
1279 return (rv);
1280 }
1281
1282
1283 /*
1284 * save_date_token_v3
1285 *
1286 * Make the value of DUMP_DATE env variable and append the values
1287 * of the current backup in the file specified with the DMP_NAME
1288 * env variable if any file is specified. The file will be
1289 * relative name in the backup directory path.
1290 *
1291 * Parameters:
1292 * params (input) - pointer to the parameters structure
1293 * nlp (input) - pointer to the nlp structure
1294 *
1295 * Returns:
1296 * void
1297 */
1298 static void
save_date_token_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)1299 save_date_token_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
1300 {
1301 char val[QUAD_DECIMAL_LEN];
1302 u_longlong_t tok;
1303
1304 if (!params || !nlp)
1305 return;
1306
1307 nlp->nlp_tokseq++;
1308 tok = ((u_longlong_t)nlp->nlp_tokseq << 32) | nlp->nlp_cdate;
1309 (void) snprintf(val, sizeof (val), "%llu", tok);
1310
1311 NDMP_LOG(LOG_DEBUG, "tok: %lld %s", tok, val);
1312
1313 if (MOD_SETENV(params, "DUMP_DATE", val) != 0) {
1314 MOD_LOGV3(params, NDMP_LOG_ERROR,
1315 "Could not set DUMP_DATE to %s", val);
1316 } else if (!nlp->nlp_dmpnm) {
1317 NDMP_LOG(LOG_DEBUG, "No log file defined");
1318 } else if (ndmpd_append_dumptime(nlp->nlp_dmpnm, nlp->nlp_backup_path,
1319 nlp->nlp_tokseq, nlp->nlp_tokdate) < 0) {
1320 MOD_LOGV3(params, NDMP_LOG_ERROR,
1321 "Saving backup date for \"%s\" in \"%s\".\n",
1322 nlp->nlp_backup_path, nlp->nlp_dmpnm);
1323 }
1324 }
1325
1326
1327 /*
1328 * save_lbr_bk_v3
1329 *
1330 * Append the backup type and date in the DMP_NAME file for
1331 * LBR-type backup if any file is specified.
1332 *
1333 * Parameters:
1334 * params (input) - pointer to the parameters structure
1335 * nlp (input) - pointer to the nlp structure
1336 *
1337 * Returns:
1338 * void
1339 */
1340 static void
save_lbr_bk_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)1341 save_lbr_bk_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
1342 {
1343 if (!params || !nlp)
1344 return;
1345
1346 if (!nlp->nlp_dmpnm) {
1347 NDMP_LOG(LOG_DEBUG, "No log file defined");
1348 } else if (ndmpd_append_dumptime(nlp->nlp_dmpnm, nlp->nlp_backup_path,
1349 nlp->nlp_clevel, nlp->nlp_cdate) < 0) {
1350 MOD_LOGV3(params, NDMP_LOG_ERROR,
1351 "Saving backup date for \"%s\" in \"%s\".\n",
1352 nlp->nlp_backup_path, nlp->nlp_dmpnm);
1353 }
1354 }
1355
1356
1357 /*
1358 * save_level_v3
1359 *
1360 * Save the date and level of the current backup in the dumpdates
1361 * file.
1362 *
1363 * Parameters:
1364 * params (input) - pointer to the parameters structure
1365 * nlp (input) - pointer to the nlp structure
1366 *
1367 * Returns:
1368 * void
1369 */
1370 static void
save_level_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)1371 save_level_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
1372 {
1373 if (!params || !nlp)
1374 return;
1375
1376 if (!NLP_SHOULD_UPDATE(nlp)) {
1377 NDMP_LOG(LOG_DEBUG, "update not requested");
1378 } else if (ndmpd_put_dumptime(nlp->nlp_backup_path, nlp->nlp_clevel,
1379 nlp->nlp_cdate) < 0) {
1380 MOD_LOGV3(params, NDMP_LOG_ERROR, "Logging backup date.\n");
1381 }
1382 }
1383
1384
1385 /*
1386 * save_backup_date_v3
1387 *
1388 * A dispatcher function to call the corresponding save function
1389 * based on the backup type.
1390 *
1391 * Parameters:
1392 * params (input) - pointer to the parameters structure
1393 * nlp (input) - pointer to the nlp structure
1394 *
1395 * Returns:
1396 * void
1397 */
1398 static void
save_backup_date_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)1399 save_backup_date_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
1400 {
1401 if (!params || !nlp)
1402 return;
1403
1404 if (NLP_ISSET(nlp, NLPF_TOKENBK))
1405 save_date_token_v3(params, nlp);
1406 else if (NLP_ISSET(nlp, NLPF_LBRBK))
1407 save_lbr_bk_v3(params, nlp);
1408 else if (NLP_ISSET(nlp, NLPF_LEVELBK))
1409 save_level_v3(params, nlp);
1410 else {
1411 MOD_LOGV3(params, NDMP_LOG_ERROR,
1412 "Internal error: lost backup level type for \"%s\".\n",
1413 nlp->nlp_backup_path);
1414 }
1415 }
1416
1417
1418 /*
1419 * backup_alloc_structs_v3
1420 *
1421 * Create the structures for V3 backup. This includes:
1422 * Job stats
1423 * Reader writer IPC
1424 * File history callback structure
1425 *
1426 * Parameters:
1427 * session (input) - pointer to the session
1428 * jname (input) - name assigned to the current backup for
1429 * job stats strucure
1430 *
1431 * Returns:
1432 * 0: on success
1433 * -1: otherwise
1434 */
1435 static int
backup_alloc_structs_v3(ndmpd_session_t * session,char * jname)1436 backup_alloc_structs_v3(ndmpd_session_t *session, char *jname)
1437 {
1438 int n;
1439 long xfer_size;
1440 ndmp_lbr_params_t *nlp;
1441 tlm_commands_t *cmds;
1442
1443 nlp = ndmp_get_nlp(session);
1444 if (!nlp) {
1445 NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1446 return (-1);
1447 }
1448
1449 nlp->nlp_jstat = tlm_new_job_stats(jname);
1450 if (!nlp->nlp_jstat) {
1451 NDMP_LOG(LOG_DEBUG, "Creating job stats");
1452 return (-1);
1453 }
1454
1455 cmds = &nlp->nlp_cmds;
1456 (void) memset(cmds, 0, sizeof (*cmds));
1457
1458 xfer_size = ndmp_buffer_get_size(session);
1459 if (xfer_size < 512*KILOBYTE) {
1460 /*
1461 * Read multiple of mover_record_size near to 512K. This
1462 * will prevent the data being copied in the mover buffer
1463 * when we write the data.
1464 */
1465 n = 512 * KILOBYTE / xfer_size;
1466 if (n <= 0)
1467 n = 1;
1468 xfer_size *= n;
1469 NDMP_LOG(LOG_DEBUG, "Adjusted read size: %d",
1470 xfer_size);
1471 }
1472
1473 cmds->tcs_command = tlm_create_reader_writer_ipc(TRUE, xfer_size);
1474 if (!cmds->tcs_command) {
1475 tlm_un_ref_job_stats(jname);
1476 return (-1);
1477 }
1478
1479 nlp->nlp_logcallbacks = lbrlog_callbacks_init(session,
1480 ndmpd_fhpath_v3_cb, ndmpd_fhdir_v3_cb, ndmpd_fhnode_v3_cb);
1481 if (!nlp->nlp_logcallbacks) {
1482 tlm_release_reader_writer_ipc(cmds->tcs_command);
1483 tlm_un_ref_job_stats(jname);
1484 return (-1);
1485 }
1486 nlp->nlp_jstat->js_callbacks = (void *)(nlp->nlp_logcallbacks);
1487 nlp->nlp_restored = NULL;
1488
1489 return (0);
1490 }
1491
1492
1493 /*
1494 * restore_alloc_structs_v3
1495 *
1496 * Create the structures for V3 Restore. This includes:
1497 * Job stats
1498 * Reader writer IPC
1499 * File recovery callback structure
1500 *
1501 * Parameters:
1502 * session (input) - pointer to the session
1503 * jname (input) - name assigned to the current backup for
1504 * job stats strucure
1505 *
1506 * Returns:
1507 * 0: on success
1508 * -1: otherwise
1509 */
1510 int
restore_alloc_structs_v3(ndmpd_session_t * session,char * jname)1511 restore_alloc_structs_v3(ndmpd_session_t *session, char *jname)
1512 {
1513 long xfer_size;
1514 ndmp_lbr_params_t *nlp;
1515 tlm_commands_t *cmds;
1516
1517 nlp = ndmp_get_nlp(session);
1518 if (!nlp) {
1519 NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1520 return (-1);
1521 }
1522
1523 /* this is used in ndmpd_path_restored_v3() */
1524 nlp->nlp_lastidx = -1;
1525
1526 nlp->nlp_jstat = tlm_new_job_stats(jname);
1527 if (!nlp->nlp_jstat) {
1528 NDMP_LOG(LOG_DEBUG, "Creating job stats");
1529 return (-1);
1530 }
1531
1532 cmds = &nlp->nlp_cmds;
1533 (void) memset(cmds, 0, sizeof (*cmds));
1534
1535 xfer_size = ndmp_buffer_get_size(session);
1536 cmds->tcs_command = tlm_create_reader_writer_ipc(FALSE, xfer_size);
1537 if (!cmds->tcs_command) {
1538 tlm_un_ref_job_stats(jname);
1539 return (-1);
1540 }
1541
1542 nlp->nlp_logcallbacks = lbrlog_callbacks_init(session,
1543 ndmpd_path_restored_v3, NULL, NULL);
1544 if (!nlp->nlp_logcallbacks) {
1545 tlm_release_reader_writer_ipc(cmds->tcs_command);
1546 tlm_un_ref_job_stats(jname);
1547 return (-1);
1548 }
1549 nlp->nlp_jstat->js_callbacks = (void *)(nlp->nlp_logcallbacks);
1550
1551 nlp->nlp_rsbm = bm_alloc(nlp->nlp_nfiles, 0);
1552 if (nlp->nlp_rsbm < 0) {
1553 NDMP_LOG(LOG_ERR, "Out of memory.");
1554 lbrlog_callbacks_done(nlp->nlp_logcallbacks);
1555 tlm_release_reader_writer_ipc(cmds->tcs_command);
1556 tlm_un_ref_job_stats(jname);
1557 return (-1);
1558 }
1559
1560 return (0);
1561 }
1562
1563
1564 /*
1565 * free_structs_v3
1566 *
1567 * Release the resources allocated by backup_alloc_structs_v3
1568 * function.
1569 *
1570 * Parameters:
1571 * session (input) - pointer to the session
1572 * jname (input) - name assigned to the current backup for
1573 * job stats strucure
1574 *
1575 * Returns:
1576 * void
1577 */
1578 /*ARGSUSED*/
1579 static void
free_structs_v3(ndmpd_session_t * session,char * jname)1580 free_structs_v3(ndmpd_session_t *session, char *jname)
1581 {
1582 ndmp_lbr_params_t *nlp;
1583 tlm_commands_t *cmds;
1584
1585 nlp = ndmp_get_nlp(session);
1586 if (!nlp) {
1587 NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1588 return;
1589 }
1590 cmds = &nlp->nlp_cmds;
1591 if (!cmds) {
1592 NDMP_LOG(LOG_DEBUG, "cmds == NULL");
1593 return;
1594 }
1595
1596 if (nlp->nlp_logcallbacks) {
1597 lbrlog_callbacks_done(nlp->nlp_logcallbacks);
1598 nlp->nlp_logcallbacks = NULL;
1599 } else
1600 NDMP_LOG(LOG_DEBUG, "FH CALLBACKS == NULL");
1601
1602 if (cmds->tcs_command) {
1603 if (cmds->tcs_command->tc_buffers != NULL)
1604 tlm_release_reader_writer_ipc(cmds->tcs_command);
1605 else
1606 NDMP_LOG(LOG_DEBUG, "BUFFERS == NULL");
1607 cmds->tcs_command = NULL;
1608 } else
1609 NDMP_LOG(LOG_DEBUG, "COMMAND == NULL");
1610
1611 if (nlp->nlp_bkmap >= 0) {
1612 (void) dbm_free(nlp->nlp_bkmap);
1613 nlp->nlp_bkmap = -1;
1614 }
1615
1616 if (session->ns_data.dd_operation == NDMP_DATA_OP_RECOVER) {
1617 if (nlp->nlp_rsbm < 0) {
1618 NDMP_LOG(LOG_DEBUG, "nlp_rsbm < 0 %d", nlp->nlp_rsbm);
1619 } else {
1620 (void) bm_free(nlp->nlp_rsbm);
1621 nlp->nlp_rsbm = -1;
1622 }
1623 }
1624 }
1625
1626
1627 /*
1628 * backup_dirv3
1629 *
1630 * Backup a directory and update the bytes processed field of the
1631 * data server.
1632 *
1633 * Parameters:
1634 * bpp (input) - pointer to the backup parameters structure
1635 * pnp (input) - pointer to the path node
1636 * enp (input) - pointer to the entry node
1637 *
1638 * Returns:
1639 * 0: on success
1640 * != 0: otherwise
1641 */
1642 static int
backup_dirv3(bk_param_v3_t * bpp,fst_node_t * pnp,fst_node_t * enp)1643 backup_dirv3(bk_param_v3_t *bpp, fst_node_t *pnp,
1644 fst_node_t *enp)
1645 {
1646 longlong_t apos, bpos;
1647 acl_t *aclp = NULL;
1648 char *acltp;
1649 struct stat64 st;
1650 char fullpath[TLM_MAX_PATH_NAME];
1651 char *p;
1652
1653 if (!bpp || !pnp || !enp) {
1654 NDMP_LOG(LOG_DEBUG, "Invalid argument");
1655 return (-1);
1656 }
1657
1658 NDMP_LOG(LOG_DEBUG, "d(%s)", bpp->bp_tmp);
1659
1660 if (lstat64(bpp->bp_tmp, &st) != 0)
1661 return (0);
1662
1663 if (acl_get(bpp->bp_tmp, ACL_NO_TRIVIAL, &aclp) != 0) {
1664 NDMP_LOG(LOG_DEBUG, "acl_get error errno=%d", errno);
1665 return (-1);
1666 }
1667 if (aclp && (acltp = acl_totext(aclp,
1668 ACL_APPEND_ID | ACL_SID_FMT | ACL_COMPACT_FMT)) != NULL) {
1669 (void) strlcpy(bpp->bp_tlmacl->acl_info.attr_info,
1670 acltp, TLM_MAX_ACL_TXT);
1671 acl_free(aclp);
1672 free(acltp);
1673 } else {
1674 *bpp->bp_tlmacl->acl_info.attr_info = '\0';
1675 }
1676
1677 bpos = tlm_get_data_offset(bpp->bp_lcmd);
1678
1679 p = bpp->bp_tmp + strlen(bpp->bp_chkpnm);
1680 if (*p == '/')
1681 (void) snprintf(fullpath, TLM_MAX_PATH_NAME, "%s%s",
1682 bpp->bp_unchkpnm, p);
1683 else
1684 (void) snprintf(fullpath, TLM_MAX_PATH_NAME, "%s/%s",
1685 bpp->bp_unchkpnm, p);
1686
1687 if (tm_tar_ops.tm_putdir != NULL)
1688 (void) (tm_tar_ops.tm_putdir)(fullpath, bpp->bp_tlmacl,
1689 bpp->bp_lcmd, bpp->bp_js);
1690
1691 apos = tlm_get_data_offset(bpp->bp_lcmd);
1692 bpp->bp_session->ns_data.dd_module.dm_stats.ms_bytes_processed +=
1693 apos - bpos;
1694
1695 return (0);
1696 }
1697
1698
1699 /*
1700 * backup_filev3
1701 *
1702 * Backup a file and update the bytes processed field of the
1703 * data server.
1704 *
1705 * Parameters:
1706 * bpp (input) - pointer to the backup parameters structure
1707 * pnp (input) - pointer to the path node
1708 * enp (input) - pointer to the entry node
1709 *
1710 * Returns:
1711 * 0: on success
1712 * != 0: otherwise
1713 */
1714 static int
backup_filev3(bk_param_v3_t * bpp,fst_node_t * pnp,fst_node_t * enp)1715 backup_filev3(bk_param_v3_t *bpp, fst_node_t *pnp,
1716 fst_node_t *enp)
1717 {
1718 char *ent;
1719 longlong_t rv;
1720 longlong_t apos, bpos;
1721 acl_t *aclp = NULL;
1722 char *acltp;
1723 struct stat64 st;
1724 char fullpath[TLM_MAX_PATH_NAME];
1725 char *p;
1726
1727 if (!bpp || !pnp || !enp) {
1728 NDMP_LOG(LOG_DEBUG, "Invalid argument");
1729 return (-1);
1730 }
1731
1732 NDMP_LOG(LOG_DEBUG, "f(%s)", bpp->bp_tmp);
1733
1734 if (lstat64(bpp->bp_tmp, &st) != 0)
1735 return (0);
1736
1737 if (!S_ISLNK(bpp->bp_tlmacl->acl_attr.st_mode)) {
1738 if (acl_get(bpp->bp_tmp, ACL_NO_TRIVIAL, &aclp) != 0) {
1739 NDMP_LOG(LOG_DEBUG, "acl_get error");
1740 return (-1);
1741 }
1742
1743 if (aclp &&
1744 (acltp = acl_totext(aclp,
1745 ACL_APPEND_ID | ACL_SID_FMT | ACL_COMPACT_FMT)) != NULL) {
1746 (void) strlcpy(bpp->bp_tlmacl->acl_info.attr_info,
1747 acltp, TLM_MAX_ACL_TXT);
1748 acl_free(aclp);
1749 free(acltp);
1750 } else {
1751 *bpp->bp_tlmacl->acl_info.attr_info = '\0';
1752 }
1753 }
1754
1755 bpos = tlm_get_data_offset(bpp->bp_lcmd);
1756 ent = enp->tn_path ? enp->tn_path : "";
1757
1758 p = pnp->tn_path + strlen(bpp->bp_chkpnm);
1759 if (*p == '/')
1760 (void) snprintf(fullpath, TLM_MAX_PATH_NAME, "%s%s",
1761 bpp->bp_unchkpnm, p);
1762 else
1763 (void) snprintf(fullpath, TLM_MAX_PATH_NAME, "%s/%s",
1764 bpp->bp_unchkpnm, p);
1765
1766 if (tm_tar_ops.tm_putfile != NULL)
1767 rv = (tm_tar_ops.tm_putfile)(fullpath, ent, pnp->tn_path,
1768 bpp->bp_tlmacl, bpp->bp_cmds, bpp->bp_lcmd, bpp->bp_js,
1769 bpp->bp_session->hardlink_q);
1770
1771 apos = tlm_get_data_offset(bpp->bp_lcmd);
1772 bpp->bp_session->ns_data.dd_module.dm_stats.ms_bytes_processed +=
1773 apos - bpos;
1774
1775 return (rv < 0 ? rv : 0);
1776 }
1777
1778
1779 /*
1780 * check_bk_args
1781 *
1782 * Check the argument of the bpp. This is shared function between
1783 * timebk_v3 and lbrbk_v3 functions. The checks include:
1784 * - The bpp itself.
1785 * - If the session pointer of the bpp is valid.
1786 * - If the session connection to the DMA is closed.
1787 * - If the nlp pointer of the bpp is valid.
1788 * - If the backup is aborted.
1789 *
1790 * Parameters:
1791 * bpp (input) - pointer to the backup parameters structure
1792 *
1793 * Returns:
1794 * 0: if everything's OK
1795 * != 0: otherwise
1796 */
1797 static int
check_bk_args(bk_param_v3_t * bpp)1798 check_bk_args(bk_param_v3_t *bpp)
1799 {
1800 int rv;
1801
1802 if (!bpp) {
1803 rv = -1;
1804 NDMP_LOG(LOG_DEBUG, "Lost bpp");
1805 } else if (!bpp->bp_session) {
1806 rv = -1;
1807 NDMP_LOG(LOG_DEBUG, "Session is NULL");
1808 } else if (bpp->bp_session->ns_eof) {
1809 rv = -1;
1810 NDMP_LOG(LOG_INFO,
1811 "Connection client is closed for backup \"%s\"",
1812 bpp->bp_nlp->nlp_backup_path);
1813 } else if (!bpp->bp_nlp) {
1814 NDMP_LOG(LOG_DEBUG, "Lost nlp");
1815 return (-1);
1816 } else if (bpp->bp_session->ns_data.dd_abort) {
1817 rv = -1;
1818 NDMP_LOG(LOG_INFO, "Backup aborted \"%s\"",
1819 bpp->bp_nlp->nlp_backup_path);
1820 } else
1821 rv = 0;
1822
1823 return (rv);
1824 }
1825
1826
1827 /*
1828 * shouldskip
1829 *
1830 * Determines if the current entry should be skipped or it
1831 * should be backed up.
1832 *
1833 * Parameters:
1834 * bpp (input) - pointer to the backup parameters structure
1835 * pnp (input) - pointer to the path node
1836 * enp (input) - pointer to the entry node
1837 * errp (output) - pointer to the error value that should be
1838 * returned by the caller
1839 *
1840 * Returns:
1841 * TRUE: if the entry should not be backed up
1842 * FALSE: otherwise
1843 */
1844 static boolean_t
shouldskip(bk_param_v3_t * bpp,fst_node_t * pnp,fst_node_t * enp,int * errp)1845 shouldskip(bk_param_v3_t *bpp, fst_node_t *pnp,
1846 fst_node_t *enp, int *errp)
1847 {
1848 char *ent;
1849 boolean_t rv;
1850 struct stat64 *estp;
1851
1852 if (!bpp || !pnp || !enp || !errp) {
1853 NDMP_LOG(LOG_DEBUG, "Invalid argument");
1854 return (TRUE);
1855 }
1856
1857 if (!enp->tn_path) {
1858 ent = "";
1859 estp = pnp->tn_st;
1860 } else {
1861 ent = enp->tn_path;
1862 estp = enp->tn_st;
1863 }
1864
1865 /*
1866 * When excluding or skipping entries, FST_SKIP should be
1867 * returned, otherwise, 0 should be returned to
1868 * get other entries in the directory of this entry.
1869 */
1870 if (!dbm_getone(bpp->bp_nlp->nlp_bkmap, (u_longlong_t)estp->st_ino)) {
1871 rv = TRUE;
1872 *errp = S_ISDIR(estp->st_mode) ? FST_SKIP : 0;
1873 NDMP_LOG(LOG_DEBUG, "Skipping %d %s/%s",
1874 *errp, pnp->tn_path, ent);
1875 } else if (tlm_is_excluded(pnp->tn_path, ent, bpp->bp_excls)) {
1876 rv = TRUE;
1877 *errp = S_ISDIR(estp->st_mode) ? FST_SKIP : 0;
1878 NDMP_LOG(LOG_DEBUG, "excl %d \"%s/%s\"",
1879 *errp, pnp->tn_path, ent);
1880 } else if (inexl(bpp->bp_nlp->nlp_exl, ent)) {
1881 rv = TRUE;
1882 *errp = S_ISDIR(estp->st_mode) ? FST_SKIP : 0;
1883 NDMP_LOG(LOG_DEBUG, "out %d \"%s/%s\"",
1884 *errp, pnp->tn_path, ent);
1885 } else if (!S_ISDIR(estp->st_mode) &&
1886 !ininc(bpp->bp_nlp->nlp_inc, ent)) {
1887 rv = TRUE;
1888 *errp = 0;
1889 NDMP_LOG(LOG_DEBUG, "!in \"%s/%s\"", pnp->tn_path, ent);
1890 } else
1891 rv = FALSE;
1892
1893 return (rv);
1894 }
1895
1896
1897 /*
1898 * ischngd
1899 *
1900 * Check if the object specified should be backed up or not.
1901 * If stp belongs to a directory and if it is marked in the
1902 * bitmap vector, it shows that either the directory itself is
1903 * modified or there is something below it that will be backed
1904 * up.
1905 *
1906 * By setting ndmp_force_bk_dirs global variable to a non-zero
1907 * value, directories are backed up anyways.
1908 *
1909 * Backing up the directories unconditionally helps
1910 * restoring the metadata of directories as well, when one
1911 * of the objects below them are being restored.
1912 *
1913 * For non-directory objects, if the modification or change
1914 * time of the object is after the date specified by the
1915 * bk_selector_t, the the object must be backed up.
1916 */
1917 static boolean_t
ischngd(struct stat64 * stp,time_t t,ndmp_lbr_params_t * nlp)1918 ischngd(struct stat64 *stp, time_t t, ndmp_lbr_params_t *nlp)
1919 {
1920 boolean_t rv;
1921
1922 if (!stp) {
1923 rv = FALSE;
1924 NDMP_LOG(LOG_DEBUG, "stp is NULL");
1925 } else if (!nlp) {
1926 rv = FALSE;
1927 NDMP_LOG(LOG_DEBUG, "nlp is NULL");
1928 } else if (t == 0) {
1929 /*
1930 * if we are doing base backup then we do not need to
1931 * check the time, for we should backup everything.
1932 */
1933 rv = TRUE;
1934 NDMP_LOG(LOG_DEBUG, "Base Backup");
1935 } else if (S_ISDIR(stp->st_mode) && ndmp_force_bk_dirs) {
1936 rv = TRUE;
1937 NDMP_LOG(LOG_DEBUG, "d(%lu)", (uint_t)stp->st_ino);
1938 } else if (S_ISDIR(stp->st_mode) &&
1939 dbm_getone(nlp->nlp_bkmap, (u_longlong_t)stp->st_ino) &&
1940 ((NLP_ISDUMP(nlp) && ndmp_dump_path_node) ||
1941 (NLP_ISTAR(nlp) && ndmp_tar_path_node))) {
1942 /*
1943 * If the object is a directory and it leads to a modified
1944 * object (that should be backed up) and for that type of
1945 * backup the path nodes should be backed up, then return
1946 * TRUE.
1947 *
1948 * This is required by some DMAs like Backup Express, which
1949 * needs to receive ADD_NODE (for dump) or ADD_PATH (for tar)
1950 * for the intermediate directories of a modified object.
1951 * Other DMAs, like net_backup and net_worker, do not have such
1952 * requirement. This requirement makes sense for dump format
1953 * but for 'tar' format, it does not. In provision to the
1954 * NDMP-v4 spec, for 'tar' format the intermediate directories
1955 * need not to be reported.
1956 */
1957 rv = TRUE;
1958 NDMP_LOG(LOG_DEBUG, "p(%lu)", (u_longlong_t)stp->st_ino);
1959 } else if (stp->st_mtime > t) {
1960 rv = TRUE;
1961 NDMP_LOG(LOG_DEBUG, "m(%lu): %lu > %lu",
1962 (uint_t)stp->st_ino, (uint_t)stp->st_mtime, (uint_t)t);
1963 } else if (stp->st_ctime > t) {
1964 if (NLP_IGNCTIME(nlp)) {
1965 rv = FALSE;
1966 NDMP_LOG(LOG_DEBUG, "ign c(%lu): %lu > %lu",
1967 (uint_t)stp->st_ino, (uint_t)stp->st_ctime,
1968 (uint_t)t);
1969 } else {
1970 rv = TRUE;
1971 NDMP_LOG(LOG_DEBUG, "c(%lu): %lu > %lu",
1972 (uint_t)stp->st_ino, (uint_t)stp->st_ctime,
1973 (uint_t)t);
1974 }
1975 } else {
1976 rv = FALSE;
1977 NDMP_LOG(LOG_DEBUG, "mc(%lu): (%lu,%lu) < %lu",
1978 (uint_t)stp->st_ino, (uint_t)stp->st_mtime,
1979 (uint_t)stp->st_ctime, (uint_t)t);
1980 }
1981
1982 return (rv);
1983 }
1984
1985
1986 /*
1987 * iscreated
1988 *
1989 * This function is used to check last mtime (currently inside the ACL
1990 * structure) instead of ctime for checking if the file is to be backed up
1991 * or not. See option "inc.lmtime" for more details
1992 */
1993 /*ARGSUSED*/
iscreated(ndmp_lbr_params_t * nlp,char * name,tlm_acls_t * tacl,time_t t)1994 int iscreated(ndmp_lbr_params_t *nlp, char *name, tlm_acls_t *tacl,
1995 time_t t)
1996 {
1997 int ret;
1998 acl_t *aclp = NULL;
1999 char *acltp;
2000
2001 NDMP_LOG(LOG_DEBUG, "flags %x", nlp->nlp_flags);
2002 if (NLP_INCLMTIME(nlp) == FALSE)
2003 return (0);
2004
2005 ret = acl_get(name, ACL_NO_TRIVIAL, &aclp);
2006 if (ret != 0) {
2007 NDMP_LOG(LOG_DEBUG,
2008 "Error getting the acl information: err %d", ret);
2009 return (0);
2010 }
2011 if (aclp && (acltp = acl_totext(aclp,
2012 ACL_APPEND_ID | ACL_SID_FMT | ACL_COMPACT_FMT)) != NULL) {
2013 (void) strlcpy(tacl->acl_info.attr_info, acltp,
2014 TLM_MAX_ACL_TXT);
2015 acl_free(aclp);
2016 free(acltp);
2017 }
2018
2019 /* Need to add support for last mtime */
2020
2021 return (0);
2022 }
2023
2024 /*
2025 * size_cb
2026 *
2027 * The callback function for calculating the size of
2028 * the backup path. This is used to get an estimate
2029 * of the progress of backup during NDMP backup
2030 */
2031 static int
size_cb(void * arg,fst_node_t * pnp,fst_node_t * enp)2032 size_cb(void *arg, fst_node_t *pnp, fst_node_t *enp)
2033 {
2034 struct stat64 *stp;
2035
2036 stp = enp->tn_path ? enp->tn_st : pnp->tn_st;
2037 *((u_longlong_t *)arg) += stp->st_size;
2038
2039 return (0);
2040 }
2041
2042 /*
2043 * timebk_v3
2044 *
2045 * The callback function for backing up objects based on
2046 * their time stamp. This is shared between token-based
2047 * and level-based backup, which look at the time stamps
2048 * of the objects to determine if they should be backed
2049 * up.
2050 *
2051 * Parameters:
2052 * arg (input) - pointer to the backup parameters structure
2053 * pnp (input) - pointer to the path node
2054 * enp (input) - pointer to the entry node
2055 *
2056 * Returns:
2057 * 0: if backup should continue
2058 * -1: if the backup should be stopped
2059 * FST_SKIP: if backing up the current directory is enough
2060 */
2061 static int
timebk_v3(void * arg,fst_node_t * pnp,fst_node_t * enp)2062 timebk_v3(void *arg, fst_node_t *pnp, fst_node_t *enp)
2063 {
2064 char *ent;
2065 int rv;
2066 time_t t;
2067 bk_param_v3_t *bpp;
2068 struct stat64 *stp;
2069 fs_fhandle_t *fhp;
2070
2071 bpp = (bk_param_v3_t *)arg;
2072
2073 rv = check_bk_args(bpp);
2074 if (rv != 0)
2075 return (rv);
2076
2077 stp = enp->tn_path ? enp->tn_st : pnp->tn_st;
2078 if (shouldskip(bpp, pnp, enp, &rv))
2079 return (rv);
2080
2081 if (enp->tn_path) {
2082 ent = enp->tn_path;
2083 stp = enp->tn_st;
2084 fhp = enp->tn_fh;
2085 } else {
2086 ent = "";
2087 stp = pnp->tn_st;
2088 fhp = pnp->tn_fh;
2089 }
2090
2091
2092 if (!tlm_cat_path(bpp->bp_tmp, pnp->tn_path, ent)) {
2093 NDMP_LOG(LOG_ERR, "Path too long %s/%s.", pnp->tn_path, ent);
2094 return (FST_SKIP);
2095 }
2096 if (NLP_ISSET(bpp->bp_nlp, NLPF_TOKENBK))
2097 t = bpp->bp_nlp->nlp_tokdate;
2098 else if (NLP_ISSET(bpp->bp_nlp, NLPF_LEVELBK)) {
2099 t = bpp->bp_nlp->nlp_ldate;
2100 } else {
2101 NDMP_LOG(LOG_DEBUG, "Unknown backup type on \"%s/%s\"",
2102 pnp->tn_path, ent);
2103 return (-1);
2104 }
2105
2106 if (S_ISDIR(stp->st_mode)) {
2107 bpp->bp_tlmacl->acl_dir_fh = *fhp;
2108 (void) ndmpd_fhdir_v3_cb(bpp->bp_nlp->nlp_logcallbacks,
2109 bpp->bp_tmp, stp);
2110
2111 if (ischngd(stp, t, bpp->bp_nlp)) {
2112 (void) memcpy(&bpp->bp_tlmacl->acl_attr, stp,
2113 sizeof (struct stat64));
2114 rv = backup_dirv3(bpp, pnp, enp);
2115 }
2116 } else {
2117 if (ischngd(stp, t, bpp->bp_nlp) ||
2118 iscreated(bpp->bp_nlp, bpp->bp_tmp, bpp->bp_tlmacl, t)) {
2119 rv = 0;
2120 (void) memcpy(&bpp->bp_tlmacl->acl_attr, stp,
2121 sizeof (struct stat64));
2122 bpp->bp_tlmacl->acl_fil_fh = *fhp;
2123 (void) backup_filev3(bpp, pnp, enp);
2124 }
2125 }
2126
2127 return (rv);
2128 }
2129
2130
2131 /*
2132 * lbrbk_v3
2133 *
2134 * The callback function for backing up objects based on
2135 * their archive directory bit. This is used in LBR-type
2136 * backup. In which the objects are backed up if their
2137 * archive bit is set.
2138 *
2139 * Parameters:
2140 * arg (input) - pointer to the backup parameters structure
2141 * pnp (input) - pointer to the path node
2142 * enp (input) - pointer to the entry node
2143 *
2144 * Returns:
2145 * 0: if backup should continue
2146 * -1: if the backup should be stopped
2147 * FST_SKIP: if backing up the current directory is enough
2148 */
2149 static int
lbrbk_v3(void * arg,fst_node_t * pnp,fst_node_t * enp)2150 lbrbk_v3(void *arg, fst_node_t *pnp, fst_node_t *enp)
2151 {
2152 char *ent;
2153 int rv;
2154 bk_param_v3_t *bpp;
2155 struct stat64 *stp;
2156 fs_fhandle_t *fhp;
2157
2158 bpp = (bk_param_v3_t *)arg;
2159 rv = check_bk_args(bpp);
2160 if (rv != 0)
2161 return (rv);
2162
2163 stp = enp->tn_path ? enp->tn_st : pnp->tn_st;
2164 if (shouldskip(bpp, pnp, enp, &rv))
2165 return (rv);
2166
2167 if (enp->tn_path) {
2168 ent = enp->tn_path;
2169 stp = enp->tn_st;
2170 fhp = enp->tn_fh;
2171 } else {
2172 ent = "";
2173 stp = pnp->tn_st;
2174 fhp = pnp->tn_fh;
2175 }
2176
2177 if (!tlm_cat_path(bpp->bp_tmp, pnp->tn_path, ent)) {
2178 NDMP_LOG(LOG_ERR, "Path too long %s/%s.", pnp->tn_path, ent);
2179 return (FST_SKIP);
2180 }
2181 if (!NLP_ISSET(bpp->bp_nlp, NLPF_LBRBK)) {
2182 NDMP_LOG(LOG_DEBUG, "!NLPF_LBRBK");
2183 return (-1);
2184 }
2185
2186 if (S_ISDIR(stp->st_mode)) {
2187 bpp->bp_tlmacl->acl_dir_fh = *fhp;
2188 (void) ndmpd_fhdir_v3_cb(bpp->bp_nlp->nlp_logcallbacks,
2189 bpp->bp_tmp, stp);
2190
2191 if (SHOULD_LBRBK(bpp)) {
2192 bpp->bp_tlmacl->acl_attr = *stp;
2193 rv = backup_dirv3(bpp, pnp, enp);
2194 }
2195 } else if (SHOULD_LBRBK(bpp)) {
2196 rv = 0;
2197 bpp->bp_tlmacl->acl_attr = *stp;
2198 bpp->bp_tlmacl->acl_fil_fh = *fhp;
2199 (void) backup_filev3(bpp, pnp, enp);
2200 }
2201
2202 return (rv);
2203 }
2204
2205
2206 /*
2207 * backup_reader_v3
2208 *
2209 * The reader thread for the backup. It sets up the callback
2210 * parameters and traverses the backup hierarchy in level-order
2211 * way.
2212 *
2213 * Parameters:
2214 * jname (input) - name assigned to the current backup for
2215 * job stats strucure
2216 * nlp (input) - pointer to the nlp structure
2217 * cmds (input) - pointer to the tlm_commands_t structure
2218 *
2219 * Returns:
2220 * 0: on success
2221 * != 0: otherwise
2222 */
2223 static int
backup_reader_v3(backup_reader_arg_t * argp)2224 backup_reader_v3(backup_reader_arg_t *argp)
2225 {
2226 int rv;
2227 tlm_cmd_t *lcmd;
2228 tlm_acls_t tlm_acls;
2229 longlong_t bpos, n;
2230 bk_param_v3_t bp;
2231 fs_traverse_t ft;
2232 char *jname;
2233 ndmp_lbr_params_t *nlp;
2234 tlm_commands_t *cmds;
2235
2236 if (!argp)
2237 return (-1);
2238
2239 jname = argp->br_jname;
2240 nlp = argp->br_nlp;
2241 cmds = argp->br_cmds;
2242
2243 rv = 0;
2244 lcmd = cmds->tcs_command;
2245 lcmd->tc_ref++;
2246 cmds->tcs_reader_count++;
2247
2248 (void) memset(&tlm_acls, 0, sizeof (tlm_acls));
2249
2250 /* NDMP parameters */
2251 bp.bp_session = nlp->nlp_session;
2252 bp.bp_nlp = nlp;
2253
2254 /* LBR-related parameters */
2255 bp.bp_js = tlm_ref_job_stats(jname);
2256 bp.bp_cmds = cmds;
2257 bp.bp_lcmd = lcmd;
2258 bp.bp_tlmacl = &tlm_acls;
2259 bp.bp_opr = 0;
2260
2261 /* release the parent thread, after referencing the job stats */
2262 (void) pthread_barrier_wait(&argp->br_barrier);
2263
2264 bp.bp_tmp = ndmp_malloc(sizeof (char) * TLM_MAX_PATH_NAME);
2265 if (!bp.bp_tmp)
2266 return (-1);
2267
2268 /*
2269 * Make the checkpointed paths for traversing the
2270 * backup hierarchy, if we make the checkpoint.
2271 */
2272 bp.bp_unchkpnm = nlp->nlp_backup_path;
2273 if (!NLP_ISCHKPNTED(nlp)) {
2274 tlm_acls.acl_checkpointed = TRUE;
2275 bp.bp_chkpnm = ndmp_malloc(sizeof (char) * TLM_MAX_PATH_NAME);
2276 if (!bp.bp_chkpnm) {
2277 NDMP_FREE(bp.bp_tmp);
2278 return (-1);
2279 }
2280 (void) tlm_build_snapshot_name(nlp->nlp_backup_path,
2281 bp.bp_chkpnm, nlp->nlp_jstat->js_job_name);
2282 } else {
2283 tlm_acls.acl_checkpointed = FALSE;
2284 bp.bp_chkpnm = nlp->nlp_backup_path;
2285 }
2286 bp.bp_excls = ndmpd_make_exc_list();
2287
2288 /* set traversing arguments */
2289 ft.ft_path = nlp->nlp_backup_path;
2290 ft.ft_lpath = bp.bp_chkpnm;
2291
2292 NDMP_LOG(LOG_DEBUG, "path %s lpath %s", ft.ft_path, ft.ft_lpath);
2293 if (NLP_ISSET(nlp, NLPF_TOKENBK) || NLP_ISSET(nlp, NLPF_LEVELBK)) {
2294 ft.ft_callbk = timebk_v3;
2295 tlm_acls.acl_clear_archive = FALSE;
2296 } else if (NLP_ISSET(nlp, NLPF_LBRBK)) {
2297 ft.ft_callbk = lbrbk_v3;
2298 tlm_acls.acl_clear_archive = FALSE;
2299
2300 NDMP_LOG(LOG_DEBUG, "bp_opr %x clr_arc %c",
2301 bp.bp_opr, NDMP_YORN(tlm_acls.acl_clear_archive));
2302 } else {
2303 rv = -1;
2304 MOD_LOGV3(nlp->nlp_params, NDMP_LOG_ERROR,
2305 "Unknow backup type.\n");
2306 }
2307 ft.ft_arg = &bp;
2308 ft.ft_logfp = (ft_log_t)ndmp_log;
2309 ft.ft_flags = FST_VERBOSE | FST_STOP_ONERR;
2310
2311 /* take into account the header written to the stream so far */
2312 n = tlm_get_data_offset(lcmd);
2313 nlp->nlp_session->ns_data.dd_module.dm_stats.ms_bytes_processed = n;
2314
2315 if (rv == 0) {
2316 /* start traversing the hierarchy and actual backup */
2317 rv = traverse_level(&ft);
2318 if (rv == 0) {
2319 /* write the trailer and update the bytes processed */
2320 bpos = tlm_get_data_offset(lcmd);
2321 (void) write_tar_eof(lcmd);
2322 n = tlm_get_data_offset(lcmd) - bpos;
2323 nlp->nlp_session->
2324 ns_data.dd_module.dm_stats.ms_bytes_processed += n;
2325 } else {
2326 MOD_LOGV3(nlp->nlp_params, NDMP_LOG_ERROR,
2327 "Filesystem traverse error.\n");
2328 ndmpd_data_error(nlp->nlp_session,
2329 NDMP_DATA_HALT_INTERNAL_ERROR);
2330 }
2331 }
2332
2333 if (!NLP_ISCHKPNTED(nlp))
2334 NDMP_FREE(bp.bp_chkpnm);
2335 NDMP_FREE(bp.bp_tmp);
2336 NDMP_FREE(bp.bp_excls);
2337
2338 cmds->tcs_reader_count--;
2339 lcmd->tc_writer = TLM_STOP;
2340 tlm_release_reader_writer_ipc(lcmd);
2341 tlm_un_ref_job_stats(jname);
2342 return (rv);
2343
2344 }
2345
2346
2347 /*
2348 * tar_backup_v3
2349 *
2350 * Traverse the backup hierarchy if needed and make the bitmap.
2351 * Then launch reader and writer threads to do the actual backup.
2352 *
2353 * Parameters:
2354 * session (input) - pointer to the session
2355 * params (input) - pointer to the parameters structure
2356 * nlp (input) - pointer to the nlp structure
2357 * jname (input) - job name
2358 *
2359 * Returns:
2360 * 0: on success
2361 * != 0: otherwise
2362 */
2363 static int
tar_backup_v3(ndmpd_session_t * session,ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp,char * jname)2364 tar_backup_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
2365 ndmp_lbr_params_t *nlp, char *jname)
2366 {
2367 tlm_commands_t *cmds;
2368 backup_reader_arg_t arg;
2369 pthread_t rdtp;
2370 char info[256];
2371 int result;
2372 ndmp_context_t nctx;
2373 int err;
2374
2375 if (ndmp_get_bk_dir_ino(nlp))
2376 return (-1);
2377
2378 result = err = 0;
2379
2380 /* exit as if there was an internal error */
2381 if (session->ns_eof)
2382 return (-1);
2383
2384 if (!session->ns_data.dd_abort) {
2385 if (backup_alloc_structs_v3(session, jname) < 0) {
2386 nlp->nlp_bkmap = -1;
2387 return (-1);
2388 }
2389
2390 if (ndmpd_mark_inodes_v3(session, nlp) != 0) {
2391 if (nlp->nlp_bkmap != -1) {
2392 (void) dbm_free(nlp->nlp_bkmap);
2393 nlp->nlp_bkmap = -1;
2394 }
2395 free_structs_v3(session, jname);
2396 return (-1);
2397 }
2398
2399 nlp->nlp_jstat->js_start_ltime = time(NULL);
2400 nlp->nlp_jstat->js_start_time = nlp->nlp_jstat->js_start_ltime;
2401 nlp->nlp_jstat->js_chkpnt_time = nlp->nlp_cdate;
2402
2403 cmds = &nlp->nlp_cmds;
2404 cmds->tcs_reader = cmds->tcs_writer = TLM_BACKUP_RUN;
2405 cmds->tcs_command->tc_reader = TLM_BACKUP_RUN;
2406 cmds->tcs_command->tc_writer = TLM_BACKUP_RUN;
2407
2408 if (ndmp_write_utf8magic(cmds->tcs_command) < 0) {
2409 free_structs_v3(session, jname);
2410 return (-1);
2411 }
2412
2413 NDMP_LOG(LOG_DEBUG,
2414 "Backing up \"%s\" started.", nlp->nlp_backup_path);
2415
2416 /* Plug-in module */
2417 if (ndmp_pl != NULL &&
2418 ndmp_pl->np_pre_backup != NULL) {
2419 (void) memset(&nctx, 0, sizeof (ndmp_context_t));
2420 nctx.nc_plversion = ndmp_pl->np_plversion;
2421 nctx.nc_plname = ndmpd_get_prop(NDMP_PLUGIN_PATH);
2422 nctx.nc_cmds = cmds;
2423 nctx.nc_params = params;
2424 nctx.nc_ddata = (void *) session;
2425 if ((err = ndmp_pl->np_pre_backup(ndmp_pl, &nctx,
2426 nlp->nlp_backup_path)) != 0) {
2427 NDMP_LOG(LOG_ERR, "Pre-backup plug-in: %m");
2428 goto backup_out;
2429 }
2430 }
2431
2432 (void) memset(&arg, 0, sizeof (backup_reader_arg_t));
2433 arg.br_jname = jname;
2434 arg.br_nlp = nlp;
2435 arg.br_cmds = cmds;
2436
2437 (void) pthread_barrier_init(&arg.br_barrier, 0, 2);
2438
2439 err = pthread_create(&rdtp, NULL, (funct_t)backup_reader_v3,
2440 (void *)&arg);
2441 if (err == 0) {
2442 (void) pthread_barrier_wait(&arg.br_barrier);
2443 (void) pthread_barrier_destroy(&arg.br_barrier);
2444 } else {
2445 (void) pthread_barrier_destroy(&arg.br_barrier);
2446 free_structs_v3(session, jname);
2447 NDMP_LOG(LOG_DEBUG, "Launch backup_reader_v3: %m");
2448 return (-1);
2449 }
2450
2451 if ((err = ndmp_tar_writer(session, params, cmds)) != 0)
2452 result = EIO;
2453
2454 nlp->nlp_jstat->js_stop_time = time(NULL);
2455
2456 (void) snprintf(info, sizeof (info),
2457 "Runtime [%s] %llu bytes (%llu): %d seconds\n",
2458 nlp->nlp_backup_path,
2459 session->ns_data.dd_module.dm_stats.ms_bytes_processed,
2460 session->ns_data.dd_module.dm_stats.ms_bytes_processed,
2461 nlp->nlp_jstat->js_stop_time -
2462 nlp->nlp_jstat->js_start_ltime);
2463 MOD_LOGV3(params, NDMP_LOG_NORMAL, info);
2464
2465 ndmp_wait_for_reader(cmds);
2466 (void) pthread_join(rdtp, NULL);
2467
2468 /* exit as if there was an internal error */
2469 if (session->ns_eof) {
2470 result = EPIPE;
2471 err = -1;
2472 }
2473 if (!session->ns_data.dd_abort) {
2474 ndmpd_audit_backup(session->ns_connection,
2475 nlp->nlp_backup_path,
2476 session->ns_data.dd_data_addr.addr_type,
2477 session->ns_tape.td_adapter_name, result);
2478 NDMP_LOG(LOG_DEBUG, "Backing up \"%s\" Finished.",
2479 nlp->nlp_backup_path);
2480 }
2481 }
2482
2483 if (session->ns_data.dd_abort) {
2484 ndmpd_audit_backup(session->ns_connection,
2485 nlp->nlp_backup_path,
2486 session->ns_data.dd_data_addr.addr_type,
2487 session->ns_tape.td_adapter_name, EINTR);
2488 NDMP_LOG(LOG_DEBUG,
2489 "Backing up \"%s\" aborted.", nlp->nlp_backup_path);
2490 err = -1;
2491 } else {
2492
2493 backup_out:
2494 /* Plug-in module */
2495 if (ndmp_pl != NULL &&
2496 ndmp_pl->np_post_backup != NULL &&
2497 ndmp_pl->np_post_backup(ndmp_pl, &nctx, err) == -1) {
2498 NDMP_LOG(LOG_DEBUG, "Post-backup plug-in: %m");
2499 return (-1);
2500 }
2501 }
2502
2503 free_structs_v3(session, jname);
2504 return (err);
2505 }
2506
2507 /*
2508 * get_backup_size
2509 *
2510 * Find the estimate of backup size. This is used to get an estimate
2511 * of the progress of backup during NDMP backup.
2512 */
2513 void
get_backup_size(ndmp_bkup_size_arg_t * sarg)2514 get_backup_size(ndmp_bkup_size_arg_t *sarg)
2515 {
2516 fs_traverse_t ft;
2517 u_longlong_t bk_size;
2518 char spath[PATH_MAX];
2519 int rv;
2520
2521 bk_size = 0;
2522 if (fs_is_chkpntvol(sarg->bs_path)) {
2523 ft.ft_path = sarg->bs_path;
2524 } else {
2525 (void) tlm_build_snapshot_name(sarg->bs_path,
2526 spath, sarg->bs_jname);
2527 ft.ft_path = spath;
2528 }
2529
2530 ft.ft_lpath = ft.ft_path;
2531 ft.ft_callbk = size_cb;
2532 ft.ft_arg = &bk_size;
2533 ft.ft_logfp = (ft_log_t)ndmp_log;
2534 ft.ft_flags = FST_VERBOSE;
2535
2536 if ((rv = traverse_level(&ft)) != 0) {
2537 NDMP_LOG(LOG_DEBUG, "bksize err=%d", rv);
2538 bk_size = 0;
2539 } else {
2540 NDMP_LOG(LOG_DEBUG, "bksize %lld, %lldKB, %lldMB\n",
2541 bk_size, bk_size / 1024, bk_size /(1024 * 1024));
2542 }
2543 sarg->bs_session->ns_data.dd_data_size = bk_size;
2544 }
2545
2546 /*
2547 * get_rs_path_v3
2548 *
2549 * Find the restore path
2550 */
2551 ndmp_error
get_rs_path_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)2552 get_rs_path_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
2553 {
2554 char *dp;
2555 ndmp_error rv;
2556 mem_ndmp_name_v3_t *ep;
2557 int i, nm_cnt;
2558 char *nm_dpath_list[MULTIPLE_DEST_DIRS];
2559 static char mdest_buf[256];
2560
2561 *mdest_buf = 0;
2562 *nm_dpath_list = "";
2563 for (i = 0, nm_cnt = 0; i < (int)nlp->nlp_nfiles; i++) {
2564 ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params, i);
2565 if (!ep) {
2566 NDMP_LOG(LOG_DEBUG, "Can't get Nlist[%d]", i);
2567 return (NDMP_ILLEGAL_ARGS_ERR);
2568 }
2569 if (strcmp(nm_dpath_list[nm_cnt], ep->nm3_dpath) != 0 &&
2570 nm_cnt < MULTIPLE_DEST_DIRS - 1)
2571 nm_dpath_list[++nm_cnt] = ep->nm3_dpath;
2572 }
2573
2574 multiple_dest_restore = (nm_cnt > 1);
2575 nlp->nlp_restore_path = mdest_buf;
2576
2577 for (i = 1; i < nm_cnt + 1; i++) {
2578 if (ISDEFINED(nm_dpath_list[i]))
2579 dp = nm_dpath_list[i];
2580 else
2581 /* the default destination path is backup directory */
2582 dp = nlp->nlp_backup_path;
2583
2584 /* check the destination directory exists and is writable */
2585 if (!fs_volexist(dp)) {
2586 rv = NDMP_ILLEGAL_ARGS_ERR;
2587 MOD_LOGV3(params, NDMP_LOG_ERROR,
2588 "Invalid destination path volume \"%s\".\n", dp);
2589 } else if (!voliswr(dp)) {
2590 rv = NDMP_ILLEGAL_ARGS_ERR;
2591 MOD_LOGV3(params, NDMP_LOG_ERROR,
2592 "The destination path volume"
2593 " is not writable \"%s\".\n", dp);
2594 } else {
2595 rv = NDMP_NO_ERR;
2596 (void) strlcat(nlp->nlp_restore_path, dp,
2597 sizeof (mdest_buf));
2598 NDMP_LOG(LOG_DEBUG, "rspath: \"%s\"", dp);
2599 }
2600
2601 /*
2602 * Exit if there is an error or it is not a multiple
2603 * destination restore mode
2604 */
2605 if (rv != NDMP_NO_ERR || !multiple_dest_restore)
2606 break;
2607
2608 if (i < nm_cnt)
2609 (void) strlcat(nlp->nlp_restore_path, ", ",
2610 sizeof (mdest_buf));
2611 }
2612
2613 return (rv);
2614 }
2615
2616
2617 /*
2618 * fix_nlist_v3
2619 *
2620 * Check if the recovery list is valid and fix it if there are some
2621 * unspecified entries in it. It checks for original, destination
2622 * and new path for all NDMP names provided inside the list.
2623 *
2624 * V3: dpath is the destination directory. If newnm is not NULL, the
2625 * destination path is dpath/newnm. Otherwise the destination path is
2626 * dpath/opath_last_node, where opath_last_node is the last node in opath.
2627 *
2628 * V4: If newnm is not NULL, dpath is the destination directory, and
2629 * dpath/newnm is the destination path. If newnm is NULL, dpath is
2630 * the destination path (opath is not involved in forming destination path).
2631 */
2632 ndmp_error
fix_nlist_v3(ndmpd_session_t * session,ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)2633 fix_nlist_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
2634 ndmp_lbr_params_t *nlp)
2635 {
2636 char *cp, *buf, *bp;
2637 int i, n;
2638 int iswrbk;
2639 int bvexists;
2640 ndmp_error rv;
2641 mem_ndmp_name_v3_t *ep;
2642 char *dp;
2643 char *nm;
2644 int existsvol;
2645 int isrwdst;
2646
2647 buf = ndmp_malloc(TLM_MAX_PATH_NAME);
2648 if (!buf) {
2649 MOD_LOGV3(params, NDMP_LOG_ERROR, "Insufficient memory.\n");
2650 return (NDMP_NO_MEM_ERR);
2651 }
2652
2653 bvexists = fs_volexist(nlp->nlp_backup_path);
2654 iswrbk = voliswr(nlp->nlp_backup_path);
2655
2656 rv = NDMP_NO_ERR;
2657 n = session->ns_data.dd_nlist_len;
2658 for (i = 0; i < n; i++) {
2659 ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params, i);
2660 if (!ep)
2661 continue;
2662
2663 /* chop off the trailing slashes */
2664 chopslash(ep->nm3_opath);
2665
2666 chopslash(ep->nm3_dpath);
2667 chopslash(ep->nm3_newnm);
2668
2669 /* existing and non-empty destination path */
2670 if (ISDEFINED(ep->nm3_dpath)) {
2671 dp = ep->nm3_dpath;
2672 existsvol = fs_volexist(dp);
2673 isrwdst = voliswr(dp);
2674 } else {
2675 /* the default destination path is backup directory */
2676 dp = nlp->nlp_backup_path;
2677 existsvol = bvexists;
2678 isrwdst = iswrbk;
2679 }
2680
2681 /* check the destination directory exists and is writable */
2682 if (!existsvol) {
2683 rv = NDMP_ILLEGAL_ARGS_ERR;
2684 MOD_LOGV3(params, NDMP_LOG_ERROR,
2685 "Invalid destination path volume "
2686 "\"%s\".\n", dp);
2687 break;
2688 }
2689 if (!isrwdst) {
2690 rv = NDMP_ILLEGAL_ARGS_ERR;
2691 MOD_LOGV3(params, NDMP_LOG_ERROR,
2692 "The destination path volume is not "
2693 "writable \"%s\".\n", dp);
2694 break;
2695 }
2696
2697 /*
2698 * If new name is not specified, the default new name is
2699 * the last component of the original path, if any
2700 * (except in V4).
2701 */
2702 if (ISDEFINED(ep->nm3_newnm)) {
2703 nm = ep->nm3_newnm;
2704 } else {
2705 char *p, *q;
2706
2707 /*
2708 * Find the last component of nm3_opath.
2709 * nm3_opath has no trailing '/'.
2710 */
2711 p = strrchr(ep->nm3_opath, '/');
2712 nm = p ? p + 1 : ep->nm3_opath;
2713
2714 /*
2715 * In DDAR the last component could
2716 * be repeated in nm3_dpath
2717 */
2718 q = strrchr(ep->nm3_dpath, '/');
2719 q = q ? q + 1 : ep->nm3_dpath;
2720 if (strcmp(nm, q) == 0)
2721 nm = NULL;
2722
2723 }
2724
2725 bp = joinpath(buf, dp, nm);
2726 if (!bp) {
2727 /*
2728 * Note: What should be done with this entry?
2729 * We leave it untouched for now, hence no path in
2730 * the backup image matches with this entry and will
2731 * be reported as not found.
2732 */
2733 MOD_LOGV3(params, NDMP_LOG_ERROR,
2734 "Destination path too long(%s/%s)", dp, nm);
2735 continue;
2736 }
2737 cp = strdup(bp);
2738 if (!cp) {
2739 MOD_LOGV3(params, NDMP_LOG_ERROR,
2740 "Insufficient memory.\n");
2741 rv = NDMP_NO_MEM_ERR;
2742 break;
2743 }
2744 free(ep->nm3_dpath);
2745 ep->nm3_dpath = cp;
2746 NDMP_FREE(ep->nm3_newnm);
2747
2748 bp = joinpath(buf, nlp->nlp_backup_path, ep->nm3_opath);
2749 if (!bp) {
2750 /*
2751 * Note: The same problem of above with long path.
2752 */
2753 MOD_LOGV3(params, NDMP_LOG_ERROR,
2754 "Path too long(%s/%s)",
2755 nlp->nlp_backup_path, ep->nm3_opath);
2756 continue;
2757 }
2758 cp = strdup(bp);
2759 if (!cp) {
2760 MOD_LOGV3(params, NDMP_LOG_ERROR,
2761 "Insufficient memory.\n");
2762 rv = NDMP_NO_MEM_ERR;
2763 break;
2764 }
2765 NDMP_FREE(ep->nm3_opath);
2766 ep->nm3_opath = cp;
2767
2768 NDMP_LOG(LOG_DEBUG, "orig[%d]: \"%s\"", i, ep->nm3_opath);
2769 if (ep->nm3_dpath) {
2770 NDMP_LOG(LOG_DEBUG,
2771 "dest[%d]: \"%s\"", i, ep->nm3_dpath);
2772 } else {
2773 NDMP_LOG(LOG_DEBUG, "dest[%d]: \"%s\"", i, "NULL");
2774 }
2775 }
2776
2777 free(buf);
2778
2779 return (rv);
2780 }
2781
2782
2783 /*
2784 * allvalidfh
2785 *
2786 * Run a sanity check on the file history info. The file history
2787 * info is the offset of the record starting the entry on the tape
2788 * and is used in DAR (direct access restore mode).
2789 */
2790 static boolean_t
allvalidfh(ndmpd_session_t * session,ndmpd_module_params_t * params)2791 allvalidfh(ndmpd_session_t *session, ndmpd_module_params_t *params)
2792 {
2793 int i, n;
2794 boolean_t rv;
2795 mem_ndmp_name_v3_t *ep;
2796
2797 rv = TRUE;
2798 n = session->ns_data.dd_nlist_len;
2799 for (i = 0; i < n; i++) {
2800 ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params, i);
2801 if (!ep)
2802 continue;
2803 /*
2804 * The fh_info's sent from the client are multiples
2805 * of RECORDSIZE which is 512 bytes.
2806 *
2807 * All our fh_info's are at the RECORDSIZE boundary. If there
2808 * is any fh_info that is less than RECORDSIZE (this covers 0
2809 * and -1 values too), then the result is that DAR cannot be
2810 * done.
2811 */
2812 if (ep->nm3_fh_info < RECORDSIZE ||
2813 ep->nm3_fh_info % RECORDSIZE != 0) {
2814 rv = FALSE;
2815 break;
2816 }
2817 }
2818
2819 return (rv);
2820 }
2821
2822
2823 /*
2824 * log_rs_params_v3
2825 *
2826 * Log a copy of all values of the restore parameters
2827 */
2828 void
log_rs_params_v3(ndmpd_session_t * session,ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)2829 log_rs_params_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
2830 ndmp_lbr_params_t *nlp)
2831 {
2832 MOD_LOGV3(params, NDMP_LOG_NORMAL, "Restoring to \"%s\".\n",
2833 (nlp->nlp_restore_path) ? nlp->nlp_restore_path : "NULL");
2834
2835 if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL) {
2836 MOD_LOGV3(params, NDMP_LOG_NORMAL, "Tape server: local.\n");
2837 MOD_LOGV3(params, NDMP_LOG_NORMAL,
2838 "Tape record size: %d.\n",
2839 session->ns_mover.md_record_size);
2840 } else if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_TCP)
2841 MOD_LOGV3(params, NDMP_LOG_NORMAL,
2842 "Tape server: remote at %s:%d.\n",
2843 inet_ntoa(IN_ADDR(session->ns_data.dd_data_addr.tcp_ip_v3)),
2844 session->ns_data.dd_data_addr.tcp_port_v3);
2845 else
2846 MOD_LOGV3(params, NDMP_LOG_ERROR,
2847 "Unknown tape server address type.\n");
2848
2849 if (NLP_ISSET(nlp, NLPF_DIRECT))
2850 MOD_LOGV3(params, NDMP_LOG_NORMAL,
2851 "Direct Access Restore.\n");
2852 }
2853
2854
2855 /*
2856 * send_unrecovered_list_v3
2857 *
2858 * Create the list of files that were in restore list but
2859 * not recovered due to some errors.
2860 */
2861 int
send_unrecovered_list_v3(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)2862 send_unrecovered_list_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
2863 {
2864 int i, rv;
2865 int err;
2866
2867 if (!params) {
2868 NDMP_LOG(LOG_DEBUG, "params == NULL");
2869 return (-1);
2870 }
2871 if (!nlp) {
2872 NDMP_LOG(LOG_DEBUG, "nlp == NULL");
2873 return (-1);
2874 }
2875
2876 if (nlp->nlp_lastidx != -1) {
2877 if (!bm_getone(nlp->nlp_rsbm, (u_longlong_t)nlp->nlp_lastidx))
2878 err = ENOENT;
2879 else
2880 err = 0;
2881 (void) ndmp_send_recovery_stat_v3(params, nlp,
2882 nlp->nlp_lastidx, err);
2883 nlp->nlp_lastidx = -1;
2884 }
2885
2886 rv = 0;
2887 for (i = 0; i < (int)nlp->nlp_nfiles; i++) {
2888 if (!bm_getone(nlp->nlp_rsbm, (u_longlong_t)i)) {
2889 rv = ndmp_send_recovery_stat_v3(params, nlp, i, ENOENT);
2890 if (rv < 0)
2891 break;
2892 }
2893 }
2894
2895 return (rv);
2896 }
2897
2898
2899
2900 /*
2901 * restore_dar_alloc_structs_v3
2902 *
2903 * Allocates the necessary structures for running DAR restore.
2904 * It just creates the reader writer IPC.
2905 * This function is called for each entry in the restore entry list.
2906 *
2907 * Parameters:
2908 * session (input) - pointer to the session
2909 * jname (input) - Job name
2910 *
2911 * Returns:
2912 * 0: on success
2913 * -1: on error
2914 */
2915 int
restore_dar_alloc_structs_v3(ndmpd_session_t * session,char * jname)2916 restore_dar_alloc_structs_v3(ndmpd_session_t *session, char *jname)
2917 {
2918 long xfer_size;
2919 ndmp_lbr_params_t *nlp;
2920 tlm_commands_t *cmds;
2921
2922 nlp = ndmp_get_nlp(session);
2923 if (!nlp) {
2924 NDMP_LOG(LOG_DEBUG, "nlp == NULL");
2925 return (-1);
2926 }
2927
2928 cmds = &nlp->nlp_cmds;
2929 (void) memset(cmds, 0, sizeof (*cmds));
2930
2931 xfer_size = ndmp_buffer_get_size(session);
2932 cmds->tcs_command = tlm_create_reader_writer_ipc(FALSE, xfer_size);
2933 if (!cmds->tcs_command) {
2934 tlm_un_ref_job_stats(jname);
2935 return (-1);
2936 }
2937
2938 return (0);
2939 }
2940
2941
2942 /*
2943 * free_dar_structs_v3
2944 *
2945 * To free the structures were created by restore_dar_alloc_structs_v3.
2946 * This funnction is called for each entry in restore entry list.
2947 *
2948 * Parameters:
2949 * session (input) - pointer to the session
2950 * jname (input) - job name
2951 *
2952 * Returns:
2953 * NONE
2954 */
2955 /*ARGSUSED*/
2956 static void
free_dar_structs_v3(ndmpd_session_t * session,char * jname)2957 free_dar_structs_v3(ndmpd_session_t *session, char *jname)
2958 {
2959 ndmp_lbr_params_t *nlp;
2960 tlm_commands_t *cmds;
2961
2962 nlp = ndmp_get_nlp(session);
2963 if (!nlp) {
2964 NDMP_LOG(LOG_DEBUG, "nlp == NULL");
2965 return;
2966 }
2967 cmds = &nlp->nlp_cmds;
2968 if (!cmds) {
2969 NDMP_LOG(LOG_DEBUG, "cmds == NULL");
2970 return;
2971 }
2972
2973 if (cmds->tcs_command) {
2974 if (cmds->tcs_command->tc_buffers != NULL)
2975 tlm_release_reader_writer_ipc(cmds->tcs_command);
2976 else
2977 NDMP_LOG(LOG_DEBUG, "BUFFERS == NULL");
2978 cmds->tcs_command = NULL;
2979 } else
2980 NDMP_LOG(LOG_DEBUG, "COMMAND == NULL");
2981 }
2982
2983
2984 /*
2985 * ndmp_dar_tar_init_v3
2986 *
2987 * Constructor for the DAR restore. Creates job name, allocates structures
2988 * needed for keeping the statistics, and reports the start of restore action.
2989 * It is called once for each DAR restore request.
2990 *
2991 * Parameters:
2992 * session (input) - pointer to the session
2993 * nlp (input) - pointer to the nlp structure
2994 *
2995 * Returns:
2996 * char pointer: on success
2997 * NULL: on error
2998 */
ndmpd_dar_tar_init_v3(ndmpd_session_t * session,ndmp_lbr_params_t * nlp)2999 static char *ndmpd_dar_tar_init_v3(ndmpd_session_t *session,
3000 ndmp_lbr_params_t *nlp)
3001 {
3002 char *jname;
3003
3004 jname = ndmp_malloc(TLM_MAX_BACKUP_JOB_NAME);
3005
3006 if (!jname)
3007 return (NULL);
3008
3009 (void) ndmp_new_job_name(jname);
3010
3011 if (!nlp) {
3012 free(jname);
3013 NDMP_LOG(LOG_DEBUG, "nlp == NULL");
3014 return (NULL);
3015 }
3016
3017 nlp->nlp_jstat = tlm_new_job_stats(jname);
3018 if (!nlp->nlp_jstat) {
3019 free(jname);
3020 NDMP_LOG(LOG_DEBUG, "Creating job stats");
3021 return (NULL);
3022 }
3023
3024 nlp->nlp_jstat->js_start_ltime = time(NULL);
3025 nlp->nlp_jstat->js_start_time = nlp->nlp_jstat->js_start_ltime;
3026
3027 nlp->nlp_logcallbacks = lbrlog_callbacks_init(session,
3028 ndmpd_path_restored_v3, NULL, NULL);
3029 if (!nlp->nlp_logcallbacks) {
3030 tlm_un_ref_job_stats(jname);
3031 free(jname);
3032 return (NULL);
3033 }
3034 nlp->nlp_jstat->js_callbacks = (void *)(nlp->nlp_logcallbacks);
3035
3036 nlp->nlp_rsbm = bm_alloc(nlp->nlp_nfiles, 0);
3037 if (nlp->nlp_rsbm < 0) {
3038 NDMP_LOG(LOG_ERR, "Out of memory.");
3039 lbrlog_callbacks_done(nlp->nlp_logcallbacks);
3040 tlm_un_ref_job_stats(jname);
3041 free(jname);
3042 return (NULL);
3043 }
3044
3045 /* this is used in ndmpd_path_restored_v3() */
3046 nlp->nlp_lastidx = -1;
3047
3048 NDMP_LOG(LOG_DEBUG, "Restoring from %s tape(s).",
3049 ndmp_data_get_mover_mode(session));
3050
3051 return (jname);
3052 }
3053
3054 /*
3055 * ndmpd_dar_tar_end_v3
3056 *
3057 * Deconstructor for the DAR restore. This function is called once per
3058 * DAR request. It deallocates memories allocated by ndmpd_dar_tar_init_v3.
3059 *
3060 * Parameters:
3061 * session (input) - pointer to the session
3062 * params (input) - pointer to the parameters structure
3063 * nlp (input) - pointer to the nlp structure
3064 * jname(input) - job name
3065 *
3066 * Returns:
3067 * 0: on success
3068 * -1: on error
3069 */
ndmpd_dar_tar_end_v3(ndmpd_session_t * session,ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp,char * jname)3070 static int ndmpd_dar_tar_end_v3(ndmpd_session_t *session,
3071 ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp, char *jname)
3072 {
3073 int err = 0;
3074
3075
3076 NDMP_LOG(LOG_DEBUG, "lastidx %d", nlp->nlp_lastidx);
3077
3078 /* nothing restored. */
3079 (void) send_unrecovered_list_v3(params, nlp);
3080
3081 if (nlp->nlp_jstat) {
3082 nlp->nlp_bytes_total =
3083 (u_longlong_t)nlp->nlp_jstat->js_bytes_total;
3084 tlm_un_ref_job_stats(jname);
3085 nlp->nlp_jstat = NULL;
3086 } else {
3087 NDMP_LOG(LOG_DEBUG, "JSTAT == NULL");
3088 }
3089
3090 if (nlp->nlp_logcallbacks) {
3091 lbrlog_callbacks_done(nlp->nlp_logcallbacks);
3092 nlp->nlp_logcallbacks = NULL;
3093 } else {
3094 NDMP_LOG(LOG_DEBUG, "FH CALLBACKS == NULL");
3095 }
3096
3097 if (session->ns_data.dd_abort) {
3098 NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" aborted.",
3099 (nlp->nlp_restore_path) ? nlp->nlp_restore_path : "NULL");
3100 err = EINTR;
3101 } else {
3102 NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" finished. (%d)",
3103 (nlp->nlp_restore_path) ? nlp->nlp_restore_path :
3104 "NULL", err);
3105 }
3106
3107 if (session->ns_data.dd_operation == NDMP_DATA_OP_RECOVER) {
3108 if (nlp->nlp_rsbm < 0) {
3109 NDMP_LOG(LOG_DEBUG, "nlp_rsbm < 0 %d", nlp->nlp_rsbm);
3110 } else {
3111 (void) bm_free(nlp->nlp_rsbm);
3112 nlp->nlp_rsbm = -1;
3113 }
3114 }
3115
3116 free(jname);
3117
3118 return (err);
3119 }
3120
3121
3122 /*
3123 * ndmpd_dar_tar_v3
3124 *
3125 * This function is called for each entry in DAR entry list. The window
3126 * is already located and we should be in the right position to read
3127 * the data from the tape.
3128 * For each entry we setup selection list; so that, if the file name from
3129 * tape is not as the name client asked for, error be returned.
3130 *
3131 * Parameters:
3132 * session (input) - pointer to the session
3133 * params (input) - pointer to the parameters structure
3134 * nlp (input) - pointer to the nlp structure
3135 * jname (input) - job name
3136 * dar_index(input) - Index of this entry in the restore list
3137 *
3138 * Returns:
3139 * 0: on success
3140 * -1: on error
3141 */
3142 static int
ndmpd_dar_tar_v3(ndmpd_session_t * session,ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp,char * jname,int dar_index)3143 ndmpd_dar_tar_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
3144 ndmp_lbr_params_t *nlp, char *jname, int dar_index)
3145 {
3146 char *excl;
3147 char **sels;
3148 int flags;
3149 int err;
3150 tlm_commands_t *cmds;
3151 struct rs_name_maker rn;
3152 int data_addr_type = session->ns_data.dd_data_addr.addr_type;
3153 ndmp_tar_reader_arg_t arg;
3154 pthread_t rdtp;
3155 ndmp_context_t nctx;
3156 mem_ndmp_name_v3_t *ep;
3157
3158 err = 0;
3159
3160 /*
3161 * We have to allocate and deallocate buffers every time we
3162 * run the restore, for we need to flush the buffers.
3163 */
3164 if (restore_dar_alloc_structs_v3(session, jname) < 0)
3165 return (-1);
3166
3167 sels = setupsels(session, params, nlp, dar_index);
3168 if (!sels) {
3169 free_dar_structs_v3(session, jname);
3170 return (-1);
3171 }
3172 excl = NULL;
3173 flags = RSFLG_OVR_ALWAYS;
3174 rn.rn_nlp = nlp;
3175 rn.rn_fp = mknewname;
3176
3177 if (!session->ns_data.dd_abort) {
3178 cmds = &nlp->nlp_cmds;
3179 cmds->tcs_reader = cmds->tcs_writer = TLM_RESTORE_RUN;
3180 cmds->tcs_command->tc_reader = TLM_RESTORE_RUN;
3181 cmds->tcs_command->tc_writer = TLM_RESTORE_RUN;
3182
3183 arg.tr_session = session;
3184 arg.tr_mod_params = params;
3185 arg.tr_cmds = cmds;
3186
3187 err = pthread_create(&rdtp, NULL, (funct_t)ndmp_tar_reader,
3188 (void *)&arg);
3189 if (err == 0) {
3190 tlm_cmd_wait(cmds->tcs_command, TLM_TAR_READER);
3191 } else {
3192 NDMP_LOG(LOG_DEBUG, "launch ndmp_tar_reader: %m");
3193 return (-1);
3194 }
3195
3196 cmds->tcs_command->tc_ref++;
3197 cmds->tcs_writer_count++;
3198
3199 /* Plug-in module */
3200 if (ndmp_pl != NULL &&
3201 ndmp_pl->np_pre_restore != NULL) {
3202 (void) memset(&nctx, 0, sizeof (ndmp_context_t));
3203 nctx.nc_cmds = cmds;
3204 nctx.nc_params = params;
3205 nctx.nc_ddata = (void *) session;
3206 ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params,
3207 dar_index - 1);
3208
3209 if ((err = ndmp_pl->np_pre_restore(ndmp_pl, &nctx,
3210 ep->nm3_opath, ep->nm3_dpath))
3211 != 0) {
3212 NDMP_LOG(LOG_ERR, "Pre-restore plug-in: %m");
3213 cmds->tcs_command->tc_reader = TLM_STOP;
3214 ndmp_stop_local_reader(session, cmds);
3215 ndmp_wait_for_reader(cmds);
3216 (void) pthread_join(rdtp, NULL);
3217 ndmp_stop_remote_reader(session);
3218 goto restore_out;
3219 }
3220 }
3221
3222 if (tm_tar_ops.tm_getdir != NULL) {
3223 err = (tm_tar_ops.tm_getdir)(cmds, cmds->tcs_command,
3224 nlp->nlp_jstat, &rn, 1, 1, sels, &excl, flags,
3225 dar_index, nlp->nlp_backup_path,
3226 session->hardlink_q);
3227 }
3228
3229 cmds->tcs_writer_count--;
3230 cmds->tcs_command->tc_ref--;
3231 cmds->tcs_command->tc_reader = TLM_STOP;
3232
3233
3234 /*
3235 * If it is a two-way restore then we stop the reader.
3236 */
3237 NDMP_LOG(LOG_DEBUG, "stop local reader.");
3238 ndmp_stop_local_reader(session, cmds);
3239
3240 ndmp_wait_for_reader(cmds);
3241 (void) pthread_join(rdtp, NULL);
3242
3243 /*
3244 * If this is the last DAR entry and it is a three-way
3245 * restore then we should close the connection.
3246 */
3247 if ((data_addr_type == NDMP_ADDR_TCP) &&
3248 (dar_index == (int)session->ns_data.dd_nlist_len)) {
3249 NDMP_LOG(LOG_DEBUG, "stop remote reader.");
3250 ndmp_stop_remote_reader(session);
3251 }
3252
3253 /* exit as if there was an internal error */
3254 if (session->ns_eof)
3255 err = -1;
3256 restore_out:
3257 /* Plug-in module */
3258 if (ndmp_pl != NULL &&
3259 ndmp_pl->np_post_restore != NULL &&
3260 ndmp_pl->np_post_restore(ndmp_pl, &nctx, err) == -1) {
3261 NDMP_LOG(LOG_DEBUG, "Post-restore plug-in: %m");
3262 err = -1;
3263 }
3264 }
3265
3266 NDMP_FREE(sels);
3267
3268 free_dar_structs_v3(session, jname);
3269
3270 return (err);
3271 }
3272
3273 /*
3274 * ndmpd_dar_locate_windwos_v3
3275 *
3276 * Locating the right window in which the requested file is backed up.
3277 * We should go through windows to find the exact location, for the
3278 * file can be located in for example 10th window after the current window.
3279 *
3280 * Parameters:
3281 * session (input) - pointer to the session
3282 * params (input) - pointer to the parameters structure
3283 * fh_info (input) - index from the beginning of the backup stream
3284 * len (input) - Length of the mover window
3285 *
3286 * Returns:
3287 * 0: on success
3288 * -1: on error
3289 */
3290 static int
ndmpd_dar_locate_window_v3(ndmpd_session_t * session,ndmpd_module_params_t * params,u_longlong_t fh_info,u_longlong_t len)3291 ndmpd_dar_locate_window_v3(ndmpd_session_t *session,
3292 ndmpd_module_params_t *params, u_longlong_t fh_info, u_longlong_t len)
3293 {
3294 int ret = 0;
3295
3296
3297 for (; ; ) {
3298 ret = (*params->mp_seek_func)(session, fh_info, len);
3299
3300 NDMP_LOG(LOG_DEBUG, "ret %d", ret);
3301 if (ret == 0) /* Seek was done successfully */
3302 break;
3303 else if (ret < 0) {
3304 NDMP_LOG(LOG_DEBUG, "Seek error");
3305 break;
3306 }
3307
3308 /*
3309 * DMA moved to a new window.
3310 * If we are reading the remainig of the file from
3311 * new window, seek is handled by ndmpd_local_read_v3.
3312 * Here we should continue the seek inside the new
3313 * window.
3314 */
3315 continue;
3316 }
3317 return (ret);
3318 }
3319
3320 /*
3321 * ndmpd_rs_dar_tar_v3
3322 *
3323 * Main DAR function. It calls the constructor, then for each entry it
3324 * calls the locate_window_v3 to find the exact position of the file. Then
3325 * it restores the file.
3326 * When all restore requests are done it calls the deconstructor to clean
3327 * everything up.
3328 *
3329 * Parameters:
3330 * session (input) - pointer to the session
3331 * params (input) - pointer to the parameters structure
3332 * nlp (input) - pointer to the nlp structure
3333 *
3334 * Returns:
3335 * 0: on success
3336 * -1: on error
3337 */
3338 static int
ndmpd_rs_dar_tar_v3(ndmpd_session_t * session,ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)3339 ndmpd_rs_dar_tar_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
3340 ndmp_lbr_params_t *nlp)
3341 {
3342 mem_ndmp_name_v3_t *ep;
3343 u_longlong_t len;
3344 char *jname;
3345 int n = session->ns_data.dd_nlist_len;
3346 int i, ret = 0;
3347 int result = 0;
3348
3349 jname = ndmpd_dar_tar_init_v3(session, nlp);
3350
3351 if (!jname)
3352 return (-1);
3353
3354 /*
3355 * We set the length = sizeof (tlm_tar_hdr_t)
3356 * This is important for three-way DAR restore, for we should
3357 * read the header first (If we ask for more data then we have
3358 * to read and discard the remaining data in the socket)
3359 */
3360 len = tlm_tarhdr_size();
3361
3362 for (i = 0; i < n; ++i) {
3363 ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params, i);
3364 if (!ep) {
3365 NDMP_LOG(LOG_DEBUG, "ep NULL, i %d", i);
3366 continue;
3367 }
3368 NDMP_LOG(LOG_DEBUG,
3369 "restoring opath %s, dpath %s, fh_info %lld",
3370 ep->nm3_opath ? ep->nm3_opath : "NULL",
3371 ep->nm3_dpath ? ep->nm3_dpath : "NULL",
3372 ep->nm3_fh_info);
3373
3374 /*
3375 * We should seek till finding the window in which file
3376 * is located.
3377 */
3378 ret = ndmpd_dar_locate_window_v3(session, params,
3379 ep->nm3_fh_info, len);
3380
3381 if (ret < 0) /* If seek fails, restore should be aborted */
3382 break;
3383 /*
3384 * We are inside the target window.
3385 * for each restore we will use one entry as selection list
3386 */
3387 if ((ret = ndmpd_dar_tar_v3(session, params, nlp, jname, i+1))
3388 != 0)
3389 result = EIO;
3390 ndmpd_audit_restore(session->ns_connection,
3391 ep->nm3_opath ? ep->nm3_opath : "NULL",
3392 session->ns_data.dd_data_addr.addr_type,
3393 session->ns_tape.td_adapter_name, result);
3394 }
3395
3396 NDMP_LOG(LOG_DEBUG, "End of restore list");
3397
3398 (void) ndmpd_dar_tar_end_v3(session, params, nlp, jname);
3399
3400 return (ret);
3401 }
3402
3403 /*
3404 * ndmp_plugin_pre_restore
3405 *
3406 * Wrapper for pre-restore callback with multiple path
3407 */
3408 static int
ndmp_plugin_pre_restore(ndmp_context_t * ctxp,ndmpd_module_params_t * params,int ncount)3409 ndmp_plugin_pre_restore(ndmp_context_t *ctxp, ndmpd_module_params_t *params,
3410 int ncount)
3411 {
3412 mem_ndmp_name_v3_t *ep;
3413 int err;
3414 int i;
3415
3416 for (i = 0; i < ncount; i++) {
3417 if (!(ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params, i)))
3418 continue;
3419 if ((err = ndmp_pl->np_pre_restore(ndmp_pl, ctxp,
3420 ep->nm3_opath, ep->nm3_dpath)) != 0)
3421 return (err);
3422 }
3423
3424 return (0);
3425 }
3426
3427 /*
3428 * get_absolute_path
3429 *
3430 * Get resolved path name which does not involve ".", ".." or extra
3431 * "/" or symbolic links.
3432 *
3433 * e.g.
3434 *
3435 * /backup/path/ -> /backup/path
3436 * /backup/path/. -> /backup/path
3437 * /backup/path/../path/ -> /backup/path
3438 * /link-to-backup-path -> /backup/path
3439 *
3440 * Returns:
3441 * Pointer to the new path (allocated)
3442 * NULL if the path doesnt exist
3443 */
3444 static char *
get_absolute_path(const char * bkpath)3445 get_absolute_path(const char *bkpath)
3446 {
3447 char *pbuf;
3448 char *rv;
3449
3450 if (!(pbuf = ndmp_malloc(TLM_MAX_PATH_NAME)))
3451 return (NULL);
3452
3453 if ((rv = realpath(bkpath, pbuf)) == NULL) {
3454 NDMP_LOG(LOG_DEBUG, "Invalid path [%s] err=%d",
3455 bkpath, errno);
3456 }
3457 return (rv);
3458 }
3459
3460 /*
3461 * Expands the format string and logs the resulting message to the
3462 * remote DMA
3463 */
3464 void
ndmp_log_dma(ndmp_context_t * nctx,ndmp_log_dma_type_t lt,const char * fmt,...)3465 ndmp_log_dma(ndmp_context_t *nctx, ndmp_log_dma_type_t lt, const char *fmt, ...)
3466 {
3467 va_list ap;
3468 char buf[256];
3469 ndmpd_module_params_t *params;
3470
3471 if (nctx == NULL ||
3472 (params = (ndmpd_module_params_t *)nctx->nc_params) == NULL)
3473 return;
3474
3475 va_start(ap, fmt);
3476 (void) vsnprintf(buf, sizeof (buf), fmt, ap);
3477 va_end(ap);
3478
3479 MOD_LOGV3(params, (ndmp_log_type)lt, "%s", buf);
3480 }
3481
3482
3483 /*
3484 * ndmpd_rs_sar_tar_v3
3485 *
3486 * Main non-DAR restore function. It will try to restore all the entries
3487 * that have been backed up.
3488 *
3489 * Parameters:
3490 * session (input) - pointer to the session
3491 * params (input) - pointer to the parameters structure
3492 * nlp (input) - pointer to the nlp structure
3493 *
3494 * Returns:
3495 * 0: on success
3496 * -1: on error
3497 */
3498 static int
ndmpd_rs_sar_tar_v3(ndmpd_session_t * session,ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)3499 ndmpd_rs_sar_tar_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
3500 ndmp_lbr_params_t *nlp)
3501 {
3502 char jname[TLM_MAX_BACKUP_JOB_NAME];
3503 char *excl;
3504 char **sels;
3505 int flags;
3506 int err;
3507 tlm_commands_t *cmds;
3508 struct rs_name_maker rn;
3509 ndmp_tar_reader_arg_t arg;
3510 pthread_t rdtp;
3511 int result;
3512 ndmp_context_t nctx;
3513
3514 result = err = 0;
3515 (void) ndmp_new_job_name(jname);
3516 if (restore_alloc_structs_v3(session, jname) < 0)
3517 return (-1);
3518
3519 sels = setupsels(session, params, nlp, 0);
3520 if (!sels) {
3521 free_structs_v3(session, jname);
3522 return (-1);
3523 }
3524 excl = NULL;
3525 flags = RSFLG_OVR_ALWAYS;
3526 rn.rn_nlp = nlp;
3527 rn.rn_fp = mknewname;
3528
3529 nlp->nlp_jstat->js_start_ltime = time(NULL);
3530 nlp->nlp_jstat->js_start_time = nlp->nlp_jstat->js_start_ltime;
3531
3532 if (!session->ns_data.dd_abort && !session->ns_data.dd_abort) {
3533 cmds = &nlp->nlp_cmds;
3534 cmds->tcs_reader = cmds->tcs_writer = TLM_RESTORE_RUN;
3535 cmds->tcs_command->tc_reader = TLM_RESTORE_RUN;
3536 cmds->tcs_command->tc_writer = TLM_RESTORE_RUN;
3537
3538 NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" started.",
3539 (nlp->nlp_restore_path) ? nlp->nlp_restore_path : "NULL");
3540
3541 arg.tr_session = session;
3542 arg.tr_mod_params = params;
3543 arg.tr_cmds = cmds;
3544 err = pthread_create(&rdtp, NULL, (funct_t)ndmp_tar_reader,
3545 (void *)&arg);
3546 if (err == 0) {
3547 tlm_cmd_wait(cmds->tcs_command, TLM_TAR_READER);
3548 } else {
3549 NDMP_LOG(LOG_DEBUG, "Launch ndmp_tar_reader: %m");
3550 free_structs_v3(session, jname);
3551 return (-1);
3552 }
3553
3554 if (!ndmp_check_utf8magic(cmds->tcs_command)) {
3555 NDMP_LOG(LOG_DEBUG, "UTF8Magic not found!");
3556 } else {
3557 NDMP_LOG(LOG_DEBUG, "UTF8Magic found");
3558 }
3559
3560 /* Plug-in module */
3561 if (ndmp_pl != NULL &&
3562 ndmp_pl->np_pre_restore != NULL) {
3563 (void) memset(&nctx, 0, sizeof (ndmp_context_t));
3564 nctx.nc_cmds = cmds;
3565 nctx.nc_params = params;
3566 nctx.nc_ddata = (void *) session;
3567 if ((err = ndmp_plugin_pre_restore(&nctx, params,
3568 nlp->nlp_nfiles))
3569 != 0) {
3570 NDMP_LOG(LOG_ERR, "Pre-restore plug-in: %m");
3571 cmds->tcs_command->tc_reader = TLM_STOP;
3572 ndmp_stop_local_reader(session, cmds);
3573 ndmp_wait_for_reader(cmds);
3574 (void) pthread_join(rdtp, NULL);
3575 ndmp_stop_remote_reader(session);
3576 goto restore_out;
3577 }
3578 }
3579
3580 cmds->tcs_command->tc_ref++;
3581 cmds->tcs_writer_count++;
3582
3583 if (tm_tar_ops.tm_getdir != NULL)
3584 err = (tm_tar_ops.tm_getdir)(cmds, cmds->tcs_command,
3585 nlp->nlp_jstat, &rn, 1, 1, sels, &excl, flags, 0,
3586 nlp->nlp_backup_path, session->hardlink_q);
3587
3588 cmds->tcs_writer_count--;
3589 cmds->tcs_command->tc_ref--;
3590 cmds->tcs_command->tc_reader = TLM_STOP;
3591 nlp->nlp_jstat->js_stop_time = time(NULL);
3592
3593 /* Send the list of un-recovered files/dirs to the client. */
3594 (void) send_unrecovered_list_v3(params, nlp);
3595
3596 ndmp_stop_local_reader(session, cmds);
3597 ndmp_wait_for_reader(cmds);
3598 (void) pthread_join(rdtp, NULL);
3599
3600 ndmp_stop_remote_reader(session);
3601
3602 /* exit as if there was an internal error */
3603 if (session->ns_eof)
3604 err = -1;
3605 if (err == -1)
3606 result = EIO;
3607 }
3608
3609 (void) send_unrecovered_list_v3(params, nlp); /* nothing restored. */
3610 if (session->ns_data.dd_abort) {
3611 NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" aborted.",
3612 (nlp->nlp_restore_path) ? nlp->nlp_restore_path : "NULL");
3613 result = EINTR;
3614 ndmpd_audit_restore(session->ns_connection,
3615 nlp->nlp_restore_path,
3616 session->ns_data.dd_data_addr.addr_type,
3617 session->ns_tape.td_adapter_name, result);
3618 err = -1;
3619 } else {
3620 NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" finished. (%d)",
3621 (nlp->nlp_restore_path) ? nlp->nlp_restore_path : "NULL",
3622 err);
3623 ndmpd_audit_restore(session->ns_connection,
3624 nlp->nlp_restore_path,
3625 session->ns_data.dd_data_addr.addr_type,
3626 session->ns_tape.td_adapter_name, result);
3627
3628 restore_out:
3629 /* Plug-in module */
3630 if (ndmp_pl != NULL &&
3631 ndmp_pl->np_post_restore != NULL &&
3632 ndmp_pl->np_post_restore(ndmp_pl, &nctx, err) == -1) {
3633 NDMP_LOG(LOG_DEBUG, "Post-restore plug-in: %m");
3634 err = -1;
3635 }
3636 }
3637
3638 NDMP_FREE(sels);
3639 free_structs_v3(session, jname);
3640
3641 return (err);
3642 }
3643
3644
3645 /*
3646 * ndmp_backup_get_params_v3
3647 *
3648 * Get the backup parameters from the NDMP env variables
3649 * and log them in the system log and as normal messages
3650 * to the DMA.
3651 *
3652 * Parameters:
3653 * session (input) - pointer to the session
3654 * params (input) - pointer to the parameters structure
3655 *
3656 * Returns:
3657 * NDMP_NO_ERR: on success
3658 * != NDMP_NO_ERR: otherwise
3659 */
3660 ndmp_error
ndmp_backup_get_params_v3(ndmpd_session_t * session,ndmpd_module_params_t * params)3661 ndmp_backup_get_params_v3(ndmpd_session_t *session,
3662 ndmpd_module_params_t *params)
3663 {
3664 ndmp_error rv;
3665 ndmp_lbr_params_t *nlp;
3666
3667 if (!session || !params)
3668 return (NDMP_ILLEGAL_ARGS_ERR);
3669
3670 rv = NDMP_NO_ERR;
3671 nlp = ndmp_get_nlp(session);
3672 if (!nlp) {
3673 MOD_LOGV3(params, NDMP_LOG_ERROR,
3674 "Internal error: NULL nlp.\n");
3675 rv = NDMP_ILLEGAL_ARGS_ERR;
3676 } else {
3677 if (!(nlp->nlp_backup_path = get_backup_path_v3(params)))
3678 rv = NDMP_FILE_NOT_FOUND_ERR;
3679 else if (!is_valid_backup_dir_v3(params, nlp->nlp_backup_path))
3680 rv = NDMP_ILLEGAL_ARGS_ERR;
3681 }
3682
3683 nlp->nlp_backup_path = get_absolute_path(nlp->nlp_backup_path);
3684 if (!nlp->nlp_backup_path)
3685 rv = NDMP_FILE_NOT_FOUND_ERR;
3686
3687 if (rv != NDMP_NO_ERR)
3688 return (rv);
3689
3690 if (fs_is_chkpntvol(nlp->nlp_backup_path) ||
3691 fs_is_rdonly(nlp->nlp_backup_path) ||
3692 !fs_is_chkpnt_enabled(nlp->nlp_backup_path))
3693 NLP_SET(nlp, NLPF_CHKPNTED_PATH);
3694 else
3695 NLP_UNSET(nlp, NLPF_CHKPNTED_PATH);
3696
3697 /* Should the st_ctime be ignored when backing up? */
3698 if (ndmp_ignore_ctime) {
3699 NDMP_LOG(LOG_DEBUG, "ignoring st_ctime");
3700 NLP_SET(nlp, NLPF_IGNCTIME);
3701 } else {
3702 NLP_UNSET(nlp, NLPF_IGNCTIME);
3703 }
3704
3705 if (ndmp_include_lmtime == TRUE) {
3706 NDMP_LOG(LOG_DEBUG, "including st_lmtime");
3707 NLP_SET(nlp, NLPF_INCLMTIME);
3708 } else {
3709 NLP_UNSET(nlp, NLPF_INCLMTIME);
3710 }
3711
3712 NDMP_LOG(LOG_DEBUG, "flags %x", nlp->nlp_flags);
3713
3714 get_hist_env_v3(params, nlp);
3715 get_exc_env_v3(params, nlp);
3716 get_inc_env_v3(params, nlp);
3717 get_direct_env_v3(params, nlp);
3718 rv = get_backup_level_v3(params, nlp);
3719
3720 return (rv);
3721 }
3722
3723
3724 /*
3725 * ndmpd_tar_backup_starter_v3
3726 *
3727 * Create the checkpoint for the backup and do the backup,
3728 * then remove the backup checkpoint if we created it.
3729 * Save the backup time information based on the backup
3730 * type and stop the data server.
3731 *
3732 * Parameters:
3733 * params (input) - pointer to the parameters structure
3734 *
3735 * Returns:
3736 * 0: on success
3737 * != 0: otherwise
3738 */
3739 int
ndmpd_tar_backup_starter_v3(void * arg)3740 ndmpd_tar_backup_starter_v3(void *arg)
3741 {
3742 ndmpd_module_params_t *params = arg;
3743 int err;
3744 ndmpd_session_t *session;
3745 ndmp_lbr_params_t *nlp;
3746 char jname[TLM_MAX_BACKUP_JOB_NAME];
3747 ndmp_bkup_size_arg_t sarg;
3748 pthread_t tid;
3749
3750 session = (ndmpd_session_t *)(params->mp_daemon_cookie);
3751 *(params->mp_module_cookie) = nlp = ndmp_get_nlp(session);
3752 ndmp_session_ref(session);
3753 (void) ndmp_new_job_name(jname);
3754
3755 err = 0;
3756 if (!NLP_ISCHKPNTED(nlp) &&
3757 ndmp_create_snapshot(nlp->nlp_backup_path, jname) < 0) {
3758 MOD_LOGV3(params, NDMP_LOG_ERROR,
3759 "Creating checkpoint on \"%s\".\n",
3760 nlp->nlp_backup_path);
3761 err = -1;
3762 }
3763
3764 NDMP_LOG(LOG_DEBUG, "err %d, chkpnted %c",
3765 err, NDMP_YORN(NLP_ISCHKPNTED(nlp)));
3766
3767 if (err == 0) {
3768 sarg.bs_session = session;
3769 sarg.bs_jname = jname;
3770 sarg.bs_path = nlp->nlp_backup_path;
3771
3772 /* Get an estimate of the data size */
3773 if (pthread_create(&tid, NULL, (funct_t)get_backup_size,
3774 (void *)&sarg) == 0)
3775 (void) pthread_detach(tid);
3776
3777 err = ndmp_get_cur_bk_time(nlp, &nlp->nlp_cdate, jname);
3778 if (err != 0) {
3779 NDMP_LOG(LOG_DEBUG, "err %d", err);
3780 } else {
3781 log_bk_params_v3(session, params, nlp);
3782 err = tar_backup_v3(session, params, nlp, jname);
3783 }
3784 }
3785
3786 if (!NLP_ISCHKPNTED(nlp))
3787 (void) ndmp_remove_snapshot(nlp->nlp_backup_path, jname);
3788
3789 NDMP_LOG(LOG_DEBUG, "err %d, update %c",
3790 err, NDMP_YORN(NLP_SHOULD_UPDATE(nlp)));
3791
3792 if (err == 0)
3793 save_backup_date_v3(params, nlp);
3794
3795 MOD_DONE(params, err);
3796
3797 /* nlp_params is allocated in start_backup_v3() */
3798 NDMP_FREE(nlp->nlp_params);
3799 NDMP_FREE(nlp->nlp_backup_path);
3800
3801 NS_DEC(nbk);
3802 ndmp_session_unref(session);
3803 return (err);
3804
3805 }
3806
3807
3808 /*
3809 * ndmpd_tar_backup_abort_v3
3810 *
3811 * Abort the backup operation and stop the reader thread.
3812 *
3813 * Parameters:
3814 * module_cookie (input) - pointer to the nlp structure
3815 *
3816 * Returns:
3817 * 0: always
3818 */
3819 int
ndmpd_tar_backup_abort_v3(void * module_cookie)3820 ndmpd_tar_backup_abort_v3(void *module_cookie)
3821 {
3822 ndmp_lbr_params_t *nlp;
3823
3824 nlp = (ndmp_lbr_params_t *)module_cookie;
3825 if (nlp && nlp->nlp_session) {
3826 if (nlp->nlp_session->ns_data.dd_data_addr.addr_type ==
3827 NDMP_ADDR_TCP &&
3828 nlp->nlp_session->ns_data.dd_sock != -1) {
3829 (void) close(nlp->nlp_session->ns_data.dd_sock);
3830 nlp->nlp_session->ns_data.dd_sock = -1;
3831 }
3832 ndmp_stop_reader_thread(nlp->nlp_session);
3833 }
3834
3835 return (0);
3836 }
3837
3838
3839 /*
3840 * ndmp_restore_get_params_v3
3841 *
3842 * Get the parameters specified for recovery such as restore path, type
3843 * of restore (DAR, non-DAR) etc
3844 *
3845 * Parameters:
3846 * session (input) - pointer to the session
3847 * params (input) - pointer to the parameters structure
3848 *
3849 * Returns:
3850 * NDMP_NO_ERR: on success
3851 * != NDMP_NO_ERR: otherwise
3852 */
3853 ndmp_error
ndmp_restore_get_params_v3(ndmpd_session_t * session,ndmpd_module_params_t * params)3854 ndmp_restore_get_params_v3(ndmpd_session_t *session,
3855 ndmpd_module_params_t *params)
3856 {
3857 ndmp_error rv;
3858 ndmp_lbr_params_t *nlp;
3859
3860 if (!(nlp = ndmp_get_nlp(session))) {
3861 NDMP_LOG(LOG_DEBUG, "nlp is NULL");
3862 rv = NDMP_ILLEGAL_ARGS_ERR;
3863 } else if (!(nlp->nlp_backup_path = get_backup_path_v3(params)))
3864 rv = NDMP_ILLEGAL_ARGS_ERR;
3865 else if ((nlp->nlp_nfiles = session->ns_data.dd_nlist_len) == 0) {
3866 NDMP_LOG(LOG_DEBUG, "nfiles: %d", nlp->nlp_nfiles);
3867 rv = NDMP_ILLEGAL_ARGS_ERR;
3868 } else if (get_rs_path_v3(params, nlp) != NDMP_NO_ERR) {
3869 rv = NDMP_ILLEGAL_ARGS_ERR;
3870 } else if ((rv = fix_nlist_v3(session, params, nlp)) != NDMP_NO_ERR) {
3871 NDMP_LOG(LOG_DEBUG, "fix_nlist_v3: %d", rv);
3872 } else {
3873 rv = NDMP_NO_ERR;
3874 get_direct_env_v3(params, nlp);
3875 if (NLP_ISSET(nlp, NLPF_DIRECT)) {
3876 if (NLP_ISSET(nlp, NLPF_RECURSIVE)) {
3877 /* Currently we dont support DAR on directory */
3878 NDMP_LOG(LOG_DEBUG,
3879 "Can't have RECURSIVE and DIRECT together");
3880 rv = NDMP_ILLEGAL_ARGS_ERR;
3881 return (rv);
3882 }
3883
3884 /*
3885 * DAR can be done if all the fh_info's are valid.
3886 */
3887 if (allvalidfh(session, params)) {
3888 ndmp_sort_nlist_v3(session);
3889 } else {
3890 MOD_LOGV3(params, NDMP_LOG_WARNING,
3891 "Cannot do direct access recovery. "
3892 "Some 'fh_info'es are not valid.\n");
3893 NLP_UNSET(nlp, NLPF_DIRECT);
3894 }
3895 }
3896
3897 log_rs_params_v3(session, params, nlp);
3898 }
3899
3900 return (rv);
3901 }
3902
3903
3904 /*
3905 * ndmpd_tar_restore_starter_v3
3906 *
3907 * The main restore starter function. It will start a DAR or
3908 * non-DAR recovery based on the parameters. (V3 and V4 only)
3909 *
3910 * Parameters:
3911 * params (input) - pointer to the parameters structure
3912 *
3913 * Returns:
3914 * NDMP_NO_ERR: on success
3915 * != NDMP_NO_ERR: otherwise
3916 */
3917 int
ndmpd_tar_restore_starter_v3(void * arg)3918 ndmpd_tar_restore_starter_v3(void *arg)
3919 {
3920 ndmpd_module_params_t *params = arg;
3921 int err;
3922 ndmpd_session_t *session;
3923 ndmp_lbr_params_t *nlp;
3924
3925
3926 session = (ndmpd_session_t *)(params->mp_daemon_cookie);
3927 *(params->mp_module_cookie) = nlp = ndmp_get_nlp(session);
3928 ndmp_session_ref(session);
3929
3930 if (NLP_ISSET(nlp, NLPF_DIRECT))
3931 err = ndmpd_rs_dar_tar_v3(session, params, nlp);
3932 else
3933 err = ndmpd_rs_sar_tar_v3(session, params, nlp);
3934
3935 MOD_DONE(params, err);
3936
3937 NS_DEC(nrs);
3938 /* nlp_params is allocated in start_recover() */
3939 NDMP_FREE(nlp->nlp_params);
3940 ndmp_session_unref(session);
3941 return (err);
3942
3943 }
3944
3945
3946 /*
3947 * ndmp_tar_restore_abort_v3
3948 *
3949 * Restore abort function (V3 and V4 only)
3950 *
3951 * Parameters:
3952 * module_cookie (input) - pointer to nlp
3953 *
3954 * Returns:
3955 * 0
3956 */
3957 int
ndmpd_tar_restore_abort_v3(void * module_cookie)3958 ndmpd_tar_restore_abort_v3(void *module_cookie)
3959 {
3960 ndmp_lbr_params_t *nlp;
3961
3962 nlp = (ndmp_lbr_params_t *)module_cookie;
3963 if (nlp != NULL && nlp->nlp_session != NULL) {
3964 if (nlp->nlp_session->ns_data.dd_mover.addr_type ==
3965 NDMP_ADDR_TCP &&
3966 nlp->nlp_session->ns_data.dd_sock != -1) {
3967 (void) close(nlp->nlp_session->ns_data.dd_sock);
3968 nlp->nlp_session->ns_data.dd_sock = -1;
3969 }
3970 nlp_event_nw(nlp->nlp_session);
3971 ndmp_stop_writer_thread(nlp->nlp_session);
3972 }
3973
3974
3975 return (0);
3976
3977 }
3978