1 /*
2  * Directory entry functions
3  *
4  * Copyright (C) 2020-2021, 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 "libfsxfs_directory_entry.h"
27 #include "libfsxfs_libcerror.h"
28 #include "libfsxfs_libuna.h"
29 
30 /* Creates directory entry
31  * Make sure the value directory_entry is referencing, is set to NULL
32  * Returns 1 if successful or -1 on error
33  */
libfsxfs_directory_entry_initialize(libfsxfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)34 int libfsxfs_directory_entry_initialize(
35      libfsxfs_directory_entry_t **directory_entry,
36      libcerror_error_t **error )
37 {
38 	static char *function = "libfsxfs_directory_entry_initialize";
39 
40 	if( directory_entry == NULL )
41 	{
42 		libcerror_error_set(
43 		 error,
44 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
45 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
46 		 "%s: invalid directory entry.",
47 		 function );
48 
49 		return( -1 );
50 	}
51 	if( *directory_entry != NULL )
52 	{
53 		libcerror_error_set(
54 		 error,
55 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
56 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
57 		 "%s: invalid directory entry value already set.",
58 		 function );
59 
60 		return( -1 );
61 	}
62 	*directory_entry = memory_allocate_structure(
63 	                    libfsxfs_directory_entry_t );
64 
65 	if( *directory_entry == NULL )
66 	{
67 		libcerror_error_set(
68 		 error,
69 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
70 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
71 		 "%s: unable to create directory entry.",
72 		 function );
73 
74 		goto on_error;
75 	}
76 	if( memory_set(
77 	     *directory_entry,
78 	     0,
79 	     sizeof( libfsxfs_directory_entry_t ) ) == NULL )
80 	{
81 		libcerror_error_set(
82 		 error,
83 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
84 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
85 		 "%s: unable to clear directory entry.",
86 		 function );
87 
88 		goto on_error;
89 	}
90 	return( 1 );
91 
92 on_error:
93 	if( *directory_entry != NULL )
94 	{
95 		memory_free(
96 		 *directory_entry );
97 
98 		*directory_entry = NULL;
99 	}
100 	return( -1 );
101 }
102 
103 /* Frees directory entry
104  * Returns 1 if successful or -1 on error
105  */
libfsxfs_directory_entry_free(libfsxfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)106 int libfsxfs_directory_entry_free(
107      libfsxfs_directory_entry_t **directory_entry,
108      libcerror_error_t **error )
109 {
110 	static char *function = "libfsxfs_directory_entry_free";
111 
112 	if( directory_entry == NULL )
113 	{
114 		libcerror_error_set(
115 		 error,
116 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
117 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
118 		 "%s: invalid directory entry.",
119 		 function );
120 
121 		return( -1 );
122 	}
123 	if( *directory_entry != NULL )
124 	{
125 		memory_free(
126 		 *directory_entry );
127 
128 		*directory_entry = NULL;
129 	}
130 	return( 1 );
131 }
132 
133 /* Clones the directory entry value
134  * Returns 1 if successful or -1 on error
135  */
libfsxfs_directory_entry_clone(libfsxfs_directory_entry_t ** destination_directory_entry,libfsxfs_directory_entry_t * source_directory_entry,libcerror_error_t ** error)136 int libfsxfs_directory_entry_clone(
137      libfsxfs_directory_entry_t **destination_directory_entry,
138      libfsxfs_directory_entry_t *source_directory_entry,
139      libcerror_error_t **error )
140 {
141 	static char *function = "libfsxfs_directory_entry_clone";
142 
143 	if( destination_directory_entry == NULL )
144 	{
145 		libcerror_error_set(
146 		 error,
147 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
148 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
149 		 "%s: invalid destination directory entry.",
150 		 function );
151 
152 		return( -1 );
153 	}
154 	if( *destination_directory_entry != NULL )
155 	{
156 		libcerror_error_set(
157 		 error,
158 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
159 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
160 		 "%s: invalid destination directory entry value already set.",
161 		 function );
162 
163 		return( -1 );
164 	}
165 	if( source_directory_entry == NULL )
166 	{
167 		*destination_directory_entry = NULL;
168 
169 		return( 1 );
170 	}
171 	*destination_directory_entry = memory_allocate_structure(
172 	                                libfsxfs_directory_entry_t );
173 
174 	if( *destination_directory_entry == NULL )
175 	{
176 		libcerror_error_set(
177 		 error,
178 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
179 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
180 		 "%s: unable to create destination directory entry.",
181 		 function );
182 
183 		goto on_error;
184 	}
185 	if( memory_copy(
186 	     *destination_directory_entry,
187 	     source_directory_entry,
188 	     sizeof( libfsxfs_directory_entry_t ) ) == NULL )
189 	{
190 		libcerror_error_set(
191 		 error,
192 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
193 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
194 		 "%s: unable to copy source to destination directory entry.",
195 		 function );
196 
197 		goto on_error;
198 	}
199 	return( 1 );
200 
201 on_error:
202 	if( *destination_directory_entry != NULL )
203 	{
204 		memory_free(
205 		 *destination_directory_entry );
206 
207 		*destination_directory_entry = NULL;
208 	}
209 	return( -1 );
210 }
211 
212 /* Retrieves the inode number
213  * Returns 1 if successful or -1 on error
214  */
libfsxfs_directory_entry_get_inode_number(libfsxfs_directory_entry_t * directory_entry,uint64_t * inode_number,libcerror_error_t ** error)215 int libfsxfs_directory_entry_get_inode_number(
216      libfsxfs_directory_entry_t *directory_entry,
217      uint64_t *inode_number,
218      libcerror_error_t **error )
219 {
220 	static char *function = "libfsxfs_directory_entry_get_inode_number";
221 
222 	if( directory_entry == NULL )
223 	{
224 		libcerror_error_set(
225 		 error,
226 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
227 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
228 		 "%s: invalid directory entry.",
229 		 function );
230 
231 		return( -1 );
232 	}
233 	if( inode_number == NULL )
234 	{
235 		libcerror_error_set(
236 		 error,
237 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
238 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
239 		 "%s: invalid inode number.",
240 		 function );
241 
242 		return( -1 );
243 	}
244 	*inode_number = directory_entry->inode_number;
245 
246 	return( 1 );
247 }
248 
249 /* Retrieves the size of the UTF-8 encoded name
250  * The returned size includes the end of string character
251  * Returns 1 if successful or -1 on error
252  */
libfsxfs_directory_entry_get_utf8_name_size(libfsxfs_directory_entry_t * directory_entry,size_t * utf8_string_size,libcerror_error_t ** error)253 int libfsxfs_directory_entry_get_utf8_name_size(
254      libfsxfs_directory_entry_t *directory_entry,
255      size_t *utf8_string_size,
256      libcerror_error_t **error )
257 {
258 	static char *function = "libfsxfs_directory_entry_get_utf8_name_size";
259 
260 	if( directory_entry == NULL )
261 	{
262 		libcerror_error_set(
263 		 error,
264 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
265 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
266 		 "%s: invalid directory entry.",
267 		 function );
268 
269 		return( -1 );
270 	}
271 	if( libuna_utf8_string_size_from_utf8_stream(
272 	     directory_entry->name,
273 	     (size_t) directory_entry->name_size,
274 	     utf8_string_size,
275 	     error ) != 1 )
276 	{
277 		libcerror_error_set(
278 		 error,
279 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
280 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
281 		 "%s: unable to retrieve UTF-8 string size.",
282 		 function );
283 
284 		return( -1 );
285 	}
286 	return( 1 );
287 }
288 
289 /* Retrieves the UTF-8 encoded name
290  * The size should include the end of string character
291  * Returns 1 if successful or -1 on error
292  */
libfsxfs_directory_entry_get_utf8_name(libfsxfs_directory_entry_t * directory_entry,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)293 int libfsxfs_directory_entry_get_utf8_name(
294      libfsxfs_directory_entry_t *directory_entry,
295      uint8_t *utf8_string,
296      size_t utf8_string_size,
297      libcerror_error_t **error )
298 {
299 	static char *function = "libfsxfs_directory_entry_get_utf8_name";
300 
301 	if( directory_entry == NULL )
302 	{
303 		libcerror_error_set(
304 		 error,
305 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
306 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
307 		 "%s: invalid directory entry.",
308 		 function );
309 
310 		return( -1 );
311 	}
312 	if( libuna_utf8_string_copy_from_utf8_stream(
313 	     utf8_string,
314 	     utf8_string_size,
315 	     directory_entry->name,
316 	     (size_t) directory_entry->name_size,
317 	     error ) != 1 )
318 	{
319 		libcerror_error_set(
320 		 error,
321 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
322 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
323 		 "%s: unable to retrieve UTF-8 string.",
324 		 function );
325 
326 		return( -1 );
327 	}
328 	return( 1 );
329 }
330 
331 /* Compares an UTF-8 string with the name of the directory entry
332  * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
333  */
libfsxfs_directory_entry_compare_with_utf8_string(libfsxfs_directory_entry_t * directory_entry,const uint8_t * utf8_string,size_t utf8_string_length,libcerror_error_t ** error)334 int libfsxfs_directory_entry_compare_with_utf8_string(
335      libfsxfs_directory_entry_t *directory_entry,
336      const uint8_t *utf8_string,
337      size_t utf8_string_length,
338      libcerror_error_t **error )
339 {
340 	static char *function = "libfsxfs_directory_entry_compare_with_utf8_string";
341 	int result            = 0;
342 
343 	if( directory_entry == NULL )
344 	{
345 		libcerror_error_set(
346 		 error,
347 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
348 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
349 		 "%s: invalid directory entry.",
350 		 function );
351 
352 		return( -1 );
353 	}
354 	result = libuna_utf8_string_compare_with_utf8_stream(
355 	          utf8_string,
356 	          utf8_string_length,
357 	          directory_entry->name,
358 	          directory_entry->name_size,
359 	          error );
360 
361 	if( result == -1 )
362 	{
363 		libcerror_error_set(
364 		 error,
365 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
366 		 LIBCERROR_RUNTIME_ERROR_GENERIC,
367 		 "%s: unable to compare UTF-8 string with directory entry name.",
368 		 function );
369 
370 		return( -1 );
371 	}
372 	return( result );
373 }
374 
375 /* Retrieves the size of the UTF-16 encoded name
376  * The returned size includes the end of string character
377  * Returns 1 if successful or -1 on error
378  */
libfsxfs_directory_entry_get_utf16_name_size(libfsxfs_directory_entry_t * directory_entry,size_t * utf16_string_size,libcerror_error_t ** error)379 int libfsxfs_directory_entry_get_utf16_name_size(
380      libfsxfs_directory_entry_t *directory_entry,
381      size_t *utf16_string_size,
382      libcerror_error_t **error )
383 {
384 	static char *function = "libfsxfs_directory_entry_get_utf16_name_size";
385 
386 	if( directory_entry == NULL )
387 	{
388 		libcerror_error_set(
389 		 error,
390 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
391 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
392 		 "%s: invalid directory entry.",
393 		 function );
394 
395 		return( -1 );
396 	}
397 	if( libuna_utf16_string_size_from_utf8_stream(
398 	     directory_entry->name,
399 	     (size_t) directory_entry->name_size,
400 	     utf16_string_size,
401 	     error ) != 1 )
402 	{
403 		libcerror_error_set(
404 		 error,
405 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
406 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
407 		 "%s: unable to retrieve UTF-16 string size.",
408 		 function );
409 
410 		return( -1 );
411 	}
412 	return( 1 );
413 }
414 
415 /* Retrieves the UTF-16 encoded name
416  * The size should include the end of string character
417  * Returns 1 if successful or -1 on error
418  */
libfsxfs_directory_entry_get_utf16_name(libfsxfs_directory_entry_t * directory_entry,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)419 int libfsxfs_directory_entry_get_utf16_name(
420      libfsxfs_directory_entry_t *directory_entry,
421      uint16_t *utf16_string,
422      size_t utf16_string_size,
423      libcerror_error_t **error )
424 {
425 	static char *function = "libfsxfs_directory_entry_get_utf16_name";
426 
427 	if( directory_entry == NULL )
428 	{
429 		libcerror_error_set(
430 		 error,
431 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
432 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
433 		 "%s: invalid directory entry.",
434 		 function );
435 
436 		return( -1 );
437 	}
438 	if( libuna_utf16_string_copy_from_utf8_stream(
439 	     utf16_string,
440 	     utf16_string_size,
441 	     directory_entry->name,
442 	     (size_t) directory_entry->name_size,
443 	     error ) != 1 )
444 	{
445 		libcerror_error_set(
446 		 error,
447 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
448 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
449 		 "%s: unable to retrieve UTF-16 string.",
450 		 function );
451 
452 		return( -1 );
453 	}
454 	return( 1 );
455 }
456 
457 /* Compares an UTF-16 string with the name of the directory entry
458  * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
459  */
libfsxfs_directory_entry_compare_with_utf16_string(libfsxfs_directory_entry_t * directory_entry,const uint16_t * utf16_string,size_t utf16_string_length,libcerror_error_t ** error)460 int libfsxfs_directory_entry_compare_with_utf16_string(
461      libfsxfs_directory_entry_t *directory_entry,
462      const uint16_t *utf16_string,
463      size_t utf16_string_length,
464      libcerror_error_t **error )
465 {
466 	static char *function = "libfsxfs_directory_entry_compare_with_utf16_string";
467 	int result            = 0;
468 
469 	if( directory_entry == NULL )
470 	{
471 		libcerror_error_set(
472 		 error,
473 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
474 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
475 		 "%s: invalid directory entry.",
476 		 function );
477 
478 		return( -1 );
479 	}
480 	result = libuna_utf16_string_compare_with_utf8_stream(
481 	          utf16_string,
482 	          utf16_string_length,
483 	          directory_entry->name,
484 	          directory_entry->name_size,
485 	          error );
486 
487 	if( result == -1 )
488 	{
489 		libcerror_error_set(
490 		 error,
491 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
492 		 LIBCERROR_RUNTIME_ERROR_GENERIC,
493 		 "%s: unable to compare UTF-16 string with directory entry name.",
494 		 function );
495 
496 		return( -1 );
497 	}
498 	return( result );
499 }
500 
501