📄 extract_list.c
字号:
/* if prompted for a tape, relay said prompt to the user */ if(sscanf(amidxtaped_line, "FEEDME %132s\n", desired_tape) == 1) { int done; g_printf(_("Load tape %s now\n"), desired_tape); dbprintf(_("Requesting tape %s from user\n"), desired_tape); done = okay_to_continue(am_has_feature(indexsrv_features, fe_amrecover_feedme_tape), 0, 0); if (done == 1) { if (am_has_feature(indexsrv_features, fe_amrecover_feedme_tape)) { char *reply = stralloc2("TAPE ", tape_device_name); send_to_tape_server(amidxtaped_streams[CTLFD].fd, reply); amfree(reply); } else { send_to_tape_server(amidxtaped_streams[CTLFD].fd, "OK"); } } else { send_to_tape_server(amidxtaped_streams[CTLFD].fd, "ERROR"); break; } } else if(strncmp_const(amidxtaped_line, "MESSAGE ") == 0) { g_printf("%s\n",&amidxtaped_line[8]); } else { g_fprintf(stderr, _("Strange message from tape server: %s"), amidxtaped_line); break; } } /* CTL might be close before DATA */ event_loop(0); aclose(child_pipe[1]); waitpid(pid, &extractor_status, 0); if(WEXITSTATUS(extractor_status) != 0){ int ret = WEXITSTATUS(extractor_status); if(ret == 255) ret = -1; g_printf(_("Extractor child exited with status %d\n"), ret); return -1; } return(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; char * cwd; char *l; int first; int otc; tapelist_t *tlist = NULL, *a_tlist; 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(a_tlist = tlist ; a_tlist != NULL; a_tlist = a_tlist->next) g_printf(" %s", a_tlist->label); g_printf("\n"); free_tapelist(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(a_tlist = tlist; a_tlist != NULL; a_tlist = a_tlist->next) g_printf(" %s", a_tlist->label); g_printf("\n"); free_tapelist(tlist); } } g_printf("\n"); cwd = g_get_current_dir(); if (cwd == NULL) { perror(_("extract_list: Current working directory unavailable")); exit(1); } g_printf(_("Restoring files into directory %s\n"), cwd); check_file_overwrite(cwd);#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 dbprintf(_("Checking with user before restoring into directory %s\n"), cwd); if (!okay_to_continue(0,0,0)) { amfree(cwd); return; } g_printf("\n"); if (!do_unlink_list()) { g_fprintf(stderr, _("Can't recover because I can't cleanup the cwd (%s)\n"), cwd); amfree(cwd); return; } free_unlink_list(); 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(a_tlist = tlist; a_tlist != NULL; a_tlist = a_tlist->next) g_printf(" %s", a_tlist->label); g_printf("\n"); free_tapelist(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); dbprintf(_("Requesting tape %s from user\n"), tlist->label); free_tapelist(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 ((extract_files_setup(elist->tape, elist->fileno)) == -1) { g_fprintf(stderr, _("amrecover - can't talk to tape server: %s\n"), errstr); return; } /* if the server have fe_amrecover_feedme_tape, it has asked for * the tape itself, even if the restore didn't succeed, we should * remove it. */ if(writer_intermediary(elist) == 0 || am_has_feature(indexsrv_features, fe_amrecover_feedme_tape)) delete_tape_list(elist); /* tape done so delete from list */ stop_amidxtaped(); }}static voidamidxtaped_response( void * datap, pkt_t * pkt, security_handle_t * sech){ int ports[NSTREAMS], *response_error = datap, i; char *p; char *tok; char *extra = NULL; assert(response_error != NULL); assert(sech != NULL); memset(ports, -1, SIZEOF(ports)); if (pkt == NULL) { errstr = newvstrallocf(errstr, _("[request failed: %s]"), security_geterror(sech)); *response_error = 1; return; } security_close_connection(sech, dump_hostname); if (pkt->type == P_NAK) {#if defined(PACKET_DEBUG) g_fprintf(stderr, _("got nak response:\n----\n%s\n----\n\n"), pkt->body);#endif tok = strtok(pkt->body, " "); if (tok == NULL || strcmp(tok, "ERROR") != 0) goto bad_nak; tok = strtok(NULL, "\n"); if (tok != NULL) { errstr = newvstralloc(errstr, "NAK: ", tok, NULL); *response_error = 1; } else {bad_nak: errstr = newstralloc(errstr, "request NAK"); *response_error = 2; } return; } if (pkt->type != P_REP) { errstr = newvstrallocf(errstr, _("received strange packet type %s: %s"), pkt_type2str(pkt->type), pkt->body); *response_error = 1; return; }#if defined(PACKET_DEBUG) g_fprintf(stderr, _("got response:\n----\n%s\n----\n\n"), pkt->body);#endif for(i = 0; i < NSTREAMS; i++) { ports[i] = -1; amidxtaped_streams[i].fd = NULL; } p = pkt->body; while((tok = strtok(p, " \n")) != NULL) { p = NULL; /* * Error response packets have "ERROR" followed by the error message * followed by a newline. */ if (strcmp(tok, "ERROR") == 0) { tok = strtok(NULL, "\n"); if (tok == NULL) tok = _("[bogus error packet]"); errstr = newstralloc(errstr, tok); *response_error = 2; return; } /* * Regular packets have CONNECT followed by three streams */ if (strcmp(tok, "CONNECT") == 0) { /* * Parse the three stream specifiers out of the packet. */ for (i = 0; i < NSTREAMS; i++) { tok = strtok(NULL, " "); if (tok == NULL || strcmp(tok, amidxtaped_streams[i].name) != 0) { extra = vstrallocf(_("CONNECT token is \"%s\": expected \"%s\""), tok ? tok : "(null)", amidxtaped_streams[i].name); goto parse_error; } tok = strtok(NULL, " \n"); if (tok == NULL || sscanf(tok, "%d", &ports[i]) != 1) { extra = vstrallocf(_("CONNECT %s token is \"%s\": expected a port number"), amidxtaped_streams[i].name, tok ? tok : "(null)"); goto parse_error; } } continue; } /* * OPTIONS [options string] '\n' */ if (strcmp(tok, "OPTIONS") == 0) { tok = strtok(NULL, "\n"); if (tok == NULL) { extra = stralloc(_("OPTIONS token is missing")); goto parse_error; }/* while((p = strchr(tok, ';')) != NULL) { *p++ = '\0'; if(strncmp_const(tok, "features=") == 0) { tok += sizeof("features=") - 1; am_release_feature_set(their_features); if((their_features = am_string_to_feature(tok)) == NULL) { errstr = newvstralloc(errstr, _("OPTIONS: bad features value: "), tok, NULL); goto parse_error; } } tok = p; }*/ continue; }/* extra = vstrallocf("next token is \"%s\": expected \"CONNECT\", \"ERROR\" or \"OPTIONS\""), tok ? tok : _("(null)")); goto parse_error;*/ } /* * Connect the streams to their remote ports */ for (i = 0; i < NSTREAMS; i++) { if (ports[i] == -1) continue; amidxtaped_streams[i].fd = security_stream_client(sech, ports[i]); dbprintf(_("amidxtaped_streams[%d].fd = %p\n"),i, amidxtaped_streams[i].fd); if (amidxtaped_streams[i].fd == NULL) { errstr = newvstrallocf(errstr,\ _("[could not connect %s stream: %s]"), amidxtaped_streams[i].name, security_geterror(sech)); goto connect_error; } } /* * Authenticate the streams */ for (i = 0; i < NSTREAMS; i++) { if (amidxtaped_streams[i].fd == NULL) continue; if (security_stream_auth(amidxtaped_streams[i].fd) < 0) { errstr = newvstrallocf(errstr, _("[could not authenticate %s stream: %s]"), amidxtaped_streams[i].name, security_stream_geterror(amidxtaped_streams[i].fd)); goto connect_error; } } /* * The CTLFD and DATAFD streams are mandatory. If we didn't get * them, complain. */ if (amidxtaped_streams[CTLFD].fd == NULL) { errstr = newvstrallocf(errstr, _("[couldn't open CTL streams]")); goto connect_error; } if (amidxtaped_streams[DATAFD].fd == NULL) { errstr = newvstrallocf(errstr, _("[couldn't open DATA streams]")); goto connect_error; } /* everything worked */ *response_error = 0; return;parse_error: if (extra) { errstr = newvstrallocf(errstr, _("[parse of reply message failed: %s]"), extra); } else { errstr = newvstrallocf(errstr, _("[parse of reply message failed: (no additional information)")); } amfree(extra); *response_error = 2; return;connect_error: stop_amidxtaped(); *response_error = 1;}/* * This is called when everything needs to shut down so event_loop() * will exit. */static voidstop_amidxtaped(void){ int i; for (i = 0; i < NSTREAMS; i++) { if (amidxtaped_streams[i].fd != NULL) { security_stream_close(amidxtaped_streams[i].fd); amidxtaped_streams[i].fd = NULL; } }}static char* ctl_buffer = NULL;/* gets a "line" from server and put in server_line *//* server_line is terminated with \0, \r\n is striped *//* returns -1 if error */intget_amidxtaped_line(void){ ssize_t size; char *newbuf, *s; void *buf; amfree(amidxtaped_line); if (!ctl_buffer) ctl_buffer = stralloc(""); while (!strstr(ctl_buffer,"\r\n")) { size = security_stream_read_sync(amidxtaped_streams[CTLFD].fd, &buf); if(size < 0) { return -1; } else if(size == 0) { return -1; } newbuf = alloc(strlen(ctl_buffer)+size+1); strncpy(newbuf, ctl_buffer, (size_t)(strlen(ctl_buffer) + size + 1)); memcpy(newbuf+strlen(ctl_buffer), buf, (size_t)size); newbuf[strlen(ctl_buffer)+size] = '\0'; amfree(ctl_buffer); ctl_buffer = newbuf; } s = strstr(ctl_buffer,"\r\n"); *s = '\0'; newbuf = stralloc(s+2); amidxtaped_line = stralloc(ctl_buffer); amfree(ctl_buffer); ctl_buffer = newbuf; return 0;}static voidread_amidxtaped_data( void * cookie, void * buf, ssize_t size){ int fd; assert(cookie != NULL); fd = *(int *)cookie; if (size < 0) { errstr = newstralloc2(errstr, _("amidxtaped read: "), security_stream_geterror(amidxtaped_streams[DATAFD].fd)); return; } /* * EOF. Stop and return. */ if (size == 0) { security_stream_close(amidxtaped_streams[DATAFD].fd); amidxtaped_streams[DATAFD].fd = NULL; /* * If the mesg fd has also shut down, then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -