/data/source/yaltools/yaltools_glob.c

https://github.com/libyal/libyal · C · 577 lines · 467 code · 73 blank · 37 comment · 66 complexity · 4969acc84e32d5f1490d1ab2a395cc27 MD5 · raw file

  1. /*
  2. * Globbing functions
  3. *
  4. * Copyright (C) ${copyright}, ${tools_authors}
  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 <narrow_string.h>
  24. #include <system_string.h>
  25. #include <types.h>
  26. #include <wide_string.h>
  27. #if defined( HAVE_ERRNO_H ) || defined( WINAPI )
  28. #include <errno.h>
  29. #endif
  30. #if defined( HAVE_STDLIB_H ) || defined( WINAPI )
  31. #include <stdlib.h>
  32. #endif
  33. #if defined( HAVE_IO_H ) || defined( WINAPI )
  34. #include <io.h>
  35. #endif
  36. #include "${tools_name}_find.h"
  37. #include "${tools_name}_glob.h"
  38. #include "${tools_name}_libcerror.h"
  39. /* TODO rename */
  40. #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
  41. #if defined( _MSC_VER )
  42. #define ${tools_name}_path_make( path, path_size, drive, directory, filename, extension ) \
  43. _wmakepath_s( path, path_size, drive, directory, filename, extension )
  44. #define ${tools_name}_path_split( path, drive, drive_size, directory, directory_size, filename, filename_size, extension, extension_size ) \
  45. _wsplitpath_s( path, drive, drive_size, directory, directory_size, filename, filename_size, extension, extension_size )
  46. #else
  47. #define ${tools_name}_path_make( path, path_size, drive, directory, filename, extension ) \
  48. _wmakepath( path, drive, directory, filename, extension )
  49. #define ${tools_name}_path_split( path, drive, drive_size, directory, directory_size, filename, filename_size, extension, extension_size ) \
  50. _wsplitpath( path, drive, directory, filename, extension )
  51. #endif
  52. #else
  53. #if defined( _MSC_VER )
  54. #define ${tools_name}_path_make( path, path_size, drive, directory, filename, extension ) \
  55. _makepath_s( path, path_size, drive, directory, filename, extension )
  56. #define ${tools_name}_path_split( path, drive, drive_size, directory, directory_size, filename, filename_size, extension, extension_size ) \
  57. _splitpath_s( path, drive, drive_size, directory, directory_size, filename, filename_size, extension, extension_size )
  58. #else
  59. #define ${tools_name}_path_make( path, path_size, drive, directory, filename, extension ) \
  60. _makepath( path, drive, directory, filename, extension )
  61. #define ${tools_name}_path_split( path, drive, drive_size, directory, directory_size, filename, filename_size, extension, extension_size ) \
  62. _splitpath( path, drive, directory, filename, extension )
  63. #endif
  64. #endif
  65. #if !defined( HAVE_GLOB_H )
  66. /* Creates a glob
  67. * Make sure the value glob is referencing, is set to NULL
  68. * Returns 1 if successful or -1 on error
  69. */
  70. int ${tools_name}_glob_initialize(
  71. ${tools_name}_glob_t **glob,
  72. libcerror_error_t **error )
  73. {
  74. static char *function = "${tools_name}_glob_initialize";
  75. if( glob == NULL )
  76. {
  77. libcerror_error_set(
  78. error,
  79. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  80. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  81. "%s: invalid glob.",
  82. function );
  83. return( -1 );
  84. }
  85. if( *glob != NULL )
  86. {
  87. libcerror_error_set(
  88. error,
  89. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  90. LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
  91. "%s: invalid glob value already set.",
  92. function );
  93. return( -1 );
  94. }
  95. *glob = memory_allocate_structure(
  96. ${tools_name}_glob_t );
  97. if( *glob == NULL )
  98. {
  99. libcerror_error_set(
  100. error,
  101. LIBCERROR_ERROR_DOMAIN_MEMORY,
  102. LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
  103. "%s: unable to create glob.",
  104. function );
  105. goto on_error;
  106. }
  107. if( memory_set(
  108. *glob,
  109. 0,
  110. sizeof( ${tools_name}_glob_t ) ) == NULL )
  111. {
  112. libcerror_error_set(
  113. error,
  114. LIBCERROR_ERROR_DOMAIN_MEMORY,
  115. LIBCERROR_MEMORY_ERROR_SET_FAILED,
  116. "%s: unable to clear glob.",
  117. function );
  118. goto on_error;
  119. }
  120. return( 1 );
  121. on_error:
  122. if( *glob != NULL )
  123. {
  124. memory_free(
  125. *glob );
  126. *glob = NULL;
  127. }
  128. return( -1 );
  129. }
  130. /* Frees a glob
  131. * Returns 1 if successful or -1 on error
  132. */
  133. int ${tools_name}_glob_free(
  134. ${tools_name}_glob_t **glob,
  135. libcerror_error_t **error )
  136. {
  137. static char *function = "${tools_name}_glob_free";
  138. int result_iterator = 0;
  139. if( glob == NULL )
  140. {
  141. libcerror_error_set(
  142. error,
  143. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  144. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  145. "%s: invalid glob.",
  146. function );
  147. return( -1 );
  148. }
  149. if( *glob != NULL )
  150. {
  151. if( ( *glob )->results != NULL )
  152. {
  153. for( result_iterator = 0;
  154. result_iterator < ( *glob )->number_of_results;
  155. result_iterator++ )
  156. {
  157. if( ( *glob )->results[ result_iterator ] != NULL )
  158. {
  159. memory_free(
  160. ( *glob )->results[ result_iterator ] );
  161. }
  162. }
  163. memory_free(
  164. ( *glob )->results );
  165. }
  166. memory_free(
  167. *glob );
  168. *glob = NULL;
  169. }
  170. return( 1 );
  171. }
  172. /* Resizes the glob
  173. * Returns 1 if successful or -1 on error
  174. */
  175. int ${tools_name}_glob_resize(
  176. ${tools_name}_glob_t *glob,
  177. int new_number_of_results,
  178. libcerror_error_t **error )
  179. {
  180. void *reallocation = NULL;
  181. static char *function = "${tools_name}_glob_resize";
  182. size_t previous_size = 0;
  183. size_t new_size = 0;
  184. if( glob == NULL )
  185. {
  186. libcerror_error_set(
  187. error,
  188. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  189. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  190. "%s: invalid glob.",
  191. function );
  192. return( -1 );
  193. }
  194. if( glob->number_of_results >= new_number_of_results )
  195. {
  196. libcerror_error_set(
  197. error,
  198. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  199. LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
  200. "%s: new number of results less equal than current.",
  201. function );
  202. return( -1 );
  203. }
  204. previous_size = sizeof( system_character_t * ) * glob->number_of_results;
  205. new_size = sizeof( system_character_t * ) * new_number_of_results;
  206. if( ( previous_size > (size_t) SSIZE_MAX )
  207. || ( new_size > (size_t) SSIZE_MAX ) )
  208. {
  209. libcerror_error_set(
  210. error,
  211. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  212. LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
  213. "%s: invalid size value exceeds maximum.",
  214. function );
  215. return( -1 );
  216. }
  217. reallocation = memory_reallocate(
  218. glob->results,
  219. new_size );
  220. if( reallocation == NULL )
  221. {
  222. libcerror_error_set(
  223. error,
  224. LIBCERROR_ERROR_DOMAIN_MEMORY,
  225. LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
  226. "%s: unable to reallocate glob results.",
  227. function );
  228. return( -1 );
  229. }
  230. glob->results = (system_character_t **) reallocation;
  231. if( memory_set(
  232. &( glob->results[ glob->number_of_results ] ),
  233. 0,
  234. new_size - previous_size ) == NULL )
  235. {
  236. libcerror_error_set(
  237. error,
  238. LIBCERROR_ERROR_DOMAIN_MEMORY,
  239. LIBCERROR_MEMORY_ERROR_SET_FAILED,
  240. "%s: unable to clear glob.",
  241. function );
  242. return( -1 );
  243. }
  244. glob->number_of_results = new_number_of_results;
  245. return( 1 );
  246. }
  247. /* Resolves filenames with wildcards (globs)
  248. * Returns 1 if successful or -1 on error
  249. */
  250. int ${tools_name}_glob_resolve(
  251. ${tools_name}_glob_t *glob,
  252. system_character_t * const patterns[],
  253. int number_of_patterns,
  254. libcerror_error_t **error )
  255. {
  256. #if defined( HAVE_IO_H ) || defined( WINAPI )
  257. ${tools_name}_find_data_t find_data;
  258. system_character_t find_path[ _MAX_PATH ];
  259. system_character_t find_drive[ _MAX_DRIVE ];
  260. system_character_t find_directory[ _MAX_DIR ];
  261. system_character_t find_name[ _MAX_FNAME ];
  262. system_character_t find_extension[ _MAX_EXT ];
  263. intptr_t find_handle = 0;
  264. #endif
  265. static char *function = "${tools_name}_glob_resolve";
  266. size_t find_path_length = 0;
  267. int globs_found = 0;
  268. int iterator = 0;
  269. if( glob == NULL )
  270. {
  271. libcerror_error_set(
  272. error,
  273. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  274. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  275. "%s: invalid glob.",
  276. function );
  277. return( -1 );
  278. }
  279. for( iterator = 0;
  280. iterator < number_of_patterns;
  281. iterator++ )
  282. {
  283. if( patterns[ iterator ] == NULL )
  284. {
  285. libcerror_error_set(
  286. error,
  287. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  288. LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
  289. "%s: missing pattern value.",
  290. function );
  291. return( -1 );
  292. }
  293. #if defined( _MSC_VER )
  294. if( ${tools_name}_path_split(
  295. patterns[ iterator ],
  296. find_drive,
  297. _MAX_DRIVE,
  298. find_directory,
  299. _MAX_DIR,
  300. find_name,
  301. _MAX_FNAME,
  302. find_extension,
  303. _MAX_EXT ) != 0 )
  304. {
  305. libcerror_error_set(
  306. error,
  307. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  308. LIBCERROR_RUNTIME_ERROR_SET_FAILED,
  309. "%s: unable to split path.",
  310. function );
  311. return( -1 );
  312. }
  313. #else
  314. ${tools_name}_path_split(
  315. patterns[ iterator ],
  316. find_drive,
  317. _MAX_DRIVE,
  318. find_directory,
  319. _MAX_DIR,
  320. find_name,
  321. _MAX_FNAME,
  322. find_extension,
  323. _MAX_EXT );
  324. #endif
  325. find_handle = ${tools_name}_find_first(
  326. patterns[ iterator ],
  327. &find_data );
  328. if( find_handle != -1 )
  329. {
  330. do
  331. {
  332. if( ${tools_name}_glob_resize(
  333. glob,
  334. glob->number_of_results + 1,
  335. error ) != 1 )
  336. {
  337. libcerror_error_set(
  338. error,
  339. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  340. LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
  341. "%s: unable to resize glob.",
  342. function );
  343. return( -1 );
  344. }
  345. #if defined( _MSC_VER )
  346. if( ${tools_name}_path_make(
  347. find_path,
  348. _MAX_PATH,
  349. find_drive,
  350. find_directory,
  351. find_data.name,
  352. _SYSTEM_STRING( "" ) ) != 0 )
  353. {
  354. libcerror_error_set(
  355. error,
  356. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  357. LIBCERROR_RUNTIME_ERROR_SET_FAILED,
  358. "%s: unable to make path.",
  359. function );
  360. return( -1 );
  361. }
  362. #elif defined( __BORLANDC__ ) && __BORLANDC__ <= 0x0520
  363. ${tools_name}_path_make(
  364. find_path,
  365. _MAX_PATH,
  366. find_drive,
  367. find_directory,
  368. find_data.ff_name,
  369. _SYSTEM_STRING( "" ) );
  370. #else
  371. ${tools_name}_path_make(
  372. find_path,
  373. _MAX_PATH,
  374. find_drive,
  375. find_directory,
  376. find_data.name,
  377. _SYSTEM_STRING( "" ) );
  378. #endif
  379. find_path_length = system_string_length(
  380. find_path );
  381. glob->results[ glob->number_of_results - 1 ] = system_string_allocate(
  382. find_path_length + 1 );
  383. if( glob->results[ glob->number_of_results - 1 ] == NULL )
  384. {
  385. libcerror_error_set(
  386. error,
  387. LIBCERROR_ERROR_DOMAIN_MEMORY,
  388. LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
  389. "%s: unable to create glob result.",
  390. function );
  391. return( -1 );
  392. }
  393. if( system_string_copy(
  394. glob->results[ glob->number_of_results - 1 ],
  395. find_path,
  396. find_path_length ) == NULL )
  397. {
  398. libcerror_error_set(
  399. error,
  400. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  401. LIBCERROR_RUNTIME_ERROR_SET_FAILED,
  402. "%s: unable to set glob result.",
  403. function );
  404. memory_free(
  405. glob->results[ glob->number_of_results - 1 ] );
  406. glob->results[ glob->number_of_results - 1 ] = NULL;
  407. return( -1 );
  408. }
  409. ( glob->results[ glob->number_of_results - 1 ] )[ find_path_length ] = 0;
  410. globs_found++;
  411. if( globs_found > (int32_t) UINT16_MAX )
  412. {
  413. libcerror_error_set(
  414. error,
  415. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  416. LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
  417. "%s: too many globs found.",
  418. function );
  419. return( -1 );
  420. }
  421. }
  422. while( ${tools_name}_find_next(
  423. find_handle,
  424. &find_data ) == 0 );
  425. if( errno != ENOENT )
  426. {
  427. libcerror_error_set(
  428. error,
  429. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  430. LIBCERROR_RUNTIME_ERROR_GET_FAILED,
  431. "%s: error finding next file entry.",
  432. function );
  433. return( -1 );
  434. }
  435. if( ${tools_name}_find_close(
  436. find_handle ) != 0 )
  437. {
  438. libcerror_error_set(
  439. error,
  440. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  441. LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
  442. "%s: error closing find handle.",
  443. function );
  444. return( -1 );
  445. }
  446. }
  447. else if( errno != ENOENT )
  448. {
  449. libcerror_error_set(
  450. error,
  451. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  452. LIBCERROR_RUNTIME_ERROR_GET_FAILED,
  453. "%s: error finding file entry.",
  454. function );
  455. return( -1 );
  456. }
  457. }
  458. return( 1 );
  459. }
  460. /* Retrieves the glob results
  461. * Returns 1 if successful or -1 on error
  462. */
  463. int ${tools_name}_glob_get_results(
  464. ${tools_name}_glob_t *glob,
  465. int *number_of_results,
  466. system_character_t ***results,
  467. libcerror_error_t **error )
  468. {
  469. static char *function = "${tools_name}_glob_resize";
  470. if( glob == NULL )
  471. {
  472. libcerror_error_set(
  473. error,
  474. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  475. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  476. "%s: invalid glob.",
  477. function );
  478. return( -1 );
  479. }
  480. if( number_of_results == NULL )
  481. {
  482. libcerror_error_set(
  483. error,
  484. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  485. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  486. "%s: invalid number of results.",
  487. function );
  488. return( -1 );
  489. }
  490. if( results == NULL )
  491. {
  492. libcerror_error_set(
  493. error,
  494. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  495. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  496. "%s: invalid results.",
  497. function );
  498. return( -1 );
  499. }
  500. *number_of_results = glob->number_of_results;
  501. *results = glob->results;
  502. return( 1 );
  503. }
  504. #endif /* !defined( HAVE_GLOB_H ) */