📄 extract_list.c
字号:
* sizeof(char *))); switch(dumptype) { case IS_SAMBA:#ifdef SAMBA_CLIENT restore_args[j++] = stralloc("smbclient"); smbpass = findpass(file.disk, &domain); if (smbpass) { restore_args[j++] = stralloc(file.disk); passwd_field=j; restore_args[j++] = stralloc("-U"); restore_args[j++] = smbpass; if (domain) { restore_args[j++] = stralloc("-W"); restore_args[j++] = stralloc(domain); } else extra_params -= 2; } else extra_params -= 6; restore_args[j++] = stralloc("-d0"); restore_args[j++] = stralloc("-Tx"); restore_args[j++] = stralloc("-"); /* data on stdin */ break;#endif case IS_TAR: case IS_GNUTAR: restore_args[j++] = stralloc("tar"); restore_args[j++] = stralloc("--numeric-owner"); restore_args[j++] = stralloc("-xpGvf"); restore_args[j++] = stralloc("-"); /* data on stdin */ break; case IS_SAMBA_TAR: restore_args[j++] = stralloc("tar"); restore_args[j++] = stralloc("-xpvf"); restore_args[j++] = stralloc("-"); /* data on stdin */ break; case IS_UNKNOWN: case IS_DUMP: restore_args[j++] = stralloc("restore");#ifdef AIX_BACKUP restore_args[j++] = stralloc("-xB");#else#if defined(XFSDUMP) if (strcmp(file.program, XFSDUMP) == 0) { restore_args[j++] = stralloc("-v"); restore_args[j++] = stralloc("silent"); } else#endif#if defined(VDUMP) if (strcmp(file.program, VDUMP) == 0) { restore_args[j++] = stralloc("xf"); restore_args[j++] = stralloc("-"); /* data on stdin */ } else#endif { restore_args[j++] = stralloc("xbf"); restore_args[j++] = stralloc("2"); /* read in units of 1K */ restore_args[j++] = stralloc("-"); /* data on stdin */ }#endif } for (i = 0, fn = elist->files; i < files_off_tape; i++, fn = fn->next) { switch (dumptype) { case IS_TAR: case IS_GNUTAR: case IS_SAMBA_TAR: case IS_SAMBA: if (strcmp(fn->path, "/") == 0) restore_args[j++] = stralloc("."); else restore_args[j++] = stralloc2(".", fn->path); break; case IS_UNKNOWN: case IS_DUMP:#if defined(XFSDUMP) if (strcmp(file.program, XFSDUMP) == 0) { /* * xfsrestore needs a -s option before each file to be * restored, and also wants them to be relative paths. */ restore_args[j++] = stralloc("-s"); restore_args[j++] = stralloc(fn->path + 1); } else#endif { restore_args[j++] = stralloc(fn->path); } } }#if defined(XFSDUMP) if (strcmp(file.program, XFSDUMP) == 0) { restore_args[j++] = stralloc("-"); restore_args[j++] = stralloc("."); }#endif restore_args[j] = NULL; switch (dumptype) { case IS_SAMBA:#ifdef SAMBA_CLIENT cmd = stralloc(SAMBA_CLIENT); break;#else /* fall through to ... */#endif case IS_TAR: case IS_GNUTAR: case IS_SAMBA_TAR:#ifndef GNUTAR g_fprintf(stderr, _("warning: GNUTAR program not available.\n")); cmd = stralloc("tar");#else cmd = stralloc(GNUTAR);#endif break; case IS_UNKNOWN: case IS_DUMP: cmd = NULL;#if defined(DUMP) if (strcmp(file.program, DUMP) == 0) { cmd = stralloc(RESTORE); }#endif#if defined(VDUMP) if (strcmp(file.program, VDUMP) == 0) { cmd = stralloc(VRESTORE); }#endif#if defined(VXDUMP) if (strcmp(file.program, VXDUMP) == 0) { cmd = stralloc(VXRESTORE); }#endif#if defined(XFSDUMP) if (strcmp(file.program, XFSDUMP) == 0) { cmd = stralloc(XFSRESTORE); }#endif if (cmd == NULL) { g_fprintf(stderr, _("warning: restore program for %s not available.\n"), file.program); cmd = stralloc("restore"); } } if (cmd) { dbprintf(_("Exec'ing %s with arguments:\n"), cmd); for (i = 0; i < j; i++) { if( i == passwd_field) dbprintf("\tXXXXX\n"); else dbprintf("\t%s\n", restore_args[i]); } safe_fd(-1, 0); (void)execv(cmd, restore_args); /* only get here if exec failed */ save_errno = errno; for (i = 0; i < j; i++) { amfree(restore_args[i]); } amfree(restore_args); errno = save_errno; perror(_("amrecover couldn't exec")); g_fprintf(stderr, _(" problem executing %s\n"), cmd); amfree(cmd); } exit(1); /*NOT REACHED */}/* * Interpose something between the process writing out the dump (writing it to * some extraction program, really) and the socket from which we're reading, so * that we can do things like prompt for human interaction for multiple tapes. */voidwriter_intermediary( int ctl_fd, int data_fd, EXTRACT_LIST * elist){ int child_pipe[2]; pid_t pid; char buffer[DISK_BLOCK_BYTES]; ssize_t bytes_read; amwait_t extractor_status; int max_fd, nfound; SELECT_ARG_TYPE readset, selectset; struct timeval timeout; /* * If there's no distinct data channel (such as if we're talking to an * older server), don't bother doing anything complicated. Just run the * extraction. */ if(data_fd == -1){ extract_files_child(ctl_fd, elist); /*NOTREACHED*/ } if(pipe(child_pipe) == -1) { error(_("extract_list - error setting up pipe to extractor: %s\n"), strerror(errno)); /*NOTREACHED*/ } /* okay, ready to extract. fork a child to do the actual work */ if ((pid = fork()) == 0) { /* this is the child process */ /* never gets out of this clause */ aclose(child_pipe[1]); extract_files_child(child_pipe[0], elist); /*NOTREACHED*/ } /* This is the parent */ if (pid == -1) { error(_("writer_intermediary - error forking child")); /*NOTREACHED*/ } aclose(child_pipe[0]); if(data_fd > ctl_fd) max_fd = data_fd+1; else max_fd = ctl_fd+1; FD_ZERO(&readset); FD_SET(data_fd, &readset); FD_SET(ctl_fd, &readset); do { timeout.tv_sec = READ_TIMEOUT; timeout.tv_usec = 0; FD_COPY(&readset, &selectset); nfound = select(max_fd, &selectset, NULL, NULL, &timeout); if(nfound < 0) { g_fprintf(stderr,_("select error: %s\n"), strerror(errno)); break; } if (nfound == 0) { /* timeout */ g_fprintf(stderr, _("timeout waiting %d seconds for restore\n"), READ_TIMEOUT); g_fprintf(stderr, _("increase READ_TIMEOUT in recover-src/extract_list.c if your tape is slow\n")); break; } if(FD_ISSET(ctl_fd, &selectset)) { bytes_read = read(ctl_fd, buffer, sizeof(buffer)-1); switch(bytes_read) { case -1: if ((errno != EINTR) && (errno != EAGAIN)) { if (errno != EPIPE) { g_fprintf(stderr,_("writer ctl fd read error: %s"), strerror(errno)); } FD_CLR(ctl_fd, &readset); } break; case 0: FD_CLR(ctl_fd, &readset); break; default: { char desired_tape[MAX_TAPE_LABEL_BUF]; buffer[bytes_read] = '\0'; /* if prompted for a tape, relay said prompt to the user */ if(sscanf(buffer, "FEEDME %132s\n", desired_tape) == 1) { int done = 0; while (!done) { char *input = NULL; g_printf(_("Please insert tape %s. Continue? [Y|n]: "), desired_tape); fflush(stdout); input = agets(stdin); /* strips \n */ if (strcasecmp("", input) == 0|| strcasecmp("y", input) == 0|| strcasecmp("yes", input) == 0) { send_to_tape_server(tape_control_sock, "OK"); done = 1; } else if (strcasecmp("n", input) == 0|| strcasecmp("no", input) == 0) { send_to_tape_server(tape_control_sock, "ERROR"); /* Abort! We are the middle process, so just die. */ exit(EXIT_FAILURE); } amfree(input); } } else { g_fprintf(stderr, _("Strange message from tape server: %s"), buffer); break; } } } } /* now read some dump data */ if(FD_ISSET(data_fd, &selectset)) { bytes_read = read(data_fd, buffer, sizeof(buffer)-1); switch(bytes_read) { case -1: if ((errno != EINTR) && (errno != EAGAIN)) { if (errno != EPIPE) { g_fprintf(stderr,_("writer data fd read error: %s"), strerror(errno)); } FD_CLR(data_fd, &readset); } break; case 0: FD_CLR(data_fd, &readset); break; default: /* * spit what we got from the server to the child * process handling actual dumpfile extraction */ if(fullwrite(child_pipe[1], buffer, (size_t)bytes_read) < 0) { if(errno == EPIPE) { error(_("pipe data reader has quit: %s\n"), strerror(errno)); /* NOTREACHED */ } error(_("Write error to extract child: %s\n"), strerror(errno)); /* NOTREACHED */ } break; } } } while(FD_ISSET(ctl_fd, &readset) || FD_ISSET(data_fd, &readset)); aclose(child_pipe[1]); waitpid(pid, &extractor_status, 0); if(WEXITSTATUS(extractor_status) != 0){ int ret = WEXITSTATUS(extractor_status); if(ret == 255) ret = -1; error(_("Extractor child exited with status %d\n"), ret); /*NOTREACHED*/ } exit(0);}/* exec restore to do the actual restoration *//* does the actual extraction of files *//* * The original design had the dump image being returned exactly as it * appears on the tape, and this routine getting from the index server * whether or not it is compressed, on the assumption that the tape * server may not know how to uncompress it. But * - Amrestore can't do that. It returns either compressed or uncompressed * (always). Amrestore assumes it can uncompress files. It is thus a good * idea to run the tape server on a machine with gzip. * - The information about compression in the disklist is really only * for future dumps. It is possible to change compression on a drive * so the information in the disklist may not necessarily relate to * the dump image on the tape. * Consequently the design was changed to assuming that amrestore can * uncompress any dump image and have it return an uncompressed file * always. */voidextract_files(void){ EXTRACT_LIST *elist; pid_t pid; amwait_t child_stat; char buf[STR_SIZE]; char *l; int first; int otc; tapelist_t *tlist = NULL; if (!is_extract_list_nonempty()) { g_printf(_("Extract list empty - No files to extract!\n")); return; } clean_extract_list(); /* get tape device name from index server if none specified */ if (tape_server_name == NULL) { tape_server_name = newstralloc(tape_server_name, server_name); } if (tape_device_name == NULL) { if (send_command("TAPE") == -1) exit(1); if (get_reply_line() == -1) exit(1); l = reply_line(); if (!server_happy()) { g_printf("%s\n", l); exit(1); } /* skip reply number */ tape_device_name = newstralloc(tape_device_name, l+4); } if (strcmp(tape_device_name, "/dev/null") == 0) { g_printf(_("amrecover: warning: using %s as the tape device will not work\n"), tape_device_name); } first=1; for (elist = first_tape_list(); elist != NULL; elist = next_tape_list(elist)) if(elist->tape[0]!='/') { if(first) { g_printf(_("\nExtracting files using tape drive %s on host %s.\n"), tape_device_name, tape_server_name); g_printf(_("The following tapes are needed:")); first=0; } else g_printf(" "); tlist = unmarshal_tapelist_str(elist->tape); for( ; tlist != NULL; tlist = tlist->next) g_printf(" %s", tlist->label); g_printf("\n"); amfree(tlist); } first=1; for (elist = first_tape_list(); elist != NULL; elist = next_tape_list(elist)) { if(elist->tape[0]=='/') { if(first) { g_printf(_("\nExtracting files from holding disk on host %s.\n"), tape_server_name); g_printf(_("The following files are needed:")); first=0; } else g_printf(" "); tlist = unmarshal_tapelist_str(elist->tape); for( ; tlist != NULL; tlist = tlist->next) g_printf(" %s", tlist->label); g_printf("\n"); amfree(tlist); } } g_printf("\n"); if (getcwd(buf, sizeof(buf)) == NULL) { perror(_("extract_list: Cannot determine current working directory")); exit(1); } g_printf(_("Restoring files into directory %s\n"), buf);#ifdef SAMBA_CLIENT if (samba_extract_method == SAMBA_SMBCLIENT) g_printf(_("(unless it is a Samba backup, that will go through to the SMB server)\n"));#endif if (!okay_to_continue(0,0,0)) return; g_printf("\n"); while ((elist = first_tape_list()) != NULL) { if(elist->tape[0]=='/') { dump_device_name = newstralloc(dump_device_name, elist->tape); g_printf(_("Extracting from file ")); tlist = unmarshal_tapelist_str(dump_device_name); for( ; tlist != NULL; tlist = tlist->next) g_printf(" %s", tlist->label); g_printf("\n"); amfree(tlist); } else { g_printf(_("Extracting files using tape drive %s on host %s.\n"), tape_device_name, tape_server_name); tlist = unmarshal_tapelist_str(elist->tape); g_printf(_("Load tape %s now\n"), tlist->label); amfree(tlist); otc = okay_to_continue(1,1,0); if (otc == 0) return; else if (otc == SKIP_TAPE) { delete_tape_list(elist); /* skip this tape */ continue; } dump_device_name = newstralloc(dump_device_name, tape_device_name); } dump_datestamp = newstralloc(dump_datestamp, elist->date); /* connect to the tape handler daemon on the tape drive server */ if ((tape_control_sock = extract_files_setup(elist->tape, elist->fileno)) == -1) { g_fprintf(stderr, _("amrecover - can't talk to tape server\n")); return; } /* okay, ready to extract. fork a child to do the actual work */ if ((pid = fork()) == 0) { /* this is the child process */ /* never gets out of this clause */ writer_intermediary(tape_control_sock, tape_data_sock, elist); /*NOT REACHED*/ } /* this is the parent */ if (pid == -1) { perror(_("extract_list - error forking child")); aclose(tape_control_sock); exit(1); } /* store the child pid globally so that it can be killed on intr */ extract_restore_child_pid = pid; /* wait for the child process to finish */ if ((pid = waitpid(-1, &child_stat, 0)) == (pid_t)-1) { perror(_("extract_list - error waiting for child")); exit(1); } if(tape_data_sock != -1) { aclose(tape_data_sock); } if (pid == extract_restore_child_pid) { extract_restore_child_pid = -1; } else { g_fprintf(stderr, _("extract list - unknown child terminated?\n")); exit(1); } if ((WIFEXITED(child_stat) != 0) && (WEXITSTATUS(child_stat) != 0)) { g_fprintf(stderr, _("extract_list - child returned non-zero status: %d\n"), WEXITSTATUS(child_stat)); otc = okay_to_continue(0,0,1); if(otc == 0) return; if(otc == 1) { delete_tape_list(elist); /* tape failed so delete from list */ } } else { delete_tape_list(elist); /* tape done so delete from list */ } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -