You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

652 lines
14 KiB

  1. /*
  2. * Attached file IO handle functions
  3. *
  4. * Copyright (C) 2008-2019, 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. #include <common.h>
  22. #include <memory.h>
  23. #include <types.h>
  24. #include "libpff_attached_file_io_handle.h"
  25. #include "libpff_attachment.h"
  26. #include "libpff_definitions.h"
  27. #include "libpff_libbfio.h"
  28. #include "libpff_libcerror.h"
  29. #include "libpff_types.h"
  30. /* Creates an attached file IO handle
  31. * Make sure the value io_handle is referencing, is set to NULL
  32. * Returns 1 if successful or -1 on error
  33. */
  34. int libpff_attached_file_io_handle_initialize(
  35. libpff_attached_file_io_handle_t **io_handle,
  36. libpff_item_t *attachment,
  37. libcerror_error_t **error )
  38. {
  39. static char *function = "libpff_attached_file_io_handle_initialize";
  40. if( io_handle == NULL )
  41. {
  42. libcerror_error_set(
  43. error,
  44. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  45. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  46. "%s: invalid IO handle.",
  47. function );
  48. return( -1 );
  49. }
  50. if( *io_handle != NULL )
  51. {
  52. libcerror_error_set(
  53. error,
  54. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  55. LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
  56. "%s: invalid IO handle value already set.",
  57. function );
  58. return( -1 );
  59. }
  60. if( attachment == NULL )
  61. {
  62. libcerror_error_set(
  63. error,
  64. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  65. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  66. "%s: invalid attachment.",
  67. function );
  68. return( -1 );
  69. }
  70. *io_handle = memory_allocate_structure(
  71. libpff_attached_file_io_handle_t );
  72. if( *io_handle == NULL )
  73. {
  74. libcerror_error_set(
  75. error,
  76. LIBCERROR_ERROR_DOMAIN_MEMORY,
  77. LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
  78. "%s: unable to create IO handle.",
  79. function );
  80. goto on_error;
  81. }
  82. if( memory_set(
  83. *io_handle,
  84. 0,
  85. sizeof( libpff_attached_file_io_handle_t ) ) == NULL )
  86. {
  87. libcerror_error_set(
  88. error,
  89. LIBCERROR_ERROR_DOMAIN_MEMORY,
  90. LIBCERROR_MEMORY_ERROR_SET_FAILED,
  91. "%s: unable to clear IO handle.",
  92. function );
  93. goto on_error;
  94. }
  95. ( *io_handle )->attachment = attachment;
  96. return( 1 );
  97. on_error:
  98. if( *io_handle != NULL )
  99. {
  100. memory_free(
  101. *io_handle );
  102. *io_handle = NULL;
  103. }
  104. return( -1 );
  105. }
  106. /* Frees an attached file IO handle
  107. * Returns 1 if succesful or -1 on error
  108. */
  109. int libpff_attached_file_io_handle_free(
  110. libpff_attached_file_io_handle_t **io_handle,
  111. libcerror_error_t **error )
  112. {
  113. static char *function = "libpff_attached_file_io_handle_free";
  114. if( io_handle == NULL )
  115. {
  116. libcerror_error_set(
  117. error,
  118. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  119. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  120. "%s: invalid IO handle.",
  121. function );
  122. return( -1 );
  123. }
  124. if( *io_handle != NULL )
  125. {
  126. /* The attachment reference is freed elsewhere
  127. */
  128. memory_free(
  129. *io_handle );
  130. *io_handle = NULL;
  131. }
  132. return( 1 );
  133. }
  134. /* Clones (duplicates) the IO handle and its attributes
  135. * Returns 1 if succesful or -1 on error
  136. */
  137. int libpff_attached_file_io_handle_clone(
  138. libpff_attached_file_io_handle_t **destination_io_handle,
  139. libpff_attached_file_io_handle_t *source_io_handle,
  140. libcerror_error_t **error )
  141. {
  142. static char *function = "libpff_attached_file_io_handle_clone";
  143. if( destination_io_handle == NULL )
  144. {
  145. libcerror_error_set(
  146. error,
  147. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  148. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  149. "%s: invalid destination IO handle.",
  150. function );
  151. return( -1 );
  152. }
  153. if( *destination_io_handle != NULL )
  154. {
  155. libcerror_error_set(
  156. error,
  157. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  158. LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
  159. "%s: destination IO handle already set.",
  160. function );
  161. return( -1 );
  162. }
  163. if( source_io_handle == NULL )
  164. {
  165. *destination_io_handle = NULL;
  166. return( 1 );
  167. }
  168. if( libpff_attached_file_io_handle_initialize(
  169. destination_io_handle,
  170. source_io_handle->attachment,
  171. error ) != 1 )
  172. {
  173. libcerror_error_set(
  174. error,
  175. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  176. LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
  177. "%s: unable to create IO handle.",
  178. function );
  179. return( -1 );
  180. }
  181. ( *destination_io_handle )->access_flags = source_io_handle->access_flags;
  182. return( 1 );
  183. }
  184. /* Opens the IO handle
  185. * Returns 1 if successful or -1 on error
  186. */
  187. int libpff_attached_file_io_handle_open(
  188. libpff_attached_file_io_handle_t *io_handle,
  189. int flags,
  190. libcerror_error_t **error )
  191. {
  192. static char *function = "libpff_attached_file_io_handle_open";
  193. if( io_handle == NULL )
  194. {
  195. libcerror_error_set(
  196. error,
  197. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  198. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  199. "%s: invalid IO handle.",
  200. function );
  201. return( -1 );
  202. }
  203. if( io_handle->attachment == NULL )
  204. {
  205. libcerror_error_set(
  206. error,
  207. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  208. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  209. "%s: invalid IO handle - missing attachment item.",
  210. function );
  211. return( -1 );
  212. }
  213. if( io_handle->is_open != 0 )
  214. {
  215. libcerror_error_set(
  216. error,
  217. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  218. LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
  219. "%s: IO handle already open.",
  220. function );
  221. return( -1 );
  222. }
  223. if( ( flags & LIBBFIO_ACCESS_FLAG_READ ) == 0 )
  224. {
  225. libcerror_error_set(
  226. error,
  227. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  228. LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
  229. "%s: unsupported flags.",
  230. function );
  231. return( -1 );
  232. }
  233. /* Currently only support for reading data
  234. */
  235. if( ( flags & ~( LIBBFIO_ACCESS_FLAG_READ ) ) != 0 )
  236. {
  237. libcerror_error_set(
  238. error,
  239. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  240. LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
  241. "%s: unsupported flags.",
  242. function );
  243. return( -1 );
  244. }
  245. io_handle->access_flags = flags;
  246. io_handle->is_open = 1;
  247. return( 1 );
  248. }
  249. /* Closes the IO handle
  250. * Returns 0 if successful or -1 on error
  251. */
  252. int libpff_attached_file_io_handle_close(
  253. libpff_attached_file_io_handle_t *io_handle,
  254. libcerror_error_t **error )
  255. {
  256. static char *function = "libpff_attached_file_io_handle_close";
  257. if( io_handle == NULL )
  258. {
  259. libcerror_error_set(
  260. error,
  261. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  262. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  263. "%s: invalid IO handle.",
  264. function );
  265. return( -1 );
  266. }
  267. if( io_handle->attachment == NULL )
  268. {
  269. libcerror_error_set(
  270. error,
  271. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  272. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  273. "%s: invalid IO handle - missing attachment item.",
  274. function );
  275. return( -1 );
  276. }
  277. if( io_handle->is_open == 0 )
  278. {
  279. libcerror_error_set(
  280. error,
  281. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  282. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  283. "%s: invalid IO handle - not open.",
  284. function );
  285. return( -1 );
  286. }
  287. io_handle->is_open = 0;
  288. return( 0 );
  289. }
  290. /* Reads a buffer from the IO handle
  291. * Returns the number of bytes read if successful, or -1 on error
  292. */
  293. ssize_t libpff_attached_file_io_handle_read(
  294. libpff_attached_file_io_handle_t *io_handle,
  295. uint8_t *buffer,
  296. size_t size,
  297. libcerror_error_t **error )
  298. {
  299. static char *function = "libpff_attached_file_io_handle_read";
  300. ssize_t read_count = 0;
  301. if( io_handle == NULL )
  302. {
  303. libcerror_error_set(
  304. error,
  305. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  306. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  307. "%s: invalid IO handle.",
  308. function );
  309. return( -1 );
  310. }
  311. if( io_handle->attachment == NULL )
  312. {
  313. libcerror_error_set(
  314. error,
  315. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  316. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  317. "%s: invalid IO handle - missing attachment item.",
  318. function );
  319. return( -1 );
  320. }
  321. if( io_handle->is_open == 0 )
  322. {
  323. libcerror_error_set(
  324. error,
  325. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  326. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  327. "%s: invalid IO handle - not open.",
  328. function );
  329. return( -1 );
  330. }
  331. if( ( io_handle->access_flags & LIBBFIO_ACCESS_FLAG_READ ) == 0 )
  332. {
  333. libcerror_error_set(
  334. error,
  335. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  336. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  337. "%s: invalid IO handle - no read access.",
  338. function );
  339. return( -1 );
  340. }
  341. read_count = libpff_attachment_data_read_buffer(
  342. io_handle->attachment,
  343. buffer,
  344. size,
  345. error );
  346. if( read_count <= -1 )
  347. {
  348. libcerror_error_set(
  349. error,
  350. LIBCERROR_ERROR_DOMAIN_IO,
  351. LIBCERROR_IO_ERROR_READ_FAILED,
  352. "%s: unable to read buffer from attachment data.",
  353. function );
  354. return( -1 );
  355. }
  356. return( read_count );
  357. }
  358. /* Writes a buffer to the IO handle
  359. * Returns the number of bytes written if successful, or -1 on error
  360. */
  361. ssize_t libpff_attached_file_io_handle_write(
  362. libpff_attached_file_io_handle_t *io_handle,
  363. const uint8_t *buffer,
  364. size_t size,
  365. libcerror_error_t **error )
  366. {
  367. static char *function = "libpff_attached_file_io_handle_write";
  368. if( io_handle == NULL )
  369. {
  370. libcerror_error_set(
  371. error,
  372. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  373. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  374. "%s: invalid IO handle.",
  375. function );
  376. return( -1 );
  377. }
  378. if( io_handle->attachment == NULL )
  379. {
  380. libcerror_error_set(
  381. error,
  382. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  383. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  384. "%s: invalid IO handle - missing attachment item.",
  385. function );
  386. return( -1 );
  387. }
  388. if( io_handle->is_open == 0 )
  389. {
  390. libcerror_error_set(
  391. error,
  392. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  393. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  394. "%s: invalid IO handle - not open.",
  395. function );
  396. return( -1 );
  397. }
  398. if( ( io_handle->access_flags & LIBBFIO_ACCESS_FLAG_WRITE ) == 0 )
  399. {
  400. libcerror_error_set(
  401. error,
  402. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  403. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  404. "%s: invalid IO handle - no write access.",
  405. function );
  406. return( -1 );
  407. }
  408. if( buffer == NULL )
  409. {
  410. libcerror_error_set(
  411. error,
  412. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  413. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  414. "%s: invalid buffer.",
  415. function );
  416. return( -1 );
  417. }
  418. if( size > (size_t) SSIZE_MAX )
  419. {
  420. libcerror_error_set(
  421. error,
  422. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  423. LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
  424. "%s: invalid size value exceeds maximum.",
  425. function );
  426. return( -1 );
  427. }
  428. return( 0 );
  429. }
  430. /* Seeks a certain offset within the IO handle
  431. * Returns the offset if the seek is successful or -1 on error
  432. */
  433. off64_t libpff_attached_file_io_handle_seek_offset(
  434. libpff_attached_file_io_handle_t *io_handle,
  435. off64_t offset,
  436. int whence,
  437. libcerror_error_t **error )
  438. {
  439. static char *function = "libpff_attached_file_io_handle_seek_offset";
  440. if( io_handle == NULL )
  441. {
  442. libcerror_error_set(
  443. error,
  444. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  445. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  446. "%s: invalid IO handle.",
  447. function );
  448. return( -1 );
  449. }
  450. if( io_handle->attachment == NULL )
  451. {
  452. libcerror_error_set(
  453. error,
  454. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  455. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  456. "%s: invalid IO handle - missing attachment item.",
  457. function );
  458. return( -1 );
  459. }
  460. if( io_handle->is_open == 0 )
  461. {
  462. libcerror_error_set(
  463. error,
  464. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  465. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  466. "%s: invalid IO handle - not open.",
  467. function );
  468. return( -1 );
  469. }
  470. offset = libpff_attachment_data_seek_offset(
  471. io_handle->attachment,
  472. offset,
  473. whence,
  474. error );
  475. if( offset == -1 )
  476. {
  477. libcerror_error_set(
  478. error,
  479. LIBCERROR_ERROR_DOMAIN_IO,
  480. LIBCERROR_IO_ERROR_SEEK_FAILED,
  481. "%s: unable to seek offset in attachment data.",
  482. function );
  483. return( -1 );
  484. }
  485. return( offset );
  486. }
  487. /* Function to determine if the attached file exists
  488. * Returns 1 if the attached file exists, 0 if not or -1 on error
  489. */
  490. int libpff_attached_file_io_handle_exists(
  491. libpff_attached_file_io_handle_t *io_handle,
  492. libcerror_error_t **error )
  493. {
  494. static char *function = "libpff_attached_file_io_handle_exists";
  495. if( io_handle == NULL )
  496. {
  497. libcerror_error_set(
  498. error,
  499. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  500. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  501. "%s: invalid IO handle.",
  502. function );
  503. return( -1 );
  504. }
  505. if( io_handle->attachment == NULL )
  506. {
  507. return( 0 );
  508. }
  509. return( 1 );
  510. }
  511. /* Check if the attached file is open
  512. * Returns 1 if open, 0 if not or -1 on error
  513. */
  514. int libpff_attached_file_io_handle_is_open(
  515. libpff_attached_file_io_handle_t *io_handle,
  516. libcerror_error_t **error )
  517. {
  518. static char *function = "libpff_attached_file_io_handle_is_open";
  519. if( io_handle == NULL )
  520. {
  521. libcerror_error_set(
  522. error,
  523. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  524. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  525. "%s: invalid IO handle.",
  526. function );
  527. return( -1 );
  528. }
  529. if( io_handle->attachment == NULL )
  530. {
  531. libcerror_error_set(
  532. error,
  533. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  534. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  535. "%s: invalid IO handle - missing attachment item.",
  536. function );
  537. return( -1 );
  538. }
  539. if( io_handle->is_open == 0 )
  540. {
  541. return( 0 );
  542. }
  543. return( 1 );
  544. }
  545. /* Retrieves the attached file size
  546. * Returns 1 if successful or -1 on error
  547. */
  548. int libpff_attached_file_io_handle_get_size(
  549. libpff_attached_file_io_handle_t *io_handle,
  550. size64_t *size,
  551. libcerror_error_t **error )
  552. {
  553. static char *function = "libpff_attached_file_io_handle_get_size";
  554. if( io_handle == NULL )
  555. {
  556. libcerror_error_set(
  557. error,
  558. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  559. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  560. "%s: invalid IO handle.",
  561. function );
  562. return( -1 );
  563. }
  564. if( libpff_attachment_get_data_size(
  565. io_handle->attachment,
  566. size,
  567. error ) != 1 )
  568. {
  569. libcerror_error_set(
  570. error,
  571. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  572. LIBCERROR_RUNTIME_ERROR_GET_FAILED,
  573. "%s: unable to retrieve attachment data size.",
  574. function );
  575. return( -1 );
  576. }
  577. return( 1 );
  578. }