2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
9 * Copyright (c) 2007, The Storage Networking Industry Association.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * - Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
22 * - Neither the name of The Storage Networking Industry Association (SNIA)
23 * nor the names of its contributors may be used to endorse or promote
24 * products derived from this software without specific prior written
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
45 #include <sys/types.h>
47 #include <sys/mkdev.h>
57 #include <ndmpd_prop.h>
58 #include "tlm_proto.h"
61 #define PM_EXACT_OR_CHILD(m) ((m) == PM_EXACT || (m) == PM_CHILD)
62 #define ERROR_IS_FATAL(err) ((err) == ENOSPC || (err) == EDQUOT)
64 typedef boolean_t
name_match_fp_t(char *s
, char *t
);
66 static int set_acl(char *name
, tlm_acls_t
*acls
);
67 static int restore_file(int *fp
,
72 boolean_t want_this_file
,
76 static long restore_xattr_hdr(int *fp
,
81 tlm_cmd_t
*local_commands
,
82 tlm_job_stats_t
*job_stats
);
83 static int get_long_name(int lib
,
88 tlm_cmd_t
*local_commands
);
89 static int get_humongus_file_header(int lib
,
95 static int create_directory(char *dir
,
97 static int create_hard_link(char *name
,
101 static int create_sym_link(char *dst
,
105 static int create_special(char,
111 static long load_acl_info(int lib
,
117 static char *get_read_buffer(int want
,
121 static boolean_t
wildcard_enabled(void);
122 static boolean_t
is_file_wanted(char *name
,
128 static char *catnames(struct rs_name_maker
*rnp
,
133 static char *rs_new_name(struct rs_name_maker
*rnp
,
138 static void rs_create_new_bkpath(char *bk_path
,
142 typedef struct stack_ent
{
152 dtree_push(cstack_t
*stp
, char *nmp
, tlm_acls_t
*acls
)
157 sp
= ndmp_malloc(sizeof (stack_ent_t
));
158 if (!sp
|| !nmp
|| !acls
) {
163 len
= strlen(nmp
) + 1;
164 sp
->se_name
= ndmp_malloc(len
);
170 (void) strlcpy(sp
->se_name
, nmp
, len
);
171 (void) memcpy(&sp
->se_acls
, acls
, sizeof (*acls
));
172 (void) memset(acls
, 0, sizeof (tlm_acls_t
));
174 return (cstack_push(stp
, (void *)sp
, sizeof (*sp
)));
181 dtree_pop(cstack_t
*stp
)
186 err
= cstack_pop(stp
, (void **)&sp
, NULL
);
190 err
= set_acl(sp
->se_name
, &sp
->se_acls
);
202 dtree_peek(cstack_t
*stp
)
207 err
= cstack_top(stp
, (void **)&sp
, NULL
);
211 return (sp
->se_name
);
215 * NBU and EBS may not send us the correct file list containing hardlinks
216 * during a DAR restore, e.g. they appear always send the first name
217 * associated with an inode, even if other link names were
218 * selected for the restore. As a workaround, we use the file name entry
219 * in sels[] (ignore the name in the tar header) as restore target.
222 rs_darhl_new_name(struct rs_name_maker
*rnp
, char *name
, char **sels
, int *pos
,
227 for (x
= 0; sels
[x
] != NULL
; x
++) {
228 if (strcmp(sels
[x
], " ")) {
230 (void) strlcpy(longname
, sels
[x
], TLM_MAX_PATH_NAME
);
232 "to replace hardlink name [%s], pos [%d]",
235 return (rs_new_name(rnp
, name
, *pos
, longname
));
244 * Main dir restore function for tar
246 * If this function returns non-zero return value it means that fatal error
250 tar_getdir(tlm_commands_t
*commands
,
251 tlm_cmd_t
*local_commands
,
252 tlm_job_stats_t
*job_stats
,
253 struct rs_name_maker
*rnp
,
256 char **sels
, /* what to get off the tape */
257 char **exls
, /* what to leave behind */
261 struct hardlink_q
*hardlink_q
)
263 int fp
= 0; /* file being restored ... */
264 /* ...need to preserve across volume changes */
265 tlm_acls_t
*acls
; /* file access info */
267 boolean_t is_long_name
= FALSE
;
270 longlong_t huge_size
= 0; /* size of a HUGE file */
271 long acl_spot
; /* any ACL info on the next volume */
272 long file_size
; /* size of file to restore */
273 long size_left
= 0; /* need this after volume change */
274 int last_action
= 0; /* what we are doing at EOT */
275 boolean_t multi_volume
= FALSE
; /* is this a multi-volume switch ? */
276 int chk_rv
; /* scratch area */
280 * if an exact match is found for
281 * restore and its position in the
284 int nzerohdr
; /* the number of empty tar headers */
286 long nm_end
, lnk_end
;
294 * The directory where temporary files may be created during a partial
295 * non-DAR restore of hardlinks. It is intended to be initialized by
296 * an environment variable that can be set by user.
298 * It is not initialized for now. We keep it here for future use.
300 char *tmplink_dir
= NULL
;
301 int dar_recovered
= 0;
308 longname
= ndmp_malloc(TLM_MAX_PATH_NAME
);
309 longlink
= ndmp_malloc(TLM_MAX_PATH_NAME
);
310 hugename
= ndmp_malloc(TLM_MAX_PATH_NAME
);
311 parentlnk
= ndmp_malloc(TLM_MAX_PATH_NAME
);
312 thname_buf
= ndmp_malloc(TLM_MAX_PATH_NAME
);
313 name
= ndmp_malloc(TLM_MAX_PATH_NAME
);
314 acls
= ndmp_malloc(sizeof (tlm_acls_t
));
316 if (longname
== NULL
|| longlink
== NULL
|| hugename
== NULL
||
317 name
== NULL
|| acls
== NULL
|| stp
== NULL
|| parentlnk
== NULL
||
318 thname_buf
== NULL
) {
327 return (-TLM_NO_SCRATCH_SPACE
);
337 (void) memset(acls
, 0, sizeof (tlm_acls_t
));
338 if (IS_SET(flags
, RSFLG_OVR_ALWAYS
)) {
339 acls
->acl_overwrite
= TRUE
;
340 NDMP_LOG(LOG_DEBUG
, "RSFLG_OVR_ALWAYS");
341 } else if (IS_SET(flags
, RSFLG_OVR_UPDATE
)) {
342 acls
->acl_update
= TRUE
;
343 NDMP_LOG(LOG_DEBUG
, "RSFLG_OVR_UPDATE");
351 while (commands
->tcs_writer
!= TLM_ABORT
&&
352 local_commands
->tc_writer
!= TLM_STOP
&& rv
== 0) {
353 tlm_tar_hdr_t fake_tar_hdr
;
358 boolean_t want_this_file
;
359 int want
= sizeof (tlm_tar_hdr_t
);
360 tlm_tar_hdr_t
*tar_hdr
;
362 /* The inode of an LF_LINK type. */
363 unsigned long hardlink_inode
= 0;
366 * Indicate whether a file with the same inode has been
369 int hardlink_done
= 0;
371 /* The path of the restored hardlink file */
372 char *hardlink_target
= NULL
;
376 * Whether a temporary file should be created for restoring
379 int hardlink_tmp_file
= 0;
380 char *hardlink_tmp_name
= ".tmphlrsnondar";
382 /* used to make up hardlink_tmp_name */
383 static int hardlink_tmp_idx
= 0;
386 NDMP_LOG(LOG_DEBUG
, "multi_volume %c %d",
387 last_action
, size_left
);
390 * the previous volume is out of data
391 * and is back in the rack, a new tape
392 * is loaded and ready to read.
394 * We need to pick up where we left off.
396 (void) memset(&fake_tar_hdr
, 0, sizeof (fake_tar_hdr
));
397 file_size
= size_left
;
398 tar_hdr
= &fake_tar_hdr
;
399 tar_hdr
->th_linkflag
= last_action
;
401 multi_volume
= FALSE
;
404 tar_hdr
= (tlm_tar_hdr_t
*)get_read_buffer(want
,
405 &erc
, &actual_size
, local_commands
);
407 if (tar_hdr
== NULL
) {
413 * we can ignore read errors here because
414 * 1) they are logged by Restore Reader
415 * 2) we are not doing anything important here
416 * just looking for the next work record.
418 if (actual_size
< want
) {
422 * wait for another buffer to come along
423 * or until the Reader thread tells us
424 * that no more tapes will be loaded ...
431 * check for "we are lost"
433 chk_rv
= tlm_vfy_tar_checksum(tar_hdr
);
435 /* one of the end of tar file marks */
436 if (++nzerohdr
>= 2) {
438 "nzerohdr %d, breaking",
440 /* end of tar file */
443 NDMP_LOG(LOG_DEBUG
, "nzerohdr %d, continuing",
446 } else if (chk_rv
< 0) {
448 /* skip this record */
454 * When files are spanned to the next tape, the
455 * information of the acls must not be over-written
456 * by the information of the LF_MULTIVOL and LF_VOLHDR
457 * header, whose information is irrelevant to the file.
458 * The information of the original header must be
461 if (tar_hdr
->th_linkflag
!= LF_MULTIVOL
&&
462 tar_hdr
->th_linkflag
!= LF_VOLHDR
) {
463 if (tar_hdr
->th_linkflag
!= LF_HUMONGUS
) {
464 acls
->acl_attr
.st_mode
=
465 oct_atoi(tar_hdr
->th_mode
);
466 acls
->acl_attr
.st_size
=
467 oct_atoi(tar_hdr
->th_size
);
468 acls
->acl_attr
.st_uid
=
469 oct_atoi(tar_hdr
->th_uid
);
470 acls
->acl_attr
.st_gid
=
471 oct_atoi(tar_hdr
->th_gid
);
472 acls
->acl_attr
.st_mtime
=
473 oct_atoi(tar_hdr
->th_mtime
);
474 (void) strlcpy(acls
->uname
,
476 sizeof (acls
->uname
));
477 (void) strlcpy(acls
->gname
,
479 sizeof (acls
->gname
));
481 file_size
= oct_atoi(tar_hdr
->th_size
);
483 last_action
= tar_hdr
->th_linkflag
;
487 NDMP_LOG(LOG_DEBUG
, "n [%s] f [%c] s %lld m %o u %d g %d t %d",
488 tar_hdr
->th_name
, tar_hdr
->th_linkflag
,
489 acls
->acl_attr
.st_size
, acls
->acl_attr
.st_mode
,
490 acls
->acl_attr
.st_uid
, acls
->acl_attr
.st_gid
,
491 acls
->acl_attr
.st_mtime
);
494 * If the restore is running using DAR we should check for
495 * extended attribute entries
498 tar_hdr
->th_linkflag
!= LF_XATTR
)
501 rs_create_new_bkpath(bk_path
, tar_hdr
->th_name
, thname_buf
);
503 switch (tar_hdr
->th_linkflag
) {
510 oct_atoi(tar_hdr
->th_shared
.th_hlink_ino
);
513 * Check if we have restored a link with the same inode
514 * If the inode is 0, we have to restore it as a
517 if (hardlink_inode
) {
518 hardlink_done
= !hardlink_q_get(hardlink_q
,
519 hardlink_inode
, 0, &hardlink_target
);
524 "found hardlink, inode = %u, target = [%s]",
526 hardlink_target
? hardlink_target
: "--");
528 /* create a hardlink to hardlink_target */
529 file_name
= (*longname
== 0) ?
530 thname_buf
: longname
;
532 if (!is_file_wanted(file_name
, sels
, exls
,
533 flags
, &mchtype
, &pos
)) {
536 * This means that DMA did not send us
537 * the correct fh_info for the file
538 * in restore list. We use the file
539 * name entry in sels[] (ignore the
540 * name in the tar header) as restore
544 nmp
= rs_darhl_new_name(rnp
,
549 nmp
= rs_new_name(rnp
, name
, pos
,
553 "can't make name for %s",
559 if (hardlink_target
) {
560 erc
= create_hard_link(
561 hardlink_target
, nmp
,
563 if (ERROR_IS_FATAL(erc
)) {
579 "no target for hardlink %s",
584 is_long_name
= FALSE
;
594 /* otherwise fall through, restore like a normal file */
598 * check for TAR's end-of-tape method
599 * of zero filled records.
601 if (tar_hdr
->th_name
[0] == 0) {
605 * otherwise fall through,
606 * this is an old style normal file header
611 job_stats
->js_files_so_far
++;
612 if (*hugename
!= 0) {
613 (void) strlcpy(longname
, hugename
,
615 } else if (*longname
== 0) {
616 if (tar_hdr
->th_name
[0] != '/') {
618 * check for old tar format, it
619 * does not have a leading "/"
623 (void) strlcat(longname
,
627 (void) strlcpy(longname
,
633 want_this_file
= is_file_wanted(longname
, sels
, exls
,
634 flags
, &mchtype
, &pos
);
635 if (!want_this_file
) {
638 * This means that DMA did not send us valid
639 * fh_info for the file in restore list. We
640 * use the file name entry in sels[] (ignore
641 * the name in the tar header) as restore
644 if (DAR
&& (tar_hdr
->th_linkflag
== LF_LINK
)) {
645 nmp
= rs_darhl_new_name(rnp
, name
,
646 sels
, &pos
, longname
);
652 want_this_file
= TRUE
;
656 nmp
= rs_new_name(rnp
, name
, pos
, longname
);
658 want_this_file
= FALSE
;
662 (void) strlcpy(parentlnk
, nmp
, strlen(nmp
) + 1);
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
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.
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
682 if (is_hardlink
&& !DAR
&& !want_this_file
&& !nmp
) {
684 (void) snprintf(name
, TLM_MAX_PATH_NAME
,
685 "%s/%s_%d", tmplink_dir
,
691 hardlink_tmp_file
= 1;
692 want_this_file
= TRUE
;
694 "To restore temp hardlink file %s.",
698 "No tmplink_dir specified.");
702 rv
= restore_file(&fp
, nmp
, file_size
,
703 huge_size
, acls
, want_this_file
, local_commands
,
704 job_stats
, &size_left
);
709 * In the case of non-DAR, we have to record the first
710 * link for an inode that has multiple links. That's
711 * the only link with data records actually backed up.
712 * In this way, when we run into the other links, they
713 * will be treated as links, and we won't go to look
714 * for the data records to restore. This is not a
715 * problem for DAR, where DMA tells the tape where
716 * to locate the data records.
718 if (is_hardlink
&& !DAR
) {
719 if (hardlink_q_add(hardlink_q
, hardlink_inode
,
720 0, nmp
, hardlink_tmp_file
))
722 "failed to add (%u, %s) to HL q",
723 hardlink_inode
, nmp
);
726 /* remove / reverse the temporary stuff */
727 if (hardlink_tmp_file
) {
729 want_this_file
= FALSE
;
730 hardlink_tmp_file
= 0;
734 * Check if it is time to set the attribute
735 * of the restored directory
737 while (nmp
&& ((bkpath
= dtree_peek(stp
)) != NULL
)) {
740 if (strstr(nmp
, bkpath
))
743 erc
= dtree_pop(stp
);
744 if (ERROR_IS_FATAL(erc
)) {
752 NDMP_LOG(LOG_DEBUG
, "sizeleft %s %d, %lld", longname
,
753 size_left
, huge_size
);
755 if (want_this_file
) {
756 job_stats
->js_bytes_total
+= file_size
;
757 job_stats
->js_files_total
++;
760 huge_size
-= file_size
;
764 if (size_left
== 0 && huge_size
== 0) {
765 if (PM_EXACT_OR_CHILD(mchtype
)) {
766 (void) tlm_entry_restored(job_stats
,
770 * Add an entry to hardlink_q to record
775 "Restored hardlink file %s",
779 (void) hardlink_q_add(
793 is_long_name
= FALSE
;
797 file_name
= (*longname
== 0) ? thname_buf
:
800 size_left
= restore_xattr_hdr(&fp
, parentlnk
,
801 file_name
, file_size
, acls
, local_commands
,
806 file_name
= (*longname
== 0) ? thname_buf
:
808 link_name
= (*longlink
== 0) ?
809 tar_hdr
->th_linkname
: longlink
;
810 NDMP_LOG(LOG_DEBUG
, "file_name[%s]", file_name
);
811 NDMP_LOG(LOG_DEBUG
, "link_name[%s]", link_name
);
812 if (is_file_wanted(file_name
, sels
, exls
, flags
,
814 nmp
= rs_new_name(rnp
, name
, pos
, file_name
);
816 erc
= create_sym_link(nmp
, link_name
,
818 if (ERROR_IS_FATAL(erc
)) {
823 PM_EXACT_OR_CHILD(mchtype
))
824 (void) tlm_entry_restored(
825 job_stats
, file_name
, pos
);
835 file_name
= *longname
== 0 ? thname_buf
:
837 if (is_file_wanted(file_name
, sels
, exls
, flags
,
840 nmp
= rs_new_name(rnp
, name
, pos
, file_name
);
841 if (nmp
&& mchtype
!= PM_PARENT
) {
842 (void) strlcpy(parentlnk
, nmp
,
844 erc
= create_directory(nmp
, job_stats
);
845 if (ERROR_IS_FATAL(erc
)) {
850 PM_EXACT_OR_CHILD(mchtype
))
851 (void) tlm_entry_restored(
852 job_stats
, file_name
, pos
);
854 * Check if it is time to set
855 * the attribute of the restored
858 while ((bkpath
= dtree_peek(stp
))
862 if (strstr(nmp
, bkpath
))
865 if (ERROR_IS_FATAL(rc
)) {
873 (void) dtree_push(stp
, nmp
, acls
);
887 file_name
= *longname
== 0 ? thname_buf
:
889 if (is_file_wanted(file_name
, sels
, exls
, flags
,
891 nmp
= rs_new_name(rnp
, name
, pos
, file_name
);
893 erc
= create_special(
894 tar_hdr
->th_linkflag
, nmp
, acls
,
895 oct_atoi(tar_hdr
->th_shared
.
897 oct_atoi(tar_hdr
->th_shared
.
898 th_dev
.th_devminor
), job_stats
);
899 if (ERROR_IS_FATAL(erc
)) {
904 PM_EXACT_OR_CHILD(mchtype
))
905 (void) tlm_entry_restored(
906 job_stats
, file_name
, pos
);
916 file_size
= min(file_size
,
917 TLM_MAX_PATH_NAME
- lnk_end
- 1);
918 file_size
= max(0, file_size
);
919 size_left
= get_long_name(lib
, drv
, file_size
, longlink
,
920 &lnk_end
, local_commands
);
924 "fsize %d sleft %d lnkend %d",
925 file_size
, size_left
, lnk_end
);
928 file_size
= min(file_size
,
929 TLM_MAX_PATH_NAME
- nm_end
- 1);
930 file_size
= max(0, file_size
);
931 size_left
= get_long_name(lib
, drv
, file_size
, longname
,
932 &nm_end
, local_commands
);
936 "fsize %d sleft %d nmend %d",
937 file_size
, size_left
, nm_end
);
941 size_left
= load_acl_info(lib
, drv
, file_size
, acls
,
942 &acl_spot
, local_commands
);
947 (void) memset(hugename
, 0, TLM_MAX_PATH_NAME
);
948 (void) get_humongus_file_header(lib
, drv
, file_size
,
949 &huge_size
, hugename
, local_commands
);
957 * If the restore is running using DAR we should check for
958 * long file names and HUGE file sizes.
960 if (DAR
&& tar_hdr
->th_linkflag
!= LF_ACL
&&
961 tar_hdr
->th_linkflag
!= LF_XATTR
&&
962 !huge_size
&& !is_long_name
&& !dir_dar
)
970 commands
->tcs_reader
= TLM_ABORT
;
974 while (dtree_pop(stp
) != -1)
988 * Main file restore function for tar (should run as a thread)
991 tar_getfile(tlm_backup_restore_arg_t
*argp
)
993 tlm_job_stats_t
*job_stats
;
994 char **sels
; /* list of files desired */
995 char **exls
; /* list of files not wanted */
996 char *dir
; /* where to restore the files */
997 char job
[TLM_MAX_BACKUP_JOB_NAME
+1];
998 /* the restore job name */
999 int erc
; /* error return codes */
1001 struct rs_name_maker rn
;
1002 tlm_commands_t
*commands
;
1003 tlm_cmd_t
*local_commands
;
1006 commands
= argp
->ba_commands
;
1007 local_commands
= argp
->ba_cmd
;
1011 dir
= ndmp_malloc(TLM_MAX_PATH_NAME
);
1013 local_commands
->tc_reader
= TLM_STOP
;
1014 (void) pthread_barrier_wait(&argp
->ba_barrier
);
1018 (void) strlcpy(job
, argp
->ba_job
, TLM_MAX_BACKUP_JOB_NAME
+1);
1019 (void) strlcpy(dir
, argp
->ba_dir
, TLM_MAX_PATH_NAME
);
1021 flags
|= RSFLG_OVR_ALWAYS
;
1022 flags
|= RSFLG_IGNORE_CASE
;
1025 * do not test for "dir" having no string, since that
1026 * is a legal condition. Restore to origional location
1027 * will not have a restore directory.
1030 NDMP_LOG(LOG_DEBUG
, "No job defined");
1031 local_commands
->tc_reader
= TLM_STOP
;
1033 (void) pthread_barrier_wait(&argp
->ba_barrier
);
1037 sels
= argp
->ba_sels
;
1039 local_commands
->tc_reader
= TLM_STOP
;
1041 (void) pthread_barrier_wait(&argp
->ba_barrier
);
1046 tlm_log_list("selections", sels
);
1047 tlm_log_list("exclusions", exls
);
1049 if (wildcard_enabled())
1050 flags
|= RSFLG_MATCH_WCARD
;
1052 local_commands
->tc_ref
++;
1053 commands
->tcs_writer_count
++;
1056 * let the launcher continue
1058 (void) pthread_barrier_wait(&argp
->ba_barrier
);
1060 job_stats
= tlm_ref_job_stats(job
);
1062 rn
.rn_fp
= catnames
;
1068 NDMP_LOG(LOG_DEBUG
, "start restore job %s", job
);
1069 erc
= tar_getdir(commands
, local_commands
, job_stats
, &rn
, 1, 1,
1070 sels
, exls
, flags
, 0, NULL
, NULL
);
1075 NDMP_LOG(LOG_DEBUG
, "end restore job %s", job
);
1076 tlm_un_ref_job_stats(job
);
1077 tlm_release_list(sels
);
1078 tlm_release_list(exls
);
1080 commands
->tcs_writer_count
--;
1081 local_commands
->tc_reader
= TLM_STOP
;
1082 tlm_release_reader_writer_ipc(local_commands
);
1088 * Creates the directories all the way down to the
1089 * end if they dont exist
1092 make_dirs(char *dir
)
1099 cp
+= strspn(cp
, "/");
1100 end
= dir
+ strlen(dir
);
1102 if (*cp
== '\0' || *cp
== '/') {
1105 if (lstat64(dir
, &st
) < 0)
1106 if (mkdir(dir
, 0777) < 0) {
1107 NDMP_LOG(LOG_DEBUG
, "Error %d"
1108 " creating directory %s",
1116 } while (++cp
<= end
);
1122 * Creates the directories leading to the given path
1125 mkbasedir(char *path
)
1131 if (!path
|| !*path
) {
1132 NDMP_LOG(LOG_DEBUG
, "Invalid argument");
1136 cp
= strrchr(path
, '/');
1139 rv
= lstat64(path
, &st
);
1140 if (rv
< 0) /* need new directories */
1141 rv
= make_dirs(path
);
1150 * read the file off the tape back onto disk
1152 * If the function returns a non-zero return code, it means that fatal error
1153 * was encountered and restore should terminate immediately.
1156 restore_file(int *fp
,
1159 longlong_t huge_size
,
1161 boolean_t want_this_file
,
1162 tlm_cmd_t
*local_commands
,
1163 tlm_job_stats_t
*job_stats
,
1171 if (want_this_file
) {
1172 NDMP_LOG(LOG_DEBUG
, "No file name but wanted!");
1173 want_this_file
= FALSE
;
1176 NDMP_LOG(LOG_DEBUG
, "new file[%s]", real_name
);
1179 * OK, some FM is creeping in here ...
1180 * int *fp is used to keep the
1181 * backup file channel open through
1182 * the interruption of EOT and
1183 * processing the headers of the
1184 * next tape. So, if *fp is zero
1185 * then no file is open yet and all
1186 * is normal. If *fp has a number
1187 * then we are returning after an
1190 * *fp is now also open for HUGE files
1191 * that are put back in sections.
1194 if (*fp
== 0 && want_this_file
) {
1196 ret
= mkbasedir(real_name
);
1198 job_stats
->js_errors
++;
1199 if (ERROR_IS_FATAL(ret
))
1203 ret
= stat64(real_name
, (struct stat64
*)&attr
);
1207 } else if (acls
->acl_overwrite
) {
1209 /* take this file no matter what */
1210 } else if (acls
->acl_update
) {
1211 if (attr
.st_mtime
< acls
->acl_attr
.st_mtime
) {
1215 /* disk file is newer */
1216 want_this_file
= FALSE
;
1220 * no overwrite, no update,
1221 * do not ever replace old files.
1223 want_this_file
= TRUE
;
1225 if (want_this_file
) {
1227 *fp
= open(real_name
, O_CREAT
| O_TRUNC
| O_WRONLY
,
1231 "Could not open %s for restore: %d",
1233 job_stats
->js_errors
++;
1234 want_this_file
= FALSE
;
1236 * In case of non-fatal error we cannot return
1237 * here, because the file is still on the tape
1238 * and must be skipped over.
1240 if (ERROR_IS_FATAL(errno
))
1244 (void) strlcpy(local_commands
->tc_file_name
, real_name
,
1249 * this is the size left in the next segment
1257 while (size
> 0 && local_commands
->tc_writer
== TLM_RESTORE_RUN
) {
1264 * Use bytes_in_file field to tell reader the amount
1265 * of data still need to be read for this file.
1267 job_stats
->js_bytes_in_file
= size
;
1270 rec
= get_read_buffer(size
, &error
, &actual_size
,
1272 if (actual_size
<= 0) {
1274 "RESTORE WRITER> error %d, actual_size %d",
1275 error
, actual_size
);
1277 /* no more data for this file for now */
1278 job_stats
->js_bytes_in_file
= 0;
1282 NDMP_LOG(LOG_DEBUG
, "Error %d in file [%s]",
1283 error
, local_commands
->tc_file_name
);
1287 write_size
= min(size
, actual_size
);
1288 if (want_this_file
) {
1289 ret
= write(*fp
, rec
, write_size
);
1292 "Write error %d for file [%s]", errno
,
1293 local_commands
->tc_file_name
);
1294 job_stats
->js_errors
++;
1295 if (ERROR_IS_FATAL(errno
)) {
1302 if (ret
< write_size
) {
1304 "Partial write for file [%s]",
1305 local_commands
->tc_file_name
);
1312 /* no more data for this file for now */
1313 job_stats
->js_bytes_in_file
= 0;
1318 if (*fp
!= 0 && huge_size
<= 0) {
1322 ret
= set_acl(real_name
, acls
);
1323 if (ERROR_IS_FATAL(ret
))
1331 * Set the extended attributes file attribute
1334 set_xattr(int fd
, struct stat64 st
)
1336 struct timeval times
[2];
1338 times
[0].tv_sec
= st
.st_atime
;
1339 times
[1].tv_sec
= st
.st_mtime
;
1341 (void) fchmod(fd
, st
.st_mode
);
1342 (void) fchown(fd
, st
.st_uid
, st
.st_gid
);
1343 (void) futimesat(fd
, ".", times
);
1347 * Read the system attribute file in a single buffer to write
1348 * it as a single write. A partial write to system attribute would
1349 * cause an EINVAL on write.
1352 get_read_one_buf(char *rec
, int actual_size
, int size
, int *error
,
1359 if (actual_size
> size
)
1362 buf
= ndmp_malloc(size
);
1367 (void) memcpy(buf
, rec
, actual_size
);
1370 while (actual_size
< size
) {
1371 p
= get_read_buffer(size
- actual_size
, error
, &read_size
, lc
);
1372 len
= min(size
- actual_size
, read_size
);
1373 (void) memcpy(buf
, p
, len
);
1382 * read the extended attribute header and write
1386 restore_xattr_hdr(int *fp
,
1391 tlm_cmd_t
*local_commands
,
1392 tlm_job_stats_t
*job_stats
)
1394 tlm_tar_hdr_t
*tar_hdr
;
1395 struct xattr_hdr
*xhdr
;
1396 struct xattr_buf
*xbuf
;
1403 NDMP_LOG(LOG_DEBUG
, "No file name but wanted!");
1405 NDMP_LOG(LOG_DEBUG
, "new xattr[%s]", fname
);
1409 xhdr
= (struct xattr_hdr
*)get_read_buffer(size
, &error
,
1410 &actual_size
, local_commands
);
1411 if (xhdr
== NULL
|| error
!= 0) {
1413 "Could not read xattr [%s:%s] for restore. ",
1415 job_stats
->js_errors
++;
1419 /* Check extended attribute header */
1420 if (strcmp(xhdr
->h_version
, XATTR_ARCH_VERS
) != 0) {
1422 "Unrecognized header format [%s]", xhdr
->h_version
);
1425 xbuf
= (struct xattr_buf
*)(((char *)xhdr
) + sizeof (struct xattr_hdr
));
1427 (void) sscanf(xbuf
->h_namesz
, "%7d", &namelen
);
1428 xattrname
= xbuf
->h_names
+ strlen(xbuf
->h_names
) + 1;
1433 fd
= attropen(name
, xattrname
, O_CREAT
| O_RDWR
, 0755);
1436 "Could not open xattr [%s:%s] for restore err=%d.",
1437 name
, xattrname
, errno
);
1438 job_stats
->js_errors
++;
1441 (void) strlcpy(local_commands
->tc_file_name
, xattrname
,
1446 /* Get the actual extended attribute file */
1447 tar_hdr
= (tlm_tar_hdr_t
*)get_read_buffer(sizeof (*tar_hdr
),
1448 &error
, &actual_size
, local_commands
);
1449 if (tar_hdr
== NULL
|| error
!= 0) {
1451 "Could not read xattr data [%s:%s] for restore. ",
1453 job_stats
->js_errors
++;
1456 acls
->acl_attr
.st_mode
= oct_atoi(tar_hdr
->th_mode
);
1457 acls
->acl_attr
.st_size
= oct_atoi(tar_hdr
->th_size
);
1458 acls
->acl_attr
.st_uid
= oct_atoi(tar_hdr
->th_uid
);
1459 acls
->acl_attr
.st_gid
= oct_atoi(tar_hdr
->th_gid
);
1460 acls
->acl_attr
.st_mtime
= oct_atoi(tar_hdr
->th_mtime
);
1462 NDMP_LOG(LOG_DEBUG
, "xattr_hdr: %s size %d mode %06o uid %d gid %d",
1463 xattrname
, acls
->acl_attr
.st_size
, acls
->acl_attr
.st_mode
,
1464 acls
->acl_attr
.st_uid
, acls
->acl_attr
.st_gid
);
1466 size
= acls
->acl_attr
.st_size
;
1467 while (size
> 0 && local_commands
->tc_writer
== TLM_RESTORE_RUN
) {
1470 int sysattr_write
= 0;
1473 rec
= get_read_buffer(size
, &error
, &actual_size
,
1476 if ((actual_size
< size
) && sysattr_rw(xattrname
)) {
1477 rec
= get_read_one_buf(rec
, actual_size
, size
, &error
,
1480 NDMP_LOG(LOG_DEBUG
, "Error %d in file [%s]",
1487 if (actual_size
<= 0) {
1489 "RESTORE WRITER> error %d, actual_size %d",
1490 error
, actual_size
);
1494 NDMP_LOG(LOG_DEBUG
, "Error %d in file [%s]",
1495 error
, local_commands
->tc_file_name
);
1498 write_size
= min(size
, actual_size
);
1499 if ((write_size
= write(*fp
, rec
, write_size
)) < 0) {
1506 NS_ADD(wdisk
, write_size
);
1515 set_xattr(*fp
, acls
->acl_attr
);
1523 * Match the name with the list
1526 exact_find(char *name
, char **list
)
1533 for (i
= 0; *list
!= NULL
; list
++, i
++) {
1534 cp
= *list
+ strspn(*list
, "/");
1535 if (match(cp
, name
)) {
1537 NDMP_LOG(LOG_DEBUG
, "exact_find> found[%s]", cp
);
1546 * On error, return FALSE and prevent restoring(probably) unwanted data.
1549 is_parent(char *parent
, char *child
, int flags
)
1551 char tmp
[TLM_MAX_PATH_NAME
];
1554 if (IS_SET(flags
, RSFLG_MATCH_WCARD
)) {
1555 if (!tlm_cat_path(tmp
, parent
, "*")) {
1557 "is_parent> path too long [%s]", parent
);
1560 rv
= (match(tmp
, child
) != 0) ? TRUE
: FALSE
;
1562 if (!tlm_cat_path(tmp
, parent
, "/")) {
1564 "is_parent> path too long [%s]", parent
);
1567 rv
= (strncmp(tmp
, child
, strlen(tmp
)) == 0) ?
1575 * Used to match the filename inside the list
1578 strexactcmp(char *s
, char *t
)
1580 return ((strcmp(s
, t
) == 0) ? TRUE
: FALSE
);
1584 * Check if the file is needed to be restored
1587 is_file_wanted(char *name
,
1595 char *uc_name
, *retry
, *namep
;
1598 name_match_fp_t
*cmp_fp
;
1600 if (name
== NULL
|| sels
== NULL
|| exls
== NULL
)
1604 if (mchtype
!= NULL
)
1610 * For empty selection, restore everything
1612 if (*sels
== NULL
|| **sels
== '\0') {
1613 NDMP_LOG(LOG_DEBUG
, "is_file_wanted: Restore all");
1617 retry
= ndmp_malloc(TLM_MAX_PATH_NAME
);
1621 if (IS_SET(flags
, RSFLG_MATCH_WCARD
))
1624 cmp_fp
= strexactcmp
;
1626 namep
= name
+ strspn(name
, "/");
1628 if (IS_SET(flags
, RSFLG_IGNORE_CASE
)) {
1629 uc_name
= ndmp_malloc(TLM_MAX_PATH_NAME
);
1630 if (uc_name
== NULL
) {
1634 (void) strlcpy(uc_name
, namep
, TLM_MAX_PATH_NAME
);
1635 (void) strupr(uc_name
);
1638 NDMP_LOG(LOG_DEBUG
, "is_file_wanted> flg: 0x%x name: [%s]",
1641 for (i
= 0; *sels
!= NULL
; sels
++, i
++) {
1642 p_sel
= *sels
+ strspn(*sels
, "/");
1647 if ((*cmp_fp
)(p_sel
, namep
)) {
1648 NDMP_LOG(LOG_DEBUG
, "match1> pos: %d [%s][%s]",
1651 if (mchtype
!= NULL
)
1652 *mchtype
= PM_EXACT
;
1656 * Try "entry/" and the current selection. The
1657 * current selection may be something like "<something>/".
1659 (void) tlm_cat_path(retry
, namep
, "/");
1660 if ((*cmp_fp
)(p_sel
, retry
)) {
1661 NDMP_LOG(LOG_DEBUG
, "match2> pos %d [%s][%s]",
1664 if (mchtype
!= NULL
)
1665 *mchtype
= PM_EXACT
;
1669 * If the following check returns true it means that the
1670 * 'name' is an entry below the 'p_sel' hierarchy.
1672 if (is_parent(p_sel
, namep
, flags
)) {
1673 NDMP_LOG(LOG_DEBUG
, "parent1> pos %d [%s][%s]",
1676 if (mchtype
!= NULL
)
1677 *mchtype
= PM_CHILD
;
1681 * There is a special case for parent directories of a
1682 * selection. If 'p_sel' is something like "*d1", the
1683 * middle directories of the final entry can't be determined
1684 * until the final entry matches with 'p_sel'. At that
1685 * time the middle directories of the entry have been passed
1686 * and they can't be restored.
1688 if (is_parent(namep
, p_sel
, flags
)) {
1689 NDMP_LOG(LOG_DEBUG
, "parent2> pos %d [%s][%s]",
1692 if (mchtype
!= NULL
)
1693 *mchtype
= PM_PARENT
;
1698 /* Check for exclusions. */
1699 if (found
&& exact_find(namep
, exls
)) {
1700 if (mchtype
!= NULL
)
1704 if (found
&& pos
!= NULL
)
1707 if (IS_SET(flags
, RSFLG_IGNORE_CASE
))
1714 * Read the specified amount data into the buffer. Detects EOT or EOF
1717 * Returns the number of bytes actually read. On error returns -1.
1727 int toread
, actual_size
, rec_size
;
1730 if (l
<= 0 || d
<= 0 || !lcmds
|| !mem
) {
1731 NDMP_LOG(LOG_DEBUG
, "Invalid argument");
1736 while (toread
> 0) {
1737 rec
= get_read_buffer(toread
, &err
, &actual_size
, lcmds
);
1738 if (actual_size
<= 0) {
1739 NDMP_LOG(LOG_DEBUG
, "err %d act_size %d detected",
1743 NDMP_LOG(LOG_DEBUG
, "error %d reading data", err
);
1746 rec_size
= min(actual_size
, toread
);
1747 (void) memcpy(mem
, rec
, rec_size
);
1752 return (len
- toread
);
1756 * pick up the name and size of a HUGE file
1759 get_humongus_file_header(int lib
,
1764 tlm_cmd_t
*local_commands
)
1766 char *p_record
, *value
;
1769 NDMP_LOG(LOG_DEBUG
, "HUGE Record found: %d", recsize
);
1774 * The humongus_file_header was written in a
1775 * RECORDSIZE block and the header.size field of this
1776 * record was 0 before this fix. For backward compatiblity
1777 * read only one RECORDSIZE-size block if the header.size
1778 * field is 0. Otherwise the header.size field should show
1779 * the length of the data of this header.
1781 NDMP_LOG(LOG_DEBUG
, "Old HUGE record found");
1782 recsize
= RECORDSIZE
;
1785 if (input_mem(lib
, drv
, local_commands
, name
, recsize
) != recsize
) {
1789 NDMP_LOG(LOG_DEBUG
, "Error reading a HUGE file name");
1791 NDMP_LOG(LOG_DEBUG
, "HUGE [%s]", name
);
1794 value
= parse(&p_record
, " ");
1795 *size
= atoll(value
);
1797 * Note: Since the backed up names are not longer than
1798 * NAME_MAX and the buffer passed to us is
1799 * TLM_MAX_PATH_NAME, it should be safe to use strlcpy
1800 * without check on the buffer size.
1802 (void) strlcpy(name
, p_record
, TLM_MAX_PATH_NAME
);
1805 NDMP_LOG(LOG_DEBUG
, "HUGE Record %lld [%s]", *size
, name
);
1811 * pick up the long name from the special tape file
1814 get_long_name(int lib
,
1819 tlm_cmd_t
*local_commands
)
1823 NDMP_LOG(LOG_DEBUG
, "LONGNAME Record found rs %d bs %d", recsize
,
1829 nread
= input_mem(lib
, drv
, local_commands
, name
+ *buf_spot
,
1832 nread
= recsize
; /* return 0 as size left */
1833 name
[*buf_spot
] = '\0';
1834 NDMP_LOG(LOG_ERR
, "Error %d reading a long file name %s.",
1838 name
[*buf_spot
] = '\0';
1839 NDMP_LOG(LOG_DEBUG
, "LONGNAME [%s]", name
);
1842 return (recsize
- nread
);
1846 * create a new directory
1849 create_directory(char *dir
, tlm_job_stats_t
*job_stats
)
1857 * Make sure all directories in this path exist, create them if
1860 NDMP_LOG(LOG_DEBUG
, "new dir[%s]", dir
);
1866 if (temp
== '/' || temp
== 0) {
1868 if (stat64(dir
, &attr
) < 0) {
1869 if (mkdir(dir
, 0777) != 0 && errno
!= EEXIST
) {
1871 job_stats
->js_errors
++;
1873 "Could not create directory %s: %d",
1881 } while (temp
!= 0);
1887 * create a new hardlink
1890 create_hard_link(char *name_old
, char *name_new
,
1891 tlm_acls_t
*acls
, tlm_job_stats_t
*job_stats
)
1895 erc
= mkbasedir(name_new
);
1899 if (link(name_old
, name_new
) != 0)
1903 /* Nothing to do if the destination already exists */
1906 job_stats
->js_errors
++;
1907 NDMP_LOG(LOG_DEBUG
, "error %d (errno %d) hardlink [%s] to [%s]",
1908 erc
, errno
, name_new
, name_old
);
1911 return (set_acl(name_new
, acls
));
1915 * create a new symlink
1919 create_sym_link(char *dst
, char *target
, tlm_acls_t
*acls
,
1920 tlm_job_stats_t
*job_stats
)
1925 erc
= mkbasedir(dst
);
1929 st
= &acls
->acl_attr
;
1930 if (symlink(target
, dst
) != 0) {
1932 job_stats
->js_errors
++;
1933 NDMP_LOG(LOG_DEBUG
, "error %d softlink [%s] to [%s]",
1934 errno
, dst
, target
);
1936 st
->st_mode
|= S_IFLNK
;
1937 erc
= set_acl(dst
, acls
);
1944 * create a new FIFO, char/block device special files
1947 create_special(char flag
, char *name
, tlm_acls_t
*acls
, int major
, int minor
,
1948 tlm_job_stats_t
*job_stats
)
1956 dev
= makedev(major
, minor
);
1960 dev
= makedev(major
, minor
);
1967 NDMP_LOG(LOG_ERR
, "unsupported flag %d", flag
);
1971 /* Remove the old entry first */
1972 if (rmdir(name
) < 0) {
1973 if (errno
== ENOTDIR
)
1974 (void) unlink(name
);
1976 if (mknod(name
, 0777 | mode
, dev
) != 0) {
1977 job_stats
->js_errors
++;
1978 NDMP_LOG(LOG_DEBUG
, "error %d mknod [%s] major"
1979 " %d minor %d", errno
, name
, major
, minor
);
1982 return (set_acl(name
, acls
));
1986 * read in the ACLs for the next file
1989 load_acl_info(int lib
,
1994 tlm_cmd_t
*local_commands
)
2000 * If the ACL is spanned on tapes, then the acl_spot should NOT be
2001 * 0 on next calls to this function to read the rest of the ACL
2004 if (*acl_spot
== 0) {
2005 (void) memset(acls
, 0, sizeof (tlm_acls_t
));
2008 bp
= ((char *)&acls
->acl_info
) + *acl_spot
;
2009 nread
= input_mem(lib
, drv
, local_commands
, (void *)bp
, file_size
);
2012 (void) memset(acls
, 0, sizeof (tlm_acls_t
));
2013 NDMP_LOG(LOG_DEBUG
, "Error reading ACL data");
2017 acls
->acl_non_trivial
= TRUE
;
2019 return (file_size
- nread
);
2023 ndmp_set_eprivs_least(void)
2025 priv_set_t
*priv_set
;
2027 if ((priv_set
= priv_allocset()) == NULL
) {
2028 NDMP_LOG(LOG_ERR
, "Out of memory.");
2032 priv_basicset(priv_set
);
2034 (void) priv_addset(priv_set
, PRIV_PROC_AUDIT
);
2035 (void) priv_addset(priv_set
, PRIV_PROC_SETID
);
2036 (void) priv_addset(priv_set
, PRIV_PROC_OWNER
);
2037 (void) priv_addset(priv_set
, PRIV_FILE_CHOWN
);
2038 (void) priv_addset(priv_set
, PRIV_FILE_CHOWN_SELF
);
2039 (void) priv_addset(priv_set
, PRIV_FILE_DAC_READ
);
2040 (void) priv_addset(priv_set
, PRIV_FILE_DAC_SEARCH
);
2041 (void) priv_addset(priv_set
, PRIV_FILE_DAC_WRITE
);
2042 (void) priv_addset(priv_set
, PRIV_FILE_OWNER
);
2043 (void) priv_addset(priv_set
, PRIV_FILE_SETID
);
2044 (void) priv_addset(priv_set
, PRIV_SYS_LINKDIR
);
2045 (void) priv_addset(priv_set
, PRIV_SYS_DEVICES
);
2046 (void) priv_addset(priv_set
, PRIV_SYS_MOUNT
);
2047 (void) priv_addset(priv_set
, PRIV_SYS_CONFIG
);
2049 if (setppriv(PRIV_SET
, PRIV_EFFECTIVE
, priv_set
) == -1) {
2050 NDMP_LOG(LOG_ERR
, "Additional privileges required.");
2051 priv_freeset(priv_set
);
2054 priv_freeset(priv_set
);
2059 ndmp_set_eprivs_all(void)
2061 priv_set_t
*priv_set
;
2063 if ((priv_set
= priv_allocset()) == NULL
) {
2064 NDMP_LOG(LOG_ERR
, "Out of memory.");
2068 priv_fillset(priv_set
);
2070 if (setppriv(PRIV_SET
, PRIV_EFFECTIVE
, priv_set
) != 0) {
2071 NDMP_LOG(LOG_ERR
, "Additional privileges required.");
2074 priv_freeset(priv_set
);
2079 * Set the standard attributes of the file
2082 set_attr(char *name
, tlm_acls_t
*acls
)
2084 struct utimbuf tbuf
;
2085 boolean_t priv_all
= FALSE
;
2097 st
= &acls
->acl_attr
;
2098 NDMP_LOG(LOG_DEBUG
, "set_attr: %s uid %d gid %d uname %s gname %s "
2099 "mode %o", name
, st
->st_uid
, st
->st_gid
, acls
->uname
, acls
->gname
,
2103 if ((pwd
= getpwnam(acls
->uname
)) != NULL
) {
2104 NDMP_LOG(LOG_DEBUG
, "set_attr: new uid %d old %d",
2110 if ((grp
= getgrnam(acls
->gname
)) != NULL
) {
2111 NDMP_LOG(LOG_DEBUG
, "set_attr: new gid %d old %d",
2116 erc
= lchown(name
, uid
, gid
);
2120 "Could not set uid or/and gid for file %s.", name
);
2123 if ((st
->st_mode
& (S_ISUID
| S_ISGID
)) != 0) {
2125 * Change effective privileges to 'all' which is required to
2126 * change setuid bit for 'root' owned files. If fails, just
2127 * send error to log file and proceed.
2129 if (ndmp_set_eprivs_all()) {
2131 "Could not set effective privileges to 'all'.");
2137 if (!S_ISLNK(st
->st_mode
)) {
2138 erc
= chmod(name
, st
->st_mode
);
2141 NDMP_LOG(LOG_ERR
, "Could not set correct file"
2142 " permission for file %s: %d", name
, errno
);
2145 tbuf
.modtime
= st
->st_mtime
;
2146 tbuf
.actime
= st
->st_atime
;
2147 (void) utime(name
, &tbuf
);
2150 if (priv_all
== TRUE
) {
2152 * Give up the 'all' privileges for effective sets and go back
2153 * to least required privileges. If fails, just send error to
2154 * log file and proceed.
2156 if (ndmp_set_eprivs_least())
2158 "Could not set least required privileges.");
2165 * Set the ACL info for the file
2168 set_acl(char *name
, tlm_acls_t
*acls
)
2174 NDMP_LOG(LOG_DEBUG
, "set_acl: %s", name
);
2178 /* Need a place to save real modification time */
2180 erc
= set_attr(name
, acls
);
2181 if (ERROR_IS_FATAL(erc
))
2184 if (!acls
->acl_non_trivial
) {
2185 (void) memset(acls
, 0, sizeof (tlm_acls_t
));
2186 NDMP_LOG(LOG_DEBUG
, "set_acl: skipping trivial");
2190 erc
= acl_fromtext(acls
->acl_info
.attr_info
, &aclp
);
2193 "TAPE RESTORE> acl_fromtext errno %d", erc
);
2196 erc
= acl_set(name
, aclp
);
2200 "TAPE RESTORE> acl_set errno %d", errno
);
2204 (void) memset(acls
, 0, sizeof (tlm_acls_t
));
2209 * a wrapper to tlm_get_read_buffer so that
2210 * we can cleanly detect ABORT commands
2211 * without involving the TLM library with
2215 get_read_buffer(int want
,
2218 tlm_cmd_t
*local_commands
)
2220 while (local_commands
->tc_writer
== TLM_RESTORE_RUN
) {
2222 rec
= tlm_get_read_buffer(want
, error
,
2223 local_commands
->tc_buffers
, actual_size
);
2230 * the job is ending, give Writer a buffer that will never be read ...
2231 * it does not matter anyhow, we are aborting.
2233 *actual_size
= RECORDSIZE
;
2238 * Enable wildcard for restore options
2241 wildcard_enabled(void)
2245 cp
= ndmpd_get_prop_default(NDMP_RESTORE_WILDCARD_ENABLE
, "n");
2246 return ((toupper(*cp
) == 'Y') ? TRUE
: FALSE
);
2251 * Concatenate two names
2255 catnames(struct rs_name_maker
*rnp
, char *buf
, int pos
, char *path
)
2261 NDMP_LOG(LOG_DEBUG
, "buf is NULL");
2263 NDMP_LOG(LOG_DEBUG
, "path is NULL");
2264 } else if (!rnp
->rn_nlp
) {
2265 NDMP_LOG(LOG_DEBUG
, "rn_nlp is NULL [%s]", path
);
2266 } else if (!tlm_cat_path(buf
, rnp
->rn_nlp
, path
)) {
2267 NDMP_LOG(LOG_DEBUG
, "Path too long [%s][%s]",
2277 * Create a new name path for restore
2280 rs_new_name(struct rs_name_maker
*rnp
, char *buf
, int pos
, char *path
)
2282 if (!rnp
|| !rnp
->rn_fp
)
2285 return (*rnp
->rn_fp
)(rnp
, buf
, pos
, path
);
2289 * Clear the extra "/" in the tar header if exists
2292 rs_create_new_bkpath(char *bk_path
, char *path
, char *pbuf
)
2296 if ((p
= strstr(path
, bk_path
)) == NULL
) {
2297 (void) strlcpy(pbuf
, path
, TLM_MAX_PATH_NAME
);
2300 if (*(p
+= strlen(bk_path
)) == '/')
2303 slashp
= bk_path
+ strlen(bk_path
) - 1;
2305 (void) snprintf(pbuf
, TLM_MAX_PATH_NAME
, "%s%s", bk_path
, p
);
2307 (void) snprintf(pbuf
, TLM_MAX_PATH_NAME
, "%s/%s", bk_path
, p
);
2309 NDMP_LOG(LOG_DEBUG
, "old path [%s] new path [%s]", path
, pbuf
);
2314 * Iterate over ZFS metadata stored in the backup stream and use the callback
2318 ndmp_iter_zfs(ndmp_context_t
*nctx
, int (*np_restore_property
)(nvlist_t
*,
2321 tlm_commands_t
*cmds
;
2322 ndmp_metadata_header_t
*mhp
;
2323 ndmp_metadata_header_ext_t
*mhpx
;
2324 ndmp_metadata_property_t
*mpp
;
2325 ndmp_metadata_property_ext_t
*mppx
;
2330 nvpair_t
*nvp
= NULL
;
2332 char *mhbuf
, *pp
, *tp
;
2334 int size
, lsize
, sz
;
2335 int align
= RECORDSIZE
- 1;
2337 if (nctx
== NULL
|| (cmds
= (tlm_commands_t
*)nctx
->nc_cmds
) == NULL
)
2340 nctx
->nc_plname
= plname
;
2341 if ((lcmd
= cmds
->tcs_command
) == NULL
||
2342 lcmd
->tc_buffers
== NULL
)
2345 /* Default minimum bytes needed */
2346 size
= sizeof (ndmp_metadata_header_t
) +
2347 ZFS_MAX_PROPS
* sizeof (ndmp_metadata_property_t
);
2351 if ((mhbuf
= malloc(size
)) == NULL
)
2354 /* LINTED improper alignment */
2355 while ((mhp
= (ndmp_metadata_header_t
*)get_read_buffer(size
, &rv
,
2356 &actual_size
, lcmd
)) != NULL
) {
2359 if (strncmp(mhp
->nh_magic
, ZFS_META_MAGIC
,
2360 sizeof (mhp
->nh_magic
)) != 0 &&
2361 strncmp(mhp
->nh_magic
, ZFS_META_MAGIC_EXT
,
2362 sizeof (mhp
->nh_magic
)) != 0) {
2363 /* No more metadata */
2364 tlm_unget_read_buffer(lcmd
->tc_buffers
, actual_size
);
2369 if (strncmp(mhp
->nh_magic
, ZFS_META_MAGIC_EXT
,
2370 sizeof (mhp
->nh_magic
)) == 0) {
2371 mhpx
= (ndmp_metadata_header_ext_t
*)mhp
;
2372 if (mhpx
->nh_total_bytes
> size
) {
2373 if ((pp
= realloc(mhbuf
, mhpx
->nh_total_bytes
))
2380 size
= mhpx
->nh_total_bytes
;
2383 (void) memcpy(pp
, (char *)mhp
, (actual_size
< size
) ?
2384 actual_size
: size
);
2385 pp
+= (actual_size
< size
) ? actual_size
: size
;
2389 ((tp
= get_read_buffer(size
- sz
, &rv
, &lsize
,
2391 (void) memcpy(pp
, tp
, lsize
);
2396 tlm_unget_read_buffer(lcmd
->tc_buffers
, sz
- size
);
2399 /* LINTED improper alignment */
2400 mhp
= (ndmp_metadata_header_t
*)mhbuf
;
2403 if (strncmp(mhp
->nh_magic
, ZFS_META_MAGIC_EXT
,
2404 sizeof (mhp
->nh_magic
)) == 0) {
2405 /* New metadata format */
2406 /* LINTED improper alignment */
2407 mhpx
= (ndmp_metadata_header_ext_t
*)mhbuf
;
2409 if (mhpx
->nh_major
> META_HDR_MAJOR_VERSION
) {
2410 /* Major header mismatch */
2411 NDMP_LOG(LOG_ERR
, "metadata header mismatch",
2412 "M%d != M%d", mhpx
->nh_major
,
2413 META_HDR_MAJOR_VERSION
);
2417 if (mhpx
->nh_major
== META_HDR_MAJOR_VERSION
&&
2418 mhpx
->nh_minor
> META_HDR_MINOR_VERSION
) {
2419 /* Minor header mismatch */
2420 NDMP_LOG(LOG_ERR
, "Warning:"
2421 "metadata header mismatch m%d != m%d",
2423 META_HDR_MINOR_VERSION
);
2427 nctx
->nc_plversion
= mhpx
->nh_plversion
;
2428 (void) strlcpy(plname
, mhpx
->nh_plname
,
2431 if (nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, 0) != 0)
2434 mppx
= &mhpx
->nh_property
[0];
2435 for (i
= 0; i
< mhpx
->nh_count
&& mppx
; i
++, mppx
++) {
2436 if (!*mppx
->mp_name
)
2439 if (nvlist_alloc(&valp
,
2440 NV_UNIQUE_NAME
, 0) != 0 ||
2441 nvlist_add_string(valp
, "value",
2442 mppx
->mp_value
) != 0 ||
2443 nvlist_add_string(valp
, "source",
2444 mppx
->mp_source
) != 0 ||
2445 nvlist_add_nvlist(nvl
, mppx
->mp_name
,
2453 nctx
->nc_plversion
= mhp
->nh_plversion
;
2454 (void) strlcpy(plname
, mhp
->nh_plname
,
2457 if (nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, 0) != 0)
2460 mpp
= &mhp
->nh_property
[0];
2461 for (i
= 0; i
< mhp
->nh_count
&& mpp
; i
++, mpp
++) {
2465 if (nvlist_alloc(&valp
,
2466 NV_UNIQUE_NAME
, 0) != 0 ||
2467 nvlist_add_string(valp
, "value",
2468 mpp
->mp_value
) != 0 ||
2469 nvlist_add_string(valp
, "source",
2470 mpp
->mp_source
) != 0 ||
2471 nvlist_add_nvlist(nvl
, mpp
->mp_name
,
2480 if (np_restore_property(nvl
, ptr
) != 0)
2483 while ((nvp
= nvlist_next_nvpair(nvl
, nvp
)) != NULL
&&
2484 nvpair_value_nvlist(nvp
, &valp
) == 0) {
2496 while ((nvp
= nvlist_next_nvpair(nvl
, nvp
)) != NULL
&&
2497 nvpair_value_nvlist(nvp
, &valp
) == 0) {
2505 * Returns the version number of the plugin which created the metadata
2508 ndmp_context_get_version(ndmp_context_t
*nctx
)
2510 tlm_commands_t
*cmds
;
2511 ndmp_metadata_header_t
*mhp
;
2516 int align
= RECORDSIZE
- 1;
2518 if (nctx
== NULL
|| (cmds
= (tlm_commands_t
*)nctx
->nc_cmds
) == NULL
)
2521 if ((lcmd
= cmds
->tcs_command
) == NULL
||
2522 lcmd
->tc_buffers
== NULL
)
2525 size
= sizeof (ndmp_metadata_header_t
);
2529 /* LINTED improper alignment */
2530 if ((mhp
= (ndmp_metadata_header_t
*)get_read_buffer(size
, &rv
,
2531 &actual_size
, lcmd
)) != NULL
) {
2532 if (strncmp(mhp
->nh_magic
, ZFS_META_MAGIC
,
2533 sizeof (mhp
->nh_magic
)) != 0) {
2534 /* No more metadata */
2535 tlm_unget_read_buffer(lcmd
->tc_buffers
, actual_size
);
2539 nctx
->nc_plversion
= mhp
->nh_plversion
;
2540 tlm_unget_read_buffer(lcmd
->tc_buffers
, actual_size
);
2543 return (nctx
->nc_plversion
);