Exemplo n.º 1
0
/* Sets an error and adds a system specific error string if possible
 * Creates the error if necessary
 * The error domain and code are set only the first time and the error message is appended for back tracing
 */
void VARARGS(
      libcerror_system_set_error,
      libcerror_error_t **error,
      int error_domain,
      int error_code,
      uint32_t system_error_code,
      const char *,
      format_string )
{
	va_list argument_list;

	libcerror_internal_error_t *internal_error          = NULL;
	libcstring_system_character_t *system_format_string = NULL;
	void *reallocation                                  = NULL;
	size_t format_string_length                         = 0;
	size_t message_size                                 = LIBCERROR_MESSAGE_INCREMENT_SIZE;
	size_t string_index                                 = 0;
	int message_index                                   = 0;
	int print_count                                     = 0;

	if( error == NULL )
	{
		return;
	}
	if( format_string == NULL )
	{
		return;
	}
	format_string_length = libcstring_narrow_string_length(
	                        format_string );

	if( format_string_length > message_size )
	{
		message_size = ( ( format_string_length / LIBCERROR_MESSAGE_INCREMENT_SIZE ) + 1 )
		             * LIBCERROR_MESSAGE_INCREMENT_SIZE;
	}
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
	do
	{
		reallocation = memory_reallocate(
		                system_format_string,
		                sizeof( libcstring_system_character_t ) * ( format_string_length + 1 ) );

		if( reallocation == NULL )
		{
			goto on_error;
		}
		system_format_string = (libcstring_system_character_t *) reallocation;

#if defined( __BORLANDC__ ) || defined( _MSC_VER )
		print_count = libcstring_wide_string_snwprintf(
		               system_format_string,
		               format_string_length + 1,
		               L"%S",
		               format_string );
#else
		print_count = libcstring_wide_string_snwprintf(
		               system_format_string,
		               format_string_length + 1,
		               L"%s",
		               format_string );
#endif

		if( print_count <= -1 )
		{
			format_string_length += LIBCERROR_MESSAGE_INCREMENT_SIZE;
		}
		else if( ( (size_t) print_count > format_string_length )
		      || ( system_format_string[ print_count ] != 0 ) )
		{
			format_string_length = (size_t) print_count;
			print_count  = -1;
		}
		if( format_string_length >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
		{
			goto on_error;
		}
	}
	while( print_count <= -1 );
#else
	system_format_string = (libcstring_system_character_t *) format_string;
#endif

#if defined( __BORLANDC__ ) || defined( _MSC_VER )
	/* Rewrite %s to %S
	 */
	string_index  = 0;

	while( string_index < format_string_length )
	{
		if( system_format_string[ string_index ] == 0 )
		{
			break;
		}
		else if( system_format_string[ string_index ] == (libcstring_system_character_t) '%' )
		{
			string_index++;

			if( system_format_string[ string_index ] == (libcstring_system_character_t) 's' )
			{
				 system_format_string[ string_index ] = (libcstring_system_character_t) 'S';
			}
		}
		string_index++;
	}
#endif
	if( *error == NULL )
	{
		internal_error = memory_allocate_structure(
		                  libcerror_internal_error_t );

		if( internal_error == NULL )
		{
			goto on_error;
		}
		internal_error->domain             = error_domain;
		internal_error->code               = error_code;
		internal_error->number_of_messages = 0;
		internal_error->messages           = NULL;
		internal_error->sizes              = NULL;

		*error = (libcerror_error_t *) internal_error;
	}
	else
	{
		internal_error = (libcerror_internal_error_t *) *error;
	}
	reallocation = memory_reallocate(
	                internal_error->messages,
	                sizeof( libcstring_system_character_t * ) * ( internal_error->number_of_messages + 1 ) );

	if( reallocation == NULL )
	{
		goto on_error;
	}
	internal_error->messages = (libcstring_system_character_t **) reallocation;

	reallocation = memory_reallocate(
	                internal_error->sizes,
	                sizeof( size_t ) * ( internal_error->number_of_messages + 1 ) );

	if( reallocation == NULL )
	{
		goto on_error;
	}
	internal_error->sizes = (size_t *) reallocation;

	message_index                             = internal_error->number_of_messages;
	internal_error->messages[ message_index ] = NULL;
	internal_error->sizes[ message_index ]    = 0;
	internal_error->number_of_messages       += 1;

	do
	{
		reallocation = memory_reallocate(
		                internal_error->messages[ message_index ],
		                sizeof( libcstring_system_character_t ) * message_size );

		if( reallocation == NULL )
		{
			memory_free(
			 internal_error->messages[ message_index ] );

			internal_error->messages[ message_index ] = NULL;

			break;
		}
		internal_error->messages[ message_index ] = (libcstring_system_character_t *) reallocation;

		VASTART(
		 argument_list,
		 const char *,
		 format_string );

		print_count = libcstring_system_string_vsprintf(
		               internal_error->messages[ message_index ],
		               message_size,
		               system_format_string,
		               argument_list );

		VAEND(
		 argument_list );

		if( print_count <= -1 )
		{
			message_size += LIBCERROR_MESSAGE_INCREMENT_SIZE;
		}
		else if( ( (size_t) print_count > message_size )
		      || ( ( internal_error->messages[ message_index ] )[ print_count ] != 0 ) )
		{
			message_size = (size_t) ( print_count + 1 );
			print_count  = -1;
		}
		if( message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
		{
			memory_free(
			 internal_error->messages[ message_index ] );

			internal_error->messages[ message_index ] = NULL;
			internal_error->sizes[ message_index ]    = 0;

			break;
		}
		internal_error->sizes[ message_index ] = (size_t) print_count + 1;
	}
	while( print_count <= -1 );

#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
	memory_free(
	 system_format_string );

	system_format_string = NULL;
#endif

	string_index = internal_error->sizes[ message_index ] - 1;

	if( ( internal_error->messages[ message_index ] != NULL )
	 && ( ( internal_error->messages[ message_index ] )[ string_index - 1 ] == (libcstring_system_character_t) '.' ) )
	{
		string_index -= 1;
	}
	reallocation = memory_reallocate(
			internal_error->messages[ message_index ],
			sizeof( libcstring_system_character_t ) * ( message_size + 13 + 512 ) );

	if( reallocation == NULL )
	{
		memory_free(
		 internal_error->messages[ message_index ] );

		internal_error->messages[ message_index ] = NULL;

		goto on_error;
	}
	internal_error->messages[ message_index ] = (libcstring_system_character_t *) reallocation;

	if( libcstring_system_string_copy(
	     &( ( internal_error->messages[ message_index ] )[ string_index ] ),
	     _LIBCSTRING_SYSTEM_STRING( " with error: " ),
	     13 ) == NULL )
	{
		memory_free(
		 internal_error->messages[ message_index ] );

		internal_error->messages[ message_index ] = NULL;

		goto on_error;
	}
	internal_error->sizes[ message_index ] += 13;
	string_index                           += 13;

	print_count = libcerror_system_copy_string_from_error_number(
	               &( ( internal_error->messages[ message_index ] )[ string_index ] ),
	               512,
	               system_error_code );

	if( print_count == -1 )
	{
		goto on_error;
	}
	message_size += (size_t) print_count;

	if( message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
	{
		memory_free(
		 internal_error->messages[ message_index ] );

		internal_error->messages[ message_index ] = NULL;
		internal_error->sizes[ message_index ]    = 0;

		goto on_error;
	}
	internal_error->sizes[ message_index ] += print_count;

	return;

on_error:
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
	if( system_format_string != NULL )
	{
		memory_free(
		 system_format_string );
	}
#endif
	if( ( *error == NULL )
	 && ( internal_error != NULL ) )
	{
		memory_free(
		 internal_error );
	}
	return;
}
Exemplo n.º 2
0
/* Sets an error and adds a system specific error string if possible
 * Creates the error if necessary
 * The error domain and code are set only the first time and the error message is appended for back tracing
 */
void VARARGS(
      libcerror_system_set_error,
      libcerror_error_t **error,
      int error_domain,
      int error_code,
      uint32_t system_error_code,
      const char *,
      format_string )
{
	va_list argument_list;

	libcerror_internal_error_t *internal_error = NULL;
	system_character_t *error_string           = NULL;
	system_character_t *system_format_string   = NULL;
	void *reallocation                         = NULL;
	size_t error_string_size                   = 0;
	size_t format_string_length                = 0;
	size_t message_size                        = 0;
	size_t next_message_size                   = LIBCERROR_MESSAGE_INCREMENT_SIZE;
	size_t string_index                        = 0;
	int message_index                          = 0;
	int print_count                            = 0;

	if( error == NULL )
	{
		return;
	}
	if( format_string == NULL )
	{
		return;
	}
	format_string_length = narrow_string_length(
	                        format_string );

#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
	libcerror_error_get_system_format_string(
	 format_string,
	 format_string_length,
	 &system_format_string );

	if( system_format_string == NULL )
	{
		return;
	}
#else
	system_format_string = (system_character_t *) format_string;
#endif
	if( *error == NULL )
	{
		if( libcerror_error_initialize(
		     error,
		     error_domain,
		     error_code ) != 1 )
		{
			goto on_error;
		}
	}
	internal_error = (libcerror_internal_error_t *) *error;

	if( libcerror_error_resize(
	     internal_error ) != 1 )
	{
		goto on_error;
	}
	if( format_string_length > next_message_size )
	{
		next_message_size = ( ( format_string_length / LIBCERROR_MESSAGE_INCREMENT_SIZE ) + 1 )
		                  * LIBCERROR_MESSAGE_INCREMENT_SIZE;
	}
	message_index = internal_error->number_of_messages - 1;
	error_string  = internal_error->messages[ message_index ];

	do
	{
		if( next_message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
		{
			next_message_size = LIBCERROR_MESSAGE_MAXIMUM_SIZE;
		}
		reallocation = memory_reallocate(
		                error_string,
		                sizeof( system_character_t ) * next_message_size );

		if( reallocation == NULL )
		{
			memory_free(
			 error_string );

			goto on_error;
		}
		error_string = (system_character_t *) reallocation;

		message_size = next_message_size;

		/* argument_list cannot be reused in successive calls to vsnprintf
		 */
		VASTART(
		 argument_list,
		 const char *,
		 format_string );

		print_count = system_string_vsnprintf(
		               error_string,
		               message_size,
		               system_format_string,
		               argument_list );

		VAEND(
		 argument_list );

		if( print_count <= -1 )
		{
			next_message_size += LIBCERROR_MESSAGE_INCREMENT_SIZE;
		}
		else if( ( (size_t) print_count >= message_size )
		      || ( error_string[ print_count ] != (system_character_t) 0 ) )
		{
			next_message_size = (size_t) ( print_count + 1 );
			print_count       = -1;
		}
		else
		{
			error_string_size = (size_t) print_count + 1;
		}
		if( message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
		{
			break;
		}
	}
	while( print_count <= -1 );

	if( message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
	{
		error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 4 ] = (system_character_t) '.';
		error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 3 ] = (system_character_t) '.';
		error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 2 ] = (system_character_t) '.';
		error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 1 ] = 0;
		error_string_size                                  = (size_t) LIBCERROR_MESSAGE_MAXIMUM_SIZE;
	}
	internal_error->messages[ message_index ] = error_string;
	internal_error->sizes[ message_index ]    = error_string_size;

#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
	memory_free(
	 system_format_string );

	system_format_string = NULL;
#endif

	message_size = internal_error->sizes[ message_index ];

	if( message_size < LIBCERROR_MESSAGE_MAXIMUM_SIZE )
	{
/* TODO move to separate helper function */
		string_index = internal_error->sizes[ message_index ] - 1;

		if( ( internal_error->messages[ message_index ] != NULL )
		 && ( ( internal_error->messages[ message_index ] )[ string_index - 1 ] == (system_character_t) '.' ) )
		{
			string_index -= 1;
		}
		reallocation = memory_reallocate(
				internal_error->messages[ message_index ],
				sizeof( system_character_t ) * ( message_size + 13 + 512 ) );

		if( reallocation == NULL )
		{
			memory_free(
			 internal_error->messages[ message_index ] );

			internal_error->messages[ message_index ] = NULL;

			goto on_error;
		}
		internal_error->messages[ message_index ] = (system_character_t *) reallocation;

		if( system_string_copy(
		     &( ( internal_error->messages[ message_index ] )[ string_index ] ),
		     _SYSTEM_STRING( " with error: " ),
		     13 ) == NULL )
		{
			memory_free(
			 internal_error->messages[ message_index ] );

			internal_error->messages[ message_index ] = NULL;

			goto on_error;
		}
		internal_error->sizes[ message_index ] += 13;
		string_index                           += 13;

		print_count = libcerror_system_copy_string_from_error_number(
		               &( ( internal_error->messages[ message_index ] )[ string_index ] ),
		               512,
		               system_error_code );

		if( print_count == -1 )
		{
			goto on_error;
		}
		message_size += (size_t) print_count;

		internal_error->sizes[ message_index ] += print_count;
	}
	if( internal_error->sizes[ message_index ] >= LIBCERROR_MESSAGE_MAXIMUM_SIZE )
	{
		internal_error->messages[ message_index ][ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 4 ] = (system_character_t) '.';
		internal_error->messages[ message_index ][ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 3 ] = (system_character_t) '.';
		internal_error->messages[ message_index ][ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 2 ] = (system_character_t) '.';
		internal_error->messages[ message_index ][ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 1 ] = 0;
		internal_error->sizes[ message_index ]                                          = (size_t) LIBCERROR_MESSAGE_MAXIMUM_SIZE;
	}
	return;

on_error:
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
	if( system_format_string != NULL )
	{
		memory_free(
		 system_format_string );
	}
#endif
	return;
}