1 /*
2  * Block data handle 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_block_data_handle.h"
27 #include "libfsxfs_libbfio.h"
28 #include "libfsxfs_libcerror.h"
29 #include "libfsxfs_libfdata.h"
30 #include "libfsxfs_unused.h"
31 
32 /* Reads data from the current offset into a buffer
33  * Callback for the cluster block data stream
34  * Returns the number of bytes read or -1 on error
35  */
libfsxfs_block_data_handle_read_segment_data(intptr_t * data_handle LIBFSXFS_ATTRIBUTE_UNUSED,libbfio_handle_t * file_io_handle,int segment_index LIBFSXFS_ATTRIBUTE_UNUSED,int segment_file_index LIBFSXFS_ATTRIBUTE_UNUSED,uint8_t * segment_data,size_t segment_data_size,uint32_t segment_flags,uint8_t read_flags LIBFSXFS_ATTRIBUTE_UNUSED,libcerror_error_t ** error)36 ssize_t libfsxfs_block_data_handle_read_segment_data(
37          intptr_t *data_handle LIBFSXFS_ATTRIBUTE_UNUSED,
38          libbfio_handle_t *file_io_handle,
39          int segment_index LIBFSXFS_ATTRIBUTE_UNUSED,
40          int segment_file_index LIBFSXFS_ATTRIBUTE_UNUSED,
41          uint8_t *segment_data,
42          size_t segment_data_size,
43          uint32_t segment_flags,
44          uint8_t read_flags LIBFSXFS_ATTRIBUTE_UNUSED,
45          libcerror_error_t **error )
46 {
47 	static char *function = "libfsxfs_block_data_handle_read_segment_data";
48 	ssize_t read_count    = 0;
49 
50 	LIBFSXFS_UNREFERENCED_PARAMETER( data_handle )
51 	LIBFSXFS_UNREFERENCED_PARAMETER( segment_index )
52 	LIBFSXFS_UNREFERENCED_PARAMETER( segment_file_index )
53 	LIBFSXFS_UNREFERENCED_PARAMETER( read_flags )
54 
55 	if( segment_data == NULL )
56 	{
57 		libcerror_error_set(
58 		 error,
59 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
60 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
61 		 "%s: invalid segment data.",
62 		 function );
63 
64 		return( -1 );
65 	}
66 	if( segment_data_size > (size_t) SSIZE_MAX )
67 	{
68 		libcerror_error_set(
69 		 error,
70 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
71 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
72 		 "%s: invalid segment data size value exceeds maximum.",
73 		 function );
74 
75 		return( -1 );
76 	}
77 	if( ( segment_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 )
78 	{
79 		if( memory_set(
80 		     segment_data,
81 		     0,
82 		     segment_data_size ) == NULL )
83 		{
84 			libcerror_error_set(
85 			 error,
86 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
87 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
88 			 "%s: unable to clear segment data.",
89 			 function );
90 
91 			return( -1 );
92 		}
93 		read_count = (ssize_t) segment_data_size;
94 	}
95 	else
96 	{
97 		read_count = libbfio_handle_read_buffer(
98 		              file_io_handle,
99 		              segment_data,
100 		              segment_data_size,
101 		              error );
102 
103 		if( read_count < 0 )
104 		{
105 			libcerror_error_set(
106 			 error,
107 			 LIBCERROR_ERROR_DOMAIN_IO,
108 			 LIBCERROR_IO_ERROR_READ_FAILED,
109 			 "%s: unable to read segment data.",
110 			 function );
111 
112 			return( -1 );
113 		}
114 	}
115 	return( read_count );
116 }
117 
118 /* Seeks a certain offset of the data
119  * Callback for the cluster block data stream
120  * Returns the offset if seek is successful or -1 on error
121  */
libfsxfs_block_data_handle_seek_segment_offset(intptr_t * data_handle LIBFSXFS_ATTRIBUTE_UNUSED,libbfio_handle_t * file_io_handle,int segment_index LIBFSXFS_ATTRIBUTE_UNUSED,int segment_file_index LIBFSXFS_ATTRIBUTE_UNUSED,off64_t segment_offset,libcerror_error_t ** error)122 off64_t libfsxfs_block_data_handle_seek_segment_offset(
123          intptr_t *data_handle LIBFSXFS_ATTRIBUTE_UNUSED,
124          libbfio_handle_t *file_io_handle,
125          int segment_index LIBFSXFS_ATTRIBUTE_UNUSED,
126          int segment_file_index LIBFSXFS_ATTRIBUTE_UNUSED,
127          off64_t segment_offset,
128          libcerror_error_t **error )
129 {
130 	static char *function = "libfsxfs_block_data_handle_seek_segment_offset";
131 
132 	LIBFSXFS_UNREFERENCED_PARAMETER( data_handle )
133 	LIBFSXFS_UNREFERENCED_PARAMETER( segment_index )
134 	LIBFSXFS_UNREFERENCED_PARAMETER( segment_file_index )
135 
136 	if( segment_offset < 0 )
137 	{
138 		libcerror_error_set(
139 		 error,
140 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
141 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
142 		 "%s: invalid segment offset value out of bounds.",
143 		 function );
144 
145 		return( -1 );
146 	}
147 	if( libbfio_handle_seek_offset(
148 	     file_io_handle,
149 	     segment_offset,
150 	     SEEK_SET,
151 	     error ) == -1 )
152 	{
153 		libcerror_error_set(
154 		 error,
155 		 LIBCERROR_ERROR_DOMAIN_IO,
156 		 LIBCERROR_IO_ERROR_SEEK_FAILED,
157 		 "%s: unable to seek segment offset: %" PRIi64 " (0x%08" PRIx64 ").",
158 		 function,
159 		 segment_offset,
160 		 segment_offset );
161 
162 		return( -1 );
163 	}
164 	return( segment_offset );
165 }
166 
167