static void write_header(void) { int chksum; unsigned char * cp; /* Calculate and store the checksum (i.e., the sum of all of the bytes of the header). The checksum field must be filled with blanks for the calculation. The checksum field is formatted differently from the other fields: it has [6] digits, a null, then a space -- rather than digits, followed by a null like the other fields... */ memset(tar.formated.chksum, ' ', sizeof(tar.formated.chksum)); for (chksum = 0, cp = tar.raw; cp < tar.raw + 512; cp++) chksum += *cp; put_octal(tar.formated.chksum, 7, chksum); fwrite(tar.raw, sizeof(tar.raw), 1, archive); offset += sizeof(tar.raw); }
int hb_vsnprintf( char * buffer, size_t bufsize, const char * format, va_list ap ) { va_list args; size_t size; char c; #ifndef __NO_ARGPOS__ const char * fmt_start = format; v_param argbuf[ _ARGBUF_SIZE ]; v_paramlst params; params.size = _ARGBUF_SIZE; params.maxarg = 0; params.arglst = argbuf; #endif #ifndef __NO_ARGPOS__ do { params.repeat = HB_FALSE; if( params.maxarg > 0 ) { va_copy( args, ap ); va_arg_fill( ¶ms, args ); va_end( args ); } format = fmt_start; #endif va_copy( args, ap ); size = 0; do { c = *format++; if( c == '%' ) { const char * pattern = format; c = *format++; if( c != 0 && c != '%' ) { /* decode pattern */ v_param argval; int param = 0, flags = 0, width = -1, precision = -1, length, value, stop = 0; /* parameter position */ if( c >= '0' && c <= '9' ) { c = get_decimal( c, &format, &value ); if( c == '$' ) param = value; else format = pattern; c = *format++; } /* flags */ while( ! stop ) { switch( c ) { case '#': flags |= _F_ALTERNATE; c = *format++; break; case '0': flags |= _F_ZEROPADED; c = *format++; break; case '-': flags |= _F_LEFTADJUSTED; c = *format++; break; case ' ': flags |= _F_SPACE; c = *format++; break; case '+': flags |= _F_SIGN; c = *format++; break; #ifdef _SUSV2_COMPAT_ case '\'': /* group with locale thousands' grouping characters */ c = *format++; break; #endif default: stop = 1; break; } } /* field width */ if( c == '*' ) { c = *format++; if( c >= '0' && c <= '9' ) { c = get_decimal( c, &format, &value ); if( c == '$' ) { width = va_arg_n( args, _x_int, value ); c = *format++; } /* else error, wrong format */ } else width = va_arg_n( args, _x_int, 0 ); } else if( c >= '0' && c <= '9' ) c = get_decimal( c, &format, &width ); /* precision */ if( c == '.' ) { precision = 0; c = *format++; if( c == '*' ) { c = *format++; if( c >= '0' && c <= '9' ) { c = get_decimal( c, &format, &value ); if( c == '$' ) { precision = va_arg_n( args, _x_int, value ); c = *format++; } /* else error, wrong format */ } else precision = va_arg_n( args, _x_int, 0 ); } else if( c >= '0' && c <= '9' ) c = get_decimal( c, &format, &precision ); } /* length modifier */ switch( c ) { case 'h': c = *format++; if( c == 'h' ) { length = _L_CHAR_; c = *format++; } else length = _L_SHORT_; break; case 'l': c = *format++; if( c == 'l' ) { length = _L_LONGLONG_; c = *format++; } else length = _L_LONG_; break; case 'L': length = _L_LONGDOUBLE_; c = *format++; break; case 'j': length = _L_INTMAX_; c = *format++; break; case 'z': length = _L_SIZE_; c = *format++; break; case 't': length = _L_PTRDIFF_; c = *format++; break; case 'I': /* MS-Windows extension */ if( format[ 0 ] == '6' && format[ 1 ] == '4' ) { length = _L_LONGLONG_; format += 2; c = *format++; break; } else if( format[ 0 ] == '1' && format[ 1 ] == '6' ) { length = _L_SHORT_; format += 2; c = *format++; break; } else if( format[ 0 ] == '3' && format[ 1 ] == '2' ) { format += 2; c = *format++; } /* no break; */ default: length = _L_UNDEF_; break; } /* conversion specifier */ switch( c ) { #ifndef __NO_DOUBLE__ case 'a': case 'A': case 'e': case 'E': case 'g': case 'G': /* redirect above conversion to 'f' or 'F' type to keep * valid parameters order */ c = ( c == 'a' || c == 'e' || c == 'g' ) ? 'f' : 'F'; /* no break; */ case 'f': /* double decimal notation */ case 'F': /* double decimal notation */ if( length == _L_LONGDOUBLE_ ) { argval.value.as_x_long_dbl = va_arg_n( args, _x_long_dbl, param ); HB_NUMTYPEL( value, argval.value.as_x_long_dbl ); } else { double d = va_arg_n( args, _x_double, param ); HB_NUMTYPE( value, d ); argval.value.as_x_long_dbl = ( value & ( _HB_NUM_NAN | _HB_NUM_PINF | _HB_NUM_NINF ) ) == 0 ? d : 0; } if( value & _HB_NUM_NAN ) size = put_str( buffer, bufsize, size, c == 'f' ? ( flags & _F_SIGN ? "+nan": "nan" ) : ( flags & _F_SIGN ? "+NAN": "NAN" ) , flags, width, -1 ); else if( value & _HB_NUM_PINF ) size = put_str( buffer, bufsize, size, c == 'f' ? ( flags & _F_SIGN ? "+inf": "inf" ) : ( flags & _F_SIGN ? "+INF": "INF" ), flags, width, -1 ); else if( value & _HB_NUM_NINF ) size = put_str( buffer, bufsize, size, c == 'f' ? "-inf" : "-INF", flags, width, -1 ); else size = put_dbl( buffer, bufsize, size, argval.value.as_x_long_dbl, flags, width, precision ); continue; #endif case 'd': case 'i': /* signed int decimal conversion */ if( length == _L_CHAR_ ) argval.value.as_x_intmax_t = ( unsigned char ) va_arg_n( args, _x_int, param ); else if( length == _L_SHORT_ ) argval.value.as_x_intmax_t = ( unsigned short ) va_arg_n( args, _x_int, param ); else if( length == _L_LONG_ ) argval.value.as_x_intmax_t = va_arg_n( args, _x_long, param ); else if( length == _L_LONGLONG_ ) argval.value.as_x_intmax_t = va_arg_n( args, _x_longlong, param ); else if( length == _L_INTMAX_ ) argval.value.as_x_intmax_t = va_arg_n( args, _x_intmax_t, param ); else if( length == _L_SIZE_ ) argval.value.as_x_intmax_t = va_arg_n( args, _x_size_t, param ); else if( length == _L_PTRDIFF_ ) argval.value.as_x_intmax_t = va_arg_n( args, _x_ptrdiff_t, param ); else argval.value.as_x_intmax_t = va_arg_n( args, _x_int, param ); value = argval.value.as_x_intmax_t < 0; argval.value.as_x_uintmax_t = value ? -argval.value.as_x_intmax_t : argval.value.as_x_intmax_t; size = put_dec( buffer, bufsize, size, argval.value.as_x_uintmax_t, flags, width, precision, value ); continue; case 'o': /* unsigned int octal conversion */ case 'u': /* unsigned int decimal conversion */ case 'x': /* unsigned int hexadecimal conversion */ case 'X': /* unsigned int hexadecimal conversion */ if( length == _L_CHAR_ ) argval.value.as_x_uintmax_t = ( unsigned char ) va_arg_n( args, _x_int, param ); else if( length == _L_SHORT_ ) argval.value.as_x_uintmax_t = ( unsigned short ) va_arg_n( args, _x_int, param ); else if( length == _L_LONG_ ) argval.value.as_x_uintmax_t = va_arg_n( args, _x_ulong, param ); else if( length == _L_LONGLONG_ ) argval.value.as_x_uintmax_t = va_arg_n( args, _x_ulonglong, param ); else if( length == _L_INTMAX_ ) argval.value.as_x_uintmax_t = va_arg_n( args, _x_uintmax_t, param ); else if( length == _L_SIZE_ ) argval.value.as_x_uintmax_t = va_arg_n( args, _x_size_t, param ); else if( length == _L_PTRDIFF_ ) argval.value.as_x_uintmax_t = va_arg_n( args, _x_ptrdiff_t, param ); else argval.value.as_x_uintmax_t = va_arg_n( args, _x_uint, param ); if( c == 'o' ) size = put_octal( buffer, bufsize, size, argval.value.as_x_uintmax_t, flags, width, precision ); else if( c == 'u' ) size = put_dec( buffer, bufsize, size, argval.value.as_x_uintmax_t, flags & ~( _F_SPACE | _F_SIGN ), width, precision, 0 ); else size = put_hex( buffer, bufsize, size, argval.value.as_x_uintmax_t, flags, width, precision, c == 'X' ); continue; case 'p': /* void * pointer */ argval.value.as_x_ptr = va_arg_n( args, _x_ptr, param ); if( argval.value.as_x_ptr ) size = put_hex( buffer, bufsize, size, ( HB_PTRUINT ) argval.value.as_x_ptr, flags | _F_ALTERNATE, width, precision, 0 ); else size = put_str( buffer, bufsize, size, "(nil)", flags, width, -1 ); continue; case 'c': /* signed int casted to unsigned char */ if( ( flags & _F_LEFTADJUSTED ) == 0 ) { while( --width > 0 ) { if( size < bufsize ) buffer[ size ] = ' '; ++size; } } c = ( unsigned char ) va_arg_n( args, _x_int, param ); if( size < bufsize ) buffer[ size ] = c; ++size; while( --width > 0 ) { if( size < bufsize ) buffer[ size ] = ' '; ++size; } continue; case 's': /* const char * */ if( length == _L_LONG_ ) { argval.value.as_x_wstr = va_arg_n( args, _x_wstr, param ); size = put_wstr( buffer, bufsize, size, argval.value.as_x_wstr, flags, width, precision ); } else { argval.value.as_x_str = va_arg_n( args, _x_str, param ); size = put_str( buffer, bufsize, size, argval.value.as_x_str, flags, width, precision ); } continue; case 'n': /* store current result size in int * arg */ /* This is very danger feature in *printf() functions * family very often used by hackers to create buffer * overflows. It can also cause unintentional memory * corruption by programmers typo in pattern so if it's * not strictly necessary it's good to disable it. */ *( va_arg_n( args, _x_intptr, param ) ) = ( int ) size; continue; case '%': /* store % consuming arguments % */ break; default: /* error, wrong format, store pattern */ format = pattern; c = '%'; break; } } } /* ISO C99 defines that when size is 0 and buffer is NULL we should * return number of characters that would have been written in case * the output string has been large enough without trailing 0. * Many implementations always returns number of characters necessary * to hold the string even if the above condition is not true so the * returned value can be used to check if buffer was large enough * and if not to allocate bigger buffer. Let's do the same. */ if( size < bufsize ) buffer[ size ] = c; ++size; } while( c != 0 ); va_end( args ); #ifndef __NO_ARGPOS__ } while( params.repeat ); if( params.arglst != argbuf ) hb_xfree( params.arglst ); #endif /* always set trailing \0 !!! */ if( bufsize ) buffer[ bufsize - 1 ] = 0; return ( int ) ( size - 1 ); }