Changeset 3877 in MondoRescue for branches/3.3/mondo/src/common/libmondo-stream.c
- Timestamp:
- Mar 8, 2024, 3:59:07 AM (4 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mondo/src/common/libmondo-stream.c
r3872 r3877 200 200 return (retval); 201 201 } 202 203 204 205 /** 206 * Start to write to the next tape. Assume the user has already inserted it. 207 * @param bkpinfo The backup information structure. @c bkpinfo->media_device is the only field used. 208 * @return 0 for success, nonzero for failure. 209 */ 210 int start_to_write_to_next_tape() 211 { 212 int res = 0; 213 char *command = NULL; 214 215 if (bkpinfo->media_device == NULL) { 216 log_it("Unable to open out from NULL device"); 217 return (1); 218 } 219 220 paranoid_pclose(g_tape_stream); 221 sync(); 222 sync(); 223 sync(); 224 log_it("New tape requested."); 225 insist_on_this_tape_number(g_current_media_number + 1); // will increment g_current_media, too 226 if (bkpinfo->backup_media_type == cdstream) { 227 mr_asprintf(command, "cdrecord -eject dev=%s speed=%d fs=24m -waiti - >> %s 2>> %s", bkpinfo->media_device, bkpinfo->cdrw_speed, MONDO_LOGFILE, MONDO_LOGFILE); 228 log_it("Opening OUT to next CD with the command"); 229 log_it(command); 230 log_it("Let's see what happens, shall we?"); 231 g_tape_stream = popen(command, "w"); 232 mr_free(command); 233 234 if (!g_tape_stream) { 235 log_to_screen("Failed to openout to cdstream (fifo)"); 236 return (1); 237 } 238 } else { 239 log_it("Opening OUT to next tape"); 240 if (!(g_tape_stream = open_device_via_buffer(bkpinfo->media_device, 'w', bkpinfo->internal_tape_block_size))) { 241 log_OS_error(g_tape_fifo); 242 log_to_screen("Cannot openin stream device"); 243 return (1); 244 } 245 } 246 g_tape_posK = 0; 247 g_sigpipe = FALSE; 248 res += write_header_block_to_stream((off_t)0, "start-of-tape", BLK_START_OF_TAPE); /* just in case */ 249 res += write_header_block_to_stream((off_t)0, "start-of-backup", BLK_START_OF_BACKUP); /* just in case */ 250 return (res); 251 } 252 253 254 255 /** 256 * Decide whether we should start a new tape. This is TRUE if we've run out of tape 257 * (got SIGPIPE) or look like we will. 258 * @param mediasize The size of the tape in megabytes. 259 * @param length_of_incoming_file The length of the file we're about to write, in bytes. 260 * @bug This seems like it'll only work for media_size != autodetect, but Mondo only allows 261 * autodetecting the size. Huh? 262 */ 263 264 /* TODO: Should be reviewed for mediasize being a off_t ??? */ 265 bool 266 should_we_write_to_next_tape(long mediasize, 267 off_t length_of_incoming_file) 268 { 269 /*@ bool's ***************************************************** */ 270 bool we_need_a_new_tape = FALSE; 271 272 /*@ end vars *************************************************** */ 273 274 if (mediasize == 0) { 275 return (FALSE); 276 } 277 if (mediasize > 0 && (g_tape_posK >> 10 >= mediasize)) { 278 log_it("mediasize = %ld", mediasize); 279 we_need_a_new_tape = TRUE; 280 log_to_screen("Should have started a new tape/CD already"); 281 } 282 if ((g_tape_posK + length_of_incoming_file / 1024) >> 10 >= 283 mediasize - (SLICE_SIZE * 4 / 1024)) { 284 log_it("g_tape_posK = %ld\nmediasize = %ld\n", g_tape_posK, 285 mediasize); 286 we_need_a_new_tape = TRUE; 287 } 288 return (we_need_a_new_tape); 289 } 290 291 202 292 203 293 … … 354 444 355 445 446 /** 447 * Copy a file from the opened stream (CD or tape) to @p outfile. 448 * @param outfile The file to write to. 449 * @param size The size of the file in the input stream. 450 * @return 0 for success, nonzero for failure. 451 */ 452 int 453 read_file_from_stream_to_file(char *outfile, long long size) 454 { 455 456 /*@ int ******************************************************** */ 457 int res; 458 459 /*@ end vars *************************************************** */ 460 461 res = read_file_from_stream_FULL(outfile, NULL, size); 462 463 return (res); 464 } 465 466 467 468 356 469 int read_EXAT_files_from_tape(long long *ptmp_size, char *tmp_fname, 357 470 int *pctrl_chr, char *xattr_fname, … … 419 532 return (res); 420 533 } 534 535 536 /** 537 * Copy @p infile to the opened stream (CD or tape). 538 * @param bkpinfo The backup information structure. @c bkpinfo->media_size is the only field used. 539 * @param infile The file to write to the stream. 540 * @return 0 for success, nonzero for failure. 541 */ 542 int write_file_to_stream_from_file(char *infile) 543 { 544 /*@ buffers **************************************************** */ 545 char datablock[TAPE_BLOCK_SIZE]; 546 char *checksum = NULL; 547 char *infile_basename; 548 549 /*@ int ******************************************************** */ 550 int retval = 0; 551 int noof_blocks; 552 553 /* unsigned int ch; */ 554 unsigned int crc16; 555 unsigned int crctt; 556 557 /*@ pointers *************************************************** */ 558 FILE *fin; 559 char *p; 560 561 /*@ long ******************************************************* */ 562 long bytes_to_read = 0; 563 long i; 564 565 off_t filesize; 566 567 #ifdef EXTRA_TAPE_CHECKSUMS 568 int ch; 569 #endif 570 571 /*@ initialize ************************************************ */ 572 crc16 = 0; 573 crctt = 0; 574 575 576 577 /*@ end vars *************************************************** */ 578 579 infile_basename = strrchr(infile, '/'); 580 if (infile_basename) { 581 infile_basename++; 582 } else { 583 infile_basename = infile; 584 } 585 filesize = length_of_file(infile); 586 if (should_we_write_to_next_tape(bkpinfo->media_size, filesize)) { 587 start_to_write_to_next_tape(); 588 write_backcatalog_to_tape(); 589 } 590 p = strrchr(infile, '/'); 591 if (!p) { 592 p = infile; 593 } else { 594 p++; 595 } 596 log_it("Writing file '%s' to tape (%ld KB)", p, (long) filesize >> 10); 597 write_header_block_to_stream(filesize, infile_basename, BLK_START_FILE); 598 //go_here_to_restart_saving_of_file: 599 if (!(fin = fopen(infile, "r"))) { 600 log_OS_error(infile); 601 return (1); 602 } 603 for (noof_blocks = 0; filesize > 0; 604 noof_blocks++, filesize -= bytes_to_read) { 605 if (filesize < TAPE_BLOCK_SIZE) { 606 bytes_to_read = (long) filesize; 607 for (i = 0; i < TAPE_BLOCK_SIZE; i++) { 608 datablock[i] = '\0'; 609 } 610 } else { 611 bytes_to_read = TAPE_BLOCK_SIZE; 612 } 613 if (fread(datablock, 1, (size_t) bytes_to_read, fin)) { 614 // FIXME 615 } 616 g_tape_posK += 617 fwrite(datablock, 1, /*bytes_to_read */ 618 (size_t) TAPE_BLOCK_SIZE, 619 g_tape_stream) / 1024; 620 if (g_sigpipe) { 621 log_it("Sigpipe occurred recently. I'll start a new tape."); 622 fclose(fin); 623 g_sigpipe = FALSE; 624 start_to_write_to_next_tape(); 625 write_backcatalog_to_tape(); // kinda-sorta recursive :) 626 return (0); 627 } 628 #ifdef EXTRA_TAPE_CHECKSUMS 629 for (i = 0; i < bytes_to_read; i++) { 630 ch = datablock[i]; 631 crc16 = updcrcr(crc16, (unsigned) ch); 632 crctt = updcrc(crctt, (unsigned) ch); 633 } 634 #endif 635 } 636 paranoid_fclose(fin); 637 mr_asprintf(checksum, "%04x%04x", crc16, crctt); 638 /* TODO: what does it do ??? */ 639 write_header_block_to_stream((off_t)g_current_media_number, checksum, BLK_STOP_FILE); 640 mr_free(checksum); 641 642 // log_it("File '%s' written to tape.", infile); 643 return (retval); 644 } 645 646 647 648 649 650 421 651 422 652 … … 566 796 } 567 797 568 569 570 571 /**572 * Open the CD stream for input.573 * @param bkpinfo The backup information structure. Passed to openin_tape().574 * @return 0 for success, nonzero for failure.575 * @note Equivalent to openin_tape() for now, but don't count on this behavior.576 */577 int openin_cdstream()578 {579 return (openin_tape());580 }581 582 /**583 * FIFO used to read/write to the tape device.584 * @bug This seems obsolete now that we call an external @c buffer program. Please look onto this.585 */586 char g_tape_fifo[MAX_STR_LEN];587 588 589 590 int set_tape_block_size_with_mt(long internal_tape_block_size)591 {592 char *tmp = NULL;593 int res;594 595 if (bkpinfo->media_device == NULL) {596 return(1);597 }598 599 if (strncmp(bkpinfo->media_device, "/dev/", 5)) {600 log_msg(1, "Not using 'mt setblk'. This isn't an actual /dev entry.");601 return (0);602 }603 mr_asprintf(tmp, "mt -f %s setblk %ld", bkpinfo->media_device, internal_tape_block_size);604 res = run_program_and_log_output(tmp, 3);605 mr_free(tmp);606 return (res);607 }608 609 /**610 * Return the non-rewinding device when passed the normal one611 * @param tapedev The tape device to open for writing.612 * @note the caller needs to free the string returned613 */614 char *get_non_rewind_dev(char *tapedev)615 {616 617 char *ntapedev = NULL;618 char *p = NULL;619 char *q = NULL;620 char *r = NULL;621 622 ntapedev = (char *)mr_malloc(strlen(tapedev)+2*sizeof(char));623 p = strrchr(tapedev,'/');624 if (p == NULL) {625 log_it("Didn't find a '/' in %s",tapedev);626 return(NULL);627 }628 629 /* Copy tapedev content up to the last / */630 q = tapedev;631 r = ntapedev;632 while (q != p) {633 *r = *q;634 r++;635 q++;636 }637 /* Copy the '/' */638 *r = *q;639 r++;640 q++;641 /* Adds a 'n' - non-rewinding */642 *r = 'n';643 r++;644 /* Copy the rest of tapedev */645 while (*q != '\0') {646 *r = *q;647 r++;648 q++;649 }650 *r = '\0';651 if (mt_says_tape_exists(ntapedev)) {652 log_it("Non-rewinding tape device is %s",ntapedev);653 } else {654 log_it("Unable to find non-rewinding tape device.");655 ntapedev = NULL;656 }657 return(ntapedev);658 }659 660 661 662 /**663 * Handle OBDR if we were asked to do so664 * @param tapedev The tape device to open for reading.665 */666 int skip_obdr(void)667 {668 char *command = NULL;669 int res = 0;670 671 if (bkpinfo->media_device == NULL) {672 return(1);673 }674 675 log_it("Skipping OBDR headers");676 mr_asprintf(command, "mt -f %s rewind",bkpinfo->media_device);677 res = run_program_and_log_output(command, 1);678 paranoid_free(command);679 680 mr_asprintf(command, "mt -f %s fsf 2",bkpinfo->media_device);681 res = run_program_and_log_output(command, 1);682 paranoid_free(command);683 684 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);685 return(res);686 }687 688 /**689 * Handle OBDR if we were asked to do so690 * @param tapedev The tape device to open for writing.691 * @return 0 for success, nonzero for failure.692 * @note This should be called ONLY from backup processes. It will OVERWRITE ANY693 * EXISTING DATA on the tape!694 */695 int create_obdr(void)696 {697 698 char *command = NULL;699 int res = 0;700 701 if (bkpinfo->media_device == NULL) {702 return(1);703 }704 705 log_it("Creating OBDR headers");706 /* OBDR: First block 10 kB of zero bs = 512 */707 mr_asprintf(command, "mt -f %s compression off",bkpinfo->media_device);708 res = run_program_and_log_output(command, 1);709 paranoid_free(command);710 711 mr_asprintf(command, "mt -f %s rewind",bkpinfo->media_device);712 res += run_program_and_log_output(command, 1);713 paranoid_free(command);714 715 set_tape_block_size_with_mt(512);716 717 mr_asprintf(command, "dd if=/dev/zero of=%s bs=512 count=20",bkpinfo->media_device);718 res += run_program_and_log_output(command, 1);719 paranoid_free(command);720 721 /* OBDR: then ISO boot image bs = 2048 */722 set_tape_block_size_with_mt(2048);723 724 mr_asprintf(command, "dd if=%s of=%s bs=2048",MINDI_CACHE"/mindi.iso",bkpinfo->media_device);725 res += run_program_and_log_output(command, 1);726 paranoid_free(command);727 728 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);729 730 /* restore compression mode on */731 mr_asprintf(command, "mt -f %s compression on",bkpinfo->media_device);732 res = run_program_and_log_output(command, 1);733 paranoid_free(command);734 735 return(res);736 }737 798 738 799 … … 871 932 872 933 934 935 /** 936 * Open the CD stream for input. 937 * @param bkpinfo The backup information structure. Passed to openin_tape(). 938 * @return 0 for success, nonzero for failure. 939 * @note Equivalent to openin_tape() for now, but don't count on this behavior. 940 */ 941 int openin_cdstream() 942 { 943 return (openin_tape()); 944 } 945 946 /** 947 * FIFO used to read/write to the tape device. 948 * @bug This seems obsolete now that we call an external @c buffer program. Please look onto this. 949 */ 950 char g_tape_fifo[MAX_STR_LEN]; 951 952 953 954 int set_tape_block_size_with_mt(long internal_tape_block_size) 955 { 956 char *tmp = NULL; 957 int res; 958 959 if (bkpinfo->media_device == NULL) { 960 return(1); 961 } 962 963 if (strncmp(bkpinfo->media_device, "/dev/", 5)) { 964 log_msg(1, "Not using 'mt setblk'. This isn't an actual /dev entry."); 965 return (0); 966 } 967 mr_asprintf(tmp, "mt -f %s setblk %ld", bkpinfo->media_device, internal_tape_block_size); 968 res = run_program_and_log_output(tmp, 3); 969 mr_free(tmp); 970 return (res); 971 } 972 973 /** 974 * Return the non-rewinding device when passed the normal one 975 * @param tapedev The tape device to open for writing. 976 * @note the caller needs to free the string returned 977 */ 978 char *get_non_rewind_dev(char *tapedev) 979 { 980 981 char *ntapedev = NULL; 982 char *p = NULL; 983 char *q = NULL; 984 char *r = NULL; 985 986 ntapedev = (char *)mr_malloc(strlen(tapedev)+2*sizeof(char)); 987 p = strrchr(tapedev,'/'); 988 if (p == NULL) { 989 log_it("Didn't find a '/' in %s",tapedev); 990 return(NULL); 991 } 992 993 /* Copy tapedev content up to the last / */ 994 q = tapedev; 995 r = ntapedev; 996 while (q != p) { 997 *r = *q; 998 r++; 999 q++; 1000 } 1001 /* Copy the '/' */ 1002 *r = *q; 1003 r++; 1004 q++; 1005 /* Adds a 'n' - non-rewinding */ 1006 *r = 'n'; 1007 r++; 1008 /* Copy the rest of tapedev */ 1009 while (*q != '\0') { 1010 *r = *q; 1011 r++; 1012 q++; 1013 } 1014 *r = '\0'; 1015 if (mt_says_tape_exists(ntapedev)) { 1016 log_it("Non-rewinding tape device is %s",ntapedev); 1017 } else { 1018 log_it("Unable to find non-rewinding tape device."); 1019 ntapedev = NULL; 1020 } 1021 return(ntapedev); 1022 } 1023 1024 1025 1026 /** 1027 * Handle OBDR if we were asked to do so 1028 * @param tapedev The tape device to open for reading. 1029 */ 1030 int skip_obdr(void) 1031 { 1032 char *command = NULL; 1033 int res = 0; 1034 1035 if (bkpinfo->media_device == NULL) { 1036 return(1); 1037 } 1038 1039 log_it("Skipping OBDR headers"); 1040 mr_asprintf(command, "mt -f %s rewind",bkpinfo->media_device); 1041 res = run_program_and_log_output(command, 1); 1042 paranoid_free(command); 1043 1044 mr_asprintf(command, "mt -f %s fsf 2",bkpinfo->media_device); 1045 res = run_program_and_log_output(command, 1); 1046 paranoid_free(command); 1047 1048 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size); 1049 return(res); 1050 } 1051 1052 /** 1053 * Handle OBDR if we were asked to do so 1054 * @param tapedev The tape device to open for writing. 1055 * @return 0 for success, nonzero for failure. 1056 * @note This should be called ONLY from backup processes. It will OVERWRITE ANY 1057 * EXISTING DATA on the tape! 1058 */ 1059 int create_obdr(void) 1060 { 1061 1062 char *command = NULL; 1063 int res = 0; 1064 1065 if (bkpinfo->media_device == NULL) { 1066 return(1); 1067 } 1068 1069 log_it("Creating OBDR headers"); 1070 /* OBDR: First block 10 kB of zero bs = 512 */ 1071 mr_asprintf(command, "mt -f %s compression off",bkpinfo->media_device); 1072 res = run_program_and_log_output(command, 1); 1073 paranoid_free(command); 1074 1075 mr_asprintf(command, "mt -f %s rewind",bkpinfo->media_device); 1076 res += run_program_and_log_output(command, 1); 1077 paranoid_free(command); 1078 1079 set_tape_block_size_with_mt(512); 1080 1081 mr_asprintf(command, "dd if=/dev/zero of=%s bs=512 count=20",bkpinfo->media_device); 1082 res += run_program_and_log_output(command, 1); 1083 paranoid_free(command); 1084 1085 /* OBDR: then ISO boot image bs = 2048 */ 1086 set_tape_block_size_with_mt(2048); 1087 1088 mr_asprintf(command, "dd if=%s of=%s bs=2048",MINDI_CACHE"/mindi.iso",bkpinfo->media_device); 1089 res += run_program_and_log_output(command, 1); 1090 paranoid_free(command); 1091 1092 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size); 1093 1094 /* restore compression mode on */ 1095 mr_asprintf(command, "mt -f %s compression on",bkpinfo->media_device); 1096 res = run_program_and_log_output(command, 1); 1097 paranoid_free(command); 1098 1099 return(res); 1100 } 1101 1102 873 1103 /** 874 1104 * Start writing to a CD stream. … … 948 1178 } 949 1179 return (0); 950 }951 952 953 954 955 /**956 * Copy a file from the opened stream (CD or tape) to @p outfile.957 * @param outfile The file to write to.958 * @param size The size of the file in the input stream.959 * @return 0 for success, nonzero for failure.960 */961 int962 read_file_from_stream_to_file(char *outfile, long long size)963 {964 965 /*@ int ******************************************************** */966 int res;967 968 /*@ end vars *************************************************** */969 970 res = read_file_from_stream_FULL(outfile, NULL, size);971 972 return (res);973 }974 975 976 977 /**978 * Copy a file from the currently opened stream (CD or tape) to the stream indicated979 * by @p fout.980 * @param bkpinfo The backup information structure. @c bkpinfo->media_size is the only field used.981 * @param fout The stream to write the file to.982 * @param size The size of the file in bytes.983 * @return 0 for success, nonzero for failure.984 */985 int986 read_file_from_stream_to_stream(FILE * fout, long long size)987 {988 989 /*@ int ******************************************************** */990 int res;991 992 /*@ end vars *************************************************** */993 994 res = read_file_from_stream_FULL(NULL, fout, size);995 /* fflush(g_tape_stream);996 fflush(fout);*/997 return (res);998 1180 } 999 1181 … … 1147 1329 1148 1330 /** 1149 * Read a header block from the currently opened stream (CD or tape). 1150 * This block indicates the length of the following file (if it's file-related) 1151 * the filename (if it's file-related), and the block type. 1152 * @param plen Where to put the length of the file. Valid only for file-related header blocks. 1153 * @param filename Where to put the name of the file. Valid only for file-related header blocks. 1154 * @param pcontrol_char Where to put the type of block (e.g. start-file, end-file, start-tape, ...) 1155 * @return 0 for success, nonzero for failure. 1156 * @note If you read a marker (@p pcontrol_char) you're not expecting, you can call wrong_marker(). 1331 * Copy a file from the currently opened stream (CD or tape) to the stream indicated 1332 * by @p fout. 1333 * @param bkpinfo The backup information structure. @c bkpinfo->media_size is the only field used. 1334 * @param fout The stream to write the file to. 1335 * @param size The size of the file in bytes. 1336 * @return 0 for success, nonzero for failure. 1157 1337 */ 1158 1338 int 1159 read_header_block_from_stream(long long *plen, char *filename, 1160 int *pcontrol_char) 1161 { 1162 1163 /*@ buffers ***************************************************** */ 1164 char *tempblock; 1165 char *tmp = NULL; 1166 1167 /*@ int ********************************************************* */ 1168 int i, retval; 1339 read_file_from_stream_to_stream(FILE * fout, long long size) 1340 { 1341 1342 /*@ int ******************************************************** */ 1343 int res; 1169 1344 1170 1345 /*@ end vars *************************************************** */ 1171 1346 1172 tempblock = (char *) malloc((size_t) TAPE_BLOCK_SIZE); 1173 1174 for (i = 0; i < (int) TAPE_BLOCK_SIZE; i++) { 1175 tempblock[i] = 0; 1176 } 1177 while (!(*pcontrol_char = tempblock[7000])) { 1178 g_tape_posK += fread(tempblock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream) / 1024; 1179 } 1180 memcpy((char *) plen, tempblock + 7001, sizeof(long long)); 1181 if (strcmp(tempblock + 6000 + *pcontrol_char, STR_HEADER)) { 1182 log_it("Bad header block at %ld K", (long) g_tape_posK); 1183 } 1184 strcpy(filename, tempblock + 1000); 1185 if (*pcontrol_char == BLK_ABORTED_BACKUP) { 1186 log_to_screen("I can't verify an aborted backup."); 1187 retval = 1; 1188 } else { 1189 retval = 0; 1190 } 1191 for (i = 1000; i < 1020; i++) { 1192 if (tempblock[i] < 32 || tempblock[i] > 126) { 1193 tempblock[i] = ' '; 1194 } 1195 } 1196 tempblock[i] = '\0'; 1197 tmp = marker_to_string(*pcontrol_char); 1198 log_msg(6, "%s (fname=%s, size=%ld K)", tmp, tempblock + 1000, (long) (*plen) >> 10); 1199 mr_free(tmp); 1200 paranoid_free(tempblock); 1201 return (retval); 1202 } 1203 1204 1205 1206 /** 1207 * Add specified file/slice to the internal catalog of all archives written. 1208 * This lets us restart on a new CD/tape/whatever if it runs out of room. We just 1209 * write the last [buffer size] MB from the catalog to the new tape, so we know 1210 * we have @e all archives on some CD/tape/whatever. 1211 * @param type The type of file we're cataloging (afioball, slice, something else) 1212 * @param number The fileset number or biggiefile number. 1213 * @param aux The slice number if it's a biggiefile, or any other additional info. 1214 * @param fn The original full pathname of the file we're recording. 1215 * @return The index of the record we just added. 1216 */ 1217 int register_in_tape_catalog(t_archtype type, int number, long aux, 1218 char *fn) 1219 { 1220 int last; 1221 char fname[MAX_TAPECAT_FNAME_LEN+1]; 1222 char *p; 1223 1224 p = strrchr(fn, '/'); 1225 if (p) { 1226 p++; 1227 } else { 1228 p = fn; 1229 } 1230 strncpy(fname, p, MAX_TAPECAT_FNAME_LEN); 1231 fname[MAX_TAPECAT_FNAME_LEN] = '\0'; 1232 last = g_tapecatalog->entries; 1233 if (last >= MAX_TAPECATALOG_ENTRIES) { 1234 log_it 1235 ("Warning - can't log #%d in tape catalog - too many entries already", 1236 number); 1237 return (-1); 1238 } 1239 g_tapecatalog->el[last].type = type; 1240 g_tapecatalog->el[last].number = number; 1241 g_tapecatalog->el[last].aux = aux; 1242 g_tapecatalog->el[last].tape_posK = g_tape_posK; 1243 strcpy(g_tapecatalog->el[last].fname, fname); 1244 g_tapecatalog->entries++; 1245 return (last); // returns the index of the record we've jsut added 1246 } 1247 1248 1249 1250 1251 /** 1252 * Decide whether we should start a new tape. This is TRUE if we've run out of tape 1253 * (got SIGPIPE) or look like we will. 1254 * @param mediasize The size of the tape in megabytes. 1255 * @param length_of_incoming_file The length of the file we're about to write, in bytes. 1256 * @bug This seems like it'll only work for media_size != autodetect, but Mondo only allows 1257 * autodetecting the size. Huh? 1258 */ 1259 1260 /* TODO: Should be reviewed for mediasize being a off_t ??? */ 1261 bool 1262 should_we_write_to_next_tape(long mediasize, 1263 off_t length_of_incoming_file) 1264 { 1265 /*@ bool's ***************************************************** */ 1266 bool we_need_a_new_tape = FALSE; 1267 1268 /*@ end vars *************************************************** */ 1269 1270 if (mediasize == 0) { 1271 return (FALSE); 1272 } 1273 if (mediasize > 0 && (g_tape_posK >> 10 >= mediasize)) { 1274 log_it("mediasize = %ld", mediasize); 1275 we_need_a_new_tape = TRUE; 1276 log_to_screen("Should have started a new tape/CD already"); 1277 } 1278 if ((g_tape_posK + length_of_incoming_file / 1024) >> 10 >= 1279 mediasize - (SLICE_SIZE * 4 / 1024)) { 1280 log_it("g_tape_posK = %ld\nmediasize = %ld\n", g_tape_posK, 1281 mediasize); 1282 we_need_a_new_tape = TRUE; 1283 } 1284 return (we_need_a_new_tape); 1347 res = read_file_from_stream_FULL(NULL, fout, size); 1348 /* fflush(g_tape_stream); 1349 fflush(fout);*/ 1350 return (res); 1285 1351 } 1286 1352 … … 1448 1514 1449 1515 /** 1450 * Start to write to the next tape. Assume the user has already inserted it. 1451 * @param bkpinfo The backup information structure. @c bkpinfo->media_device is the only field used. 1452 * @return 0 for success, nonzero for failure. 1453 */ 1454 int start_to_write_to_next_tape() 1455 { 1456 int res = 0; 1457 char *command = NULL; 1458 1459 if (bkpinfo->media_device == NULL) { 1460 log_it("Unable to open out from NULL device"); 1461 return (1); 1462 } 1463 1464 paranoid_pclose(g_tape_stream); 1465 sync(); 1466 sync(); 1467 sync(); 1468 log_it("New tape requested."); 1469 insist_on_this_tape_number(g_current_media_number + 1); // will increment g_current_media, too 1470 if (bkpinfo->backup_media_type == cdstream) { 1471 mr_asprintf(command, "cdrecord -eject dev=%s speed=%d fs=24m -waiti - >> %s 2>> %s", bkpinfo->media_device, bkpinfo->cdrw_speed, MONDO_LOGFILE, MONDO_LOGFILE); 1472 log_it("Opening OUT to next CD with the command"); 1473 log_it(command); 1474 log_it("Let's see what happens, shall we?"); 1475 g_tape_stream = popen(command, "w"); 1476 mr_free(command); 1477 1478 if (!g_tape_stream) { 1479 log_to_screen("Failed to openout to cdstream (fifo)"); 1480 return (1); 1481 } 1482 } else { 1483 log_it("Opening OUT to next tape"); 1484 if (!(g_tape_stream = open_device_via_buffer(bkpinfo->media_device, 'w', bkpinfo->internal_tape_block_size))) { 1485 log_OS_error(g_tape_fifo); 1486 log_to_screen("Cannot openin stream device"); 1487 return (1); 1488 } 1489 } 1490 g_tape_posK = 0; 1491 g_sigpipe = FALSE; 1492 res += write_header_block_to_stream((off_t)0, "start-of-tape", BLK_START_OF_TAPE); /* just in case */ 1493 res += write_header_block_to_stream((off_t)0, "start-of-backup", BLK_START_OF_BACKUP); /* just in case */ 1494 return (res); 1516 * Read a header block from the currently opened stream (CD or tape). 1517 * This block indicates the length of the following file (if it's file-related) 1518 * the filename (if it's file-related), and the block type. 1519 * @param plen Where to put the length of the file. Valid only for file-related header blocks. 1520 * @param filename Where to put the name of the file. Valid only for file-related header blocks. 1521 * @param pcontrol_char Where to put the type of block (e.g. start-file, end-file, start-tape, ...) 1522 * @return 0 for success, nonzero for failure. 1523 * @note If you read a marker (@p pcontrol_char) you're not expecting, you can call wrong_marker(). 1524 */ 1525 int 1526 read_header_block_from_stream(long long *plen, char *filename, 1527 int *pcontrol_char) 1528 { 1529 1530 /*@ buffers ***************************************************** */ 1531 char *tempblock; 1532 char *tmp = NULL; 1533 1534 /*@ int ********************************************************* */ 1535 int i, retval; 1536 1537 /*@ end vars *************************************************** */ 1538 1539 tempblock = (char *) malloc((size_t) TAPE_BLOCK_SIZE); 1540 1541 for (i = 0; i < (int) TAPE_BLOCK_SIZE; i++) { 1542 tempblock[i] = 0; 1543 } 1544 while (!(*pcontrol_char = tempblock[7000])) { 1545 g_tape_posK += fread(tempblock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream) / 1024; 1546 } 1547 memcpy((char *) plen, tempblock + 7001, sizeof(long long)); 1548 if (strcmp(tempblock + 6000 + *pcontrol_char, STR_HEADER)) { 1549 log_it("Bad header block at %ld K", (long) g_tape_posK); 1550 } 1551 strcpy(filename, tempblock + 1000); 1552 if (*pcontrol_char == BLK_ABORTED_BACKUP) { 1553 log_to_screen("I can't verify an aborted backup."); 1554 retval = 1; 1555 } else { 1556 retval = 0; 1557 } 1558 for (i = 1000; i < 1020; i++) { 1559 if (tempblock[i] < 32 || tempblock[i] > 126) { 1560 tempblock[i] = ' '; 1561 } 1562 } 1563 tempblock[i] = '\0'; 1564 tmp = marker_to_string(*pcontrol_char); 1565 log_msg(6, "%s (fname=%s, size=%ld K)", tmp, tempblock + 1000, (long) (*plen) >> 10); 1566 mr_free(tmp); 1567 paranoid_free(tempblock); 1568 return (retval); 1569 } 1570 1571 1572 1573 /** 1574 * Add specified file/slice to the internal catalog of all archives written. 1575 * This lets us restart on a new CD/tape/whatever if it runs out of room. We just 1576 * write the last [buffer size] MB from the catalog to the new tape, so we know 1577 * we have @e all archives on some CD/tape/whatever. 1578 * @param type The type of file we're cataloging (afioball, slice, something else) 1579 * @param number The fileset number or biggiefile number. 1580 * @param aux The slice number if it's a biggiefile, or any other additional info. 1581 * @param fn The original full pathname of the file we're recording. 1582 * @return The index of the record we just added. 1583 */ 1584 int register_in_tape_catalog(t_archtype type, int number, long aux, 1585 char *fn) 1586 { 1587 int last; 1588 char fname[MAX_TAPECAT_FNAME_LEN+1]; 1589 char *p; 1590 1591 p = strrchr(fn, '/'); 1592 if (p) { 1593 p++; 1594 } else { 1595 p = fn; 1596 } 1597 strncpy(fname, p, MAX_TAPECAT_FNAME_LEN); 1598 fname[MAX_TAPECAT_FNAME_LEN] = '\0'; 1599 last = g_tapecatalog->entries; 1600 if (last >= MAX_TAPECATALOG_ENTRIES) { 1601 log_it 1602 ("Warning - can't log #%d in tape catalog - too many entries already", 1603 number); 1604 return (-1); 1605 } 1606 g_tapecatalog->el[last].type = type; 1607 g_tapecatalog->el[last].number = number; 1608 g_tapecatalog->el[last].aux = aux; 1609 g_tapecatalog->el[last].tape_posK = g_tape_posK; 1610 strcpy(g_tapecatalog->el[last].fname, fname); 1611 g_tapecatalog->entries++; 1612 return (last); // returns the index of the record we've jsut added 1495 1613 } 1496 1614 … … 1600 1718 1601 1719 1602 /**1603 * Copy @p infile to the opened stream (CD or tape).1604 * @param bkpinfo The backup information structure. @c bkpinfo->media_size is the only field used.1605 * @param infile The file to write to the stream.1606 * @return 0 for success, nonzero for failure.1607 */1608 int write_file_to_stream_from_file(char *infile)1609 {1610 /*@ buffers **************************************************** */1611 char datablock[TAPE_BLOCK_SIZE];1612 char *checksum = NULL;1613 char *infile_basename;1614 1615 /*@ int ******************************************************** */1616 int retval = 0;1617 int noof_blocks;1618 1619 /* unsigned int ch; */1620 unsigned int crc16;1621 unsigned int crctt;1622 1623 /*@ pointers *************************************************** */1624 FILE *fin;1625 char *p;1626 1627 /*@ long ******************************************************* */1628 long bytes_to_read = 0;1629 long i;1630 1631 off_t filesize;1632 1633 #ifdef EXTRA_TAPE_CHECKSUMS1634 int ch;1635 #endif1636 1637 /*@ initialize ************************************************ */1638 crc16 = 0;1639 crctt = 0;1640 1641 1642 1643 /*@ end vars *************************************************** */1644 1645 infile_basename = strrchr(infile, '/');1646 if (infile_basename) {1647 infile_basename++;1648 } else {1649 infile_basename = infile;1650 }1651 filesize = length_of_file(infile);1652 if (should_we_write_to_next_tape(bkpinfo->media_size, filesize)) {1653 start_to_write_to_next_tape();1654 write_backcatalog_to_tape();1655 }1656 p = strrchr(infile, '/');1657 if (!p) {1658 p = infile;1659 } else {1660 p++;1661 }1662 log_it("Writing file '%s' to tape (%ld KB)", p, (long) filesize >> 10);1663 write_header_block_to_stream(filesize, infile_basename, BLK_START_FILE);1664 //go_here_to_restart_saving_of_file:1665 if (!(fin = fopen(infile, "r"))) {1666 log_OS_error(infile);1667 return (1);1668 }1669 for (noof_blocks = 0; filesize > 0;1670 noof_blocks++, filesize -= bytes_to_read) {1671 if (filesize < TAPE_BLOCK_SIZE) {1672 bytes_to_read = (long) filesize;1673 for (i = 0; i < TAPE_BLOCK_SIZE; i++) {1674 datablock[i] = '\0';1675 }1676 } else {1677 bytes_to_read = TAPE_BLOCK_SIZE;1678 }1679 if (fread(datablock, 1, (size_t) bytes_to_read, fin)) {1680 // FIXME1681 }1682 g_tape_posK +=1683 fwrite(datablock, 1, /*bytes_to_read */1684 (size_t) TAPE_BLOCK_SIZE,1685 g_tape_stream) / 1024;1686 if (g_sigpipe) {1687 log_it("Sigpipe occurred recently. I'll start a new tape.");1688 fclose(fin);1689 g_sigpipe = FALSE;1690 start_to_write_to_next_tape();1691 write_backcatalog_to_tape(); // kinda-sorta recursive :)1692 return (0);1693 }1694 #ifdef EXTRA_TAPE_CHECKSUMS1695 for (i = 0; i < bytes_to_read; i++) {1696 ch = datablock[i];1697 crc16 = updcrcr(crc16, (unsigned) ch);1698 crctt = updcrc(crctt, (unsigned) ch);1699 }1700 #endif1701 }1702 paranoid_fclose(fin);1703 mr_asprintf(checksum, "%04x%04x", crc16, crctt);1704 /* TODO: what does it do ??? */1705 write_header_block_to_stream((off_t)g_current_media_number, checksum, BLK_STOP_FILE);1706 mr_free(checksum);1707 1708 // log_it("File '%s' written to tape.", infile);1709 return (retval);1710 }1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1720 1721
Note:
See TracChangeset
for help on using the changeset viewer.