zend_list.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.00 of the Zend license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.zend.com/license/2_00.txt. |
  11. | If you did not receive a copy of the Zend license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@zend.com so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Andi Gutmans <andi@zend.com> |
  16. | Zeev Suraski <zeev@zend.com> |
  17. +----------------------------------------------------------------------+
  18. */
  19. /* $Id$ */
  20. /* resource lists */
  21. #include "zend.h"
  22. #include "zend_list.h"
  23. #include "zend_API.h"
  24. #include "zend_globals.h"
  25. ZEND_API int le_index_ptr;
  26. /* true global */
  27. static HashTable list_destructors;
  28. ZEND_API int zend_list_insert(void *ptr, int type TSRMLS_DC)
  29. {
  30. int index;
  31. zend_rsrc_list_entry le;
  32. le.ptr=ptr;
  33. le.type=type;
  34. le.refcount=1;
  35. index = zend_hash_next_free_element(&EG(regular_list));
  36. zend_hash_index_update(&EG(regular_list), index, (void *) &le, sizeof(zend_rsrc_list_entry), NULL);
  37. return index;
  38. }
  39. ZEND_API int _zend_list_delete(int id TSRMLS_DC)
  40. {
  41. zend_rsrc_list_entry *le;
  42. if (zend_hash_index_find(&EG(regular_list), id, (void **) &le)==SUCCESS) {
  43. /* printf("del(%d): %d->%d\n", id, le->refcount, le->refcount-1); */
  44. if (--le->refcount<=0) {
  45. return zend_hash_index_del(&EG(regular_list), id);
  46. } else {
  47. return SUCCESS;
  48. }
  49. } else {
  50. return FAILURE;
  51. }
  52. }
  53. ZEND_API void *_zend_list_find(int id, int *type TSRMLS_DC)
  54. {
  55. zend_rsrc_list_entry *le;
  56. if (zend_hash_index_find(&EG(regular_list), id, (void **) &le)==SUCCESS) {
  57. *type = le->type;
  58. return le->ptr;
  59. } else {
  60. *type = -1;
  61. return NULL;
  62. }
  63. }
  64. ZEND_API int _zend_list_addref(int id TSRMLS_DC)
  65. {
  66. zend_rsrc_list_entry *le;
  67. if (zend_hash_index_find(&EG(regular_list), id, (void **) &le)==SUCCESS) {
  68. /* printf("add(%d): %d->%d\n", id, le->refcount, le->refcount+1); */
  69. le->refcount++;
  70. return SUCCESS;
  71. } else {
  72. return FAILURE;
  73. }
  74. }
  75. ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type TSRMLS_DC)
  76. {
  77. int rsrc_id;
  78. rsrc_id = zend_list_insert(rsrc_pointer, rsrc_type TSRMLS_CC);
  79. if (rsrc_result) {
  80. rsrc_result->value.lval = rsrc_id;
  81. rsrc_result->type = IS_RESOURCE;
  82. }
  83. return rsrc_id;
  84. }
  85. ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, const char *resource_type_name, int *found_resource_type, int num_resource_types, ...)
  86. {
  87. int id;
  88. int actual_resource_type;
  89. void *resource;
  90. va_list resource_types;
  91. int i;
  92. const char *space;
  93. const char *class_name;
  94. if (default_id==-1) { /* use id */
  95. if (!passed_id) {
  96. if (resource_type_name) {
  97. class_name = get_active_class_name(&space TSRMLS_CC);
  98. zend_error(E_WARNING, "%s%s%s(): no %s resource supplied", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name);
  99. }
  100. return NULL;
  101. } else if ((*passed_id)->type != IS_RESOURCE) {
  102. if (resource_type_name) {
  103. class_name = get_active_class_name(&space TSRMLS_CC);
  104. zend_error(E_WARNING, "%s%s%s(): supplied argument is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name);
  105. }
  106. return NULL;
  107. }
  108. id = (*passed_id)->value.lval;
  109. } else {
  110. id = default_id;
  111. }
  112. resource = zend_list_find(id, &actual_resource_type);
  113. if (!resource) {
  114. if (resource_type_name) {
  115. class_name = get_active_class_name(&space TSRMLS_CC);
  116. zend_error(E_WARNING, "%s%s%s(): %d is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), id, resource_type_name);
  117. }
  118. return NULL;
  119. }
  120. va_start(resource_types, num_resource_types);
  121. for (i=0; i<num_resource_types; i++) {
  122. if (actual_resource_type == va_arg(resource_types, int)) {
  123. va_end(resource_types);
  124. if (found_resource_type) {
  125. *found_resource_type = actual_resource_type;
  126. }
  127. return resource;
  128. }
  129. }
  130. va_end(resource_types);
  131. if (resource_type_name) {
  132. class_name = get_active_class_name(&space TSRMLS_CC);
  133. zend_error(E_WARNING, "%s%s%s(): supplied resource is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name);
  134. }
  135. return NULL;
  136. }
  137. void list_entry_destructor(void *ptr)
  138. {
  139. zend_rsrc_list_entry *le = (zend_rsrc_list_entry *) ptr;
  140. zend_rsrc_list_dtors_entry *ld;
  141. TSRMLS_FETCH();
  142. if (zend_hash_index_find(&list_destructors, le->type, (void **) &ld)==SUCCESS) {
  143. switch (ld->type) {
  144. case ZEND_RESOURCE_LIST_TYPE_STD:
  145. if (ld->list_dtor) {
  146. (ld->list_dtor)(le->ptr);
  147. }
  148. break;
  149. case ZEND_RESOURCE_LIST_TYPE_EX:
  150. if (ld->list_dtor_ex) {
  151. ld->list_dtor_ex(le TSRMLS_CC);
  152. }
  153. break;
  154. EMPTY_SWITCH_DEFAULT_CASE()
  155. }
  156. } else {
  157. zend_error(E_WARNING,"Unknown list entry type in request shutdown (%d)", le->type);
  158. }
  159. }
  160. void plist_entry_destructor(void *ptr)
  161. {
  162. zend_rsrc_list_entry *le = (zend_rsrc_list_entry *) ptr;
  163. zend_rsrc_list_dtors_entry *ld;
  164. TSRMLS_FETCH();
  165. if (zend_hash_index_find(&list_destructors, le->type, (void **) &ld)==SUCCESS) {
  166. switch (ld->type) {
  167. case ZEND_RESOURCE_LIST_TYPE_STD:
  168. if (ld->plist_dtor) {
  169. (ld->plist_dtor)(le->ptr);
  170. }
  171. break;
  172. case ZEND_RESOURCE_LIST_TYPE_EX:
  173. if (ld->plist_dtor_ex) {
  174. ld->plist_dtor_ex(le TSRMLS_CC);
  175. }
  176. break;
  177. EMPTY_SWITCH_DEFAULT_CASE()
  178. }
  179. } else {
  180. zend_error(E_WARNING,"Unknown persistent list entry type in module shutdown (%d)", le->type);
  181. }
  182. }
  183. int zend_init_rsrc_list(TSRMLS_D)
  184. {
  185. if (zend_hash_init(&EG(regular_list), 0, NULL, list_entry_destructor, 0)==SUCCESS) {
  186. EG(regular_list).nNextFreeElement=1; /* we don't want resource id 0 */
  187. return SUCCESS;
  188. } else {
  189. return FAILURE;
  190. }
  191. }
  192. int zend_init_rsrc_plist(TSRMLS_D)
  193. {
  194. return zend_hash_init_ex(&EG(persistent_list), 0, NULL, plist_entry_destructor, 1, 0);
  195. }
  196. void zend_destroy_rsrc_list(HashTable *ht TSRMLS_DC)
  197. {
  198. zend_hash_graceful_reverse_destroy(ht);
  199. }
  200. static int clean_module_resource(zend_rsrc_list_entry *le, int *resource_id TSRMLS_DC)
  201. {
  202. if (le->type == *resource_id) {
  203. return 1;
  204. } else {
  205. return 0;
  206. }
  207. }
  208. static int zend_clean_module_rsrc_dtors_cb(zend_rsrc_list_dtors_entry *ld, int *module_number TSRMLS_DC)
  209. {
  210. if (ld->module_number == *module_number) {
  211. zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) clean_module_resource, (void *) &(ld->resource_id) TSRMLS_CC);
  212. return 1;
  213. } else {
  214. return 0;
  215. }
  216. }
  217. void zend_clean_module_rsrc_dtors(int module_number TSRMLS_DC)
  218. {
  219. zend_hash_apply_with_argument(&list_destructors, (apply_func_arg_t) zend_clean_module_rsrc_dtors_cb, (void *) &module_number TSRMLS_CC);
  220. }
  221. ZEND_API int zend_register_list_destructors(void (*ld)(void *), void (*pld)(void *), int module_number)
  222. {
  223. zend_rsrc_list_dtors_entry lde;
  224. #if 0
  225. printf("Registering destructors %d for module %d\n", list_destructors.nNextFreeElement, module_number);
  226. #endif
  227. lde.list_dtor=(void (*)(void *)) ld;
  228. lde.plist_dtor=(void (*)(void *)) pld;
  229. lde.list_dtor_ex = lde.plist_dtor_ex = NULL;
  230. lde.module_number = module_number;
  231. lde.resource_id = list_destructors.nNextFreeElement;
  232. lde.type = ZEND_RESOURCE_LIST_TYPE_STD;
  233. lde.type_name = NULL;
  234. if (zend_hash_next_index_insert(&list_destructors, (void *) &lde, sizeof(zend_rsrc_list_dtors_entry), NULL)==FAILURE) {
  235. return FAILURE;
  236. }
  237. return list_destructors.nNextFreeElement-1;
  238. }
  239. ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, const char *type_name, int module_number)
  240. {
  241. zend_rsrc_list_dtors_entry lde;
  242. #if 0
  243. printf("Registering destructors %d for module %d\n", list_destructors.nNextFreeElement, module_number);
  244. #endif
  245. lde.list_dtor = NULL;
  246. lde.plist_dtor = NULL;
  247. lde.list_dtor_ex = ld;
  248. lde.plist_dtor_ex = pld;
  249. lde.module_number = module_number;
  250. lde.resource_id = list_destructors.nNextFreeElement;
  251. lde.type = ZEND_RESOURCE_LIST_TYPE_EX;
  252. lde.type_name = type_name;
  253. if (zend_hash_next_index_insert(&list_destructors, (void *) &lde, sizeof(zend_rsrc_list_dtors_entry), NULL)==FAILURE) {
  254. return FAILURE;
  255. }
  256. return list_destructors.nNextFreeElement-1;
  257. }
  258. ZEND_API int zend_fetch_list_dtor_id(char *type_name)
  259. {
  260. zend_rsrc_list_dtors_entry *lde;
  261. HashPosition pos;
  262. zend_hash_internal_pointer_reset_ex(&list_destructors, &pos);
  263. while (zend_hash_get_current_data_ex(&list_destructors, (void **)&lde, &pos) == SUCCESS) {
  264. if (lde->type_name && (strcmp(type_name, lde->type_name) == 0)) {
  265. #if 0
  266. printf("Found resource id %d for resource type %s\n", (*lde).resource_id, type_name);
  267. #endif
  268. return lde->resource_id;
  269. }
  270. zend_hash_move_forward_ex(&list_destructors, &pos);
  271. }
  272. return 0;
  273. }
  274. int zend_init_rsrc_list_dtors(void)
  275. {
  276. int retval;
  277. retval = zend_hash_init(&list_destructors, 50, NULL, NULL, 1);
  278. list_destructors.nNextFreeElement=1; /* we don't want resource type 0 */
  279. return retval;
  280. }
  281. void zend_destroy_rsrc_list_dtors(void)
  282. {
  283. zend_hash_destroy(&list_destructors);
  284. }
  285. const char *zend_rsrc_list_get_rsrc_type(int resource TSRMLS_DC)
  286. {
  287. zend_rsrc_list_dtors_entry *lde;
  288. int rsrc_type;
  289. if (!zend_list_find(resource, &rsrc_type))
  290. return NULL;
  291. if (zend_hash_index_find(&list_destructors, rsrc_type, (void **) &lde)==SUCCESS) {
  292. return lde->type_name;
  293. } else {
  294. return NULL;
  295. }
  296. }
  297. /*
  298. * Local variables:
  299. * tab-width: 4
  300. * c-basic-offset: 4
  301. * indent-tabs-mode: t
  302. * End:
  303. */