/* * gts2tiff.c - Part of AFD, an automatic file distribution program. * Copyright (c) 1996 - 2018 Deutscher Wetterdienst (DWD), * Holger Kiehl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "afddefs.h" DESCR__S_M3 /* ** NAME ** gts2tiff - changes GTS (T4) files to TIFF files ** ** SYNOPSIS ** off_t gts2tiff(char *path, char *filename) ** path - path where the TIFF file can be found ** filename - file name of the TIFF file ** ** DESCRIPTION ** Converts CCITT Group 3 or Group 4 encoded data to TIFF data. ** If the T4 file has a WMO vertical resolution factor of 2, ** all lines will be duplicated. ** ** ** RETURN VALUES ** Returns INCORRECT when it fails to convert the file. Otherwise ** the size of the converted file is returned. ** ** AUTHOR ** H.Kiehl ** ** HISTORY ** 12.10.1996 H.Kiehl Created ** 13.11.1996 T.Freyberg Debugged function dup_count_eols(). ** 02.09.2002 H.Kiehl Return file name with TIFF_END. ** 20.11.2002 H.Kiehl Don't mark T4 code wrong if it does not have ** the 6 EOL's at end. ** 05.02.2003 H.Kiehl Remove the strlen() to get header length and ** put in more size checks so we don't go beyond ** our memory. ** */ DESCR__E_M3 #include /* sprintf() */ #include /* strcat(), memcpy() */ #include /* exit() */ #include /* lseek(), unlink() */ #include #include #ifdef HAVE_MMAP # include /* mmap(), munmap() */ #endif #if defined (_TIFF_CONVERSION_TIME_TEST) || defined (_EOL_TIME_TEST) # include #endif #include #include #include "amgdefs.h" #define TIFF_END "-tiff" #define NO_OF_TAGS 14 #define TIFF_SHORT 3 #define TIFF_LONG 4 #define TIFF_RATIONAL 5 #ifndef MAP_FILE /* Required for BSD. */ # define MAP_FILE 0 /* All others do not need it. */ #endif /* Global local variables. */ static int hr, /* Horizontal resolution */ vr, /* Vertical resolution */ bhl; /* Bulletin header length */ #ifdef _WITH_FILE_INFO char bh[100]; #endif /* Local function prototypes. */ static int evaluate_wmo_stuff(char *, size_t), dup_count_eols(char *, size_t, char *), #ifdef _EOL_TIME_TEST count_eols1(char *, size_t), count_eols2(char *, size_t), #endif count_eols(char *, size_t); /*############################## gts2tiff() #############################*/ off_t gts2tiff(char *path, char *filename) { #ifdef _EOL_TIME_TEST register i; clock_t start_time, end_time; #endif #ifdef _TIFF_CONVERSION_TIME_TEST clock_t start_total_time, end_total_time; #endif #if defined (_TIFF_CONVERSION_TIME_TEST) || defined (_EOL_TIME_TEST) clock_t clktck; struct tms tmsdummy; #endif int byte_order = 1, word_offset, total_size, fdin, fdout, ifd_offset, offset, no_of_eols; size_t tiff_file_size; char *src, *dst, from[MAX_PATH_LENGTH], to[MAX_PATH_LENGTH + 5]; struct stat stat_buf; #if defined (_TIFF_CONVERSION_TIME_TEST) || defined (_EOL_TIME_TEST) if ((clktck = sysconf(_SC_CLK_TCK)) <= 0) { (void)fprintf(stderr, _("ERROR : Could not get clock ticks per second : %s (%s %d)\n"), strerror(errno), __FILE__, __LINE__); return(INCORRECT); } #endif #ifdef _TIFF_CONVERSION_TIME_TEST start_total_time = times(&tmsdummy); #endif /* Open source file. */ if (path[0] == '\0') { (void)strcpy(from, filename); } else { (void)snprintf(from, MAX_PATH_LENGTH, "%s/%s", path, filename); } if ((fdin = open(from, O_RDONLY)) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Could not open() `%s' for copying : %s"), from, strerror(errno)); return(INCORRECT); } if (fstat(fdin, &stat_buf) < 0) /* need size of input file */ { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Could not fstat() `%s' : %s"), from, strerror(errno)); (void)close(fdin); return(INCORRECT); } /* Open and create destination file. */ (void)snprintf(to, MAX_PATH_LENGTH + 5, "%s%s", from, TIFF_END); if ((fdout = open(to, (O_RDWR | O_CREAT | O_TRUNC), stat_buf.st_mode)) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Could not open() `%s' for copying : %s"), to, strerror(errno)); (void)close(fdin); return(INCORRECT); } if (stat_buf.st_size > 0) { #ifdef HAVE_MMAP if ((src = mmap(NULL, stat_buf.st_size, PROT_READ, (MAP_FILE | MAP_SHARED), fdin, 0)) == (caddr_t) -1) #else if ((src = mmap_emu(NULL, stat_buf.st_size, PROT_READ, (MAP_FILE | MAP_SHARED), from, 0)) == (caddr_t) -1) #endif { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Could not mmap() file `%s' : %s"), from, strerror(errno)); (void)close(fdin); (void)close(fdout); if (unlink(to) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to unlink() `%s' : %s"), to, strerror(errno)); } return(INCORRECT); } /* * WARNING: Do NOT close the memory mapped file yet! */ if (evaluate_wmo_stuff(src, stat_buf.st_size) < 0) { #ifdef HAVE_MMAP if (munmap(src, stat_buf.st_size) < 0) #else if (munmap_emu(src) < 0) #endif { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("munmap() error : %s"), strerror(errno)); } (void)close(fdin); (void)close(fdout); if (unlink(to) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to unlink() `%s' : %s"), to, strerror(errno)); } return(INCORRECT); } if (vr == 2) { total_size = (2 * stat_buf.st_size) - bhl - 4; } else { total_size = stat_buf.st_size; } switch (total_size % 4) { case 0: word_offset = 2; break; case 1: word_offset = 1; break; case 2: word_offset = 0; break; case 3: word_offset = 3; break; default: receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Impossible!!!!")); (void)close(fdin); (void)close(fdout); if (unlink(to) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to unlink() `%s' : %s"), to, strerror(errno)); } return(INCORRECT); } tiff_file_size = 8 + /* TIFF Header */ total_size + /* T4 code + WMO stuff */ word_offset + /* word offset for IFD */ (2 + (NO_OF_TAGS * 12) + 4) + /* IFD */ 8 + /* X-Resolution */ 8; /* Y-Resolution */ /* Set size of output file. */ if (lseek(fdout, tiff_file_size - 1, SEEK_SET) == -1) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Could not lseek() on `%s' : %s"), to, strerror(errno)); (void)close(fdin); (void)close(fdout); if (unlink(to) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to unlink() `%s' : %s"), to, strerror(errno)); } return(INCORRECT); } if (write(fdout, "", 1) != 1) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Could not write() to `%s' : %s"), to, strerror(errno)); (void)close(fdin); (void)close(fdout); if (unlink(to) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to unlink() `%s' : %s"), to, strerror(errno)); } return(INCORRECT); } #ifdef HAVE_MMAP if ((dst = mmap(NULL, tiff_file_size, (PROT_READ | PROT_WRITE), (MAP_FILE | MAP_SHARED), fdout, 0)) == (caddr_t) -1) #else if ((dst = mmap_emu(NULL, tiff_file_size, (PROT_READ | PROT_WRITE), (MAP_FILE | MAP_SHARED), to, 0)) == (caddr_t) -1) #endif { #ifdef HAVE_MMAP if (munmap(src, stat_buf.st_size) < 0) #else if (munmap_emu(src) < 0) #endif { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("munmap() error : %s"), strerror(errno)); } receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Could not mmap() file `%s' : %s"), to, strerror(errno)); (void)close(fdin); (void)close(fdout); if (unlink(to) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to unlink() `%s' : %s"), to, strerror(errno)); } return(INCORRECT); } #ifdef _EOL_TIME_TEST /* Lets take a look how long it takes to find the EOL's. */ no_of_eols = 0; start_time = times(&tmsdummy); for (i = 0; i < 100; i++) { no_of_eols += count_eols(&src[bhl], (stat_buf.st_size - bhl - 4)); } end_time = times(&tmsdummy); (void)fprintf(stderr, "Ver 0 : %7.2f for %d EOL's\n", (end_time - start_time) / (double)clktck, no_of_eols); if (*(char *)&byte_order == 1) { no_of_eols = 0; start_time = times(&tmsdummy); for (i = 0; i < 100; i++) { no_of_eols += count_eols2(&src[bhl], (stat_buf.st_size - bhl - 4)); } end_time = times(&tmsdummy); } else { no_of_eols = 0; start_time = times(&tmsdummy); for (i = 0; i < 100; i++) { no_of_eols += count_eols1(&src[bhl], (stat_buf.st_size - bhl - 4)); } end_time = times(&tmsdummy); } (void)fprintf(stderr, "Ver 1 : %7.2f for %d EOL's\n", (end_time - start_time) / (double)clktck, no_of_eols); /* See how long it takes to duplicate all lines. */ no_of_eols = 0; start_time = times(&tmsdummy); for (i = 0; i < 100; i++) { no_of_eols += dup_count_eols(src, stat_buf.st_size, dst); } end_time = times(&tmsdummy); (void)fprintf(stderr, "duplication : %7.2f for %d EOL's\n", (end_time - start_time) / (double)clktck, no_of_eols); #endif /* _EOL_TIME_TEST */ if (vr == 2) { if ((no_of_eols = dup_count_eols(src, stat_buf.st_size, dst)) < 1) { if (no_of_eols < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("T4-code is corrupt since there were no 6 EOL's in a row.")); } else { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("There are no EOL's.")); } #ifdef HAVE_MMAP if (munmap(src, stat_buf.st_size) < 0) #else if (munmap_emu(src) < 0) #endif { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("munmap() error : %s"), strerror(errno)); } (void)close(fdin); (void)close(fdout); if (unlink(to) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to unlink() `%s` : %s"), to, strerror(errno)); } return(INCORRECT); } } else { if ((no_of_eols = count_eols(&src[bhl], (stat_buf.st_size - bhl - 4))) < 1) { if (no_of_eols < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("T4-code is corrupt since there were no 6 EOL's in a row.")); } else { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("There are no EOL's")); } #ifdef HAVE_MMAP if (munmap(src, stat_buf.st_size) < 0) #else if (munmap_emu(src) < 0) #endif { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("munmap() error : %s"), strerror(errno)); } (void)close(fdin); (void)close(fdout); if (unlink(to) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to unlink() `%s' : %s"), to, strerror(errno)); } return(INCORRECT); } } } else { if (close(fdin) == -1) { receive_log(DEBUG_SIGN, __FILE__, __LINE__, 0L, _("close() error : %s"), strerror(errno)); } if (close(fdout) == -1) { receive_log(DEBUG_SIGN, __FILE__, __LINE__, 0L, _("close() error : %s"), strerror(errno)); } if (unlink(to) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to unlink() `%s' : %s"), to, strerror(errno)); } receive_log(WARN_SIGN, __FILE__, __LINE__, 0L, _("Unusable data size (%d) for file `%s'"), stat_buf.st_size, from); return(stat_buf.st_size); } /* * Create TIFF-header */ if (*(char *)&byte_order == 1) { /* little-endian */ dst[0] = dst[1] = 'I'; /* TIFF identifier */ dst[2] = 42; dst[3] = 0; } else { /* big-endian */ dst[0] = dst[1] = 'M'; /* TIFF identifier */ dst[2] = 0; dst[3] = 42; } /* Insert offset to the first IFD as follows: */ /* 8 Byte TIFF header + T4 contents + offset to next word */ ifd_offset = 4 + 4 + total_size + word_offset; *(int *)&dst[4] = ifd_offset; if (vr != 2) { /* * Now lets copy the T4 plus WMO data to the TIFF file. */ (void)memcpy(&dst[8], src, stat_buf.st_size); } /* * Create the IFD of the TIFF-file. */ *(short *)&dst[ifd_offset] = NO_OF_TAGS; /* write no. of tags */ /* New subfile type */ *(short *)&dst[ifd_offset + 2] = 254; /* Tag ID */ *(short *)&dst[ifd_offset + 4] = TIFF_LONG; /* Type */ *(int *)&dst[ifd_offset + 6] = 1; /* Count */ *(int *)&dst[ifd_offset + 10] = 0; /* Data */ offset = ifd_offset + 10 + 4; /* Image width */ *(short *)&dst[offset] = 256; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_SHORT; /* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(short *)&dst[offset + 8] = hr; /* Data */ *(short *)&dst[offset + 10] = 0; /* Data */ offset += 12; /* Image length */ *(short *)&dst[offset] = 257; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_SHORT; /* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(short *)&dst[offset + 8] = no_of_eols; /* Data */ *(short *)&dst[offset + 10] = 0; /* Data */ offset += 12; /* Compression */ *(short *)&dst[offset] = 259; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_SHORT; /* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(short *)&dst[offset + 8] = 3; /* Data */ *(short *)&dst[offset + 10] = 0; /* Data */ offset += 12; /* Photometric interpretation */ *(short *)&dst[offset] = 262; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_SHORT; /* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(int *) &dst[offset + 8] = 0; /* Data */ offset += 12; /* Fill order (Bits in a byte) */ *(short *)&dst[offset] = 266; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_SHORT; /* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(short *)&dst[offset + 8] = 1; /* Data */ *(short *)&dst[offset + 10] = 0; /* Data */ offset += 12; /* Strip offset */ *(short *)&dst[offset] = 273; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_LONG; /* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(int *) &dst[offset + 8] = 8 + bhl; /* Data */ offset += 12; /* Orientation */ *(short *)&dst[offset] = 274; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_SHORT; /* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(short *)&dst[offset + 8] = 1; /* Data */ *(short *)&dst[offset + 10] = 0; /* Data */ offset += 12; /* Samples/pixels */ *(short *)&dst[offset] = 277; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_SHORT; /* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(short *)&dst[offset + 8] = 1; /* Data */ *(short *)&dst[offset + 10] = 0; /* Data */ offset += 12; /* Rows/strip */ *(short *)&dst[offset] = 278; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_SHORT; /* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(short *)&dst[offset + 8] = no_of_eols; /* Data */ *(short *)&dst[offset + 10] = 0; /* Data */ offset += 12; /* Strip byte count */ *(short *)&dst[offset] = 279; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_LONG; /* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(int *) &dst[offset + 8] = total_size; /* Data */ offset += 12; /* X-Resolution */ *(short *)&dst[offset] = 282; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_RATIONAL;/* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(int *) &dst[offset + 8] = tiff_file_size - 16; /* Offset */ *(int *) &dst[tiff_file_size - 16] = 803721; /* 1728 / 21,5*/ *(int *) &dst[tiff_file_size - 12] = 10000; offset += 12; /* Y-Resolution */ *(short *)&dst[offset] = 283; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_RATIONAL;/* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(int *) &dst[offset + 8] = tiff_file_size - 8; /* Offset */ *(int *)&dst[tiff_file_size - 8] = 770000; *(int *)&dst[tiff_file_size - 4] = 10000; offset += 12; /* Resolution unit */ *(short *)&dst[offset] = 296; /* Tag ID */ *(short *)&dst[offset + 2] = TIFF_SHORT; /* Type */ *(int *) &dst[offset + 4] = 1; /* Count */ *(short *)&dst[offset + 8] = 3; /* Data */ *(short *)&dst[offset + 10] = 0; /* Data */ offset += 12; #ifdef _WITH_FILE_INFO receive_log(INFO_SIGN, __FILE__, __LINE__, 0L, _("T4 to TIFF conversion : %s %s"), filename, bh); receive_log(INFO_SIGN, __FILE__, __LINE__, 0L, " : hr = %d vr = %d eol's = %d", hr, vr, no_of_eols); #endif #ifdef HAVE_MMAP if (munmap(src, stat_buf.st_size) < 0) #else if (munmap_emu(src) < 0) #endif { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("munmap() error : %s"), strerror(errno)); (void)close(fdin); (void)close(fdout); return(INCORRECT); } #ifdef HAVE_MMAP if (munmap(dst, tiff_file_size) < 0) #else if (munmap_emu(dst) < 0) #endif { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("munmap() error : %s"), strerror(errno)); (void)close(fdin); (void)close(fdout); return(INCORRECT); } /* Time to remove the file with T4 code only */ if (unlink(from) < 0) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to unlink() `%s' : %s"), from, strerror(errno)); } #ifdef _TIFF_CONVERSION_TIME_TEST end_total_time = times(&tmsdummy); (void)fprintf(stderr, "Total time to convert file: %7.2f s\n", (end_total_time - start_total_time) / (double)clktck); #endif if (close(fdin) == -1) { receive_log(DEBUG_SIGN, __FILE__, __LINE__, 0L, _("close() error : %s"), strerror(errno)); } if (close(fdout) == -1) { receive_log(DEBUG_SIGN, __FILE__, __LINE__, 0L, _("close() error : %s"), strerror(errno)); } /* Append TIFF ending to the original filename. */ (void)strcat(filename, TIFF_END); return(tiff_file_size); } /*++++++++++++++++++++++++ evaluate_wmo_stuff() +++++++++++++++++++++++++*/ static int evaluate_wmo_stuff(char *buf, size_t size) { char *ptr, search_str[3]; #ifdef _WITH_FILE_INFO char *bh_start, *bh_end; #endif search_str[0] = search_str[1] = 13; search_str[2] = 10; if ((ptr = lposi(buf, search_str, 3)) != NULL) { if ((ptr - buf) > size) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("This file does not seem to have a valid WMO header.")); return(INCORRECT); } if ((ptr = lposi(ptr, search_str, 3)) != NULL) { char *tmp_ptr; #ifdef _WITH_FILE_INFO bh_start = ptr - 1; #endif if ((ptr - buf) > size) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("This file does not seem to have a valid WMO header.")); return(INCORRECT); } if ((tmp_ptr = lposi(ptr, search_str, 3)) != NULL) { ptr = tmp_ptr; /* In case it is NULL, just assume counter is missing */ /* and continue. */ } if ((ptr + 8 - buf) > size) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("This file does not seem to have a valid WMO header.")); return(INCORRECT); } #ifdef _WITH_FILE_INFO bh_end = ptr; (void)strncpy(bh, bh_start, (bh_end - bh_start - 4)); #endif } else { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to find second .")); return(INCORRECT); } } else { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to find first .")); return(INCORRECT); } /* Get the vertical and horizontal resolution. */ vr = 0; ptr--; if (ptr[0] == 'D') { if (ptr[1] == 'F') { if (ptr[2] == 'A') { if (ptr[3] == 'X') { vr = ptr[7] - 48; if (ptr[6] == '6') { hr = 1728; } else if (ptr[6] == '7') { hr = 3456; } else if (ptr[6] == '8') { hr = 2432; } else { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Unknown horizontal resolution of %c."), ptr[6]); return(INCORRECT); } } } } } if ((vr != 2) && (vr != 4)) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to get the vertical resolution (%d)."), vr); return(INCORRECT); } /* Determine the bulletin header length. */ bhl = ptr + 8 - buf; /* Check end for */ if ((buf[(size - 1)] != 3) || (buf[(size - 2)] != 10) || (buf[(size - 3)] != 13) || (buf[(size - 4)] != 13)) { receive_log(ERROR_SIGN, __FILE__, __LINE__, 0L, _("Failed to locate bulletin end.")); return(INCORRECT); } return(SUCCESS); } /*++++++++++++++++++++++++++++ count_eols() +++++++++++++++++++++++++++++*/ static int count_eols(char *buf, size_t size) { static int no_of_eols; unsigned char shifter; unsigned int count = 0; register int i, zero_hit = 0, last_was_eol = 0; no_of_eols = 0; while (count < size) { shifter = buf[count]; for (i = 0; i < 8; i++) { if ((shifter & 0x80) == 0) { if (zero_hit++ == 11) { last_was_eol = 0; } } else { if (zero_hit >= 11) { if (++last_was_eol == 6) { return((no_of_eols - 6)); /* 1 at start and 6 at end */ } no_of_eols++; zero_hit = 0; } else { zero_hit = last_was_eol = 0; } } shifter = shifter << 1; } count++; } if (no_of_eols > 0) { receive_log(INFO_SIGN, __FILE__, __LINE__, 0L, _("Failed to read 6 EOL's in a row, after reading %d EOL's [last_was_eol = %d]."), no_of_eols, last_was_eol); return((no_of_eols - 7)); } /* Since we did not read 6 EOL's in a row, lets assume */ /* the T4-code is corrupt. */ return(INCORRECT); } /*++++++++++++++++++++++++++ dup_count_eols() +++++++++++++++++++++++++++*/ static int dup_count_eols(char *buf, size_t size, char *dst) { static int no_of_eols; int bit_offset_start = -1, byte_offset_start = -1; unsigned char d_shifter = 0, /* destination shifter */ s_shifter, /* source shifter */ s_shifter_copy; /* source shifter when coping */ unsigned int d_count = 8 + bhl, s_count = bhl; register int i, j, k, bit_count = 0, zero_hit = 0, last_was_eol = 0; /* * Copy bulletin header. */ (void)memcpy(&dst[8], buf, bhl); no_of_eols = 0; while (s_count < size) { s_shifter = buf[s_count]; for (i = 0; i < 8; i++) { if ((s_shifter & 0x80) == 0) { if (zero_hit++ == 11) { last_was_eol = 0; } s_shifter = s_shifter << 1; if (++bit_count == 8) { dst[d_count++] = d_shifter; bit_count = d_shifter = 0; } else { d_shifter = d_shifter << 1; } } else { /* Copy bit */ d_shifter |= 0x01; s_shifter = s_shifter << 1; if (++bit_count == 8) { dst[d_count++] = d_shifter; bit_count = d_shifter = 0; } else { d_shifter = d_shifter << 1; } if (zero_hit >= 11) { if (bit_offset_start == -1) { bit_offset_start = i + 1; byte_offset_start = s_count; } else { /* Time to duplicate last line? */ if (last_was_eol == 0) { /* * Duplicate last line */ /* Copy bits in first byte we have to copy. */ s_shifter_copy = buf[byte_offset_start]; s_shifter_copy = s_shifter_copy << bit_offset_start; for (j = bit_offset_start; j < 8; j++) { if ((s_shifter_copy & 0x80) != 0) { d_shifter |= 0x01; } s_shifter_copy = s_shifter_copy << 1; if (++bit_count == 8) { dst[d_count++] = d_shifter; bit_count = d_shifter = 0; } else { d_shifter = d_shifter << 1; } } /* Copy all bytes between start and end. */ for (j = (byte_offset_start + 1); j < s_count; j++) { s_shifter_copy = buf[j]; for (k = 0; k < 8; k++) { if ((s_shifter_copy & 0x80) != 0) { d_shifter |= 0x01; } s_shifter_copy = s_shifter_copy << 1; if (++bit_count == 8) { dst[d_count++] = d_shifter; bit_count = d_shifter = 0; } else { d_shifter = d_shifter << 1; } } } /* Copy bits in last byte. */ s_shifter_copy = buf[s_count]; for (j = 0; j < (i + 1); j++) { if ((s_shifter_copy & 0x80) != 0) { d_shifter |= 0x01; } s_shifter_copy = s_shifter_copy << 1; if (++bit_count == 8) { dst[d_count++] = d_shifter; bit_count = d_shifter = 0; } else { d_shifter = d_shifter << 1; } } /* Remember the start offset for the next line. */ if (i == 7) { bit_offset_start = 0; byte_offset_start = s_count + 1; } else { bit_offset_start = i + 1; byte_offset_start = s_count; } no_of_eols++; } if (++last_was_eol == 6) { /* Don't forget to shift in destination buffer. */ if (bit_count != 0) { d_shifter = d_shifter << (8 - bit_count); dst[d_count++] = d_shifter; } /* Write bulletin end */ dst[d_count] = dst[d_count + 1] = 13; dst[d_count + 2] = 10; dst[d_count + 3] = '\0'; return((no_of_eols - 6)); /* 1 at start and 5 at end */ } } no_of_eols++; zero_hit = 0; } else { zero_hit = last_was_eol = 0; } } } s_count++; } if (no_of_eols > 0) { receive_log(INFO_SIGN, __FILE__, __LINE__, 0L, _("Failed to read 6 EOL's in a row, after reading %d EOL's [last_was_eol = %d]."), no_of_eols, last_was_eol); /* Don't forget to shift in destination buffer. */ if (bit_count != 0) { d_shifter = d_shifter << (8 - bit_count); dst[d_count++] = d_shifter; } /* Write bulletin end */ dst[d_count] = dst[d_count + 1] = 13; dst[d_count + 2] = 10; dst[d_count + 3] = '\0'; return((no_of_eols - 7)); /* 1 at start and 5 at end */ } /* Since we did not read 6 EOL's in a row, lets assume */ /* the T4-code is corrupt. */ return(INCORRECT); } #ifdef _EOL_TIME_TEST /*+++++++++++++++++++++++++++ count_eols1() +++++++++++++++++++++++++++++*/ /* * NOTE : only for MM */ static int count_eols1(char *buf, size_t size) { static int no_of_eols; unsigned int shifter, count = 0; register i, zero_hit = 0, last_was_eol = 0; no_of_eols = 0; while (count < size) { (void)memcpy(&shifter, &buf[count], 4); for (i = 0; i < 32; i++) { if ((shifter & 0x80000000) == 0) { if (zero_hit++ == 11) { last_was_eol = 0; } } else { if (zero_hit >= 11) { if (++last_was_eol == 6) { return((no_of_eols - 6)); /* 1 at start and 5 at end */ } no_of_eols++; zero_hit = 0; } else { zero_hit = last_was_eol = 0; } } shifter = shifter << 1; } count += 4; } /* Since we did not read 6 EOL's in a row, lets assume */ /* the T4-code is corrupt. */ return(INCORRECT); } /*+++++++++++++++++++++++++++ count_eols2() +++++++++++++++++++++++++++++*/ /* * NOTE : only for II */ static int count_eols2(char *buf, size_t size) { unsigned char tmp_byte; static int no_of_eols; unsigned int shifter, count = 0; register i, zero_hit = 0, last_was_eol = 0; no_of_eols = 0; while (count < size) { (void)memcpy(&shifter, &buf[count], 4); /* Swap bytes */ tmp_byte = ((char *)&shifter)[0]; ((char *)&shifter)[0] = ((char *)&shifter)[3]; ((char *)&shifter)[3] = tmp_byte; tmp_byte = ((char *)&shifter)[1]; ((char *)&shifter)[1] = ((char *)&shifter)[2]; ((char *)&shifter)[2] = tmp_byte; for (i = 0; i < 32; i++) { if ((shifter & 0x80000000) == 0) { if (zero_hit++ == 11) { last_was_eol = 0; } } else { if (zero_hit >= 11) { if (++last_was_eol == 6) { return((no_of_eols - 6)); /* 1 at start and 5 at end */ } no_of_eols++; zero_hit = 0; } else { zero_hit = last_was_eol = 0; } } shifter = shifter << 1; } count += 4; } /* Since we did not read 6 EOL's in a row, lets assume */ /* the T4-code is corrupt. */ return(INCORRECT); } #endif /* _EOL_TIME_TEST */