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 #include <stdlib.h>
39 #include <ctype.h>
40 #include <stdio.h>
41 #include <limits.h>
42 #include <string.h>
43 #include <time.h>
44 #include <sys/types.h>
45 #include <sys/acl.h>
46 #include <sys/mkdev.h>
47 #include <utime.h>
48 #include <unistd.h>
49 #include <pthread.h>
50 #include <archives.h>
51 #include <priv.h>
52 #include <tlm.h>
53 #include <libzfs.h>
54 #include <pwd.h>
55 #include <grp.h>
56 #include <ndmpd_prop.h>
57 #include "tlm_proto.h"
58
59
60 #define PM_EXACT_OR_CHILD(m) ((m) == PM_EXACT || (m) == PM_CHILD)
61
62 typedef boolean_t name_match_fp_t(char *s, char *t);
63
64 static void set_acl(char *name,
65 tlm_acls_t *acls);
66 static long restore_file(int *fp,
67 char *real_name,
68 long size,
69 longlong_t huge_size,
70 tlm_acls_t *,
71 boolean_t want_this_file,
72 tlm_cmd_t *,
73 tlm_job_stats_t *);
74 static long restore_xattr_hdr(int *fp,
75 char *name,
76 char *fname,
77 long size,
78 tlm_acls_t *acls,
79 tlm_cmd_t *local_commands,
80 tlm_job_stats_t *job_stats);
81 static int get_long_name(int lib,
82 int drv,
83 long recsize,
84 char *name,
85 long *buf_spot,
86 tlm_cmd_t *local_commands);
87 static int get_humongus_file_header(int lib,
88 int drv,
89 long recsize,
90 longlong_t *size,
91 char *name,
92 tlm_cmd_t *);
93 static int create_directory(char *dir,
94 tlm_job_stats_t *);
95 static int create_hard_link(char *name,
96 char *link,
97 tlm_acls_t *,
98 tlm_job_stats_t *);
99 static int create_sym_link(char *dst,
100 char *target,
101 tlm_acls_t *,
102 tlm_job_stats_t *);
103 static int create_special(char,
104 char *name,
105 tlm_acls_t *,
106 int,
107 int,
108 tlm_job_stats_t *);
109 static long load_acl_info(int lib,
110 int drv,
111 long size,
112 tlm_acls_t *,
113 long *acl_spot,
114 tlm_cmd_t *);
115 static char *get_read_buffer(int want,
116 int *error,
117 int *actual_size,
118 tlm_cmd_t *);
119 static boolean_t wildcard_enabled(void);
120 static boolean_t is_file_wanted(char *name,
121 char **sels,
122 char **exls,
123 int flags,
124 int *mchtype,
125 int *pos);
126 static char *catnames(struct rs_name_maker *rnp,
127 char *buf,
128 int pos,
129 char *path);
130
131 static char *rs_new_name(struct rs_name_maker *rnp,
132 char *real_name,
133 int pos,
134 char *path);
135
136 static void rs_create_new_bkpath(char *bk_path,
137 char *path,
138 char *pbuf);
139
140 typedef struct stack_ent {
141 char *se_name;
142 tlm_acls_t se_acls;
143 } stack_ent_t;
144
145
146 /*
147 * dtree_push
148 */
149 int
dtree_push(cstack_t * stp,char * nmp,tlm_acls_t * acls)150 dtree_push(cstack_t *stp, char *nmp, tlm_acls_t *acls)
151 {
152 int len;
153 stack_ent_t *sp;
154
155 sp = ndmp_malloc(sizeof (stack_ent_t));
156 if (!sp || !nmp || !acls) {
157 free(sp);
158 return (-1);
159 }
160
161 len = strlen(nmp) + 1;
162 sp->se_name = ndmp_malloc(len);
163 if (!sp->se_name) {
164 free(sp);
165 return (-1);
166 }
167
168 (void) strlcpy(sp->se_name, nmp, len);
169 (void) memcpy(&sp->se_acls, acls, sizeof (*acls));
170 (void) memset(acls, 0, sizeof (tlm_acls_t));
171
172 return (cstack_push(stp, (void *)sp, sizeof (*sp)));
173 }
174
175 /*
176 * dtree_pop
177 */
178 int
dtree_pop(cstack_t * stp)179 dtree_pop(cstack_t *stp)
180 {
181 int err;
182 stack_ent_t *sp;
183
184 err = cstack_pop(stp, (void **)&sp, (void *)NULL);
185 if (err)
186 return (-1);
187
188 set_acl(sp->se_name, &sp->se_acls);
189
190 free(sp->se_name);
191 free(sp);
192 return (err);
193 }
194
195
196 /*
197 * dtree_peek
198 */
199 char *
dtree_peek(cstack_t * stp)200 dtree_peek(cstack_t *stp)
201 {
202 int err;
203 stack_ent_t *sp;
204
205 err = cstack_top(stp, (void **)&sp, (void *)NULL);
206 if (err)
207 return (NULL);
208
209 return (sp->se_name);
210 }
211
212 /*
213 * NBU and EBS may not send us the correct file list containing hardlinks
214 * during a DAR restore, e.g. they appear always send the first name
215 * associated with an inode, even if other link names were
216 * selected for the restore. As a workaround, we use the file name entry
217 * in sels[] (ignore the name in the tar header) as restore target.
218 */
219 static char *
rs_darhl_new_name(struct rs_name_maker * rnp,char * name,char ** sels,int * pos,char * longname)220 rs_darhl_new_name(struct rs_name_maker *rnp, char *name, char **sels, int *pos,
221 char *longname)
222 {
223 int x;
224
225 for (x = 0; sels[x] != NULL; x++) {
226 if (strcmp(sels[x], " ")) {
227 *pos = x;
228 (void) strlcpy(longname, sels[x], TLM_MAX_PATH_NAME);
229 NDMP_LOG(LOG_DEBUG,
230 "to replace hardlink name [%s], pos [%d]",
231 longname, *pos);
232
233 return (rs_new_name(rnp, name, *pos, longname));
234 }
235 }
236
237 return (NULL);
238 }
239
240
241 /*
242 * Main dir restore function for tar
243 */
244 int
tar_getdir(tlm_commands_t * commands,tlm_cmd_t * local_commands,tlm_job_stats_t * job_stats,struct rs_name_maker * rnp,int lib,int drv,char ** sels,char ** exls,int flags,int DAR,char * bk_path,struct hardlink_q * hardlink_q)245 tar_getdir(tlm_commands_t *commands,
246 tlm_cmd_t *local_commands,
247 tlm_job_stats_t *job_stats,
248 struct rs_name_maker *rnp,
249 int lib,
250 int drv,
251 char **sels, /* what to get off the tape */
252 char **exls, /* what to leave behind */
253 int flags,
254 int DAR,
255 char *bk_path,
256 struct hardlink_q *hardlink_q)
257 {
258 int fp = 0; /* file being restored ... */
259 /* ...need to preserve across volume changes */
260 tlm_acls_t *acls; /* file access info */
261 char *longname;
262 boolean_t is_long_name = FALSE;
263 char *longlink;
264 char *hugename;
265 longlong_t huge_size = 0; /* size of a HUGE file */
266 long acl_spot; /* any ACL info on the next volume */
267 long file_size; /* size of file to restore */
268 long size_left = 0; /* need this after volume change */
269 int last_action = 0; /* what we are doing at EOT */
270 boolean_t multi_volume = FALSE; /* is this a multi-volume switch ? */
271 int chk_rv; /* scratch area */
272
273 int mchtype, pos;
274 /*
275 * if an exact match is found for
276 * restore and its position in the
277 * selections list
278 */
279 int nzerohdr; /* the number of empty tar headers */
280 boolean_t break_flg; /* exit the while loop */
281 int rv;
282 long nm_end, lnk_end;
283 char *name, *nmp;
284 cstack_t *stp;
285 char *bkpath;
286 char *parentlnk;
287 int dir_dar = 0;
288
289 /*
290 * The directory where temporary files may be created during a partial
291 * non-DAR restore of hardlinks. It is intended to be initialized by
292 * an environment variable that can be set by user.
293 *
294 * It is not initialized for now. We keep it here for future use.
295 */
296 char *tmplink_dir = NULL;
297 int dar_recovered = 0;
298 char *thname_buf;
299
300 /*
301 * startup
302 */
303
304 longname = ndmp_malloc(TLM_MAX_PATH_NAME);
305 longlink = ndmp_malloc(TLM_MAX_PATH_NAME);
306 hugename = ndmp_malloc(TLM_MAX_PATH_NAME);
307 parentlnk = ndmp_malloc(TLM_MAX_PATH_NAME);
308 thname_buf = ndmp_malloc(TLM_MAX_PATH_NAME);
309 name = ndmp_malloc(TLM_MAX_PATH_NAME);
310 acls = ndmp_malloc(sizeof (tlm_acls_t));
311 stp = cstack_new();
312 if (longname == NULL || longlink == NULL || hugename == NULL ||
313 name == NULL || acls == NULL || stp == NULL || parentlnk == NULL ||
314 thname_buf == NULL) {
315 cstack_delete(stp);
316 free(longname);
317 free(longlink);
318 free(hugename);
319 free(parentlnk);
320 free(name);
321 free(acls);
322 free(thname_buf);
323 return (-TLM_NO_SCRATCH_SPACE);
324 }
325
326 acl_spot = 0;
327 *hugename = '\0';
328 *parentlnk = '\0';
329 nm_end = 0;
330 *longname = '\0';
331 lnk_end = 0;
332 *longlink = '\0';
333 (void) memset(acls, 0, sizeof (tlm_acls_t));
334 if (IS_SET(flags, RSFLG_OVR_ALWAYS)) {
335 acls->acl_overwrite = TRUE;
336 NDMP_LOG(LOG_DEBUG, "RSFLG_OVR_ALWAYS");
337 } else if (IS_SET(flags, RSFLG_OVR_UPDATE)) {
338 acls->acl_update = TRUE;
339 NDMP_LOG(LOG_DEBUG, "RSFLG_OVR_UPDATE");
340 }
341
342 /*
343 * work
344 */
345 rv = 0;
346 nzerohdr = 0;
347 break_flg = FALSE;
348 while (commands->tcs_writer != TLM_ABORT &&
349 local_commands->tc_writer != TLM_STOP) {
350 tlm_tar_hdr_t fake_tar_hdr;
351 char *file_name;
352 char *link_name;
353 int erc;
354 int actual_size;
355 boolean_t want_this_file;
356 int want = sizeof (tlm_tar_hdr_t);
357 tlm_tar_hdr_t *tar_hdr;
358
359 /* The inode of an LF_LINK type. */
360 unsigned long hardlink_inode = 0;
361
362 /*
363 * Indicate whether a file with the same inode has been
364 * restored.
365 */
366 int hardlink_done = 0;
367
368 /* The path of the restored hardlink file */
369 char *hardlink_target = NULL;
370 int is_hardlink = 0;
371
372 /*
373 * Whether a temporary file should be created for restoring
374 * hardlink.
375 */
376 int hardlink_tmp_file = 0;
377 char *hardlink_tmp_name = ".tmphlrsnondar";
378
379 /* used to make up hardlink_tmp_name */
380 static int hardlink_tmp_idx = 0;
381
382 if (break_flg) {
383 NDMP_LOG(LOG_DEBUG,
384 "Exiting writer thread drive %d", drv);
385 break;
386 }
387
388 if (multi_volume) {
389 NDMP_LOG(LOG_DEBUG, "multi_volume %c %d",
390 last_action, size_left);
391
392 /*
393 * the previous volume is out of data
394 * and is back in the rack, a new tape
395 * is loaded and ready to read.
396 *
397 * We need to pick up where we left off.
398 */
399 (void) memset(&fake_tar_hdr, 0, sizeof (fake_tar_hdr));
400 file_size = size_left;
401 tar_hdr = &fake_tar_hdr;
402 tar_hdr->th_linkflag = last_action;
403
404 multi_volume = FALSE;
405 last_action = 0;
406 } else {
407 tar_hdr = (tlm_tar_hdr_t *)get_read_buffer(want,
408 &erc, &actual_size, local_commands);
409
410 if (tar_hdr == NULL) {
411 rv = -1;
412 continue;
413 }
414
415 /*
416 * we can ignore read errors here because
417 * 1) they are logged by Restore Reader
418 * 2) we are not doing anything important here
419 * just looking for the next work record.
420 */
421 if (actual_size < want) {
422 /*
423 * EOF hits here
424 *
425 * wait for another buffer to come along
426 * or until the Reader thread tells us
427 * that no more tapes will be loaded ...
428 * time to stop.
429 */
430 continue;
431 }
432
433 /*
434 * check for "we are lost"
435 */
436 chk_rv = tlm_vfy_tar_checksum(tar_hdr);
437 if (chk_rv == 0) {
438 /* one of the end of tar file marks */
439 if (++nzerohdr >= 2) {
440 NDMP_LOG(LOG_DEBUG,
441 "nzerohdr %d, breaking",
442 nzerohdr);
443 /* end of tar file */
444 break;
445 }
446 NDMP_LOG(LOG_DEBUG, "nzerohdr %d, continuing",
447 nzerohdr);
448 continue;
449 } else if (chk_rv < 0) {
450 nzerohdr = 0;
451 /* skip this record */
452 continue;
453 }
454 nzerohdr = 0;
455
456 /*
457 * When files are spanned to the next tape, the
458 * information of the acls must not be over-written
459 * by the information of the LF_MULTIVOL and LF_VOLHDR
460 * header, whose information is irrelevant to the file.
461 * The information of the original header must be
462 * kept in the 'acl'.
463 */
464 if (tar_hdr->th_linkflag != LF_MULTIVOL &&
465 tar_hdr->th_linkflag != LF_VOLHDR) {
466 if (tar_hdr->th_linkflag != LF_HUMONGUS) {
467 acls->acl_attr.st_mode =
468 oct_atoi(tar_hdr->th_mode);
469 acls->acl_attr.st_size =
470 oct_atoi(tar_hdr->th_size);
471 acls->acl_attr.st_uid =
472 oct_atoi(tar_hdr->th_uid);
473 acls->acl_attr.st_gid =
474 oct_atoi(tar_hdr->th_gid);
475 acls->acl_attr.st_mtime =
476 oct_atoi(tar_hdr->th_mtime);
477 (void) strlcpy(acls->uname,
478 tar_hdr->th_uname,
479 sizeof (acls->uname));
480 (void) strlcpy(acls->gname,
481 tar_hdr->th_gname,
482 sizeof (acls->gname));
483 }
484 file_size = oct_atoi(tar_hdr->th_size);
485 acl_spot = 0;
486 last_action = tar_hdr->th_linkflag;
487 }
488 }
489
490 NDMP_LOG(LOG_DEBUG, "n [%s] f [%c] s %lld m %o u %d g %d t %d",
491 tar_hdr->th_name, tar_hdr->th_linkflag,
492 acls->acl_attr.st_size, acls->acl_attr.st_mode,
493 acls->acl_attr.st_uid, acls->acl_attr.st_gid,
494 acls->acl_attr.st_mtime);
495
496 /*
497 * If the restore is running using DAR we should check for
498 * extended attribute entries
499 */
500 if (dar_recovered &&
501 tar_hdr->th_linkflag != LF_XATTR)
502 break;
503
504 rs_create_new_bkpath(bk_path, tar_hdr->th_name, thname_buf);
505
506 switch (tar_hdr->th_linkflag) {
507 case LF_MULTIVOL:
508 multi_volume = TRUE;
509 break;
510 case LF_LINK:
511 is_hardlink = 1;
512 hardlink_inode =
513 oct_atoi(tar_hdr->th_shared.th_hlink_ino);
514
515 /*
516 * Check if we have restored a link with the same inode
517 * If the inode is 0, we have to restore it as a
518 * regular file.
519 */
520 if (hardlink_inode) {
521 hardlink_done = !hardlink_q_get(hardlink_q,
522 hardlink_inode, 0, &hardlink_target);
523 }
524
525 if (hardlink_done) {
526 NDMP_LOG(LOG_DEBUG,
527 "found hardlink, inode = %u, target = [%s]",
528 hardlink_inode,
529 hardlink_target? hardlink_target : "--");
530
531 /* create a hardlink to hardlink_target */
532 file_name = (*longname == 0) ?
533 thname_buf : longname;
534
535 if (!is_file_wanted(file_name, sels, exls,
536 flags, &mchtype, &pos)) {
537 nmp = NULL;
538 /*
539 * This means that DMA did not send us
540 * the correct fh_info for the file
541 * in restore list. We use the file
542 * name entry in sels[] (ignore the
543 * name in the tar header) as restore
544 * target.
545 */
546 if (DAR) {
547 nmp = rs_darhl_new_name(rnp,
548 name, sels, &pos,
549 file_name);
550 }
551 } else {
552 nmp = rs_new_name(rnp, name, pos,
553 file_name);
554 if (!nmp) {
555 NDMP_LOG(LOG_DEBUG,
556 "can't make name for %s",
557 longname);
558 }
559 }
560
561 if (nmp) {
562 if (hardlink_target) {
563 erc = create_hard_link(
564 hardlink_target, nmp,
565 acls, job_stats);
566 if (erc == 0) {
567 (void)
568 tlm_entry_restored(
569 job_stats,
570 file_name, pos);
571 NDMP_LOG(LOG_DEBUG,
572 "restored %s -> %s",
573 nmp,
574 hardlink_target);
575 }
576 } else {
577 NDMP_LOG(LOG_DEBUG,
578 "no target for hardlink %s",
579 nmp);
580 }
581
582 name[0] = 0;
583 is_long_name = FALSE;
584 }
585
586 nm_end = 0;
587 longname[0] = 0;
588 lnk_end = 0;
589 longlink[0] = 0;
590
591 break;
592 }
593 /* otherwise fall through, restore like a normal file */
594 /*FALLTHROUGH*/
595 case LF_OLDNORMAL:
596 /*
597 * check for TAR's end-of-tape method
598 * of zero filled records.
599 */
600 if (tar_hdr->th_name[0] == 0) {
601 break;
602 }
603 /*
604 * otherwise fall through,
605 * this is an old style normal file header
606 */
607 /*FALLTHROUGH*/
608 case LF_NORMAL:
609 case LF_CONTIG:
610 job_stats->js_files_so_far++;
611 if (*hugename != 0) {
612 (void) strlcpy(longname, hugename,
613 TLM_MAX_PATH_NAME);
614 } else if (*longname == 0) {
615 if (tar_hdr->th_name[0] != '/') {
616 /*
617 * check for old tar format, it
618 * does not have a leading "/"
619 */
620 longname[0] = '/';
621 longname[1] = 0;
622 (void) strlcat(longname,
623 tar_hdr->th_name,
624 TLM_MAX_PATH_NAME);
625 } else {
626 (void) strlcpy(longname,
627 thname_buf,
628 TLM_MAX_PATH_NAME);
629 }
630 }
631
632 want_this_file = is_file_wanted(longname, sels, exls,
633 flags, &mchtype, &pos);
634 if (!want_this_file) {
635 nmp = NULL;
636 /*
637 * This means that DMA did not send us valid
638 * fh_info for the file in restore list. We
639 * use the file name entry in sels[] (ignore
640 * the name in the tar header) as restore
641 * target.
642 */
643 if (DAR && (tar_hdr->th_linkflag == LF_LINK)) {
644 nmp = rs_darhl_new_name(rnp, name,
645 sels, &pos, longname);
646
647 if (nmp) {
648 want_this_file = TRUE;
649 mchtype = PM_EXACT;
650 } else {
651 break_flg = TRUE;
652 break;
653 }
654 }
655 } else {
656 nmp = rs_new_name(rnp, name, pos, longname);
657 if (!nmp)
658 want_this_file = FALSE;
659 }
660
661 if (nmp)
662 (void) strlcpy(parentlnk, nmp, strlen(nmp) + 1);
663
664 /*
665 * For a hardlink, even if it's not asked to be
666 * restored, we restore it to a temporary location,
667 * in case other links to the same file need to be
668 * restored later.
669 *
670 * The temp files are created in tmplink_dir, with
671 * names like ".tmphlrsnondar*". They are cleaned up
672 * at the completion of a restore. However, if a
673 * restore were interrupted, e.g. by a system reboot,
674 * they would have to be cleaned up manually in order
675 * for the disk space to be freed.
676 *
677 * If tmplink_dir is NULL, no temperorary files are
678 * created during a restore. This may result in some
679 * hardlinks not being restored during a partial
680 * restore.
681 */
682 if (is_hardlink && !DAR && !want_this_file && !nmp) {
683 if (tmplink_dir) {
684 (void) snprintf(name, TLM_MAX_PATH_NAME,
685 "%s/%s_%d", tmplink_dir,
686 hardlink_tmp_name,
687 hardlink_tmp_idx);
688 nmp = name;
689
690 hardlink_tmp_idx++;
691 hardlink_tmp_file = 1;
692 want_this_file = TRUE;
693 NDMP_LOG(LOG_DEBUG,
694 "To restore temp hardlink file %s.",
695 nmp);
696 } else {
697 NDMP_LOG(LOG_DEBUG,
698 "No tmplink_dir specified.");
699 }
700 }
701
702 size_left = restore_file(&fp, nmp, file_size,
703 huge_size, acls, want_this_file, local_commands,
704 job_stats);
705
706 /*
707 * In the case of non-DAR, we have to record the first
708 * link for an inode that has multiple links. That's
709 * the only link with data records actually backed up.
710 * In this way, when we run into the other links, they
711 * will be treated as links, and we won't go to look
712 * for the data records to restore. This is not a
713 * problem for DAR, where DMA tells the tape where
714 * to locate the data records.
715 */
716 if (is_hardlink && !DAR) {
717 if (hardlink_q_add(hardlink_q, hardlink_inode,
718 0, nmp, hardlink_tmp_file))
719 NDMP_LOG(LOG_DEBUG,
720 "failed to add (%u, %s) to HL q",
721 hardlink_inode, nmp);
722 }
723
724 /* remove / reverse the temporary stuff */
725 if (hardlink_tmp_file) {
726 nmp = NULL;
727 want_this_file = FALSE;
728 hardlink_tmp_file = 0;
729 }
730
731 /*
732 * Check if it is time to set the attribute
733 * of the restored directory
734 */
735 while (nmp && ((bkpath = dtree_peek(stp)) != NULL)) {
736 if (strstr(nmp, bkpath))
737 break;
738
739 (void) dtree_pop(stp);
740 }
741
742 NDMP_LOG(LOG_DEBUG, "sizeleft %s %d, %lld", longname,
743 size_left, huge_size);
744
745 if (size_left == -TLM_STOP) {
746 break_flg = TRUE;
747 rv = -1;
748 commands->tcs_reader = TLM_ABORT;
749 NDMP_LOG(LOG_DEBUG, "restoring [%s] failed",
750 longname);
751 break;
752 }
753
754 if (want_this_file) {
755 job_stats->js_bytes_total += file_size;
756 job_stats->js_files_total++;
757 }
758
759 huge_size -= file_size;
760 if (huge_size < 0) {
761 huge_size = 0;
762 }
763 if (size_left == 0 && huge_size == 0) {
764 if (PM_EXACT_OR_CHILD(mchtype)) {
765 (void) tlm_entry_restored(job_stats,
766 longname, pos);
767
768 /*
769 * Add an entry to hardlink_q to record
770 * this hardlink.
771 */
772 if (is_hardlink) {
773 NDMP_LOG(LOG_DEBUG,
774 "Restored hardlink file %s",
775 nmp);
776
777 if (DAR) {
778 (void) hardlink_q_add(
779 hardlink_q,
780 hardlink_inode, 0,
781 nmp, 0);
782 }
783 }
784 }
785
786 nm_end = 0;
787 longname[0] = 0;
788 lnk_end = 0;
789 longlink[0] = 0;
790 hugename[0] = 0;
791 name[0] = 0;
792 is_long_name = FALSE;
793 }
794 break;
795 case LF_XATTR:
796 file_name = (*longname == 0) ? thname_buf :
797 longname;
798
799 size_left = restore_xattr_hdr(&fp, parentlnk,
800 file_name, file_size, acls, local_commands,
801 job_stats);
802
803 break;
804 case LF_SYMLINK:
805 file_name = (*longname == 0) ? thname_buf :
806 longname;
807 link_name = (*longlink == 0) ?
808 tar_hdr->th_linkname : longlink;
809 NDMP_LOG(LOG_DEBUG, "file_name[%s]", file_name);
810 NDMP_LOG(LOG_DEBUG, "link_name[%s]", link_name);
811 if (is_file_wanted(file_name, sels, exls, flags,
812 &mchtype, &pos)) {
813 nmp = rs_new_name(rnp, name, pos, file_name);
814 if (nmp) {
815 erc = create_sym_link(nmp, link_name,
816 acls, job_stats);
817 if (erc == 0 &&
818 PM_EXACT_OR_CHILD(mchtype))
819 (void) tlm_entry_restored(
820 job_stats, file_name, pos);
821 name[0] = 0;
822 }
823 }
824 nm_end = 0;
825 longname[0] = 0;
826 lnk_end = 0;
827 longlink[0] = 0;
828 break;
829 case LF_DIR:
830 file_name = *longname == 0 ? thname_buf :
831 longname;
832 if (is_file_wanted(file_name, sels, exls, flags,
833 &mchtype, &pos)) {
834 dir_dar = DAR;
835 nmp = rs_new_name(rnp, name, pos, file_name);
836 if (nmp && mchtype != PM_PARENT) {
837 (void) strlcpy(parentlnk, nmp,
838 strlen(nmp));
839 erc = create_directory(nmp, job_stats);
840 if (erc == 0 &&
841 PM_EXACT_OR_CHILD(mchtype))
842 (void) tlm_entry_restored(
843 job_stats, file_name, pos);
844 /*
845 * Check if it is time to set
846 * the attribute of the restored
847 * directory
848 */
849 while ((bkpath = dtree_peek(stp))
850 != NULL) {
851 if (strstr(nmp, bkpath))
852 break;
853 (void) dtree_pop(stp);
854 }
855
856 (void) dtree_push(stp, nmp, acls);
857 name[0] = 0;
858 }
859 } else {
860 dir_dar = 0;
861 }
862 nm_end = 0;
863 longname[0] = 0;
864 lnk_end = 0;
865 longlink[0] = 0;
866 break;
867 case LF_FIFO:
868 case LF_BLK:
869 case LF_CHR:
870 file_name = *longname == 0 ? thname_buf :
871 longname;
872 if (is_file_wanted(file_name, sels, exls, flags,
873 &mchtype, &pos)) {
874 nmp = rs_new_name(rnp, name, pos, file_name);
875 if (nmp) {
876 erc = create_special(
877 tar_hdr->th_linkflag, nmp, acls,
878 oct_atoi(tar_hdr->th_shared.
879 th_dev.th_devmajor),
880 oct_atoi(tar_hdr->th_shared.
881 th_dev.th_devminor), job_stats);
882 if (erc == 0 &&
883 PM_EXACT_OR_CHILD(mchtype))
884 (void) tlm_entry_restored(
885 job_stats, file_name, pos);
886 name[0] = 0;
887 }
888 }
889 nm_end = 0;
890 longname[0] = 0;
891 lnk_end = 0;
892 longlink[0] = 0;
893 break;
894 case LF_LONGLINK:
895 file_size = min(file_size,
896 TLM_MAX_PATH_NAME - lnk_end - 1);
897 file_size = max(0, file_size);
898 size_left = get_long_name(lib, drv, file_size, longlink,
899 &lnk_end, local_commands);
900
901 if (size_left != 0)
902 NDMP_LOG(LOG_DEBUG,
903 "fsize %d sleft %d lnkend %d",
904 file_size, size_left, lnk_end);
905 break;
906 case LF_LONGNAME:
907 file_size = min(file_size,
908 TLM_MAX_PATH_NAME - nm_end - 1);
909 file_size = max(0, file_size);
910 size_left = get_long_name(lib, drv, file_size, longname,
911 &nm_end, local_commands);
912
913 if (size_left != 0)
914 NDMP_LOG(LOG_DEBUG,
915 "fsize %d sleft %d nmend %d",
916 file_size, size_left, nm_end);
917 is_long_name = TRUE;
918 break;
919 case LF_ACL:
920 size_left = load_acl_info(lib, drv, file_size, acls,
921 &acl_spot, local_commands);
922 break;
923 case LF_VOLHDR:
924 break;
925 case LF_HUMONGUS:
926 (void) memset(hugename, 0, TLM_MAX_PATH_NAME);
927 (void) get_humongus_file_header(lib, drv, file_size,
928 &huge_size, hugename, local_commands);
929 break;
930 default:
931 break;
932
933 }
934
935 /*
936 * If the restore is running using DAR we should check for
937 * long file names and HUGE file sizes.
938 */
939 if (DAR && tar_hdr->th_linkflag != LF_ACL &&
940 tar_hdr->th_linkflag != LF_XATTR &&
941 !huge_size && !is_long_name && !dir_dar)
942 dar_recovered = 1;
943 }
944
945 /*
946 * tear down
947 */
948 if (fp != 0) {
949 (void) close(fp);
950 }
951 while (dtree_pop(stp) != -1)
952 ;
953 cstack_delete(stp);
954 free(acls);
955 free(longname);
956 free(parentlnk);
957 free(longlink);
958 free(hugename);
959 free(name);
960 free(thname_buf);
961 return (rv);
962 }
963
964 /*
965 * Main file restore function for tar (should run as a thread)
966 */
967 int
tar_getfile(tlm_backup_restore_arg_t * argp)968 tar_getfile(tlm_backup_restore_arg_t *argp)
969 {
970 tlm_job_stats_t *job_stats;
971 char **sels; /* list of files desired */
972 char **exls; /* list of files not wanted */
973 char *dir; /* where to restore the files */
974 char job[TLM_MAX_BACKUP_JOB_NAME+1];
975 /* the restore job name */
976 int erc; /* error return codes */
977 int flags;
978 struct rs_name_maker rn;
979 tlm_commands_t *commands;
980 tlm_cmd_t *local_commands;
981 char *list = NULL;
982
983 commands = argp->ba_commands;
984 local_commands = argp->ba_cmd;
985
986 flags = 0;
987
988 dir = ndmp_malloc(TLM_MAX_PATH_NAME);
989 if (dir == NULL) {
990 local_commands->tc_reader = TLM_STOP;
991 (void) pthread_barrier_wait(&argp->ba_barrier);
992 return (-1);
993 }
994
995 (void) strlcpy(job, argp->ba_job, TLM_MAX_BACKUP_JOB_NAME+1);
996 (void) strlcpy(dir, argp->ba_dir, TLM_MAX_PATH_NAME);
997
998 flags |= RSFLG_OVR_ALWAYS;
999 flags |= RSFLG_IGNORE_CASE;
1000
1001 /*
1002 * do not test for "dir" having no string, since that
1003 * is a legal condition. Restore to origional location
1004 * will not have a restore directory.
1005 */
1006 if (*job == '\0') {
1007 NDMP_LOG(LOG_DEBUG, "No job defined");
1008 local_commands->tc_reader = TLM_STOP;
1009 free(dir);
1010 (void) pthread_barrier_wait(&argp->ba_barrier);
1011 return (-1);
1012 }
1013
1014 sels = argp->ba_sels;
1015 if (sels == NULL) {
1016 local_commands->tc_reader = TLM_STOP;
1017 free(dir);
1018 (void) pthread_barrier_wait(&argp->ba_barrier);
1019 return (-1);
1020 }
1021 exls = &list;
1022
1023 tlm_log_list("selections", sels);
1024 tlm_log_list("exclusions", exls);
1025
1026 if (wildcard_enabled())
1027 flags |= RSFLG_MATCH_WCARD;
1028
1029 local_commands->tc_ref++;
1030 commands->tcs_writer_count++;
1031
1032 /*
1033 * let the launcher continue
1034 */
1035 (void) pthread_barrier_wait(&argp->ba_barrier);
1036
1037 job_stats = tlm_ref_job_stats(job);
1038
1039 rn.rn_fp = catnames;
1040 rn.rn_nlp = dir;
1041
1042 /*
1043 * work
1044 */
1045 NDMP_LOG(LOG_DEBUG, "start restore job %s", job);
1046 erc = tar_getdir(commands, local_commands, job_stats, &rn, 1, 1,
1047 sels, exls, flags, 0, NULL, NULL);
1048
1049 /*
1050 * teardown
1051 */
1052 NDMP_LOG(LOG_DEBUG, "end restore job %s", job);
1053 tlm_un_ref_job_stats(job);
1054 tlm_release_list(sels);
1055 tlm_release_list(exls);
1056
1057 commands->tcs_writer_count--;
1058 local_commands->tc_reader = TLM_STOP;
1059 tlm_release_reader_writer_ipc(local_commands);
1060 free(dir);
1061 return (erc);
1062 }
1063
1064 /*
1065 * Creates the directories all the way down to the
1066 * end if they dont exist
1067 */
1068 int
make_dirs(char * dir)1069 make_dirs(char *dir)
1070 {
1071 char c;
1072 char *cp, *end;
1073 struct stat64 st;
1074
1075 cp = dir;
1076 cp += strspn(cp, "/");
1077 end = dir + strlen(dir);
1078 do {
1079 if (*cp == '\0' || *cp == '/') {
1080 c = *cp;
1081 *cp = '\0';
1082 if (lstat64(dir, &st) < 0)
1083 if (mkdir(dir, 0777) < 0) {
1084 NDMP_LOG(LOG_DEBUG, "Error %d"
1085 " creating directory %s",
1086 errno, dir);
1087 *cp = c;
1088 return (-1);
1089 }
1090
1091 *cp = c;
1092 }
1093 } while (++cp <= end);
1094
1095 return (0);
1096 }
1097
1098 /*
1099 * Creates the directories leading to the given path
1100 */
1101 int
mkbasedir(char * path)1102 mkbasedir(char *path)
1103 {
1104 int rv;
1105 char *cp;
1106 struct stat64 st;
1107
1108 if (!path || !*path) {
1109 NDMP_LOG(LOG_DEBUG, "Invalid argument");
1110 return (-1);
1111 }
1112
1113 cp = strrchr(path, '/');
1114 if (cp)
1115 *cp = '\0';
1116 rv = lstat64(path, &st);
1117 if (rv < 0) /* need new directories */
1118 rv = make_dirs(path);
1119 if (cp)
1120 *cp = '/';
1121
1122 return (rv);
1123 }
1124
1125
1126 /*
1127 * read the file off the tape back onto disk
1128 */
1129 static long
restore_file(int * fp,char * real_name,long size,longlong_t huge_size,tlm_acls_t * acls,boolean_t want_this_file,tlm_cmd_t * local_commands,tlm_job_stats_t * job_stats)1130 restore_file(int *fp,
1131 char *real_name,
1132 long size,
1133 longlong_t huge_size,
1134 tlm_acls_t *acls,
1135 boolean_t want_this_file,
1136 tlm_cmd_t *local_commands,
1137 tlm_job_stats_t *job_stats)
1138 {
1139 struct stat64 attr;
1140
1141 if (!real_name) {
1142 if (want_this_file) {
1143 NDMP_LOG(LOG_DEBUG, "No file name but wanted!");
1144 want_this_file = FALSE;
1145 }
1146 } else
1147 NDMP_LOG(LOG_DEBUG, "new file[%s]", real_name);
1148
1149 /*
1150 * OK, some FM is creeping in here ...
1151 * int *fp is used to keep the
1152 * backup file channel open through
1153 * the interruption of EOT and
1154 * processing the headers of the
1155 * next tape. So, if *fp is zero
1156 * then no file is open yet and all
1157 * is normal. If *fp has a number
1158 * then we are returning after an
1159 * EOT break.
1160 *
1161 * *fp is now also open for HUGE files
1162 * that are put back in sections.
1163 */
1164
1165 if (*fp == 0 && want_this_file) {
1166 int erc_stat;
1167
1168 if (mkbasedir(real_name) < 0)
1169 job_stats->js_errors++;
1170
1171 erc_stat = stat64(real_name, (struct stat64 *)&attr);
1172 if (erc_stat < 0) {
1173 /*EMPTY*/
1174 /* new file */
1175 } else if (acls->acl_overwrite) {
1176 /*EMPTY*/
1177 /* take this file no matter what */
1178 } else if (acls->acl_update) {
1179 if (attr.st_mtime < acls->acl_attr.st_mtime) {
1180 /*EMPTY*/
1181 /* tape is newer */
1182 } else {
1183 /* disk file is newer */
1184 want_this_file = FALSE;
1185 }
1186 } else {
1187 /*
1188 * no overwrite, no update,
1189 * do not ever replace old files.
1190 */
1191 want_this_file = TRUE;
1192 }
1193 if (want_this_file) {
1194
1195 *fp = open(real_name, O_CREAT | O_TRUNC | O_WRONLY,
1196 S_IRUSR | S_IWUSR);
1197 if (*fp == -1) {
1198 NDMP_LOG(LOG_ERR,
1199 "Could not open %s for restore.",
1200 real_name);
1201 NDMP_LOG(LOG_DEBUG,
1202 "fp=%d err=%d ", *fp, errno);
1203 job_stats->js_errors++;
1204 want_this_file = FALSE;
1205 /*
1206 * we cannot return here,
1207 * the file is still on
1208 * the tape and must be
1209 * skipped over.
1210 */
1211 }
1212 }
1213 (void) strlcpy(local_commands->tc_file_name, real_name,
1214 TLM_MAX_PATH_NAME);
1215 }
1216
1217 /*
1218 * this is the size left in the next segment
1219 */
1220 huge_size -= size;
1221
1222 /*
1223 * work
1224 */
1225 while (size > 0 && local_commands->tc_writer == TLM_RESTORE_RUN) {
1226 int actual_size;
1227 int error;
1228 char *rec;
1229 int write_size;
1230
1231 /*
1232 * Use bytes_in_file field to tell reader the amount
1233 * of data still need to be read for this file.
1234 */
1235 job_stats->js_bytes_in_file = size;
1236
1237 error = 0;
1238 rec = get_read_buffer(size, &error, &actual_size,
1239 local_commands);
1240 if (actual_size <= 0) {
1241 NDMP_LOG(LOG_DEBUG,
1242 "RESTORE WRITER> error %d, actual_size %d",
1243 error, actual_size);
1244
1245 /* no more data for this file for now */
1246 job_stats->js_bytes_in_file = 0;
1247
1248 return (size);
1249 } else if (error) {
1250 NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]",
1251 error, local_commands->tc_file_name);
1252 break;
1253 } else {
1254 write_size = min(size, actual_size);
1255 if (want_this_file) {
1256 write_size = write(*fp, rec, write_size);
1257 NS_ADD(wdisk, write_size);
1258 NS_INC(wfile);
1259 }
1260 size -= write_size;
1261 }
1262 }
1263
1264 /* no more data for this file for now */
1265 job_stats->js_bytes_in_file = 0;
1266
1267 /*
1268 * teardown
1269 */
1270 if (*fp != 0 && huge_size <= 0) {
1271 (void) close(*fp);
1272 *fp = 0;
1273 set_acl(real_name, acls);
1274 }
1275 return (0);
1276 }
1277
1278 /*
1279 * Set the extended attributes file attribute
1280 */
1281 static void
set_xattr(int fd,struct stat64 st)1282 set_xattr(int fd, struct stat64 st)
1283 {
1284 struct timeval times[2];
1285
1286 times[0].tv_sec = st.st_atime;
1287 times[1].tv_sec = st.st_mtime;
1288
1289 (void) fchmod(fd, st.st_mode);
1290 (void) fchown(fd, st.st_uid, st.st_gid);
1291 (void) futimesat(fd, ".", times);
1292 }
1293
1294 /*
1295 * Read the system attribute file in a single buffer to write
1296 * it as a single write. A partial write to system attribute would
1297 * cause an EINVAL on write.
1298 */
1299 static char *
get_read_one_buf(char * rec,int actual_size,int size,int * error,tlm_cmd_t * lc)1300 get_read_one_buf(char *rec, int actual_size, int size, int *error,
1301 tlm_cmd_t *lc)
1302 {
1303 char *buf, *p;
1304 int read_size;
1305 int len;
1306
1307 if (actual_size > size)
1308 return (rec);
1309
1310 buf = ndmp_malloc(size);
1311 if (buf == NULL) {
1312 *error = ENOMEM;
1313 return (NULL);
1314 }
1315 (void) memcpy(buf, rec, actual_size);
1316 rec = buf;
1317 buf += actual_size;
1318 while (actual_size < size) {
1319 p = get_read_buffer(size - actual_size, error, &read_size, lc);
1320 len = min(size - actual_size, read_size);
1321 (void) memcpy(buf, p, len);
1322 actual_size += len;
1323 buf += len;
1324 }
1325 return (rec);
1326 }
1327
1328
1329 /*
1330 * read the extended attribute header and write
1331 * it to the file
1332 */
1333 static long
restore_xattr_hdr(int * fp,char * name,char * fname,long size,tlm_acls_t * acls,tlm_cmd_t * local_commands,tlm_job_stats_t * job_stats)1334 restore_xattr_hdr(int *fp,
1335 char *name,
1336 char *fname,
1337 long size,
1338 tlm_acls_t *acls,
1339 tlm_cmd_t *local_commands,
1340 tlm_job_stats_t *job_stats)
1341 {
1342 tlm_tar_hdr_t *tar_hdr;
1343 struct xattr_hdr *xhdr;
1344 struct xattr_buf *xbuf;
1345 int namelen;
1346 char *xattrname;
1347 int actual_size;
1348 int error;
1349
1350 if (!fname) {
1351 NDMP_LOG(LOG_DEBUG, "No file name but wanted!");
1352 } else {
1353 NDMP_LOG(LOG_DEBUG, "new xattr[%s]", fname);
1354 }
1355
1356 error = 0;
1357 xhdr = (struct xattr_hdr *)get_read_buffer(size, &error,
1358 &actual_size, local_commands);
1359 if (xhdr == NULL || error != 0) {
1360 NDMP_LOG(LOG_DEBUG,
1361 "Could not read xattr [%s:%s] for restore. ",
1362 name, fname);
1363 job_stats->js_errors++;
1364 return (0);
1365 }
1366
1367 /* Check extended attribute header */
1368 if (strcmp(xhdr->h_version, XATTR_ARCH_VERS) != 0) {
1369 NDMP_LOG(LOG_DEBUG,
1370 "Unrecognized header format [%s]", xhdr->h_version);
1371 return (0);
1372 }
1373 xbuf = (struct xattr_buf *)(((char *)xhdr) + sizeof (struct xattr_hdr));
1374
1375 (void) sscanf(xbuf->h_namesz, "%7d", &namelen);
1376 xattrname = xbuf->h_names + strlen(xbuf->h_names) + 1;
1377
1378 if (*fp == 0) {
1379 int fd;
1380
1381 fd = attropen(name, xattrname, O_CREAT | O_RDWR, 0755);
1382 if (fd == -1) {
1383 NDMP_LOG(LOG_DEBUG,
1384 "Could not open xattr [%s:%s] for restore err=%d.",
1385 name, xattrname, errno);
1386 job_stats->js_errors++;
1387 return (0);
1388 }
1389 (void) strlcpy(local_commands->tc_file_name, xattrname,
1390 TLM_MAX_PATH_NAME);
1391 *fp = fd;
1392 }
1393
1394 /* Get the actual extended attribute file */
1395 tar_hdr = (tlm_tar_hdr_t *)get_read_buffer(sizeof (*tar_hdr),
1396 &error, &actual_size, local_commands);
1397 if (tar_hdr == NULL || error != 0) {
1398 NDMP_LOG(LOG_DEBUG,
1399 "Could not read xattr data [%s:%s] for restore. ",
1400 fname, xattrname);
1401 job_stats->js_errors++;
1402 return (0);
1403 }
1404 acls->acl_attr.st_mode = oct_atoi(tar_hdr->th_mode);
1405 acls->acl_attr.st_size = oct_atoi(tar_hdr->th_size);
1406 acls->acl_attr.st_uid = oct_atoi(tar_hdr->th_uid);
1407 acls->acl_attr.st_gid = oct_atoi(tar_hdr->th_gid);
1408 acls->acl_attr.st_mtime = oct_atoi(tar_hdr->th_mtime);
1409
1410 NDMP_LOG(LOG_DEBUG, "xattr_hdr: %s size %d mode %06o uid %d gid %d",
1411 xattrname, acls->acl_attr.st_size, acls->acl_attr.st_mode,
1412 acls->acl_attr.st_uid, acls->acl_attr.st_gid);
1413
1414 size = acls->acl_attr.st_size;
1415 while (size > 0 && local_commands->tc_writer == TLM_RESTORE_RUN) {
1416 char *rec;
1417 int write_size;
1418 int sysattr_write = 0;
1419
1420 error = 0;
1421 rec = get_read_buffer(size, &error, &actual_size,
1422 local_commands);
1423
1424 if ((actual_size < size) && sysattr_rw(xattrname)) {
1425 rec = get_read_one_buf(rec, actual_size, size, &error,
1426 local_commands);
1427 if (rec == NULL) {
1428 NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]",
1429 error, xattrname);
1430 return (size);
1431 }
1432 actual_size = size;
1433 sysattr_write = 1;
1434 }
1435 if (actual_size <= 0) {
1436 NDMP_LOG(LOG_DEBUG,
1437 "RESTORE WRITER> error %d, actual_size %d",
1438 error, actual_size);
1439
1440 return (size);
1441 } else if (error) {
1442 NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]",
1443 error, local_commands->tc_file_name);
1444 break;
1445 } else {
1446 write_size = min(size, actual_size);
1447 if ((write_size = write(*fp, rec, write_size)) < 0) {
1448 if (sysattr_write)
1449 free(rec);
1450
1451 break;
1452 }
1453
1454 NS_ADD(wdisk, write_size);
1455 NS_INC(wfile);
1456 size -= write_size;
1457 }
1458 if (sysattr_write)
1459 free(rec);
1460 }
1461
1462 if (*fp != 0) {
1463 set_xattr(*fp, acls->acl_attr);
1464 (void) close(*fp);
1465 *fp = 0;
1466 }
1467 return (0);
1468 }
1469
1470 /*
1471 * Match the name with the list
1472 */
1473 static int
exact_find(char * name,char ** list)1474 exact_find(char *name, char **list)
1475 {
1476 boolean_t found;
1477 int i;
1478 char *cp;
1479
1480 found = FALSE;
1481 for (i = 0; *list != NULL; list++, i++) {
1482 cp = *list + strspn(*list, "/");
1483 if (match(cp, name)) {
1484 found = TRUE;
1485 NDMP_LOG(LOG_DEBUG, "exact_find> found[%s]", cp);
1486 break;
1487 }
1488 }
1489
1490 return (found);
1491 }
1492
1493 /*
1494 * On error, return FALSE and prevent restoring(probably) unwanted data.
1495 */
1496 static int
is_parent(char * parent,char * child,int flags)1497 is_parent(char *parent, char *child, int flags)
1498 {
1499 char tmp[TLM_MAX_PATH_NAME];
1500 boolean_t rv;
1501
1502 if (IS_SET(flags, RSFLG_MATCH_WCARD)) {
1503 if (!tlm_cat_path(tmp, parent, "*")) {
1504 NDMP_LOG(LOG_DEBUG,
1505 "is_parent> path too long [%s]", parent);
1506 rv = FALSE;
1507 } else
1508 rv = (match(tmp, child) != 0) ? TRUE : FALSE;
1509 } else {
1510 if (!tlm_cat_path(tmp, parent, "/")) {
1511 NDMP_LOG(LOG_DEBUG,
1512 "is_parent> path too long [%s]", parent);
1513 rv = FALSE;
1514 } else
1515 rv = (strncmp(tmp, child, strlen(tmp)) == 0) ?
1516 TRUE : FALSE;
1517 }
1518
1519 return (rv);
1520 }
1521
1522 /*
1523 * Used to match the filename inside the list
1524 */
1525 static boolean_t
strexactcmp(char * s,char * t)1526 strexactcmp(char *s, char *t)
1527 {
1528 return ((strcmp(s, t) == 0) ? TRUE : FALSE);
1529 }
1530
1531 /*
1532 * Check if the file is needed to be restored
1533 */
1534 static boolean_t
is_file_wanted(char * name,char ** sels,char ** exls,int flags,int * mchtype,int * pos)1535 is_file_wanted(char *name,
1536 char **sels,
1537 char **exls,
1538 int flags,
1539 int *mchtype,
1540 int *pos)
1541 {
1542 char *p_sel;
1543 char *uc_name, *retry, *namep;
1544 boolean_t found;
1545 int i;
1546 name_match_fp_t *cmp_fp;
1547
1548 if (name == NULL || sels == NULL || exls == NULL)
1549 return (FALSE);
1550
1551 found = FALSE;
1552 if (mchtype != NULL)
1553 *mchtype = PM_NONE;
1554 if (pos != NULL)
1555 *pos = 0;
1556
1557 /*
1558 * For empty selection, restore everything
1559 */
1560 if (*sels == NULL || **sels == '\0') {
1561 NDMP_LOG(LOG_DEBUG, "is_file_wanted: Restore all");
1562 return (TRUE);
1563 }
1564
1565 retry = ndmp_malloc(TLM_MAX_PATH_NAME);
1566 if (retry == NULL)
1567 return (FALSE);
1568
1569 if (IS_SET(flags, RSFLG_MATCH_WCARD))
1570 cmp_fp = match;
1571 else
1572 cmp_fp = strexactcmp;
1573
1574 namep = name + strspn(name, "/");
1575
1576 if (IS_SET(flags, RSFLG_IGNORE_CASE)) {
1577 uc_name = ndmp_malloc(TLM_MAX_PATH_NAME);
1578 if (uc_name == NULL) {
1579 free(retry);
1580 return (FALSE);
1581 }
1582 (void) strlcpy(uc_name, namep, TLM_MAX_PATH_NAME);
1583 (void) strupr(uc_name);
1584 namep = uc_name;
1585 }
1586 NDMP_LOG(LOG_DEBUG, "is_file_wanted> flg: 0x%x name: [%s]",
1587 flags, name);
1588
1589 for (i = 0; *sels != NULL; sels++, i++) {
1590 p_sel = *sels + strspn(*sels, "/");
1591
1592 /*
1593 * Try exact match.
1594 */
1595 if ((*cmp_fp)(p_sel, namep)) {
1596 NDMP_LOG(LOG_DEBUG, "match1> pos: %d [%s][%s]",
1597 i, p_sel, name);
1598 found = TRUE;
1599 if (mchtype != NULL)
1600 *mchtype = PM_EXACT;
1601 break;
1602 }
1603 /*
1604 * Try "entry/" and the current selection. The
1605 * current selection may be something like "<something>/".
1606 */
1607 (void) tlm_cat_path(retry, namep, "/");
1608 if ((*cmp_fp)(p_sel, retry)) {
1609 NDMP_LOG(LOG_DEBUG, "match2> pos %d [%s][%s]",
1610 i, p_sel, name);
1611 found = TRUE;
1612 if (mchtype != NULL)
1613 *mchtype = PM_EXACT;
1614 break;
1615 }
1616 /*
1617 * If the following check returns true it means that the
1618 * 'name' is an entry below the 'p_sel' hierarchy.
1619 */
1620 if (is_parent(p_sel, namep, flags)) {
1621 NDMP_LOG(LOG_DEBUG, "parent1> pos %d [%s][%s]",
1622 i, p_sel, name);
1623 found = TRUE;
1624 if (mchtype != NULL)
1625 *mchtype = PM_CHILD;
1626 break;
1627 }
1628 /*
1629 * There is a special case for parent directories of a
1630 * selection. If 'p_sel' is something like "*d1", the
1631 * middle directories of the final entry can't be determined
1632 * until the final entry matches with 'p_sel'. At that
1633 * time the middle directories of the entry have been passed
1634 * and they can't be restored.
1635 */
1636 if (is_parent(namep, p_sel, flags)) {
1637 NDMP_LOG(LOG_DEBUG, "parent2> pos %d [%s][%s]",
1638 i, p_sel, name);
1639 found = TRUE;
1640 if (mchtype != NULL)
1641 *mchtype = PM_PARENT;
1642 break;
1643 }
1644 }
1645
1646 /* Check for exclusions. */
1647 if (found && exact_find(namep, exls)) {
1648 if (mchtype != NULL)
1649 *mchtype = PM_NONE;
1650 found = FALSE;
1651 }
1652 if (found && pos != NULL)
1653 *pos = i;
1654
1655 if (IS_SET(flags, RSFLG_IGNORE_CASE))
1656 free(uc_name);
1657 free(retry);
1658 return (found);
1659 }
1660
1661 /*
1662 * Read the specified amount data into the buffer. Detects EOT or EOF
1663 * during read.
1664 *
1665 * Returns the number of bytes actually read. On error returns -1.
1666 */
1667 static int
input_mem(int l,int d,tlm_cmd_t * lcmds,char * mem,int len)1668 input_mem(int l,
1669 int d,
1670 tlm_cmd_t *lcmds,
1671 char *mem,
1672 int len)
1673 {
1674 int err;
1675 int toread, actual_size, rec_size;
1676 char *rec;
1677
1678 if (l <= 0 || d <= 0 || !lcmds || !mem) {
1679 NDMP_LOG(LOG_DEBUG, "Invalid argument");
1680 return (-1);
1681 }
1682
1683 toread = len;
1684 while (toread > 0) {
1685 rec = get_read_buffer(toread, &err, &actual_size, lcmds);
1686 if (actual_size <= 0) {
1687 NDMP_LOG(LOG_DEBUG, "err %d act_size %d detected",
1688 err, actual_size);
1689 break;
1690 } else if (err) {
1691 NDMP_LOG(LOG_DEBUG, "error %d reading data", err);
1692 return (-1);
1693 }
1694 rec_size = min(actual_size, toread);
1695 (void) memcpy(mem, rec, rec_size);
1696 mem += rec_size;
1697 toread -= rec_size;
1698 }
1699
1700 return (len - toread);
1701 }
1702
1703 /*
1704 * pick up the name and size of a HUGE file
1705 */
1706 static int
get_humongus_file_header(int lib,int drv,long recsize,longlong_t * size,char * name,tlm_cmd_t * local_commands)1707 get_humongus_file_header(int lib,
1708 int drv,
1709 long recsize,
1710 longlong_t *size,
1711 char *name,
1712 tlm_cmd_t *local_commands)
1713 {
1714 char *p_record, *value;
1715 int rv;
1716
1717 NDMP_LOG(LOG_DEBUG, "HUGE Record found: %d", recsize);
1718
1719 rv = 0;
1720 if (recsize == 0) {
1721 /*
1722 * The humongus_file_header was written in a
1723 * RECORDSIZE block and the header.size field of this
1724 * record was 0 before this fix. For backward compatiblity
1725 * read only one RECORDSIZE-size block if the header.size
1726 * field is 0. Otherwise the header.size field should show
1727 * the length of the data of this header.
1728 */
1729 NDMP_LOG(LOG_DEBUG, "Old HUGE record found");
1730 recsize = RECORDSIZE;
1731 }
1732
1733 if (input_mem(lib, drv, local_commands, name, recsize) != recsize) {
1734 rv = -1;
1735 *size = 0;
1736 *name = '\0';
1737 NDMP_LOG(LOG_DEBUG, "Error reading a HUGE file name");
1738 } else {
1739 NDMP_LOG(LOG_DEBUG, "HUGE [%s]", name);
1740
1741 p_record = name;
1742 value = parse(&p_record, " ");
1743 *size = atoll(value);
1744 /*
1745 * Note: Since the backed up names are not longer than
1746 * NAME_MAX and the buffer passed to us is
1747 * TLM_MAX_PATH_NAME, it should be safe to use strlcpy
1748 * without check on the buffer size.
1749 */
1750 (void) strlcpy(name, p_record, TLM_MAX_PATH_NAME);
1751 }
1752
1753 NDMP_LOG(LOG_DEBUG, "HUGE Record %lld [%s]", *size, name);
1754
1755 return (rv);
1756 }
1757
1758 /*
1759 * pick up the long name from the special tape file
1760 */
1761 static int
get_long_name(int lib,int drv,long recsize,char * name,long * buf_spot,tlm_cmd_t * local_commands)1762 get_long_name(int lib,
1763 int drv,
1764 long recsize,
1765 char *name,
1766 long *buf_spot,
1767 tlm_cmd_t *local_commands)
1768 {
1769 int nread;
1770
1771 NDMP_LOG(LOG_DEBUG, "LONGNAME Record found rs %d bs %d", recsize,
1772 *buf_spot);
1773
1774 if (*buf_spot < 0)
1775 *buf_spot = 0;
1776
1777 nread = input_mem(lib, drv, local_commands, name + *buf_spot,
1778 recsize);
1779 if (nread < 0) {
1780 nread = recsize; /* return 0 as size left */
1781 name[*buf_spot] = '\0';
1782 NDMP_LOG(LOG_ERR, "Error %d reading a long file name %s.",
1783 nread, name);
1784 } else {
1785 *buf_spot += nread;
1786 name[*buf_spot] = '\0';
1787 NDMP_LOG(LOG_DEBUG, "LONGNAME [%s]", name);
1788 }
1789
1790 return (recsize - nread);
1791 }
1792
1793 /*
1794 * create a new directory
1795 */
1796 static int
create_directory(char * dir,tlm_job_stats_t * job_stats)1797 create_directory(char *dir, tlm_job_stats_t *job_stats)
1798 {
1799 struct stat64 attr;
1800 char *p;
1801 char temp;
1802 int erc;
1803
1804 /*
1805 * Make sure all directories in this path exist, create them if
1806 * needed.
1807 */
1808 NDMP_LOG(LOG_DEBUG, "new dir[%s]", dir);
1809
1810 erc = 0;
1811 p = &dir[1];
1812 do {
1813 temp = *p;
1814 if (temp == '/' || temp == 0) {
1815 *p = 0;
1816 if (stat64(dir, &attr) < 0) {
1817 erc = mkdir(dir, 0777);
1818 if (erc < 0) {
1819 job_stats->js_errors++;
1820 NDMP_LOG(LOG_DEBUG,
1821 "Could not create directory %s",
1822 dir);
1823 break;
1824 }
1825 }
1826 *p = temp;
1827 }
1828 p++;
1829 } while (temp != 0);
1830
1831 return (erc);
1832 }
1833
1834 /*
1835 * create a new hardlink
1836 */
1837 static int
create_hard_link(char * name_old,char * name_new,tlm_acls_t * acls,tlm_job_stats_t * job_stats)1838 create_hard_link(char *name_old, char *name_new,
1839 tlm_acls_t *acls, tlm_job_stats_t *job_stats)
1840 {
1841 int erc;
1842
1843 if (mkbasedir(name_new)) {
1844 NDMP_LOG(LOG_DEBUG, "faile to make base dir for [%s]",
1845 name_new);
1846
1847 return (-1);
1848 }
1849
1850 erc = link(name_old, name_new);
1851
1852 /* Nothing to do if the destination already exists */
1853 if (erc && (errno == EEXIST))
1854 return (0);
1855
1856 if (erc) {
1857 job_stats->js_errors++;
1858 NDMP_LOG(LOG_DEBUG, "error %d (errno %d) hardlink [%s] to [%s]",
1859 erc, errno, name_new, name_old);
1860 } else {
1861 set_acl(name_new, acls);
1862 }
1863 return (erc);
1864 }
1865
1866 /*
1867 * create a new symlink
1868 */
1869 /*ARGSUSED*/
1870 static int
create_sym_link(char * dst,char * target,tlm_acls_t * acls,tlm_job_stats_t * job_stats)1871 create_sym_link(char *dst, char *target, tlm_acls_t *acls,
1872 tlm_job_stats_t *job_stats)
1873 {
1874 int erc;
1875 struct stat64 *st;
1876
1877 if (mkbasedir(dst) < 0)
1878 return (-1);
1879
1880 st = &acls->acl_attr;
1881 erc = symlink(target, dst);
1882 if (erc) {
1883 job_stats->js_errors++;
1884 NDMP_LOG(LOG_DEBUG, "error %d (errno %d) softlink [%s] to [%s]",
1885 erc, errno, dst, target);
1886 } else {
1887 st->st_mode |= S_IFLNK;
1888 set_acl(dst, acls);
1889 }
1890
1891 return (erc);
1892 }
1893
1894 /*
1895 * create a new FIFO, char/block device special files
1896 */
1897 static int
create_special(char flag,char * name,tlm_acls_t * acls,int major,int minor,tlm_job_stats_t * job_stats)1898 create_special(char flag, char *name, tlm_acls_t *acls, int major, int minor,
1899 tlm_job_stats_t *job_stats)
1900 {
1901 dev_t dev;
1902 mode_t mode;
1903 int erc;
1904
1905 switch (flag) {
1906 case LF_CHR:
1907 mode = S_IFCHR;
1908 dev = makedev(major, minor);
1909 break;
1910 case LF_BLK:
1911 mode = S_IFBLK;
1912 dev = makedev(major, minor);
1913 break;
1914 case LF_FIFO:
1915 mode = S_IFIFO;
1916 dev = 0;
1917 break;
1918 default:
1919 NDMP_LOG(LOG_ERR, "unsupported flag %d", flag);
1920 return (-1);
1921 }
1922
1923 /* Remove the old entry first */
1924 if (rmdir(name) < 0) {
1925 if (errno == ENOTDIR)
1926 (void) unlink(name);
1927 }
1928 erc = mknod(name, 0777 | mode, dev);
1929 if (erc) {
1930 job_stats->js_errors++;
1931 NDMP_LOG(LOG_DEBUG, "error %d (errno %d) mknod [%s] major"
1932 " %d minor %d", erc, errno, name, major, minor);
1933 } else {
1934 set_acl(name, acls);
1935 }
1936 return (erc);
1937 }
1938
1939 /*
1940 * read in the ACLs for the next file
1941 */
1942 static long
load_acl_info(int lib,int drv,long file_size,tlm_acls_t * acls,long * acl_spot,tlm_cmd_t * local_commands)1943 load_acl_info(int lib,
1944 int drv,
1945 long file_size,
1946 tlm_acls_t *acls,
1947 long *acl_spot,
1948 tlm_cmd_t *local_commands)
1949 {
1950 char *bp;
1951 int nread;
1952
1953 /*
1954 * If the ACL is spanned on tapes, then the acl_spot should NOT be
1955 * 0 on next calls to this function to read the rest of the ACL
1956 * on next tapes.
1957 */
1958 if (*acl_spot == 0) {
1959 (void) memset(acls, 0, sizeof (tlm_acls_t));
1960 }
1961
1962 bp = ((char *)&acls->acl_info) + *acl_spot;
1963 nread = input_mem(lib, drv, local_commands, (void *)bp, file_size);
1964 if (nread < 0) {
1965 *acl_spot = 0;
1966 (void) memset(acls, 0, sizeof (tlm_acls_t));
1967 NDMP_LOG(LOG_DEBUG, "Error reading ACL data");
1968 return (0);
1969 }
1970 *acl_spot += nread;
1971 acls->acl_non_trivial = TRUE;
1972
1973 return (file_size - nread);
1974 }
1975
1976 static int
ndmp_set_eprivs_least(void)1977 ndmp_set_eprivs_least(void)
1978 {
1979 priv_set_t *priv_set;
1980
1981 if ((priv_set = priv_allocset()) == NULL) {
1982 NDMP_LOG(LOG_ERR, "Out of memory.");
1983 return (-1);
1984 }
1985
1986 priv_basicset(priv_set);
1987
1988 (void) priv_addset(priv_set, PRIV_PROC_AUDIT);
1989 (void) priv_addset(priv_set, PRIV_PROC_SETID);
1990 (void) priv_addset(priv_set, PRIV_PROC_OWNER);
1991 (void) priv_addset(priv_set, PRIV_FILE_CHOWN);
1992 (void) priv_addset(priv_set, PRIV_FILE_CHOWN_SELF);
1993 (void) priv_addset(priv_set, PRIV_FILE_DAC_READ);
1994 (void) priv_addset(priv_set, PRIV_FILE_DAC_SEARCH);
1995 (void) priv_addset(priv_set, PRIV_FILE_DAC_WRITE);
1996 (void) priv_addset(priv_set, PRIV_FILE_OWNER);
1997 (void) priv_addset(priv_set, PRIV_FILE_SETID);
1998 (void) priv_addset(priv_set, PRIV_SYS_LINKDIR);
1999 (void) priv_addset(priv_set, PRIV_SYS_DEVICES);
2000 (void) priv_addset(priv_set, PRIV_SYS_MOUNT);
2001 (void) priv_addset(priv_set, PRIV_SYS_CONFIG);
2002
2003 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) {
2004 NDMP_LOG(LOG_ERR, "Additional privileges required.");
2005 priv_freeset(priv_set);
2006 return (-1);
2007 }
2008 priv_freeset(priv_set);
2009 return (0);
2010 }
2011
2012 static int
ndmp_set_eprivs_all(void)2013 ndmp_set_eprivs_all(void)
2014 {
2015 priv_set_t *priv_set;
2016
2017 if ((priv_set = priv_allocset()) == NULL) {
2018 NDMP_LOG(LOG_ERR, "Out of memory.");
2019 return (-1);
2020 }
2021
2022 priv_fillset(priv_set);
2023
2024 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) != 0) {
2025 NDMP_LOG(LOG_ERR, "Additional privileges required.");
2026 return (-1);
2027 }
2028 priv_freeset(priv_set);
2029 return (0);
2030 }
2031
2032 /*
2033 * Set the standard attributes of the file
2034 */
2035 static void
set_attr(char * name,tlm_acls_t * acls)2036 set_attr(char *name, tlm_acls_t *acls)
2037 {
2038 struct utimbuf tbuf;
2039 boolean_t priv_all = FALSE;
2040 struct stat64 *st;
2041 uid_t uid;
2042 gid_t gid;
2043 struct passwd *pwd;
2044 struct group *grp;
2045
2046
2047 if (!name || !acls)
2048 return;
2049
2050 st = &acls->acl_attr;
2051 NDMP_LOG(LOG_DEBUG, "set_attr: %s uid %d gid %d uname %s gname %s "
2052 "mode %o", name, st->st_uid, st->st_gid, acls->uname, acls->gname,
2053 st->st_mode);
2054
2055 uid = st->st_uid;
2056 if ((pwd = getpwnam(acls->uname)) != NULL) {
2057 NDMP_LOG(LOG_DEBUG, "set_attr: new uid %d old %d",
2058 pwd->pw_uid, uid);
2059 uid = pwd->pw_uid;
2060 }
2061
2062 gid = st->st_gid;
2063 if ((grp = getgrnam(acls->gname)) != NULL) {
2064 NDMP_LOG(LOG_DEBUG, "set_attr: new gid %d old %d",
2065 grp->gr_gid, gid);
2066 gid = grp->gr_gid;
2067 }
2068
2069 if (lchown(name, uid, gid))
2070 NDMP_LOG(LOG_ERR,
2071 "Could not set uid or/and gid for file %s.", name);
2072
2073 if ((st->st_mode & (S_ISUID | S_ISGID)) != 0) {
2074 /*
2075 * Change effective privileges to 'all' which is required to
2076 * change setuid bit for 'root' owned files. If fails, just
2077 * send error to log file and proceed.
2078 */
2079 if (ndmp_set_eprivs_all()) {
2080 NDMP_LOG(LOG_ERR,
2081 "Could not set effective privileges to 'all'.");
2082 } else {
2083 priv_all = TRUE;
2084 }
2085 }
2086
2087 if (!S_ISLNK(st->st_mode)) {
2088 if (chmod(name, st->st_mode))
2089 NDMP_LOG(LOG_ERR, "Could not set correct file"
2090 " permission for file %s.", name);
2091
2092 tbuf.modtime = st->st_mtime;
2093 tbuf.actime = st->st_atime;
2094 (void) utime(name, &tbuf);
2095 }
2096
2097 if (priv_all == TRUE) {
2098 /*
2099 * Give up the 'all' privileges for effective sets and go back
2100 * to least required privileges. If fails, just send error to
2101 * log file and proceed.
2102 */
2103 if (ndmp_set_eprivs_least())
2104 NDMP_LOG(LOG_ERR,
2105 "Could not set least required privileges.");
2106 }
2107 }
2108
2109 /*
2110 * Set the ACL info for the file
2111 */
2112 static void
set_acl(char * name,tlm_acls_t * acls)2113 set_acl(char *name, tlm_acls_t *acls)
2114 {
2115 int erc;
2116 acl_t *aclp = NULL;
2117
2118 if (name)
2119 NDMP_LOG(LOG_DEBUG, "set_acl: %s", name);
2120 if (acls != 0) {
2121 /* Need a place to save real modification time */
2122
2123 set_attr(name, acls);
2124
2125 if (!acls->acl_non_trivial) {
2126 (void) memset(acls, 0, sizeof (tlm_acls_t));
2127 NDMP_LOG(LOG_DEBUG, "set_acl: skipping trivial");
2128 return;
2129 }
2130
2131 erc = acl_fromtext(acls->acl_info.attr_info, &aclp);
2132 if (erc != 0) {
2133 NDMP_LOG(LOG_DEBUG,
2134 "TAPE RESTORE> acl_fromtext errno %d", erc);
2135 }
2136 if (aclp) {
2137 erc = acl_set(name, aclp);
2138 if (erc < 0) {
2139 NDMP_LOG(LOG_DEBUG,
2140 "TAPE RESTORE> acl_set errno %d", errno);
2141 }
2142 acl_free(aclp);
2143 }
2144 (void) memset(acls, 0, sizeof (tlm_acls_t));
2145 }
2146 }
2147
2148 /*
2149 * a wrapper to tlm_get_read_buffer so that
2150 * we can cleanly detect ABORT commands
2151 * without involving the TLM library with
2152 * our problems.
2153 */
2154 static char *
get_read_buffer(int want,int * error,int * actual_size,tlm_cmd_t * local_commands)2155 get_read_buffer(int want,
2156 int *error,
2157 int *actual_size,
2158 tlm_cmd_t *local_commands)
2159 {
2160 while (local_commands->tc_writer == TLM_RESTORE_RUN) {
2161 char *rec;
2162 rec = tlm_get_read_buffer(want, error,
2163 local_commands->tc_buffers, actual_size);
2164 if (rec != 0) {
2165 return (rec);
2166 }
2167 }
2168
2169 /*
2170 * the job is ending, give Writer a buffer that will never be read ...
2171 * it does not matter anyhow, we are aborting.
2172 */
2173 *actual_size = RECORDSIZE;
2174 return (NULL);
2175 }
2176
2177 /*
2178 * Enable wildcard for restore options
2179 */
2180 static boolean_t
wildcard_enabled(void)2181 wildcard_enabled(void)
2182 {
2183 char *cp;
2184
2185 cp = ndmpd_get_prop_default(NDMP_RESTORE_WILDCARD_ENABLE, "n");
2186 return ((toupper(*cp) == 'Y') ? TRUE : FALSE);
2187 }
2188
2189
2190 /*
2191 * Concatenate two names
2192 */
2193 /*ARGSUSED*/
2194 static char *
catnames(struct rs_name_maker * rnp,char * buf,int pos,char * path)2195 catnames(struct rs_name_maker *rnp, char *buf, int pos, char *path)
2196 {
2197 char *rv;
2198
2199 rv = NULL;
2200 if (!buf) {
2201 NDMP_LOG(LOG_DEBUG, "buf is NULL");
2202 } else if (!path) {
2203 NDMP_LOG(LOG_DEBUG, "path is NULL");
2204 } else if (!rnp->rn_nlp) {
2205 NDMP_LOG(LOG_DEBUG, "rn_nlp is NULL [%s]", path);
2206 } else if (!tlm_cat_path(buf, rnp->rn_nlp, path)) {
2207 NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]",
2208 rnp->rn_nlp, path);
2209 } else
2210 rv = buf;
2211
2212 return (rv);
2213 }
2214
2215
2216 /*
2217 * Create a new name path for restore
2218 */
2219 static char *
rs_new_name(struct rs_name_maker * rnp,char * buf,int pos,char * path)2220 rs_new_name(struct rs_name_maker *rnp, char *buf, int pos, char *path)
2221 {
2222 if (!rnp || !rnp->rn_fp)
2223 return (NULL);
2224
2225 return (*rnp->rn_fp)(rnp, buf, pos, path);
2226 }
2227
2228 /*
2229 * Clear the extra "/" in the tar header if exists
2230 */
2231 static void
rs_create_new_bkpath(char * bk_path,char * path,char * pbuf)2232 rs_create_new_bkpath(char *bk_path, char *path, char *pbuf)
2233 {
2234 char *p, *slashp;
2235
2236 if ((p = strstr(path, bk_path)) == NULL) {
2237 (void) strlcpy(pbuf, path, TLM_MAX_PATH_NAME);
2238 return;
2239 }
2240 if (*(p += strlen(bk_path)) == '/')
2241 p++;
2242
2243 slashp = bk_path + strlen(bk_path) - 1;
2244 if (*slashp == '/')
2245 (void) snprintf(pbuf, TLM_MAX_PATH_NAME, "%s%s", bk_path, p);
2246 else
2247 (void) snprintf(pbuf, TLM_MAX_PATH_NAME, "%s/%s", bk_path, p);
2248
2249 NDMP_LOG(LOG_DEBUG, "old path [%s] new path [%s]", path, pbuf);
2250 }
2251
2252
2253 /*
2254 * Iterate over ZFS metadata stored in the backup stream and use the callback
2255 * to restore it.
2256 */
2257 int
ndmp_iter_zfs(ndmp_context_t * nctx,int (* np_restore_property)(nvlist_t *,void *),void * ptr)2258 ndmp_iter_zfs(ndmp_context_t *nctx, int (*np_restore_property)(nvlist_t *,
2259 void *), void *ptr)
2260 {
2261 tlm_commands_t *cmds;
2262 ndmp_metadata_header_t *mhp;
2263 ndmp_metadata_header_ext_t *mhpx;
2264 ndmp_metadata_property_t *mpp;
2265 ndmp_metadata_property_ext_t *mppx;
2266 tlm_cmd_t *lcmd;
2267 int actual_size;
2268 nvlist_t *nvl;
2269 nvlist_t *valp;
2270 nvpair_t *nvp = NULL;
2271 char plname[100];
2272 char *mhbuf, *pp, *tp;
2273 int rv, i;
2274 int size, lsize, sz;
2275 int align = RECORDSIZE - 1;
2276
2277 if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL)
2278 return (-1);
2279
2280 nctx->nc_plname = plname;
2281 if ((lcmd = cmds->tcs_command) == NULL ||
2282 lcmd->tc_buffers == NULL)
2283 return (-1);
2284
2285 /* Default minimum bytes needed */
2286 size = sizeof (ndmp_metadata_header_t) +
2287 ZFS_MAX_PROPS * sizeof (ndmp_metadata_property_t);
2288 size += align;
2289 size &= ~align;
2290
2291 if ((mhbuf = malloc(size)) == NULL)
2292 return (-1);
2293
2294 /* LINTED improper alignment */
2295 while ((mhp = (ndmp_metadata_header_t *)get_read_buffer(size, &rv,
2296 &actual_size, lcmd)) != NULL) {
2297 pp = mhbuf;
2298
2299 if (strncmp(mhp->nh_magic, ZFS_META_MAGIC,
2300 sizeof (mhp->nh_magic)) != 0 &&
2301 strncmp(mhp->nh_magic, ZFS_META_MAGIC_EXT,
2302 sizeof (mhp->nh_magic)) != 0) {
2303 /* No more metadata */
2304 tlm_unget_read_buffer(lcmd->tc_buffers, actual_size);
2305 free(mhbuf);
2306 return (0);
2307 }
2308
2309 if (strncmp(mhp->nh_magic, ZFS_META_MAGIC_EXT,
2310 sizeof (mhp->nh_magic)) == 0) {
2311 mhpx = (ndmp_metadata_header_ext_t *)mhp;
2312 if (mhpx->nh_total_bytes > size) {
2313 if ((pp = realloc(mhbuf, mhpx->nh_total_bytes))
2314 == NULL) {
2315 free(mhbuf);
2316 return (-1);
2317 }
2318 mhbuf = pp;
2319 }
2320 size = mhpx->nh_total_bytes;
2321 }
2322
2323 (void) memcpy(pp, (char *)mhp, (actual_size < size) ?
2324 actual_size : size);
2325 pp += (actual_size < size) ? actual_size : size;
2326
2327 sz = actual_size;
2328 while (sz < size &&
2329 ((tp = get_read_buffer(size - sz, &rv, &lsize,
2330 lcmd))) != NULL) {
2331 (void) memcpy(pp, tp, lsize);
2332 sz += lsize;
2333 pp += lsize;
2334 }
2335 if (sz > size) {
2336 tlm_unget_read_buffer(lcmd->tc_buffers, sz - size);
2337 }
2338
2339 /* LINTED improper alignment */
2340 mhp = (ndmp_metadata_header_t *)mhbuf;
2341
2342 nvl = NULL;
2343 if (strncmp(mhp->nh_magic, ZFS_META_MAGIC_EXT,
2344 sizeof (mhp->nh_magic)) == 0) {
2345 /* New metadata format */
2346 /* LINTED improper alignment */
2347 mhpx = (ndmp_metadata_header_ext_t *)mhbuf;
2348
2349 if (mhpx->nh_major > META_HDR_MAJOR_VERSION) {
2350 /* Major header mismatch */
2351 NDMP_LOG(LOG_ERR, "metadata header mismatch",
2352 "M%d != M%d", mhpx->nh_major,
2353 META_HDR_MAJOR_VERSION);
2354 free(mhbuf);
2355 return (-1);
2356 }
2357 if (mhpx->nh_major == META_HDR_MAJOR_VERSION &&
2358 mhpx->nh_minor > META_HDR_MINOR_VERSION) {
2359 /* Minor header mismatch */
2360 NDMP_LOG(LOG_ERR, "Warning:"
2361 "metadata header mismatch m%d != m%d",
2362 mhpx->nh_minor,
2363 META_HDR_MINOR_VERSION);
2364 continue;
2365 }
2366
2367 nctx->nc_plversion = mhpx->nh_plversion;
2368 (void) strlcpy(plname, mhpx->nh_plname,
2369 sizeof (plname));
2370
2371 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
2372 goto nvlist_err;
2373
2374 mppx = &mhpx->nh_property[0];
2375 for (i = 0; i < mhpx->nh_count && mppx; i++, mppx++) {
2376 if (!*mppx->mp_name)
2377 continue;
2378 valp = NULL;
2379 if (nvlist_alloc(&valp,
2380 NV_UNIQUE_NAME, 0) != 0 ||
2381 nvlist_add_string(valp, "value",
2382 mppx->mp_value) != 0 ||
2383 nvlist_add_string(valp, "source",
2384 mppx->mp_source) != 0 ||
2385 nvlist_add_nvlist(nvl, mppx->mp_name,
2386 valp) != 0) {
2387 nvlist_free(valp);
2388 goto nvlist_err;
2389 }
2390 nvlist_free(valp);
2391 }
2392 } else {
2393 nctx->nc_plversion = mhp->nh_plversion;
2394 (void) strlcpy(plname, mhp->nh_plname,
2395 sizeof (plname));
2396
2397 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
2398 goto nvlist_err;
2399
2400 mpp = &mhp->nh_property[0];
2401 for (i = 0; i < mhp->nh_count && mpp; i++, mpp++) {
2402 if (!*mpp->mp_name)
2403 continue;
2404 valp = NULL;
2405 if (nvlist_alloc(&valp,
2406 NV_UNIQUE_NAME, 0) != 0 ||
2407 nvlist_add_string(valp, "value",
2408 mpp->mp_value) != 0 ||
2409 nvlist_add_string(valp, "source",
2410 mpp->mp_source) != 0 ||
2411 nvlist_add_nvlist(nvl, mpp->mp_name,
2412 valp) != 0) {
2413 nvlist_free(valp);
2414 goto nvlist_err;
2415 }
2416 nvlist_free(valp);
2417 }
2418 }
2419
2420 if (np_restore_property(nvl, ptr) != 0)
2421 goto nvlist_err;
2422
2423 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL &&
2424 nvpair_value_nvlist(nvp, &valp) == 0) {
2425 nvlist_free(valp);
2426 }
2427 nvlist_free(nvl);
2428 }
2429
2430 free(mhbuf);
2431 return (0);
2432
2433 nvlist_err:
2434 free(mhbuf);
2435
2436 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL &&
2437 nvpair_value_nvlist(nvp, &valp) == 0) {
2438 nvlist_free(valp);
2439 }
2440 nvlist_free(nvl);
2441 return (-1);
2442 }
2443
2444 /*
2445 * Returns the version number of the plugin which created the metadata
2446 */
2447 uint_t
ndmp_context_get_version(ndmp_context_t * nctx)2448 ndmp_context_get_version(ndmp_context_t *nctx)
2449 {
2450 tlm_commands_t *cmds;
2451 ndmp_metadata_header_t *mhp;
2452 tlm_cmd_t *lcmd;
2453 int actual_size;
2454 int rv;
2455 int size;
2456 int align = RECORDSIZE - 1;
2457
2458 if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL)
2459 return (0);
2460
2461 if ((lcmd = cmds->tcs_command) == NULL ||
2462 lcmd->tc_buffers == NULL)
2463 return (0);
2464
2465 size = sizeof (ndmp_metadata_header_t);
2466 size += align;
2467 size &= ~align;
2468
2469 /* LINTED improper alignment */
2470 if ((mhp = (ndmp_metadata_header_t *)get_read_buffer(size, &rv,
2471 &actual_size, lcmd)) != NULL) {
2472 if (strncmp(mhp->nh_magic, ZFS_META_MAGIC,
2473 sizeof (mhp->nh_magic)) != 0) {
2474 /* No more metadata */
2475 tlm_unget_read_buffer(lcmd->tc_buffers, actual_size);
2476 return (0);
2477 }
2478
2479 nctx->nc_plversion = mhp->nh_plversion;
2480 tlm_unget_read_buffer(lcmd->tc_buffers, actual_size);
2481 }
2482
2483 return (nctx->nc_plversion);
2484 }
2485