/* * See in the tree with selected files what files were selected to be restored. */ static inline int set_files_to_restore(JCR *jcr, struct ndm_job_param *job, int32_t FileIndex, const char *restore_prefix, const char *ndmp_filesystem) { int len; int cnt = 0; TREE_NODE *node, *parent; POOL_MEM restore_pathname, tmp; node = first_tree_node(jcr->restore_tree_root); while (node) { /* * See if this is the wanted FileIndex and the user asked to extract it. */ if (node->FileIndex == FileIndex && node->extract) { pm_strcpy(restore_pathname, node->fname); /* * Walk up the parent until we hit the head of the list. */ for (parent = node->parent; parent; parent = parent->parent) { pm_strcpy(tmp, restore_pathname.c_str()); Mmsg(restore_pathname, "%s/%s", parent->fname, tmp.c_str()); } /* * We only want to restore the non pseudo NDMP names e.g. not the full backup stream name. */ if (!bstrncmp(restore_pathname.c_str(), "/@NDMP/", 7)) { /* * See if we need to strip the prefix from the filename. */ len = strlen(ndmp_filesystem); if (bstrncmp(restore_pathname.c_str(), ndmp_filesystem, len)) { add_to_namelist(job, restore_pathname.c_str() + len, restore_prefix, (char *)"", (char *)"", NDMP_INVALID_U_QUAD); } else { add_to_namelist(job, restore_pathname.c_str(), restore_prefix, (char *)"", (char *)"", NDMP_INVALID_U_QUAD); } cnt++; } } node = next_tree_node(node); } return cnt; }
static int file_tree_callback(const char *fpath, const struct stat *sb, int typeflag, __unused__ struct FTW *ftwbuf) { if (typeflag == FTW_DNR) return FTW_CONTINUE; if (typeflag == FTW_NS) return FTW_CONTINUE; if (ignore_files(fpath)) return FTW_SKIP_SUBTREE; // Check we can read it. if (check_stat_file(sb) == -1) return FTW_CONTINUE; if (shm->exit_reason != STILL_RUNNING) return FTW_STOP; add_to_namelist(fpath); files_in_index++; return FTW_CONTINUE; }
static void open_fds_from_path(const char *dirpath) { int before = files_in_index; /* old declaration int flags = FTW_DEPTH | FTW_ACTIONRETVAL | FTW_MOUNT; * android > 4.4 doesn't support FTW_ACTIONRETVAL anymore */ int flags = FTW_DEPTH | FTW_MOUNT; int ret; /* By default, don't follow symlinks so we only get each file once. * But, if we do something like -V /lib, then follow it * * I'm not sure about this, might remove later. */ if (victim_path == NULL) flags |= FTW_PHYS; if (victim_dev == NULL) { //run normally if no specific dev speficied ret = nftw(dirpath, file_tree_callback, 32, flags); if (ret != 0) { if (shm->exit_reason != EXIT_SIGINT) output(0, "Something went wrong during nftw(%s). (%d:%s)\n", dirpath, ret, strerror(errno)); return; } } else { //adding victim dev only! no recursion from file tree callback add_to_namelist(victim_dev); outputstd ("Adding only victim device: %s", victim_dev); files_in_index++; } output(0, "Added %d filenames from %s\n", files_in_index - before, dirpath); }
/* * Fill the NDMP restore environment table with the data for the data agent to act on. */ static inline bool fill_restore_environment(JCR *jcr, int32_t current_fi, struct ndm_job_param *job) { int i; char *bp; ndmp9_pval pv; FILESETRES *fileset; char *restore_pathname, *ndmp_filesystem, *restore_prefix, *level; POOL_MEM tape_device; POOL_MEM destination_path; ndmp_backup_format_option *nbf_options; /* * See if we know this backup format and get it options. */ nbf_options = ndmp_lookup_backup_format_options(job->bu_type); /* * Lookup the current fileindex and map it to an actual pathname. */ restore_pathname = lookup_fileindex(jcr, current_fi); if (!restore_pathname) { return false; } else { /* * Skip over the /@NDMP prefix. */ ndmp_filesystem = restore_pathname + 6; } /* * See if there is a level embedded in the pathname. */ bp = strrchr(ndmp_filesystem, '%'); if (bp) { *bp++ = '\0'; level = bp; } else { level = NULL; } /* * Lookup the environment stack saved during the backup so we can restore it. */ if (!db_get_ndmp_environment_string(jcr, jcr->db, &jcr->jr, ndmp_env_handler, &job->env_tab)) { /* * Fallback code try to build a environment stack that is good enough to * restore this NDMP backup. This is used when the data is not available in * the database when its either expired or when an old NDMP backup is restored * where the whole environment was not saved. */ if (!nbf_options || nbf_options->uses_file_history) { /* * We asked during the NDMP backup to receive file history info. */ pv.name = ndmp_env_keywords[NDMP_ENV_KW_HIST]; pv.value = ndmp_env_values[NDMP_ENV_VALUE_YES]; ndma_store_env_list(&job->env_tab, &pv); } /* * Tell the data agent what type of restore stream to expect. */ pv.name = ndmp_env_keywords[NDMP_ENV_KW_TYPE]; pv.value = job->bu_type; ndma_store_env_list(&job->env_tab, &pv); /* * Tell the data agent that this is a NDMP backup which uses a level indicator. */ if (level) { pv.name = ndmp_env_keywords[NDMP_ENV_KW_LEVEL]; pv.value = level; ndma_store_env_list(&job->env_tab, &pv); } /* * Tell the data engine what was backuped. */ pv.name = ndmp_env_keywords[NDMP_ENV_KW_FILESYSTEM]; pv.value = ndmp_filesystem; ndma_store_env_list(&job->env_tab, &pv); } /* * Lookup any meta tags that need to be added. */ fileset = jcr->res.fileset; for (i = 0; i < fileset->num_includes; i++) { int j; char *item; INCEXE *ie = fileset->include_items[i]; /* * Loop over each file = entry of the fileset. */ for (j = 0; j < ie->name_list.size(); j++) { item = (char *)ie->name_list.get(j); /* * See if the original path matches. */ if (bstrcasecmp(item, ndmp_filesystem)) { int k, l; FOPTS *fo; for (k = 0; k < ie->num_opts; k++) { fo = ie->opts_list[i]; /* * Parse all specific META tags for this option block. */ for (l = 0; l < fo->meta.size(); l++) { ndmp_parse_meta_tag(&job->env_tab, (char *)fo->meta.get(l)); } } } } } /* * See where to restore the data. */ restore_prefix = NULL; if (jcr->where) { restore_prefix = jcr->where; } else { restore_prefix = jcr->res.job->RestoreWhere; } if (!restore_prefix) { return false; } /* * Tell the data engine where to restore. */ if (nbf_options && nbf_options->restore_prefix_relative) { switch (*restore_prefix) { case '^': /* * Use the restore_prefix as an absolute restore prefix. * We skip the leading ^ that is the trigger for absolute restores. */ pm_strcpy(destination_path, restore_prefix + 1); break; default: /* * Use the restore_prefix as an relative restore prefix. */ if (strlen(restore_prefix) == 1 && *restore_prefix == '/') { pm_strcpy(destination_path, ndmp_filesystem); } else { pm_strcpy(destination_path, ndmp_filesystem); pm_strcat(destination_path, restore_prefix); } } } else { if (strlen(restore_prefix) == 1 && *restore_prefix == '/') { /* * Use the original pathname as restore prefix. */ pm_strcpy(destination_path, ndmp_filesystem); } else { /* * Use the restore_prefix as an absolute restore prefix. */ pm_strcpy(destination_path, restore_prefix); } } pv.name = ndmp_env_keywords[NDMP_ENV_KW_PREFIX]; pv.value = ndmp_filesystem; ndma_store_env_list(&job->env_tab, &pv); if (!nbf_options || nbf_options->needs_namelist) { if (set_files_to_restore(jcr, job, current_fi, destination_path.c_str(), ndmp_filesystem) == 0) { /* * There is no specific filename selected so restore everything. */ add_to_namelist(job, (char *)"", destination_path.c_str(), (char *)"", (char *)"", NDMP_INVALID_U_QUAD); } } /* * If we have a paired storage definition we put the storage daemon * auth key and the filesystem into the tape device name of the * NDMP session. This way the storage daemon can link the NDMP * data and the normal save session together. */ if (jcr->store_bsock) { Mmsg(tape_device, "%s@%s", jcr->sd_auth_key, restore_pathname + 6); job->tape_device = bstrdup(tape_device.c_str()); } free(restore_pathname); return true; }