1 /*
2  * Empty block test functions
3  *
4  * Copyright (c) 2006-2014, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <memory.h>
24 #include <types.h>
25 
26 #include "libewf_empty_block.h"
27 #include "libewf_libcerror.h"
28 
29 /* Check for empty block
30  * An empty block is a block that contains the same value for every byte
31  * Returns 1 if block is empty, 0 if not or -1 on error
32  */
libewf_empty_block_test(const uint8_t * block_buffer,size_t block_size,libcerror_error_t ** error)33 int libewf_empty_block_test(
34      const uint8_t *block_buffer,
35      size_t block_size,
36      libcerror_error_t **error )
37 {
38 	static char *function = "libewf_empty_block_test";
39 
40 	if( block_buffer == NULL )
41 	{
42 		libcerror_error_set(
43 		 error,
44 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
45 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
46 		 "%s: invalid block buffer.",
47 		 function );
48 
49 		return( -1 );
50 	}
51 	if( block_size > (size_t) SSIZE_MAX )
52 	{
53 		libcerror_error_set(
54 		 error,
55 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
56 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
57 		 "%s: invalid block size value exceeds maximum.",
58 		 function );
59 
60 		return( -1 );
61 	}
62 	if( block_size == 0 )
63 	{
64 		return( 0 );
65 	}
66 	else if( block_size == 1 )
67 	{
68 		return( 1 );
69 	}
70 	if( memory_compare(
71 	     block_buffer,
72 	     &( block_buffer[ 1 ] ),
73 	     block_size - 1 ) != 0 )
74 	{
75 		return( 0 );
76 	}
77 	return( 1 );
78 }
79 
80 /* Previous version keep for now */
81 #ifdef TEST_EMPTY_BLOCK_MEMCMP
82 
83 /* The largest primary (or scalar) available
84  * supported by a single load and store instruction
85  */
86 typedef unsigned long int libewf_aligned_t;
87 
88 /* Check for empty block
89  * An empty block is a block that contains the same value for every byte
90  * Returns 1 if block is empty, 0 if not or -1 on error
91  */
libewf_empty_block_test(const uint8_t * block_buffer,size_t block_size,libcerror_error_t ** error)92 int libewf_empty_block_test(
93      const uint8_t *block_buffer,
94      size_t block_size,
95      libcerror_error_t **error )
96 {
97 	uint8_t *block_iterator   = NULL;
98 	uint8_t *block_start      = NULL;
99 	static char *function     = "libewf_empty_block_test";
100 	size_t aligned_block_size = 0;
101 
102 	if( block_buffer == NULL )
103 	{
104 		libcerror_error_set(
105 		 error,
106 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
107 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
108 		 "%s: invalid block buffer.",
109 		 function );
110 
111 		return( -1 );
112 	}
113 	if( block_size > (size_t) SSIZE_MAX )
114 	{
115 		libcerror_error_set(
116 		 error,
117 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
118 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
119 		 "%s: invalid block size value exceeds maximum.",
120 		 function );
121 
122 		return( -1 );
123 	}
124 	block_start    = (uint8_t *) block_buffer;
125 	block_iterator = (uint8_t *) block_buffer + 1;
126 	block_size    -= 1;
127 
128 	/* Only optimize for blocks larger than the alignment
129 	 */
130 	if( block_size > ( 2 * sizeof( libewf_aligned_t ) ) )
131 	{
132 		/* Align the block start
133 		 */
134 		while( ( (intptr_t) block_start % sizeof( libewf_aligned_t ) ) != 0 )
135 		{
136 			if( *block_start != *block_iterator )
137 			{
138 				return( 0 );
139 			}
140 			block_start    += 1;
141 			block_iterator += 1;
142 			block_size     -= 1;
143 		}
144 		aligned_block_size = ( block_size / sizeof( libewf_aligned_t ) ) * sizeof( libewf_aligned_t );
145 
146 		if( memory_compare(
147 		     block_start,
148 		     &( block_start[ sizeof( libewf_aligned_t ) ] ),
149 		     aligned_block_size - sizeof( libewf_aligned_t ) ) != 0 )
150 		{
151 			return( 0 );
152 		}
153 		block_iterator = &( block_start[ aligned_block_size ] );
154 		block_size    -= aligned_block_size;
155 	}
156 	while( block_size != 0 )
157 	{
158 		if( *block_start != *block_iterator )
159 		{
160 			return( 0 );
161 		}
162 		block_iterator += 1;
163 		block_size     -= 1;
164 	}
165 	return( 1 );
166 }
167 
168 #endif /* TEST_EMPTY_BLOCK_MEMCMP */
169 
170