noderb 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (424) hide show
  1. data/LICENSE +19 -0
  2. data/README.md +25 -0
  3. data/ext/noderb_extension/extconf.rb +11 -0
  4. data/ext/noderb_extension/libuv/AUTHORS +11 -0
  5. data/ext/noderb_extension/libuv/LICENSE +48 -0
  6. data/ext/noderb_extension/libuv/Makefile +119 -0
  7. data/ext/noderb_extension/libuv/README +45 -0
  8. data/ext/noderb_extension/libuv/build/all.gyp +254 -0
  9. data/ext/noderb_extension/libuv/build/common.gypi +13 -0
  10. data/ext/noderb_extension/libuv/build/gyp_uv +43 -0
  11. data/ext/noderb_extension/libuv/config-mingw.mk +67 -0
  12. data/ext/noderb_extension/libuv/config-unix.mk +121 -0
  13. data/ext/noderb_extension/libuv/create-msvs-files.bat +14 -0
  14. data/ext/noderb_extension/libuv/deps/pthread-win32/ANNOUNCE +482 -0
  15. data/ext/noderb_extension/libuv/deps/pthread-win32/BUGS +141 -0
  16. data/ext/noderb_extension/libuv/deps/pthread-win32/Bmakefile +268 -0
  17. data/ext/noderb_extension/libuv/deps/pthread-win32/CONTRIBUTORS +140 -0
  18. data/ext/noderb_extension/libuv/deps/pthread-win32/COPYING +150 -0
  19. data/ext/noderb_extension/libuv/deps/pthread-win32/COPYING.LIB +504 -0
  20. data/ext/noderb_extension/libuv/deps/pthread-win32/ChangeLog +5194 -0
  21. data/ext/noderb_extension/libuv/deps/pthread-win32/FAQ +451 -0
  22. data/ext/noderb_extension/libuv/deps/pthread-win32/GNUmakefile +593 -0
  23. data/ext/noderb_extension/libuv/deps/pthread-win32/MAINTAINERS +4 -0
  24. data/ext/noderb_extension/libuv/deps/pthread-win32/Makefile +516 -0
  25. data/ext/noderb_extension/libuv/deps/pthread-win32/NEWS +1245 -0
  26. data/ext/noderb_extension/libuv/deps/pthread-win32/Nmakefile +24 -0
  27. data/ext/noderb_extension/libuv/deps/pthread-win32/Nmakefile.tests +260 -0
  28. data/ext/noderb_extension/libuv/deps/pthread-win32/PROGRESS +4 -0
  29. data/ext/noderb_extension/libuv/deps/pthread-win32/README +601 -0
  30. data/ext/noderb_extension/libuv/deps/pthread-win32/README.Borland +57 -0
  31. data/ext/noderb_extension/libuv/deps/pthread-win32/README.CV +3036 -0
  32. data/ext/noderb_extension/libuv/deps/pthread-win32/README.NONPORTABLE +783 -0
  33. data/ext/noderb_extension/libuv/deps/pthread-win32/README.Watcom +62 -0
  34. data/ext/noderb_extension/libuv/deps/pthread-win32/README.WinCE +6 -0
  35. data/ext/noderb_extension/libuv/deps/pthread-win32/TODO +7 -0
  36. data/ext/noderb_extension/libuv/deps/pthread-win32/WinCE-PORT +222 -0
  37. data/ext/noderb_extension/libuv/deps/pthread-win32/attr.c +53 -0
  38. data/ext/noderb_extension/libuv/deps/pthread-win32/autostatic.c +69 -0
  39. data/ext/noderb_extension/libuv/deps/pthread-win32/barrier.c +47 -0
  40. data/ext/noderb_extension/libuv/deps/pthread-win32/build/all.gyp +207 -0
  41. data/ext/noderb_extension/libuv/deps/pthread-win32/builddmc.bat +9 -0
  42. data/ext/noderb_extension/libuv/deps/pthread-win32/cancel.c +44 -0
  43. data/ext/noderb_extension/libuv/deps/pthread-win32/cleanup.c +148 -0
  44. data/ext/noderb_extension/libuv/deps/pthread-win32/condvar.c +50 -0
  45. data/ext/noderb_extension/libuv/deps/pthread-win32/config.h +153 -0
  46. data/ext/noderb_extension/libuv/deps/pthread-win32/context.h +74 -0
  47. data/ext/noderb_extension/libuv/deps/pthread-win32/create.c +308 -0
  48. data/ext/noderb_extension/libuv/deps/pthread-win32/dll.c +92 -0
  49. data/ext/noderb_extension/libuv/deps/pthread-win32/errno.c +94 -0
  50. data/ext/noderb_extension/libuv/deps/pthread-win32/exit.c +44 -0
  51. data/ext/noderb_extension/libuv/deps/pthread-win32/fork.c +39 -0
  52. data/ext/noderb_extension/libuv/deps/pthread-win32/global.c +107 -0
  53. data/ext/noderb_extension/libuv/deps/pthread-win32/implement.h +944 -0
  54. data/ext/noderb_extension/libuv/deps/pthread-win32/misc.c +50 -0
  55. data/ext/noderb_extension/libuv/deps/pthread-win32/mutex.c +62 -0
  56. data/ext/noderb_extension/libuv/deps/pthread-win32/need_errno.h +145 -0
  57. data/ext/noderb_extension/libuv/deps/pthread-win32/nonportable.c +47 -0
  58. data/ext/noderb_extension/libuv/deps/pthread-win32/private.c +54 -0
  59. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread.c +66 -0
  60. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread.dsp +142 -0
  61. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread.dsw +29 -0
  62. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread.h +1368 -0
  63. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_destroy.c +79 -0
  64. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getdetachstate.c +86 -0
  65. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getinheritsched.c +51 -0
  66. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getschedparam.c +52 -0
  67. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getschedpolicy.c +61 -0
  68. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getscope.c +54 -0
  69. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getstackaddr.c +97 -0
  70. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_getstacksize.c +100 -0
  71. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_init.c +117 -0
  72. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setdetachstate.c +91 -0
  73. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setinheritsched.c +57 -0
  74. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setschedparam.c +63 -0
  75. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setschedpolicy.c +55 -0
  76. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setscope.c +62 -0
  77. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setstackaddr.c +97 -0
  78. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_attr_setstacksize.c +110 -0
  79. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrier_destroy.c +103 -0
  80. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrier_init.c +69 -0
  81. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrier_wait.c +104 -0
  82. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrierattr_destroy.c +83 -0
  83. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrierattr_getpshared.c +95 -0
  84. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrierattr_init.c +85 -0
  85. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_barrierattr_setpshared.c +119 -0
  86. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_cancel.c +189 -0
  87. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_cond_destroy.c +253 -0
  88. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_cond_init.c +167 -0
  89. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_cond_signal.c +231 -0
  90. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_cond_wait.c +567 -0
  91. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_condattr_destroy.c +86 -0
  92. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_condattr_getpshared.c +97 -0
  93. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_condattr_init.c +87 -0
  94. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_condattr_setpshared.c +117 -0
  95. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_delay_np.c +172 -0
  96. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_detach.c +136 -0
  97. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_equal.c +76 -0
  98. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_exit.c +106 -0
  99. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_getconcurrency.c +45 -0
  100. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_getschedparam.c +75 -0
  101. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_getspecific.c +87 -0
  102. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_getunique_np.c +47 -0
  103. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_getw32threadhandle_np.c +65 -0
  104. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_join.c +157 -0
  105. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_key_create.c +108 -0
  106. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_key_delete.c +125 -0
  107. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_kill.c +105 -0
  108. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_consistent.c +187 -0
  109. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_destroy.c +148 -0
  110. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_init.c +130 -0
  111. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_lock.c +269 -0
  112. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_timedlock.c +324 -0
  113. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_trylock.c +154 -0
  114. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutex_unlock.c +175 -0
  115. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_destroy.c +83 -0
  116. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_getkind_np.c +44 -0
  117. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_getpshared.c +95 -0
  118. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_getrobust.c +113 -0
  119. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_gettype.c +56 -0
  120. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_init.c +86 -0
  121. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_setkind_np.c +44 -0
  122. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_setpshared.c +119 -0
  123. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_setrobust.c +119 -0
  124. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_mutexattr_settype.c +143 -0
  125. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_num_processors_np.c +56 -0
  126. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_once.c +79 -0
  127. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_destroy.c +143 -0
  128. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_init.c +109 -0
  129. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_rdlock.c +102 -0
  130. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_timedrdlock.c +109 -0
  131. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_timedwrlock.c +139 -0
  132. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_tryrdlock.c +102 -0
  133. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_trywrlock.c +122 -0
  134. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_unlock.c +93 -0
  135. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlock_wrlock.c +133 -0
  136. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlockattr_destroy.c +84 -0
  137. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlockattr_getpshared.c +97 -0
  138. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlockattr_init.c +83 -0
  139. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_rwlockattr_setpshared.c +120 -0
  140. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_self.c +141 -0
  141. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_setcancelstate.c +125 -0
  142. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_setcanceltype.c +126 -0
  143. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_setconcurrency.c +53 -0
  144. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_setschedparam.c +123 -0
  145. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_setspecific.c +167 -0
  146. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_spin_destroy.c +111 -0
  147. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_spin_init.c +123 -0
  148. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_spin_lock.c +80 -0
  149. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_spin_trylock.c +77 -0
  150. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_spin_unlock.c +71 -0
  151. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_testcancel.c +103 -0
  152. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_timechange_handler_np.c +108 -0
  153. data/ext/noderb_extension/libuv/deps/pthread-win32/pthread_win32_attach_detach_np.c +258 -0
  154. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_MCS_lock.c +278 -0
  155. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_callUserDestroyRoutines.c +232 -0
  156. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_calloc.c +56 -0
  157. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_cond_check_need_init.c +78 -0
  158. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_getprocessors.c +91 -0
  159. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_is_attr.c +47 -0
  160. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_mutex_check_need_init.c +92 -0
  161. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_new.c +94 -0
  162. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_processInitialize.c +92 -0
  163. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_processTerminate.c +105 -0
  164. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_relmillisecs.c +132 -0
  165. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_reuse.c +151 -0
  166. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_rwlock_cancelwrwait.c +50 -0
  167. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_rwlock_check_need_init.c +77 -0
  168. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_semwait.c +135 -0
  169. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_spinlock_check_need_init.c +78 -0
  170. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_threadDestroy.c +79 -0
  171. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_threadStart.c +357 -0
  172. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_throw.c +189 -0
  173. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_timespec.c +83 -0
  174. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_tkAssocCreate.c +118 -0
  175. data/ext/noderb_extension/libuv/deps/pthread-win32/ptw32_tkAssocDestroy.c +114 -0
  176. data/ext/noderb_extension/libuv/deps/pthread-win32/rwlock.c +51 -0
  177. data/ext/noderb_extension/libuv/deps/pthread-win32/sched.c +53 -0
  178. data/ext/noderb_extension/libuv/deps/pthread-win32/sched.h +183 -0
  179. data/ext/noderb_extension/libuv/deps/pthread-win32/sched_get_priority_max.c +134 -0
  180. data/ext/noderb_extension/libuv/deps/pthread-win32/sched_get_priority_min.c +135 -0
  181. data/ext/noderb_extension/libuv/deps/pthread-win32/sched_getscheduler.c +71 -0
  182. data/ext/noderb_extension/libuv/deps/pthread-win32/sched_setscheduler.c +83 -0
  183. data/ext/noderb_extension/libuv/deps/pthread-win32/sched_yield.c +71 -0
  184. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_close.c +58 -0
  185. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_destroy.c +144 -0
  186. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_getvalue.c +110 -0
  187. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_init.c +169 -0
  188. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_open.c +58 -0
  189. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_post.c +128 -0
  190. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_post_multiple.c +142 -0
  191. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_timedwait.c +238 -0
  192. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_trywait.c +117 -0
  193. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_unlink.c +58 -0
  194. data/ext/noderb_extension/libuv/deps/pthread-win32/sem_wait.c +187 -0
  195. data/ext/noderb_extension/libuv/deps/pthread-win32/semaphore.c +69 -0
  196. data/ext/noderb_extension/libuv/deps/pthread-win32/semaphore.h +169 -0
  197. data/ext/noderb_extension/libuv/deps/pthread-win32/signal.c +179 -0
  198. data/ext/noderb_extension/libuv/deps/pthread-win32/spin.c +46 -0
  199. data/ext/noderb_extension/libuv/deps/pthread-win32/sync.c +43 -0
  200. data/ext/noderb_extension/libuv/deps/pthread-win32/tsd.c +44 -0
  201. data/ext/noderb_extension/libuv/deps/pthread-win32/version.rc +388 -0
  202. data/ext/noderb_extension/libuv/deps/pthread-win32/w32_CancelableWait.c +161 -0
  203. data/ext/noderb_extension/libuv/doc/desired-api.md +159 -0
  204. data/ext/noderb_extension/libuv/doc/iocp-links.html +574 -0
  205. data/ext/noderb_extension/libuv/include/ares.h +582 -0
  206. data/ext/noderb_extension/libuv/include/ares_version.h +24 -0
  207. data/ext/noderb_extension/libuv/include/eio.h +376 -0
  208. data/ext/noderb_extension/libuv/include/ev.h +835 -0
  209. data/ext/noderb_extension/libuv/include/ngx-queue.h +102 -0
  210. data/ext/noderb_extension/libuv/include/tree.h +762 -0
  211. data/ext/noderb_extension/libuv/include/uv-unix.h +138 -0
  212. data/ext/noderb_extension/libuv/include/uv-win.h +187 -0
  213. data/ext/noderb_extension/libuv/include/uv.h +635 -0
  214. data/ext/noderb_extension/libuv/src/ares/AUTHORS +37 -0
  215. data/ext/noderb_extension/libuv/src/ares/CHANGES +1198 -0
  216. data/ext/noderb_extension/libuv/src/ares/CMakeLists.txt +22 -0
  217. data/ext/noderb_extension/libuv/src/ares/NEWS +21 -0
  218. data/ext/noderb_extension/libuv/src/ares/README +60 -0
  219. data/ext/noderb_extension/libuv/src/ares/README.cares +13 -0
  220. data/ext/noderb_extension/libuv/src/ares/README.msvc +118 -0
  221. data/ext/noderb_extension/libuv/src/ares/README.node +21 -0
  222. data/ext/noderb_extension/libuv/src/ares/RELEASE-NOTES +25 -0
  223. data/ext/noderb_extension/libuv/src/ares/TODO +23 -0
  224. data/ext/noderb_extension/libuv/src/ares/ares__close_sockets.c +66 -0
  225. data/ext/noderb_extension/libuv/src/ares/ares__get_hostent.c +263 -0
  226. data/ext/noderb_extension/libuv/src/ares/ares__read_line.c +71 -0
  227. data/ext/noderb_extension/libuv/src/ares/ares__timeval.c +111 -0
  228. data/ext/noderb_extension/libuv/src/ares/ares_cancel.c +63 -0
  229. data/ext/noderb_extension/libuv/src/ares/ares_data.c +190 -0
  230. data/ext/noderb_extension/libuv/src/ares/ares_data.h +65 -0
  231. data/ext/noderb_extension/libuv/src/ares/ares_destroy.c +105 -0
  232. data/ext/noderb_extension/libuv/src/ares/ares_dns.h +90 -0
  233. data/ext/noderb_extension/libuv/src/ares/ares_expand_name.c +193 -0
  234. data/ext/noderb_extension/libuv/src/ares/ares_expand_string.c +75 -0
  235. data/ext/noderb_extension/libuv/src/ares/ares_fds.c +62 -0
  236. data/ext/noderb_extension/libuv/src/ares/ares_free_hostent.c +39 -0
  237. data/ext/noderb_extension/libuv/src/ares/ares_free_string.c +25 -0
  238. data/ext/noderb_extension/libuv/src/ares/ares_gethostbyaddr.c +292 -0
  239. data/ext/noderb_extension/libuv/src/ares/ares_gethostbyname.c +515 -0
  240. data/ext/noderb_extension/libuv/src/ares/ares_getnameinfo.c +426 -0
  241. data/ext/noderb_extension/libuv/src/ares/ares_getopt.c +122 -0
  242. data/ext/noderb_extension/libuv/src/ares/ares_getopt.h +53 -0
  243. data/ext/noderb_extension/libuv/src/ares/ares_getsock.c +72 -0
  244. data/ext/noderb_extension/libuv/src/ares/ares_init.c +1665 -0
  245. data/ext/noderb_extension/libuv/src/ares/ares_ipv6.h +78 -0
  246. data/ext/noderb_extension/libuv/src/ares/ares_library_init.c +132 -0
  247. data/ext/noderb_extension/libuv/src/ares/ares_library_init.h +39 -0
  248. data/ext/noderb_extension/libuv/src/ares/ares_llist.c +86 -0
  249. data/ext/noderb_extension/libuv/src/ares/ares_llist.h +42 -0
  250. data/ext/noderb_extension/libuv/src/ares/ares_mkquery.c +195 -0
  251. data/ext/noderb_extension/libuv/src/ares/ares_nowarn.c +59 -0
  252. data/ext/noderb_extension/libuv/src/ares/ares_nowarn.h +24 -0
  253. data/ext/noderb_extension/libuv/src/ares/ares_options.c +253 -0
  254. data/ext/noderb_extension/libuv/src/ares/ares_parse_a_reply.c +260 -0
  255. data/ext/noderb_extension/libuv/src/ares/ares_parse_aaaa_reply.c +256 -0
  256. data/ext/noderb_extension/libuv/src/ares/ares_parse_mx_reply.c +170 -0
  257. data/ext/noderb_extension/libuv/src/ares/ares_parse_ns_reply.c +182 -0
  258. data/ext/noderb_extension/libuv/src/ares/ares_parse_ptr_reply.c +208 -0
  259. data/ext/noderb_extension/libuv/src/ares/ares_parse_srv_reply.c +179 -0
  260. data/ext/noderb_extension/libuv/src/ares/ares_parse_txt_reply.c +201 -0
  261. data/ext/noderb_extension/libuv/src/ares/ares_private.h +351 -0
  262. data/ext/noderb_extension/libuv/src/ares/ares_process.c +1296 -0
  263. data/ext/noderb_extension/libuv/src/ares/ares_query.c +183 -0
  264. data/ext/noderb_extension/libuv/src/ares/ares_rules.h +144 -0
  265. data/ext/noderb_extension/libuv/src/ares/ares_search.c +322 -0
  266. data/ext/noderb_extension/libuv/src/ares/ares_send.c +134 -0
  267. data/ext/noderb_extension/libuv/src/ares/ares_setup.h +191 -0
  268. data/ext/noderb_extension/libuv/src/ares/ares_strcasecmp.c +66 -0
  269. data/ext/noderb_extension/libuv/src/ares/ares_strcasecmp.h +30 -0
  270. data/ext/noderb_extension/libuv/src/ares/ares_strdup.c +42 -0
  271. data/ext/noderb_extension/libuv/src/ares/ares_strdup.h +26 -0
  272. data/ext/noderb_extension/libuv/src/ares/ares_strerror.c +56 -0
  273. data/ext/noderb_extension/libuv/src/ares/ares_timeout.c +80 -0
  274. data/ext/noderb_extension/libuv/src/ares/ares_version.c +11 -0
  275. data/ext/noderb_extension/libuv/src/ares/ares_writev.c +79 -0
  276. data/ext/noderb_extension/libuv/src/ares/ares_writev.h +36 -0
  277. data/ext/noderb_extension/libuv/src/ares/bitncmp.c +59 -0
  278. data/ext/noderb_extension/libuv/src/ares/bitncmp.h +26 -0
  279. data/ext/noderb_extension/libuv/src/ares/config_cygwin/ares_config.h +510 -0
  280. data/ext/noderb_extension/libuv/src/ares/config_darwin/ares_config.h +510 -0
  281. data/ext/noderb_extension/libuv/src/ares/config_freebsd/ares_config.h +510 -0
  282. data/ext/noderb_extension/libuv/src/ares/config_linux/ares_config.h +510 -0
  283. data/ext/noderb_extension/libuv/src/ares/config_openbsd/ares_config.h +510 -0
  284. data/ext/noderb_extension/libuv/src/ares/config_sunos/ares_config.h +510 -0
  285. data/ext/noderb_extension/libuv/src/ares/config_win32/ares_config.h +369 -0
  286. data/ext/noderb_extension/libuv/src/ares/get_ver.awk +35 -0
  287. data/ext/noderb_extension/libuv/src/ares/inet_net_pton.c +450 -0
  288. data/ext/noderb_extension/libuv/src/ares/inet_net_pton.h +31 -0
  289. data/ext/noderb_extension/libuv/src/ares/inet_ntop.c +232 -0
  290. data/ext/noderb_extension/libuv/src/ares/inet_ntop.h +27 -0
  291. data/ext/noderb_extension/libuv/src/ares/nameser.h +193 -0
  292. data/ext/noderb_extension/libuv/src/ares/setup_once.h +488 -0
  293. data/ext/noderb_extension/libuv/src/ares/windows_port.c +22 -0
  294. data/ext/noderb_extension/libuv/src/eio/Changes +63 -0
  295. data/ext/noderb_extension/libuv/src/eio/LICENSE +36 -0
  296. data/ext/noderb_extension/libuv/src/eio/Makefile.am +15 -0
  297. data/ext/noderb_extension/libuv/src/eio/aclocal.m4 +8957 -0
  298. data/ext/noderb_extension/libuv/src/eio/autogen.sh +3 -0
  299. data/ext/noderb_extension/libuv/src/eio/config.h.in +86 -0
  300. data/ext/noderb_extension/libuv/src/eio/config_cygwin.h +77 -0
  301. data/ext/noderb_extension/libuv/src/eio/config_darwin.h +137 -0
  302. data/ext/noderb_extension/libuv/src/eio/config_freebsd.h +78 -0
  303. data/ext/noderb_extension/libuv/src/eio/config_linux.h +101 -0
  304. data/ext/noderb_extension/libuv/src/eio/config_sunos.h +81 -0
  305. data/ext/noderb_extension/libuv/src/eio/configure.ac +22 -0
  306. data/ext/noderb_extension/libuv/src/eio/demo.c +194 -0
  307. data/ext/noderb_extension/libuv/src/eio/ecb.h +370 -0
  308. data/ext/noderb_extension/libuv/src/eio/eio.3 +3428 -0
  309. data/ext/noderb_extension/libuv/src/eio/eio.c +2562 -0
  310. data/ext/noderb_extension/libuv/src/eio/eio.pod +969 -0
  311. data/ext/noderb_extension/libuv/src/eio/libeio.m4 +195 -0
  312. data/ext/noderb_extension/libuv/src/eio/xthread.h +164 -0
  313. data/ext/noderb_extension/libuv/src/ev/Changes +388 -0
  314. data/ext/noderb_extension/libuv/src/ev/LICENSE +36 -0
  315. data/ext/noderb_extension/libuv/src/ev/Makefile.am +18 -0
  316. data/ext/noderb_extension/libuv/src/ev/Makefile.in +771 -0
  317. data/ext/noderb_extension/libuv/src/ev/README +58 -0
  318. data/ext/noderb_extension/libuv/src/ev/aclocal.m4 +8957 -0
  319. data/ext/noderb_extension/libuv/src/ev/autogen.sh +6 -0
  320. data/ext/noderb_extension/libuv/src/ev/config.guess +1526 -0
  321. data/ext/noderb_extension/libuv/src/ev/config.h.in +125 -0
  322. data/ext/noderb_extension/libuv/src/ev/config.sub +1658 -0
  323. data/ext/noderb_extension/libuv/src/ev/config_cygwin.h +123 -0
  324. data/ext/noderb_extension/libuv/src/ev/config_darwin.h +122 -0
  325. data/ext/noderb_extension/libuv/src/ev/config_freebsd.h +120 -0
  326. data/ext/noderb_extension/libuv/src/ev/config_linux.h +130 -0
  327. data/ext/noderb_extension/libuv/src/ev/config_sunos.h +122 -0
  328. data/ext/noderb_extension/libuv/src/ev/configure +13037 -0
  329. data/ext/noderb_extension/libuv/src/ev/configure.ac +18 -0
  330. data/ext/noderb_extension/libuv/src/ev/depcomp +630 -0
  331. data/ext/noderb_extension/libuv/src/ev/ev++.h +816 -0
  332. data/ext/noderb_extension/libuv/src/ev/ev.3 +5311 -0
  333. data/ext/noderb_extension/libuv/src/ev/ev.c +3913 -0
  334. data/ext/noderb_extension/libuv/src/ev/ev.pod +5243 -0
  335. data/ext/noderb_extension/libuv/src/ev/ev_epoll.c +266 -0
  336. data/ext/noderb_extension/libuv/src/ev/ev_kqueue.c +198 -0
  337. data/ext/noderb_extension/libuv/src/ev/ev_poll.c +148 -0
  338. data/ext/noderb_extension/libuv/src/ev/ev_port.c +179 -0
  339. data/ext/noderb_extension/libuv/src/ev/ev_select.c +310 -0
  340. data/ext/noderb_extension/libuv/src/ev/ev_vars.h +203 -0
  341. data/ext/noderb_extension/libuv/src/ev/ev_win32.c +153 -0
  342. data/ext/noderb_extension/libuv/src/ev/ev_wrap.h +196 -0
  343. data/ext/noderb_extension/libuv/src/ev/event.c +402 -0
  344. data/ext/noderb_extension/libuv/src/ev/event.h +170 -0
  345. data/ext/noderb_extension/libuv/src/ev/install-sh +294 -0
  346. data/ext/noderb_extension/libuv/src/ev/libev.m4 +39 -0
  347. data/ext/noderb_extension/libuv/src/ev/ltmain.sh +8413 -0
  348. data/ext/noderb_extension/libuv/src/ev/missing +336 -0
  349. data/ext/noderb_extension/libuv/src/ev/mkinstalldirs +111 -0
  350. data/ext/noderb_extension/libuv/src/uv-common.c +172 -0
  351. data/ext/noderb_extension/libuv/src/uv-common.h +53 -0
  352. data/ext/noderb_extension/libuv/src/uv-cygwin.c +52 -0
  353. data/ext/noderb_extension/libuv/src/uv-darwin.c +64 -0
  354. data/ext/noderb_extension/libuv/src/uv-eio.c +113 -0
  355. data/ext/noderb_extension/libuv/src/uv-eio.h +13 -0
  356. data/ext/noderb_extension/libuv/src/uv-freebsd.c +65 -0
  357. data/ext/noderb_extension/libuv/src/uv-linux.c +51 -0
  358. data/ext/noderb_extension/libuv/src/uv-sunos.c +60 -0
  359. data/ext/noderb_extension/libuv/src/uv-unix.c +2408 -0
  360. data/ext/noderb_extension/libuv/src/win/async.c +129 -0
  361. data/ext/noderb_extension/libuv/src/win/cares.c +304 -0
  362. data/ext/noderb_extension/libuv/src/win/core.c +155 -0
  363. data/ext/noderb_extension/libuv/src/win/error.c +140 -0
  364. data/ext/noderb_extension/libuv/src/win/getaddrinfo.c +341 -0
  365. data/ext/noderb_extension/libuv/src/win/handle.c +176 -0
  366. data/ext/noderb_extension/libuv/src/win/internal.h +237 -0
  367. data/ext/noderb_extension/libuv/src/win/loop-watcher.c +128 -0
  368. data/ext/noderb_extension/libuv/src/win/pipe.c +828 -0
  369. data/ext/noderb_extension/libuv/src/win/process.c +936 -0
  370. data/ext/noderb_extension/libuv/src/win/req.c +141 -0
  371. data/ext/noderb_extension/libuv/src/win/stdio.c +75 -0
  372. data/ext/noderb_extension/libuv/src/win/stream.c +149 -0
  373. data/ext/noderb_extension/libuv/src/win/tcp.c +895 -0
  374. data/ext/noderb_extension/libuv/src/win/timer.c +269 -0
  375. data/ext/noderb_extension/libuv/src/win/util.c +82 -0
  376. data/ext/noderb_extension/libuv/test/benchmark-ares.c +117 -0
  377. data/ext/noderb_extension/libuv/test/benchmark-getaddrinfo.c +90 -0
  378. data/ext/noderb_extension/libuv/test/benchmark-list.h +77 -0
  379. data/ext/noderb_extension/libuv/test/benchmark-ping-pongs.c +210 -0
  380. data/ext/noderb_extension/libuv/test/benchmark-pound.c +237 -0
  381. data/ext/noderb_extension/libuv/test/benchmark-pump.c +459 -0
  382. data/ext/noderb_extension/libuv/test/benchmark-sizes.c +39 -0
  383. data/ext/noderb_extension/libuv/test/benchmark-spawn.c +154 -0
  384. data/ext/noderb_extension/libuv/test/dns-server.c +323 -0
  385. data/ext/noderb_extension/libuv/test/echo-server.c +299 -0
  386. data/ext/noderb_extension/libuv/test/run-benchmarks.c +64 -0
  387. data/ext/noderb_extension/libuv/test/run-tests.c +82 -0
  388. data/ext/noderb_extension/libuv/test/runner-unix.c +335 -0
  389. data/ext/noderb_extension/libuv/test/runner-unix.h +36 -0
  390. data/ext/noderb_extension/libuv/test/runner-win.c +343 -0
  391. data/ext/noderb_extension/libuv/test/runner-win.h +42 -0
  392. data/ext/noderb_extension/libuv/test/runner.c +311 -0
  393. data/ext/noderb_extension/libuv/test/runner.h +155 -0
  394. data/ext/noderb_extension/libuv/test/task.h +111 -0
  395. data/ext/noderb_extension/libuv/test/test-async.c +218 -0
  396. data/ext/noderb_extension/libuv/test/test-callback-stack.c +205 -0
  397. data/ext/noderb_extension/libuv/test/test-connection-fail.c +149 -0
  398. data/ext/noderb_extension/libuv/test/test-delayed-accept.c +198 -0
  399. data/ext/noderb_extension/libuv/test/test-fail-always.c +29 -0
  400. data/ext/noderb_extension/libuv/test/test-get-currentexe.c +53 -0
  401. data/ext/noderb_extension/libuv/test/test-getaddrinfo.c +110 -0
  402. data/ext/noderb_extension/libuv/test/test-gethostbyname.c +192 -0
  403. data/ext/noderb_extension/libuv/test/test-getsockname.c +196 -0
  404. data/ext/noderb_extension/libuv/test/test-hrtime.c +51 -0
  405. data/ext/noderb_extension/libuv/test/test-idle.c +83 -0
  406. data/ext/noderb_extension/libuv/test/test-list.h +165 -0
  407. data/ext/noderb_extension/libuv/test/test-loop-handles.c +361 -0
  408. data/ext/noderb_extension/libuv/test/test-pass-always.c +28 -0
  409. data/ext/noderb_extension/libuv/test/test-ping-pong.c +256 -0
  410. data/ext/noderb_extension/libuv/test/test-pipe-bind-error.c +148 -0
  411. data/ext/noderb_extension/libuv/test/test-ref.c +91 -0
  412. data/ext/noderb_extension/libuv/test/test-shutdown-eof.c +183 -0
  413. data/ext/noderb_extension/libuv/test/test-spawn.c +345 -0
  414. data/ext/noderb_extension/libuv/test/test-tcp-bind-error.c +204 -0
  415. data/ext/noderb_extension/libuv/test/test-tcp-bind6-error.c +164 -0
  416. data/ext/noderb_extension/libuv/test/test-tcp-writealot.c +198 -0
  417. data/ext/noderb_extension/libuv/test/test-timer-again.c +141 -0
  418. data/ext/noderb_extension/libuv/test/test-timer.c +134 -0
  419. data/ext/noderb_extension/noderb.c +340 -0
  420. data/ext/noderb_extension/noderb.h +2 -0
  421. data/lib/noderb/connection.rb +21 -0
  422. data/lib/noderb/process.rb +17 -0
  423. data/lib/noderb.rb +25 -0
  424. metadata +470 -0
@@ -0,0 +1,2562 @@
1
+ /*
2
+ * libeio implementation
3
+ *
4
+ * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libeio@schmorp.de>
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without modifica-
8
+ * tion, are permitted provided that the following conditions are met:
9
+ *
10
+ * 1. Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ *
13
+ * 2. Redistributions in binary form must reproduce the above copyright
14
+ * notice, this list of conditions and the following disclaimer in the
15
+ * documentation and/or other materials provided with the distribution.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19
+ * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
21
+ * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
25
+ * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * Alternatively, the contents of this file may be used under the terms of
29
+ * the GNU General Public License ("GPL") version 2 or any later version,
30
+ * in which case the provisions of the GPL are applicable instead of
31
+ * the above. If you wish to allow the use of your version of this file
32
+ * only under the terms of the GPL and not to allow others to use your
33
+ * version of this file under the BSD license, indicate your decision
34
+ * by deleting the provisions above and replace them with the notice
35
+ * and other provisions required by the GPL. If you do not delete the
36
+ * provisions above, a recipient may use your version of this file under
37
+ * either the BSD or the GPL.
38
+ */
39
+
40
+ #ifdef EIO_CONFIG_H
41
+ # include EIO_CONFIG_H
42
+ #endif
43
+
44
+ /* Undone by libuv for easy build scripts.
45
+ * #ifndef _WIN32
46
+ * # include "config.h"
47
+ * #endif
48
+ */
49
+
50
+ #include "eio.h"
51
+ #include "ecb.h"
52
+
53
+ #ifdef EIO_STACKSIZE
54
+ # define X_STACKSIZE EIO_STACKSIZE
55
+ #endif
56
+ #include "xthread.h"
57
+
58
+ #include <errno.h>
59
+ #include <stddef.h>
60
+ #include <stdlib.h>
61
+ #include <string.h>
62
+ #include <errno.h>
63
+ #include <sys/types.h>
64
+ #include <sys/stat.h>
65
+ #include <limits.h>
66
+ #include <fcntl.h>
67
+ #include <assert.h>
68
+
69
+ /* intptr_t comes from unistd.h, says POSIX/UNIX/tradition */
70
+ /* intptr_t only comes from stdint.h, says idiot openbsd coder */
71
+ #if HAVE_STDINT_H
72
+ # include <stdint.h>
73
+ #endif
74
+
75
+ #ifndef ECANCELED
76
+ # define ECANCELED EDOM
77
+ #endif
78
+ #ifndef ELOOP
79
+ # define ELOOP EDOM
80
+ #endif
81
+
82
+ #if !defined(ENOTSOCK) && defined(WSAENOTSOCK)
83
+ # define ENOTSOCK WSAENOTSOCK
84
+ #endif
85
+
86
+ static void eio_destroy (eio_req *req);
87
+
88
+ #ifndef EIO_FINISH
89
+ # define EIO_FINISH(req) ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0
90
+ #endif
91
+
92
+ #ifndef EIO_DESTROY
93
+ # define EIO_DESTROY(req) do { if ((req)->destroy) (req)->destroy (req); } while (0)
94
+ #endif
95
+
96
+ #ifndef EIO_FEED
97
+ # define EIO_FEED(req) do { if ((req)->feed ) (req)->feed (req); } while (0)
98
+ #endif
99
+
100
+ #ifndef EIO_FD_TO_WIN32_HANDLE
101
+ # define EIO_FD_TO_WIN32_HANDLE(fd) _get_osfhandle (fd)
102
+ #endif
103
+ #ifndef EIO_WIN32_HANDLE_TO_FD
104
+ # define EIO_WIN32_HANDLE_TO_FD(handle) _open_osfhandle (handle, 0)
105
+ #endif
106
+
107
+ #define EIO_ERRNO(errval,retval) ((errno = errval), retval)
108
+
109
+ #define EIO_ENOSYS() EIO_ERRNO (ENOSYS, -1)
110
+
111
+ #ifdef _WIN32
112
+
113
+ #undef PAGESIZE
114
+ #define PAGESIZE 4096 /* GetSystemInfo? */
115
+
116
+ /* TODO: look at how perl does stat (non-sloppy), unlink (ro-files), utime, link */
117
+
118
+ #ifdef EIO_STRUCT_STATI64
119
+ /* look at perl's non-sloppy stat */
120
+ #define stat(path,buf) _stati64 (path,buf)
121
+ #define fstat(fd,buf) _fstati64 (fd,buf)
122
+ #endif
123
+ #define lstat(path,buf) stat (path,buf)
124
+ #define fsync(fd) (FlushFileBuffers ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd)) ? 0 : EIO_ERRNO (EBADF, -1))
125
+ #define mkdir(path,mode) _mkdir (path)
126
+ #define link(old,neu) (CreateHardLink (neu, old, 0) ? 0 : EIO_ERRNO (ENOENT, -1))
127
+
128
+ #define chmod(path,mode) _chmod (path, mode)
129
+ #define dup(fd) _dup (fd)
130
+ #define dup2(fd1,fd2) _dup2 (fd1, fd2)
131
+
132
+ #define fchmod(fd,mode) EIO_ENOSYS ()
133
+ #define chown(path,uid,gid) EIO_ENOSYS ()
134
+ #define fchown(fd,uid,gid) EIO_ENOSYS ()
135
+ #define truncate(path,offs) EIO_ENOSYS () /* far-miss: SetEndOfFile */
136
+ #define ftruncate(fd,offs) EIO_ENOSYS () /* near-miss: SetEndOfFile */
137
+ #define mknod(path,mode,dev) EIO_ENOSYS ()
138
+ #define sync() EIO_ENOSYS ()
139
+ #define readlink(path,buf,s) EIO_ENOSYS ()
140
+ #define statvfs(path,buf) EIO_ENOSYS ()
141
+ #define fstatvfs(fd,buf) EIO_ENOSYS ()
142
+
143
+ /* rename() uses MoveFile, which fails to overwrite */
144
+ #define rename(old,neu) eio__rename (old, neu)
145
+
146
+ static int
147
+ eio__rename (const char *old, const char *neu)
148
+ {
149
+ if (MoveFileEx (old, neu, MOVEFILE_REPLACE_EXISTING))
150
+ return 0;
151
+
152
+ /* should steal _dosmaperr */
153
+ switch (GetLastError ())
154
+ {
155
+ case ERROR_FILE_NOT_FOUND:
156
+ case ERROR_PATH_NOT_FOUND:
157
+ case ERROR_INVALID_DRIVE:
158
+ case ERROR_NO_MORE_FILES:
159
+ case ERROR_BAD_NETPATH:
160
+ case ERROR_BAD_NET_NAME:
161
+ case ERROR_BAD_PATHNAME:
162
+ case ERROR_FILENAME_EXCED_RANGE:
163
+ errno = ENOENT;
164
+ break;
165
+
166
+ default:
167
+ errno = EACCES;
168
+ break;
169
+ }
170
+
171
+ return -1;
172
+ }
173
+
174
+ /* we could even stat and see if it exists */
175
+ static int
176
+ symlink (const char *old, const char *neu)
177
+ {
178
+ #if WINVER >= 0x0600
179
+ if (CreateSymbolicLink (neu, old, 1))
180
+ return 0;
181
+
182
+ if (CreateSymbolicLink (neu, old, 0))
183
+ return 0;
184
+ #endif
185
+
186
+ return EIO_ERRNO (ENOENT, -1);
187
+ }
188
+
189
+ /* POSIX API only */
190
+ #define CreateHardLink(neu,old,flags) 0
191
+ #define CreateSymbolicLink(neu,old,flags) 0
192
+
193
+ struct statvfs
194
+ {
195
+ int dummy;
196
+ };
197
+
198
+ #define DT_DIR EIO_DT_DIR
199
+ #define DT_REG EIO_DT_REG
200
+ #define D_NAME(entp) entp.cFileName
201
+ #define D_TYPE(entp) (entp.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? DT_DIR : DT_REG)
202
+
203
+ #include <sys/utime.h>
204
+ #define utime(path, times) _utime(path, times)
205
+ #define utimbuf _utimbuf
206
+
207
+ #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
208
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
209
+ #else
210
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
211
+ #endif
212
+
213
+ struct timezone
214
+ {
215
+ int tz_minuteswest; /* minutes W of Greenwich */
216
+ int tz_dsttime; /* type of dst correction */
217
+ };
218
+
219
+ static int gettimeofday(struct timeval *tv, struct timezone *tz)
220
+ {
221
+ FILETIME ft;
222
+ unsigned __int64 tmpres = 0;
223
+ static int tzflag;
224
+
225
+ if (NULL != tv)
226
+ {
227
+ GetSystemTimeAsFileTime(&ft);
228
+
229
+ tmpres |= ft.dwHighDateTime;
230
+ tmpres <<= 32;
231
+ tmpres |= ft.dwLowDateTime;
232
+
233
+ /*converting file time to unix epoch*/
234
+ tmpres -= DELTA_EPOCH_IN_MICROSECS;
235
+ tmpres /= 10; /*convert into microseconds*/
236
+ tv->tv_sec = (long)(tmpres / 1000000UL);
237
+ tv->tv_usec = (long)(tmpres % 1000000UL);
238
+ }
239
+
240
+ if (NULL != tz)
241
+ {
242
+ if (!tzflag)
243
+ {
244
+ _tzset();
245
+ tzflag++;
246
+ }
247
+ tz->tz_minuteswest = _timezone / 60;
248
+ tz->tz_dsttime = _daylight;
249
+ }
250
+
251
+ return 0;
252
+ }
253
+
254
+ #else
255
+
256
+ #include <sys/time.h>
257
+ #include <sys/select.h>
258
+ #include <sys/statvfs.h>
259
+ #include <unistd.h>
260
+ #include <signal.h>
261
+ #include <dirent.h>
262
+
263
+ #if _POSIX_MEMLOCK || _POSIX_MEMLOCK_RANGE || _POSIX_MAPPED_FILES
264
+ #include <sys/mman.h>
265
+ #endif
266
+
267
+ #define D_NAME(entp) entp->d_name
268
+
269
+ /* POSIX_SOURCE is useless on bsd's, and XOPEN_SOURCE is unreliable there, too */
270
+ #if __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
271
+ #define _DIRENT_HAVE_D_TYPE /* sigh */
272
+ #define D_INO(de) (de)->d_fileno
273
+ #define D_NAMLEN(de) (de)->d_namlen
274
+ #elif __linux || defined d_ino || _XOPEN_SOURCE >= 600
275
+ #define D_INO(de) (de)->d_ino
276
+ #endif
277
+
278
+ #ifdef _D_EXACT_NAMLEN
279
+ #undef D_NAMLEN
280
+ #define D_NAMLEN(de) _D_EXACT_NAMLEN (de)
281
+ #endif
282
+
283
+ #ifdef _DIRENT_HAVE_D_TYPE
284
+ #define D_TYPE(de) (de)->d_type
285
+ #endif
286
+
287
+ #ifndef EIO_STRUCT_DIRENT
288
+ #define EIO_STRUCT_DIRENT struct dirent
289
+ #endif
290
+
291
+ #endif
292
+
293
+ #if HAVE_UTIMES
294
+ # include <utime.h>
295
+ #endif
296
+
297
+ #if HAVE_SYS_SYSCALL_H
298
+ # include <sys/syscall.h>
299
+ #endif
300
+
301
+ #if HAVE_SYS_PRCTL_H
302
+ # include <sys/prctl.h>
303
+ #endif
304
+
305
+ #if HAVE_SENDFILE
306
+ # if __linux
307
+ # include <sys/sendfile.h>
308
+ # elif __FreeBSD__ || defined __APPLE__
309
+ # include <sys/socket.h>
310
+ # include <sys/uio.h>
311
+ # elif __hpux
312
+ # include <sys/socket.h>
313
+ # elif __solaris
314
+ # include <sys/sendfile.h>
315
+ # else
316
+ # error sendfile support requested but not available
317
+ # endif
318
+ #endif
319
+
320
+ #ifndef D_TYPE
321
+ # define D_TYPE(de) 0
322
+ #endif
323
+ #ifndef D_INO
324
+ # define D_INO(de) 0
325
+ #endif
326
+ #ifndef D_NAMLEN
327
+ # define D_NAMLEN(entp) strlen (D_NAME (entp))
328
+ #endif
329
+
330
+ /* used for struct dirent, AIX doesn't provide it */
331
+ #ifndef NAME_MAX
332
+ # define NAME_MAX 4096
333
+ #endif
334
+
335
+ /* used for readlink etc. */
336
+ #ifndef PATH_MAX
337
+ # define PATH_MAX 4096
338
+ #endif
339
+
340
+ /* buffer size for various temporary buffers */
341
+ #define EIO_BUFSIZE 65536
342
+
343
+ #define dBUF \
344
+ char *eio_buf = malloc (EIO_BUFSIZE); \
345
+ errno = ENOMEM; \
346
+ if (!eio_buf) \
347
+ return -1
348
+
349
+ #define FUBd \
350
+ free (eio_buf)
351
+
352
+ #define EIO_TICKS ((1000000 + 1023) >> 10)
353
+
354
+ #define ETP_PRI_MIN EIO_PRI_MIN
355
+ #define ETP_PRI_MAX EIO_PRI_MAX
356
+
357
+ struct etp_worker;
358
+
359
+ #define ETP_REQ eio_req
360
+ #define ETP_DESTROY(req) eio_destroy (req)
361
+ static int eio_finish (eio_req *req);
362
+ #define ETP_FINISH(req) eio_finish (req)
363
+ static void eio_execute (struct etp_worker *self, eio_req *req);
364
+ #define ETP_EXECUTE(wrk,req) eio_execute (wrk,req)
365
+
366
+ /*****************************************************************************/
367
+
368
+ #define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1)
369
+
370
+ /* calculate time difference in ~1/EIO_TICKS of a second */
371
+ ecb_inline int
372
+ tvdiff (struct timeval *tv1, struct timeval *tv2)
373
+ {
374
+ return (tv2->tv_sec - tv1->tv_sec ) * EIO_TICKS
375
+ + ((tv2->tv_usec - tv1->tv_usec) >> 10);
376
+ }
377
+
378
+ static unsigned int started, idle, wanted = 4;
379
+
380
+ static void (*want_poll_cb) (void);
381
+ static void (*done_poll_cb) (void);
382
+
383
+ static unsigned int max_poll_time; /* reslock */
384
+ static unsigned int max_poll_reqs; /* reslock */
385
+
386
+ static unsigned int nreqs; /* reqlock */
387
+ static unsigned int nready; /* reqlock */
388
+ static unsigned int npending; /* reqlock */
389
+ static unsigned int max_idle = 4; /* maximum number of threads that can idle indefinitely */
390
+ static unsigned int idle_timeout = 10; /* number of seconds after which an idle threads exit */
391
+
392
+ static xmutex_t wrklock;
393
+ static xmutex_t reslock;
394
+ static xmutex_t reqlock;
395
+ static xcond_t reqwait;
396
+
397
+ #if !HAVE_PREADWRITE
398
+ /*
399
+ * make our pread/pwrite emulation safe against themselves, but not against
400
+ * normal read/write by using a mutex. slows down execution a lot,
401
+ * but that's your problem, not mine.
402
+ */
403
+ static xmutex_t preadwritelock;
404
+ #endif
405
+
406
+ typedef struct etp_worker
407
+ {
408
+ /* locked by wrklock */
409
+ struct etp_worker *prev, *next;
410
+
411
+ xthread_t tid;
412
+
413
+ /* locked by reslock, reqlock or wrklock */
414
+ ETP_REQ *req; /* currently processed request */
415
+
416
+ #ifdef ETP_WORKER_COMMON
417
+ ETP_WORKER_COMMON
418
+ #endif
419
+ } etp_worker;
420
+
421
+ static etp_worker wrk_first; /* NOT etp */
422
+
423
+ #define ETP_WORKER_LOCK(wrk) X_LOCK (wrklock)
424
+ #define ETP_WORKER_UNLOCK(wrk) X_UNLOCK (wrklock)
425
+
426
+ /* worker threads management */
427
+
428
+ static void ecb_cold
429
+ etp_worker_clear (etp_worker *wrk)
430
+ {
431
+ }
432
+
433
+ static void ecb_cold
434
+ etp_worker_free (etp_worker *wrk)
435
+ {
436
+ wrk->next->prev = wrk->prev;
437
+ wrk->prev->next = wrk->next;
438
+
439
+ free (wrk);
440
+ }
441
+
442
+ static unsigned int
443
+ etp_nreqs (void)
444
+ {
445
+ int retval;
446
+ if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
447
+ retval = nreqs;
448
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
449
+ return retval;
450
+ }
451
+
452
+ static unsigned int
453
+ etp_nready (void)
454
+ {
455
+ unsigned int retval;
456
+
457
+ if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
458
+ retval = nready;
459
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
460
+
461
+ return retval;
462
+ }
463
+
464
+ static unsigned int
465
+ etp_npending (void)
466
+ {
467
+ unsigned int retval;
468
+
469
+ if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
470
+ retval = npending;
471
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
472
+
473
+ return retval;
474
+ }
475
+
476
+ static unsigned int
477
+ etp_nthreads (void)
478
+ {
479
+ unsigned int retval;
480
+
481
+ if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
482
+ retval = started;
483
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
484
+
485
+ return retval;
486
+ }
487
+
488
+ /*
489
+ * a somewhat faster data structure might be nice, but
490
+ * with 8 priorities this actually needs <20 insns
491
+ * per shift, the most expensive operation.
492
+ */
493
+ typedef struct {
494
+ ETP_REQ *qs[ETP_NUM_PRI], *qe[ETP_NUM_PRI]; /* qstart, qend */
495
+ int size;
496
+ } etp_reqq;
497
+
498
+ static etp_reqq req_queue;
499
+ static etp_reqq res_queue;
500
+
501
+ static void ecb_noinline ecb_cold
502
+ reqq_init (etp_reqq *q)
503
+ {
504
+ int pri;
505
+
506
+ for (pri = 0; pri < ETP_NUM_PRI; ++pri)
507
+ q->qs[pri] = q->qe[pri] = 0;
508
+
509
+ q->size = 0;
510
+ }
511
+
512
+ static int ecb_noinline
513
+ reqq_push (etp_reqq *q, ETP_REQ *req)
514
+ {
515
+ int pri = req->pri;
516
+ req->next = 0;
517
+
518
+ if (q->qe[pri])
519
+ {
520
+ q->qe[pri]->next = req;
521
+ q->qe[pri] = req;
522
+ }
523
+ else
524
+ q->qe[pri] = q->qs[pri] = req;
525
+
526
+ return q->size++;
527
+ }
528
+
529
+ static ETP_REQ * ecb_noinline
530
+ reqq_shift (etp_reqq *q)
531
+ {
532
+ int pri;
533
+
534
+ if (!q->size)
535
+ return 0;
536
+
537
+ --q->size;
538
+
539
+ for (pri = ETP_NUM_PRI; pri--; )
540
+ {
541
+ eio_req *req = q->qs[pri];
542
+
543
+ if (req)
544
+ {
545
+ if (!(q->qs[pri] = (eio_req *)req->next))
546
+ q->qe[pri] = 0;
547
+
548
+ return req;
549
+ }
550
+ }
551
+
552
+ abort ();
553
+ }
554
+
555
+ static int ecb_cold
556
+ etp_init (void (*want_poll)(void), void (*done_poll)(void))
557
+ {
558
+ X_MUTEX_CREATE (wrklock);
559
+ X_MUTEX_CREATE (reslock);
560
+ X_MUTEX_CREATE (reqlock);
561
+ X_COND_CREATE (reqwait);
562
+
563
+ reqq_init (&req_queue);
564
+ reqq_init (&res_queue);
565
+
566
+ wrk_first.next =
567
+ wrk_first.prev = &wrk_first;
568
+
569
+ started = 0;
570
+ idle = 0;
571
+ nreqs = 0;
572
+ nready = 0;
573
+ npending = 0;
574
+
575
+ want_poll_cb = want_poll;
576
+ done_poll_cb = done_poll;
577
+
578
+ return 0;
579
+ }
580
+
581
+ X_THREAD_PROC (etp_proc);
582
+
583
+ static void ecb_cold
584
+ etp_start_thread (void)
585
+ {
586
+ etp_worker *wrk = calloc (1, sizeof (etp_worker));
587
+
588
+ /*TODO*/
589
+ assert (("unable to allocate worker thread data", wrk));
590
+
591
+ X_LOCK (wrklock);
592
+
593
+ if (thread_create (&wrk->tid, etp_proc, (void *)wrk))
594
+ {
595
+ wrk->prev = &wrk_first;
596
+ wrk->next = wrk_first.next;
597
+ wrk_first.next->prev = wrk;
598
+ wrk_first.next = wrk;
599
+ ++started;
600
+ }
601
+ else
602
+ free (wrk);
603
+
604
+ X_UNLOCK (wrklock);
605
+ }
606
+
607
+ static void
608
+ etp_maybe_start_thread (void)
609
+ {
610
+ if (ecb_expect_true (etp_nthreads () >= wanted))
611
+ return;
612
+
613
+ /* todo: maybe use idle here, but might be less exact */
614
+ if (ecb_expect_true (0 <= (int)etp_nthreads () + (int)etp_npending () - (int)etp_nreqs ()))
615
+ return;
616
+
617
+ etp_start_thread ();
618
+ }
619
+
620
+ static void ecb_cold
621
+ etp_end_thread (void)
622
+ {
623
+ eio_req *req = calloc (1, sizeof (eio_req));
624
+
625
+ req->type = -1;
626
+ req->pri = ETP_PRI_MAX - ETP_PRI_MIN;
627
+
628
+ X_LOCK (reqlock);
629
+ reqq_push (&req_queue, req);
630
+ X_COND_SIGNAL (reqwait);
631
+ X_UNLOCK (reqlock);
632
+
633
+ X_LOCK (wrklock);
634
+ --started;
635
+ X_UNLOCK (wrklock);
636
+ }
637
+
638
+ static int
639
+ etp_poll (void)
640
+ {
641
+ unsigned int maxreqs;
642
+ unsigned int maxtime;
643
+ struct timeval tv_start, tv_now;
644
+
645
+ X_LOCK (reslock);
646
+ maxreqs = max_poll_reqs;
647
+ maxtime = max_poll_time;
648
+ X_UNLOCK (reslock);
649
+
650
+ if (maxtime)
651
+ gettimeofday (&tv_start, 0);
652
+
653
+ for (;;)
654
+ {
655
+ ETP_REQ *req;
656
+
657
+ etp_maybe_start_thread ();
658
+
659
+ X_LOCK (reslock);
660
+ req = reqq_shift (&res_queue);
661
+
662
+ if (req)
663
+ {
664
+ --npending;
665
+
666
+ if (!res_queue.size && done_poll_cb)
667
+ done_poll_cb ();
668
+ }
669
+
670
+ X_UNLOCK (reslock);
671
+
672
+ if (!req)
673
+ return 0;
674
+
675
+ X_LOCK (reqlock);
676
+ --nreqs;
677
+ X_UNLOCK (reqlock);
678
+
679
+ if (ecb_expect_false (req->type == EIO_GROUP && req->size))
680
+ {
681
+ req->int1 = 1; /* mark request as delayed */
682
+ continue;
683
+ }
684
+ else
685
+ {
686
+ int res = ETP_FINISH (req);
687
+ if (ecb_expect_false (res))
688
+ return res;
689
+ }
690
+
691
+ if (ecb_expect_false (maxreqs && !--maxreqs))
692
+ break;
693
+
694
+ if (maxtime)
695
+ {
696
+ gettimeofday (&tv_now, 0);
697
+
698
+ if (tvdiff (&tv_start, &tv_now) >= maxtime)
699
+ break;
700
+ }
701
+ }
702
+
703
+ errno = EAGAIN;
704
+ return -1;
705
+ }
706
+
707
+ static void
708
+ etp_cancel (ETP_REQ *req)
709
+ {
710
+ req->cancelled = 1;
711
+
712
+ eio_grp_cancel (req);
713
+ }
714
+
715
+ static void
716
+ etp_submit (ETP_REQ *req)
717
+ {
718
+ req->pri -= ETP_PRI_MIN;
719
+
720
+ if (ecb_expect_false (req->pri < ETP_PRI_MIN - ETP_PRI_MIN)) req->pri = ETP_PRI_MIN - ETP_PRI_MIN;
721
+ if (ecb_expect_false (req->pri > ETP_PRI_MAX - ETP_PRI_MIN)) req->pri = ETP_PRI_MAX - ETP_PRI_MIN;
722
+
723
+ if (ecb_expect_false (req->type == EIO_GROUP))
724
+ {
725
+ /* I hope this is worth it :/ */
726
+ X_LOCK (reqlock);
727
+ ++nreqs;
728
+ X_UNLOCK (reqlock);
729
+
730
+ X_LOCK (reslock);
731
+
732
+ ++npending;
733
+
734
+ if (!reqq_push (&res_queue, req) && want_poll_cb)
735
+ want_poll_cb ();
736
+
737
+ X_UNLOCK (reslock);
738
+ }
739
+ else
740
+ {
741
+ X_LOCK (reqlock);
742
+ ++nreqs;
743
+ ++nready;
744
+ reqq_push (&req_queue, req);
745
+ X_COND_SIGNAL (reqwait);
746
+ X_UNLOCK (reqlock);
747
+
748
+ etp_maybe_start_thread ();
749
+ }
750
+ }
751
+
752
+ static void ecb_cold
753
+ etp_set_max_poll_time (double nseconds)
754
+ {
755
+ if (WORDACCESS_UNSAFE) X_LOCK (reslock);
756
+ max_poll_time = nseconds * EIO_TICKS;
757
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reslock);
758
+ }
759
+
760
+ static void ecb_cold
761
+ etp_set_max_poll_reqs (unsigned int maxreqs)
762
+ {
763
+ if (WORDACCESS_UNSAFE) X_LOCK (reslock);
764
+ max_poll_reqs = maxreqs;
765
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reslock);
766
+ }
767
+
768
+ static void ecb_cold
769
+ etp_set_max_idle (unsigned int nthreads)
770
+ {
771
+ if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
772
+ max_idle = nthreads;
773
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
774
+ }
775
+
776
+ static void ecb_cold
777
+ etp_set_idle_timeout (unsigned int seconds)
778
+ {
779
+ if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
780
+ idle_timeout = seconds;
781
+ if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
782
+ }
783
+
784
+ static void ecb_cold
785
+ etp_set_min_parallel (unsigned int nthreads)
786
+ {
787
+ if (wanted < nthreads)
788
+ wanted = nthreads;
789
+ }
790
+
791
+ static void ecb_cold
792
+ etp_set_max_parallel (unsigned int nthreads)
793
+ {
794
+ if (wanted > nthreads)
795
+ wanted = nthreads;
796
+
797
+ while (started > wanted)
798
+ etp_end_thread ();
799
+ }
800
+
801
+ /*****************************************************************************/
802
+
803
+ static void
804
+ grp_try_feed (eio_req *grp)
805
+ {
806
+ while (grp->size < grp->int2 && !EIO_CANCELLED (grp))
807
+ {
808
+ grp->flags &= ~EIO_FLAG_GROUPADD;
809
+
810
+ EIO_FEED (grp);
811
+
812
+ /* stop if no progress has been made */
813
+ if (!(grp->flags & EIO_FLAG_GROUPADD))
814
+ {
815
+ grp->feed = 0;
816
+ break;
817
+ }
818
+ }
819
+ }
820
+
821
+ static int
822
+ grp_dec (eio_req *grp)
823
+ {
824
+ --grp->size;
825
+
826
+ /* call feeder, if applicable */
827
+ grp_try_feed (grp);
828
+
829
+ /* finish, if done */
830
+ if (!grp->size && grp->int1)
831
+ return eio_finish (grp);
832
+ else
833
+ return 0;
834
+ }
835
+
836
+ static void
837
+ eio_destroy (eio_req *req)
838
+ {
839
+ if ((req)->flags & EIO_FLAG_PTR1_FREE) free (req->ptr1);
840
+ if ((req)->flags & EIO_FLAG_PTR2_FREE) free (req->ptr2);
841
+
842
+ EIO_DESTROY (req);
843
+ }
844
+
845
+ static int
846
+ eio_finish (eio_req *req)
847
+ {
848
+ int res = EIO_FINISH (req);
849
+
850
+ if (req->grp)
851
+ {
852
+ int res2;
853
+ eio_req *grp = req->grp;
854
+
855
+ /* unlink request */
856
+ if (req->grp_next) req->grp_next->grp_prev = req->grp_prev;
857
+ if (req->grp_prev) req->grp_prev->grp_next = req->grp_next;
858
+
859
+ if (grp->grp_first == req)
860
+ grp->grp_first = req->grp_next;
861
+
862
+ res2 = grp_dec (grp);
863
+
864
+ if (!res)
865
+ res = res2;
866
+ }
867
+
868
+ eio_destroy (req);
869
+
870
+ return res;
871
+ }
872
+
873
+ void
874
+ eio_grp_cancel (eio_req *grp)
875
+ {
876
+ for (grp = grp->grp_first; grp; grp = grp->grp_next)
877
+ eio_cancel (grp);
878
+ }
879
+
880
+ void
881
+ eio_cancel (eio_req *req)
882
+ {
883
+ etp_cancel (req);
884
+ }
885
+
886
+ void
887
+ eio_submit (eio_req *req)
888
+ {
889
+ etp_submit (req);
890
+ }
891
+
892
+ unsigned int
893
+ eio_nreqs (void)
894
+ {
895
+ return etp_nreqs ();
896
+ }
897
+
898
+ unsigned int
899
+ eio_nready (void)
900
+ {
901
+ return etp_nready ();
902
+ }
903
+
904
+ unsigned int
905
+ eio_npending (void)
906
+ {
907
+ return etp_npending ();
908
+ }
909
+
910
+ unsigned int ecb_cold
911
+ eio_nthreads (void)
912
+ {
913
+ return etp_nthreads ();
914
+ }
915
+
916
+ void ecb_cold
917
+ eio_set_max_poll_time (double nseconds)
918
+ {
919
+ etp_set_max_poll_time (nseconds);
920
+ }
921
+
922
+ void ecb_cold
923
+ eio_set_max_poll_reqs (unsigned int maxreqs)
924
+ {
925
+ etp_set_max_poll_reqs (maxreqs);
926
+ }
927
+
928
+ void ecb_cold
929
+ eio_set_max_idle (unsigned int nthreads)
930
+ {
931
+ etp_set_max_idle (nthreads);
932
+ }
933
+
934
+ void ecb_cold
935
+ eio_set_idle_timeout (unsigned int seconds)
936
+ {
937
+ etp_set_idle_timeout (seconds);
938
+ }
939
+
940
+ void ecb_cold
941
+ eio_set_min_parallel (unsigned int nthreads)
942
+ {
943
+ etp_set_min_parallel (nthreads);
944
+ }
945
+
946
+ void ecb_cold
947
+ eio_set_max_parallel (unsigned int nthreads)
948
+ {
949
+ etp_set_max_parallel (nthreads);
950
+ }
951
+
952
+ int eio_poll (void)
953
+ {
954
+ return etp_poll ();
955
+ }
956
+
957
+ /*****************************************************************************/
958
+ /* work around various missing functions */
959
+
960
+ #if !HAVE_PREADWRITE
961
+ # undef pread
962
+ # undef pwrite
963
+ # define pread eio__pread
964
+ # define pwrite eio__pwrite
965
+
966
+ eio_ssize_t
967
+ eio__pread (int fd, void *buf, size_t count, off_t offset)
968
+ {
969
+ eio_ssize_t res;
970
+ off_t ooffset;
971
+
972
+ X_LOCK (preadwritelock);
973
+ ooffset = lseek (fd, 0, SEEK_CUR);
974
+ lseek (fd, offset, SEEK_SET);
975
+ res = read (fd, buf, count);
976
+ lseek (fd, ooffset, SEEK_SET);
977
+ X_UNLOCK (preadwritelock);
978
+
979
+ return res;
980
+ }
981
+
982
+ eio_ssize_t
983
+ eio__pwrite (int fd, void *buf, size_t count, off_t offset)
984
+ {
985
+ eio_ssize_t res;
986
+ off_t ooffset;
987
+
988
+ X_LOCK (preadwritelock);
989
+ ooffset = lseek (fd, 0, SEEK_CUR);
990
+ lseek (fd, offset, SEEK_SET);
991
+ res = write (fd, buf, count);
992
+ lseek (fd, ooffset, SEEK_SET);
993
+ X_UNLOCK (preadwritelock);
994
+
995
+ return res;
996
+ }
997
+ #endif
998
+
999
+ #ifndef HAVE_UTIMES
1000
+
1001
+ # undef utimes
1002
+ # define utimes(path,times) eio__utimes (path, times)
1003
+
1004
+ static int
1005
+ eio__utimes (const char *filename, const struct timeval times[2])
1006
+ {
1007
+ if (times)
1008
+ {
1009
+ struct utimbuf buf;
1010
+
1011
+ buf.actime = times[0].tv_sec;
1012
+ buf.modtime = times[1].tv_sec;
1013
+
1014
+ return utime (filename, &buf);
1015
+ }
1016
+ else
1017
+ return utime (filename, 0);
1018
+ }
1019
+
1020
+ #endif
1021
+
1022
+ #ifndef HAVE_FUTIMES
1023
+
1024
+ # undef futimes
1025
+ # define futimes(fd,times) eio__futimes (fd, times)
1026
+
1027
+ static int
1028
+ eio__futimes (int fd, const struct timeval tv[2])
1029
+ {
1030
+ errno = ENOSYS;
1031
+ return -1;
1032
+ }
1033
+
1034
+ #endif
1035
+
1036
+ #if !HAVE_FDATASYNC
1037
+ # undef fdatasync
1038
+ # define fdatasync(fd) fsync (fd)
1039
+ #endif
1040
+
1041
+ static int
1042
+ eio__syncfs (int fd)
1043
+ {
1044
+ int res;
1045
+
1046
+ #if HAVE_SYS_SYNCFS
1047
+ res = (int)syscall (__NR_syncfs, (int)(fd));
1048
+ #else
1049
+ res = -1;
1050
+ errno = ENOSYS;
1051
+ #endif
1052
+
1053
+ if (res < 0 && errno == ENOSYS && fd >= 0)
1054
+ sync ();
1055
+
1056
+ return res;
1057
+ }
1058
+
1059
+ /* sync_file_range always needs emulation */
1060
+ static int
1061
+ eio__sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags)
1062
+ {
1063
+ #if HAVE_SYNC_FILE_RANGE
1064
+ int res;
1065
+
1066
+ if (EIO_SYNC_FILE_RANGE_WAIT_BEFORE != SYNC_FILE_RANGE_WAIT_BEFORE
1067
+ || EIO_SYNC_FILE_RANGE_WRITE != SYNC_FILE_RANGE_WRITE
1068
+ || EIO_SYNC_FILE_RANGE_WAIT_AFTER != SYNC_FILE_RANGE_WAIT_AFTER)
1069
+ {
1070
+ flags = 0
1071
+ | (flags & EIO_SYNC_FILE_RANGE_WAIT_BEFORE ? SYNC_FILE_RANGE_WAIT_BEFORE : 0)
1072
+ | (flags & EIO_SYNC_FILE_RANGE_WRITE ? SYNC_FILE_RANGE_WRITE : 0)
1073
+ | (flags & EIO_SYNC_FILE_RANGE_WAIT_AFTER ? SYNC_FILE_RANGE_WAIT_AFTER : 0);
1074
+ }
1075
+
1076
+ res = sync_file_range (fd, offset, nbytes, flags);
1077
+
1078
+ if (!res || errno != ENOSYS)
1079
+ return res;
1080
+ #endif
1081
+
1082
+ /* even though we could play tricks with the flags, it's better to always
1083
+ * call fdatasync, as that matches the expectation of its users best */
1084
+ return fdatasync (fd);
1085
+ }
1086
+
1087
+ static int
1088
+ eio__fallocate (int fd, int mode, off_t offset, size_t len)
1089
+ {
1090
+ #if HAVE_FALLOCATE
1091
+ return fallocate (fd, mode, offset, len);
1092
+ #else
1093
+ errno = ENOSYS;
1094
+ return -1;
1095
+ #endif
1096
+ }
1097
+
1098
+ #if !HAVE_READAHEAD
1099
+ # undef readahead
1100
+ # define readahead(fd,offset,count) eio__readahead (fd, offset, count, self)
1101
+
1102
+ static eio_ssize_t
1103
+ eio__readahead (int fd, off_t offset, size_t count, etp_worker *self)
1104
+ {
1105
+ size_t todo = count;
1106
+ dBUF;
1107
+
1108
+ while (todo > 0)
1109
+ {
1110
+ size_t len = todo < EIO_BUFSIZE ? todo : EIO_BUFSIZE;
1111
+
1112
+ pread (fd, eio_buf, len, offset);
1113
+ offset += len;
1114
+ todo -= len;
1115
+ }
1116
+
1117
+ FUBd;
1118
+
1119
+ errno = 0;
1120
+ return count;
1121
+ }
1122
+
1123
+ #endif
1124
+
1125
+ /* sendfile always needs emulation */
1126
+ static eio_ssize_t
1127
+ eio__sendfile (int ofd, int ifd, off_t offset, size_t count)
1128
+ {
1129
+ eio_ssize_t written = 0;
1130
+ eio_ssize_t res;
1131
+
1132
+ if (!count)
1133
+ return 0;
1134
+
1135
+ for (;;)
1136
+ {
1137
+ #ifdef __APPLE__
1138
+ # undef HAVE_SENDFILE /* broken, as everything on os x */
1139
+ #endif
1140
+ #if HAVE_SENDFILE
1141
+ # if __linux
1142
+ off_t soffset = offset;
1143
+ res = sendfile (ofd, ifd, &soffset, count);
1144
+
1145
+ # elif __FreeBSD__
1146
+ /*
1147
+ * Of course, the freebsd sendfile is a dire hack with no thoughts
1148
+ * wasted on making it similar to other I/O functions.
1149
+ */
1150
+ off_t sbytes;
1151
+ res = sendfile (ifd, ofd, offset, count, 0, &sbytes, 0);
1152
+
1153
+ #if 0 /* according to the manpage, this is correct, but broken behaviour */
1154
+ /* freebsd' sendfile will return 0 on success */
1155
+ /* freebsd 8 documents it as only setting *sbytes on EINTR and EAGAIN, but */
1156
+ /* not on e.g. EIO or EPIPE - sounds broken */
1157
+ if ((res < 0 && (errno == EAGAIN || errno == EINTR) && sbytes) || res == 0)
1158
+ res = sbytes;
1159
+ #endif
1160
+
1161
+ /* according to source inspection, this is correct, and useful behaviour */
1162
+ if (sbytes)
1163
+ res = sbytes;
1164
+
1165
+ # elif defined (__APPLE__)
1166
+ off_t sbytes = count;
1167
+ res = sendfile (ifd, ofd, offset, &sbytes, 0, 0);
1168
+
1169
+ /* according to the manpage, sbytes is always valid */
1170
+ if (sbytes)
1171
+ res = sbytes;
1172
+
1173
+ # elif __hpux
1174
+ res = sendfile (ofd, ifd, offset, count, 0, 0);
1175
+
1176
+ # elif __solaris
1177
+ struct sendfilevec vec;
1178
+ size_t sbytes;
1179
+
1180
+ vec.sfv_fd = ifd;
1181
+ vec.sfv_flag = 0;
1182
+ vec.sfv_off = offset;
1183
+ vec.sfv_len = count;
1184
+
1185
+ res = sendfilev (ofd, &vec, 1, &sbytes);
1186
+
1187
+ if (res < 0 && sbytes)
1188
+ res = sbytes;
1189
+
1190
+ # endif
1191
+
1192
+ #elif defined (_WIN32) && 0
1193
+ /* does not work, just for documentation of what would need to be done */
1194
+ /* actually, cannot be done like this, as TransmitFile changes the file offset, */
1195
+ /* libeio guarantees that the file offset does not change, and windows */
1196
+ /* has no way to get an independent handle to the same file description */
1197
+ HANDLE h = TO_SOCKET (ifd);
1198
+ SetFilePointer (h, offset, 0, FILE_BEGIN);
1199
+ res = TransmitFile (TO_SOCKET (ofd), h, count, 0, 0, 0, 0);
1200
+
1201
+ #else
1202
+ res = -1;
1203
+ errno = ENOSYS;
1204
+ #endif
1205
+
1206
+ /* we assume sendfile can copy at least 128mb in one go */
1207
+ if (res <= 128 * 1024 * 1024)
1208
+ {
1209
+ if (res > 0)
1210
+ written += res;
1211
+
1212
+ if (written)
1213
+ return written;
1214
+
1215
+ break;
1216
+ }
1217
+ else
1218
+ {
1219
+ /* if we requested more, then probably the kernel was lazy */
1220
+ written += res;
1221
+ offset += res;
1222
+ count -= res;
1223
+
1224
+ if (!count)
1225
+ return written;
1226
+ }
1227
+ }
1228
+
1229
+ if (res < 0
1230
+ && (errno == ENOSYS || errno == EINVAL || errno == ENOTSOCK
1231
+ /* BSDs */
1232
+ #ifdef ENOTSUP /* sigh, if the steenking pile called openbsd would only try to at least compile posix code... */
1233
+ || errno == ENOTSUP
1234
+ #endif
1235
+ #ifdef EOPNOTSUPP /* windows */
1236
+ || errno == EOPNOTSUPP /* BSDs */
1237
+ #endif
1238
+ #if __solaris
1239
+ || errno == EAFNOSUPPORT || errno == EPROTOTYPE
1240
+ #endif
1241
+ )
1242
+ )
1243
+ {
1244
+ /* emulate sendfile. this is a major pain in the ass */
1245
+ dBUF;
1246
+
1247
+ res = 0;
1248
+
1249
+ while (count)
1250
+ {
1251
+ eio_ssize_t cnt;
1252
+
1253
+ cnt = pread (ifd, eio_buf, count > EIO_BUFSIZE ? EIO_BUFSIZE : count, offset);
1254
+
1255
+ if (cnt <= 0)
1256
+ {
1257
+ if (cnt && !res) res = -1;
1258
+ break;
1259
+ }
1260
+
1261
+ cnt = write (ofd, eio_buf, cnt);
1262
+
1263
+ if (cnt <= 0)
1264
+ {
1265
+ if (cnt && !res) res = -1;
1266
+ break;
1267
+ }
1268
+
1269
+ offset += cnt;
1270
+ res += cnt;
1271
+ count -= cnt;
1272
+ }
1273
+
1274
+ FUBd;
1275
+ }
1276
+
1277
+ return res;
1278
+ }
1279
+
1280
+ #ifdef PAGESIZE
1281
+ # define eio_pagesize() PAGESIZE
1282
+ #else
1283
+ static intptr_t
1284
+ eio_pagesize (void)
1285
+ {
1286
+ static intptr_t page;
1287
+
1288
+ if (!page)
1289
+ page = sysconf (_SC_PAGESIZE);
1290
+
1291
+ return page;
1292
+ }
1293
+ #endif
1294
+
1295
+ static void
1296
+ eio_page_align (void **addr, size_t *length)
1297
+ {
1298
+ intptr_t mask = eio_pagesize () - 1;
1299
+
1300
+ /* round down addr */
1301
+ intptr_t adj = mask & (intptr_t)*addr;
1302
+
1303
+ *addr = (void *)((intptr_t)*addr - adj);
1304
+ *length += adj;
1305
+
1306
+ /* round up length */
1307
+ *length = (*length + mask) & ~mask;
1308
+ }
1309
+
1310
+ #if !_POSIX_MEMLOCK
1311
+ # define eio__mlockall(a) EIO_ENOSYS ()
1312
+ #else
1313
+
1314
+ static int
1315
+ eio__mlockall (int flags)
1316
+ {
1317
+ #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7
1318
+ extern int mallopt (int, int);
1319
+ mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */
1320
+ #endif
1321
+
1322
+ if (EIO_MCL_CURRENT != MCL_CURRENT
1323
+ || EIO_MCL_FUTURE != MCL_FUTURE)
1324
+ {
1325
+ flags = 0
1326
+ | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0)
1327
+ | (flags & EIO_MCL_FUTURE ? MCL_FUTURE : 0);
1328
+ }
1329
+
1330
+ return mlockall (flags);
1331
+ }
1332
+ #endif
1333
+
1334
+ #if !_POSIX_MEMLOCK_RANGE
1335
+ # define eio__mlock(a,b) EIO_ENOSYS ()
1336
+ #else
1337
+
1338
+ static int
1339
+ eio__mlock (void *addr, size_t length)
1340
+ {
1341
+ eio_page_align (&addr, &length);
1342
+
1343
+ return mlock (addr, length);
1344
+ }
1345
+
1346
+ #endif
1347
+
1348
+ #if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO)
1349
+ # define eio__msync(a,b,c) EIO_ENOSYS ()
1350
+ #else
1351
+
1352
+ static int
1353
+ eio__msync (void *mem, size_t len, int flags)
1354
+ {
1355
+ eio_page_align (&mem, &len);
1356
+
1357
+ if (EIO_MS_ASYNC != MS_SYNC
1358
+ || EIO_MS_INVALIDATE != MS_INVALIDATE
1359
+ || EIO_MS_SYNC != MS_SYNC)
1360
+ {
1361
+ flags = 0
1362
+ | (flags & EIO_MS_ASYNC ? MS_ASYNC : 0)
1363
+ | (flags & EIO_MS_INVALIDATE ? MS_INVALIDATE : 0)
1364
+ | (flags & EIO_MS_SYNC ? MS_SYNC : 0);
1365
+ }
1366
+
1367
+ return msync (mem, len, flags);
1368
+ }
1369
+
1370
+ #endif
1371
+
1372
+ static int
1373
+ eio__mtouch (eio_req *req)
1374
+ {
1375
+ void *mem = req->ptr2;
1376
+ size_t len = req->size;
1377
+ int flags = req->int1;
1378
+
1379
+ eio_page_align (&mem, &len);
1380
+
1381
+ {
1382
+ intptr_t addr = (intptr_t)mem;
1383
+ intptr_t end = addr + len;
1384
+ intptr_t page = eio_pagesize ();
1385
+
1386
+ if (addr < end)
1387
+ if (flags & EIO_MT_MODIFY) /* modify */
1388
+ do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len && !EIO_CANCELLED (req));
1389
+ else
1390
+ do { *((volatile sig_atomic_t *)addr) ; } while ((addr += page) < len && !EIO_CANCELLED (req));
1391
+ }
1392
+
1393
+ return 0;
1394
+ }
1395
+
1396
+ /*****************************************************************************/
1397
+ /* requests implemented outside eio_execute, because they are so large */
1398
+
1399
+ static void
1400
+ eio__realpath (eio_req *req, etp_worker *self)
1401
+ {
1402
+ char *rel = req->ptr1;
1403
+ char *res;
1404
+ char *tmp1, *tmp2;
1405
+ #if SYMLOOP_MAX > 32
1406
+ int symlinks = SYMLOOP_MAX;
1407
+ #else
1408
+ int symlinks = 32;
1409
+ #endif
1410
+
1411
+ req->result = -1;
1412
+
1413
+ errno = EINVAL;
1414
+ if (!rel)
1415
+ return;
1416
+
1417
+ errno = ENOENT;
1418
+ if (!*rel)
1419
+ return;
1420
+
1421
+ if (!req->ptr2)
1422
+ {
1423
+ X_LOCK (wrklock);
1424
+ req->flags |= EIO_FLAG_PTR2_FREE;
1425
+ X_UNLOCK (wrklock);
1426
+ req->ptr2 = malloc (PATH_MAX * 3);
1427
+
1428
+ errno = ENOMEM;
1429
+ if (!req->ptr2)
1430
+ return;
1431
+ }
1432
+
1433
+ res = req->ptr2;
1434
+ tmp1 = res + PATH_MAX;
1435
+ tmp2 = tmp1 + PATH_MAX;
1436
+
1437
+ #if 0 /* disabled, the musl way to do things is just too racy */
1438
+ #if __linux && defined(O_NONBLOCK) && defined(O_NOATIME)
1439
+ /* on linux we may be able to ask the kernel */
1440
+ {
1441
+ int fd = open (rel, O_RDONLY | O_NONBLOCK | O_NOCTTY | O_NOATIME);
1442
+
1443
+ if (fd >= 0)
1444
+ {
1445
+ sprintf (tmp1, "/proc/self/fd/%d", fd);
1446
+ req->result = readlink (tmp1, res, PATH_MAX);
1447
+ close (fd);
1448
+
1449
+ /* here we should probably stat the open file and the disk file, to make sure they still match */
1450
+
1451
+ if (req->result > 0)
1452
+ goto done;
1453
+ }
1454
+ else if (errno == ELOOP || errno == ENAMETOOLONG || errno == ENOENT || errno == ENOTDIR || errno == EIO)
1455
+ return;
1456
+ }
1457
+ #endif
1458
+ #endif
1459
+
1460
+ if (*rel != '/')
1461
+ {
1462
+ if (!getcwd (res, PATH_MAX))
1463
+ return;
1464
+
1465
+ if (res [1]) /* only use if not / */
1466
+ res += strlen (res);
1467
+ }
1468
+
1469
+ while (*rel)
1470
+ {
1471
+ eio_ssize_t len, linklen;
1472
+ char *beg = rel;
1473
+
1474
+ while (*rel && *rel != '/')
1475
+ ++rel;
1476
+
1477
+ len = rel - beg;
1478
+
1479
+ if (!len) /* skip slashes */
1480
+ {
1481
+ ++rel;
1482
+ continue;
1483
+ }
1484
+
1485
+ if (beg [0] == '.')
1486
+ {
1487
+ if (len == 1)
1488
+ continue; /* . - nop */
1489
+
1490
+ if (beg [1] == '.' && len == 2)
1491
+ {
1492
+ /* .. - back up one component, if possible */
1493
+
1494
+ while (res != req->ptr2)
1495
+ if (*--res == '/')
1496
+ break;
1497
+
1498
+ continue;
1499
+ }
1500
+ }
1501
+
1502
+ errno = ENAMETOOLONG;
1503
+ if (res + 1 + len + 1 >= tmp1)
1504
+ return;
1505
+
1506
+ /* copy one component */
1507
+ *res = '/';
1508
+ memcpy (res + 1, beg, len);
1509
+
1510
+ /* zero-terminate, for readlink */
1511
+ res [len + 1] = 0;
1512
+
1513
+ /* now check if it's a symlink */
1514
+ linklen = readlink (req->ptr2, tmp1, PATH_MAX);
1515
+
1516
+ if (linklen < 0)
1517
+ {
1518
+ if (errno != EINVAL)
1519
+ return;
1520
+
1521
+ /* it's a normal directory. hopefully */
1522
+ res += len + 1;
1523
+ }
1524
+ else
1525
+ {
1526
+ /* yay, it was a symlink - build new path in tmp2 */
1527
+ int rellen = strlen (rel);
1528
+
1529
+ errno = ENAMETOOLONG;
1530
+ if (linklen + 1 + rellen >= PATH_MAX)
1531
+ return;
1532
+
1533
+ errno = ELOOP;
1534
+ if (!--symlinks)
1535
+ return;
1536
+
1537
+ if (*tmp1 == '/')
1538
+ res = req->ptr2; /* symlink resolves to an absolute path */
1539
+
1540
+ /* we need to be careful, as rel might point into tmp2 already */
1541
+ memmove (tmp2 + linklen + 1, rel, rellen + 1);
1542
+ tmp2 [linklen] = '/';
1543
+ memcpy (tmp2, tmp1, linklen);
1544
+
1545
+ rel = tmp2;
1546
+ }
1547
+ }
1548
+
1549
+ /* special case for the lone root path */
1550
+ if (res == req->ptr2)
1551
+ *res++ = '/';
1552
+
1553
+ req->result = res - (char *)req->ptr2;
1554
+
1555
+ done:
1556
+ req->ptr2 = realloc (req->ptr2, req->result); /* trade time for space savings */
1557
+ }
1558
+
1559
+ static signed char
1560
+ eio_dent_cmp (const eio_dirent *a, const eio_dirent *b)
1561
+ {
1562
+ return a->score - b->score ? a->score - b->score /* works because our signed char is always 0..100 */
1563
+ : a->inode < b->inode ? -1
1564
+ : a->inode > b->inode ? 1
1565
+ : 0;
1566
+ }
1567
+
1568
+ #define EIO_DENT_CMP(i,op,j) eio_dent_cmp (&i, &j) op 0
1569
+
1570
+ #define EIO_SORT_CUTOFF 30 /* quite high, but performs well on many filesystems */
1571
+ #define EIO_SORT_FAST 60 /* when to only use insertion sort */
1572
+
1573
+ static void
1574
+ eio_dent_radix_sort (eio_dirent *dents, int size, signed char score_bits, eio_ino_t inode_bits)
1575
+ {
1576
+ unsigned char bits [9 + sizeof (eio_ino_t) * 8];
1577
+ unsigned char *bit = bits;
1578
+
1579
+ assert (CHAR_BIT == 8);
1580
+ assert (sizeof (eio_dirent) * 8 < 256);
1581
+ assert (offsetof (eio_dirent, inode)); /* we use bit #0 as sentinel */
1582
+ assert (offsetof (eio_dirent, score)); /* we use bit #0 as sentinel */
1583
+
1584
+ if (size <= EIO_SORT_FAST)
1585
+ return;
1586
+
1587
+ /* first prepare an array of bits to test in our radix sort */
1588
+ /* try to take endianness into account, as well as differences in eio_ino_t sizes */
1589
+ /* inode_bits must contain all inodes ORed together */
1590
+ /* which is used to skip bits that are 0 everywhere, which is very common */
1591
+ {
1592
+ eio_ino_t endianness;
1593
+ int i, j;
1594
+
1595
+ /* we store the byte offset of byte n into byte n of "endianness" */
1596
+ for (i = 0; i < sizeof (eio_ino_t); ++i)
1597
+ ((unsigned char *)&endianness)[i] = i;
1598
+
1599
+ *bit++ = 0;
1600
+
1601
+ for (i = 0; i < sizeof (eio_ino_t); ++i)
1602
+ {
1603
+ /* shifting off the byte offsets out of "endianness" */
1604
+ int offs = (offsetof (eio_dirent, inode) + (endianness & 0xff)) * 8;
1605
+ endianness >>= 8;
1606
+
1607
+ for (j = 0; j < 8; ++j)
1608
+ if (inode_bits & (((eio_ino_t)1) << (i * 8 + j)))
1609
+ *bit++ = offs + j;
1610
+ }
1611
+
1612
+ for (j = 0; j < 8; ++j)
1613
+ if (score_bits & (1 << j))
1614
+ *bit++ = offsetof (eio_dirent, score) * 8 + j;
1615
+ }
1616
+
1617
+ /* now actually do the sorting (a variant of MSD radix sort) */
1618
+ {
1619
+ eio_dirent *base_stk [9 + sizeof (eio_ino_t) * 8], *base;
1620
+ eio_dirent *end_stk [9 + sizeof (eio_ino_t) * 8], *end;
1621
+ unsigned char *bit_stk [9 + sizeof (eio_ino_t) * 8];
1622
+ int stk_idx = 0;
1623
+
1624
+ base_stk [stk_idx] = dents;
1625
+ end_stk [stk_idx] = dents + size;
1626
+ bit_stk [stk_idx] = bit - 1;
1627
+
1628
+ do
1629
+ {
1630
+ base = base_stk [stk_idx];
1631
+ end = end_stk [stk_idx];
1632
+ bit = bit_stk [stk_idx];
1633
+
1634
+ for (;;)
1635
+ {
1636
+ unsigned char O = *bit >> 3;
1637
+ unsigned char M = 1 << (*bit & 7);
1638
+
1639
+ eio_dirent *a = base;
1640
+ eio_dirent *b = end;
1641
+
1642
+ if (b - a < EIO_SORT_CUTOFF)
1643
+ break;
1644
+
1645
+ /* now bit-partition the array on the bit */
1646
+ /* this ugly asymmetric loop seems to perform much better than typical */
1647
+ /* partition algos found in the literature */
1648
+ do
1649
+ if (!(((unsigned char *)a)[O] & M))
1650
+ ++a;
1651
+ else if (!(((unsigned char *)--b)[O] & M))
1652
+ {
1653
+ eio_dirent tmp = *a; *a = *b; *b = tmp;
1654
+ ++a;
1655
+ }
1656
+ while (b > a);
1657
+
1658
+ /* next bit, or stop, if no bits left in this path */
1659
+ if (!*--bit)
1660
+ break;
1661
+
1662
+ base_stk [stk_idx] = a;
1663
+ end_stk [stk_idx] = end;
1664
+ bit_stk [stk_idx] = bit;
1665
+ ++stk_idx;
1666
+
1667
+ end = a;
1668
+ }
1669
+ }
1670
+ while (stk_idx--);
1671
+ }
1672
+ }
1673
+
1674
+ static void
1675
+ eio_dent_insertion_sort (eio_dirent *dents, int size)
1676
+ {
1677
+ /* first move the smallest element to the front, to act as a sentinel */
1678
+ {
1679
+ int i;
1680
+ eio_dirent *min = dents;
1681
+
1682
+ /* the radix pre-pass ensures that the minimum element is in the first EIO_SORT_CUTOFF + 1 elements */
1683
+ for (i = size > EIO_SORT_FAST ? EIO_SORT_CUTOFF + 1 : size; --i; )
1684
+ if (EIO_DENT_CMP (dents [i], <, *min))
1685
+ min = &dents [i];
1686
+
1687
+ /* swap elements 0 and j (minimum) */
1688
+ {
1689
+ eio_dirent tmp = *dents; *dents = *min; *min = tmp;
1690
+ }
1691
+ }
1692
+
1693
+ /* then do standard insertion sort, assuming that all elements are >= dents [0] */
1694
+ {
1695
+ eio_dirent *i, *j;
1696
+
1697
+ for (i = dents + 1; i < dents + size; ++i)
1698
+ {
1699
+ eio_dirent value = *i;
1700
+
1701
+ for (j = i - 1; EIO_DENT_CMP (*j, >, value); --j)
1702
+ j [1] = j [0];
1703
+
1704
+ j [1] = value;
1705
+ }
1706
+ }
1707
+ }
1708
+
1709
+ static void
1710
+ eio_dent_sort (eio_dirent *dents, int size, signed char score_bits, eio_ino_t inode_bits)
1711
+ {
1712
+ if (size <= 1)
1713
+ return; /* our insertion sort relies on size > 0 */
1714
+
1715
+ /* first we use a radix sort, but only for dirs >= EIO_SORT_FAST */
1716
+ /* and stop sorting when the partitions are <= EIO_SORT_CUTOFF */
1717
+ eio_dent_radix_sort (dents, size, score_bits, inode_bits);
1718
+
1719
+ /* use an insertion sort at the end, or for small arrays, */
1720
+ /* as insertion sort is more efficient for small partitions */
1721
+ eio_dent_insertion_sort (dents, size);
1722
+ }
1723
+
1724
+ /* read a full directory */
1725
+ static void
1726
+ eio__scandir (eio_req *req, etp_worker *self)
1727
+ {
1728
+ char *name, *names;
1729
+ int namesalloc = 4096 - sizeof (void *) * 4;
1730
+ int namesoffs = 0;
1731
+ int flags = req->int1;
1732
+ eio_dirent *dents = 0;
1733
+ int dentalloc = 128;
1734
+ int dentoffs = 0;
1735
+ eio_ino_t inode_bits = 0;
1736
+ #ifdef _WIN32
1737
+ HANDLE dirp;
1738
+ WIN32_FIND_DATA entp;
1739
+ #else
1740
+ DIR *dirp;
1741
+ EIO_STRUCT_DIRENT *entp;
1742
+ #endif
1743
+
1744
+ req->result = -1;
1745
+
1746
+ if (!(flags & EIO_READDIR_DENTS))
1747
+ flags &= ~(EIO_READDIR_DIRS_FIRST | EIO_READDIR_STAT_ORDER);
1748
+
1749
+ #ifdef _WIN32
1750
+ {
1751
+ int len = strlen ((const char *)req->ptr1);
1752
+ char *path = malloc (MAX_PATH);
1753
+ const char *fmt;
1754
+
1755
+ if (!len)
1756
+ fmt = "./*";
1757
+ else if (((const char *)req->ptr1)[len - 1] == '/' || ((const char *)req->ptr1)[len - 1] == '\\')
1758
+ fmt = "%s*";
1759
+ else
1760
+ fmt = "%s/*";
1761
+
1762
+ _snprintf (path, MAX_PATH, fmt, (const char *)req->ptr1);
1763
+ dirp = FindFirstFile (path, &entp);
1764
+ free (path);
1765
+
1766
+ if (dirp == INVALID_HANDLE_VALUE)
1767
+ {
1768
+ dirp = 0;
1769
+
1770
+ /* should steal _dosmaperr */
1771
+ switch (GetLastError ())
1772
+ {
1773
+ case ERROR_FILE_NOT_FOUND:
1774
+ req->result = 0;
1775
+ break;
1776
+
1777
+ case ERROR_INVALID_NAME:
1778
+ case ERROR_PATH_NOT_FOUND:
1779
+ case ERROR_NO_MORE_FILES:
1780
+ errno = ENOENT;
1781
+ break;
1782
+
1783
+ case ERROR_NOT_ENOUGH_MEMORY:
1784
+ errno = ENOMEM;
1785
+ break;
1786
+
1787
+ default:
1788
+ errno = EINVAL;
1789
+ break;
1790
+ }
1791
+ }
1792
+ }
1793
+ #else
1794
+ dirp = opendir (req->ptr1);
1795
+ #endif
1796
+
1797
+ if (req->flags & EIO_FLAG_PTR1_FREE)
1798
+ free (req->ptr1);
1799
+
1800
+ req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE;
1801
+ req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0;
1802
+ req->ptr2 = names = malloc (namesalloc);
1803
+
1804
+ if (dirp && names && (!flags || dents))
1805
+ for (;;)
1806
+ {
1807
+ int done;
1808
+
1809
+ #ifdef _WIN32
1810
+ done = !dirp;
1811
+ #else
1812
+ errno = 0;
1813
+ entp = readdir (dirp);
1814
+ done = !entp;
1815
+ #endif
1816
+
1817
+ if (done)
1818
+ {
1819
+ #ifndef _WIN32
1820
+ int old_errno = errno;
1821
+ closedir (dirp);
1822
+ errno = old_errno;
1823
+
1824
+ if (errno)
1825
+ break;
1826
+ #endif
1827
+
1828
+ /* sort etc. */
1829
+ req->int1 = flags;
1830
+ req->result = dentoffs;
1831
+
1832
+ if (flags & EIO_READDIR_STAT_ORDER)
1833
+ eio_dent_sort (dents, dentoffs, flags & EIO_READDIR_DIRS_FIRST ? 7 : 0, inode_bits);
1834
+ else if (flags & EIO_READDIR_DIRS_FIRST)
1835
+ if (flags & EIO_READDIR_FOUND_UNKNOWN)
1836
+ eio_dent_sort (dents, dentoffs, 7, inode_bits); /* sort by score and inode */
1837
+ else
1838
+ {
1839
+ /* in this case, all is known, and we just put dirs first and sort them */
1840
+ eio_dirent *oth = dents + dentoffs;
1841
+ eio_dirent *dir = dents;
1842
+
1843
+ /* now partition dirs to the front, and non-dirs to the back */
1844
+ /* by walking from both sides and swapping if necessary */
1845
+ while (oth > dir)
1846
+ {
1847
+ if (dir->type == EIO_DT_DIR)
1848
+ ++dir;
1849
+ else if ((--oth)->type == EIO_DT_DIR)
1850
+ {
1851
+ eio_dirent tmp = *dir; *dir = *oth; *oth = tmp;
1852
+
1853
+ ++dir;
1854
+ }
1855
+ }
1856
+
1857
+ /* now sort the dirs only (dirs all have the same score) */
1858
+ eio_dent_sort (dents, dir - dents, 0, inode_bits);
1859
+ }
1860
+
1861
+ break;
1862
+ }
1863
+
1864
+ /* now add the entry to our list(s) */
1865
+ name = D_NAME (entp);
1866
+
1867
+ /* skip . and .. entries */
1868
+ if (name [0] != '.' || (name [1] && (name [1] != '.' || name [2])))
1869
+ {
1870
+ int len = D_NAMLEN (entp) + 1;
1871
+
1872
+ while (ecb_expect_false (namesoffs + len > namesalloc))
1873
+ {
1874
+ namesalloc *= 2;
1875
+ req->ptr2 = names = realloc (names, namesalloc);
1876
+
1877
+ if (!names)
1878
+ break;
1879
+ }
1880
+
1881
+ memcpy (names + namesoffs, name, len);
1882
+
1883
+ if (dents)
1884
+ {
1885
+ struct eio_dirent *ent;
1886
+
1887
+ if (ecb_expect_false (dentoffs == dentalloc))
1888
+ {
1889
+ dentalloc *= 2;
1890
+ req->ptr1 = dents = realloc (dents, dentalloc * sizeof (eio_dirent));
1891
+
1892
+ if (!dents)
1893
+ break;
1894
+ }
1895
+
1896
+ ent = dents + dentoffs;
1897
+
1898
+ ent->nameofs = namesoffs; /* rather dirtily we store the offset in the pointer */
1899
+ ent->namelen = len - 1;
1900
+ ent->inode = D_INO (entp);
1901
+
1902
+ inode_bits |= ent->inode;
1903
+
1904
+ switch (D_TYPE (entp))
1905
+ {
1906
+ default:
1907
+ ent->type = EIO_DT_UNKNOWN;
1908
+ flags |= EIO_READDIR_FOUND_UNKNOWN;
1909
+ break;
1910
+
1911
+ #ifdef DT_FIFO
1912
+ case DT_FIFO: ent->type = EIO_DT_FIFO; break;
1913
+ #endif
1914
+ #ifdef DT_CHR
1915
+ case DT_CHR: ent->type = EIO_DT_CHR; break;
1916
+ #endif
1917
+ #ifdef DT_MPC
1918
+ case DT_MPC: ent->type = EIO_DT_MPC; break;
1919
+ #endif
1920
+ #ifdef DT_DIR
1921
+ case DT_DIR: ent->type = EIO_DT_DIR; break;
1922
+ #endif
1923
+ #ifdef DT_NAM
1924
+ case DT_NAM: ent->type = EIO_DT_NAM; break;
1925
+ #endif
1926
+ #ifdef DT_BLK
1927
+ case DT_BLK: ent->type = EIO_DT_BLK; break;
1928
+ #endif
1929
+ #ifdef DT_MPB
1930
+ case DT_MPB: ent->type = EIO_DT_MPB; break;
1931
+ #endif
1932
+ #ifdef DT_REG
1933
+ case DT_REG: ent->type = EIO_DT_REG; break;
1934
+ #endif
1935
+ #ifdef DT_NWK
1936
+ case DT_NWK: ent->type = EIO_DT_NWK; break;
1937
+ #endif
1938
+ #ifdef DT_CMP
1939
+ case DT_CMP: ent->type = EIO_DT_CMP; break;
1940
+ #endif
1941
+ #ifdef DT_LNK
1942
+ case DT_LNK: ent->type = EIO_DT_LNK; break;
1943
+ #endif
1944
+ #ifdef DT_SOCK
1945
+ case DT_SOCK: ent->type = EIO_DT_SOCK; break;
1946
+ #endif
1947
+ #ifdef DT_DOOR
1948
+ case DT_DOOR: ent->type = EIO_DT_DOOR; break;
1949
+ #endif
1950
+ #ifdef DT_WHT
1951
+ case DT_WHT: ent->type = EIO_DT_WHT; break;
1952
+ #endif
1953
+ }
1954
+
1955
+ ent->score = 7;
1956
+
1957
+ if (flags & EIO_READDIR_DIRS_FIRST)
1958
+ {
1959
+ if (ent->type == EIO_DT_UNKNOWN)
1960
+ {
1961
+ if (*name == '.') /* leading dots are likely directories, and, in any case, rare */
1962
+ ent->score = 1;
1963
+ else if (!strchr (name, '.')) /* absense of dots indicate likely dirs */
1964
+ ent->score = len <= 2 ? 4 - len : len <= 4 ? 4 : len <= 7 ? 5 : 6; /* shorter == more likely dir, but avoid too many classes */
1965
+ }
1966
+ else if (ent->type == EIO_DT_DIR)
1967
+ ent->score = 0;
1968
+ }
1969
+ }
1970
+
1971
+ namesoffs += len;
1972
+ ++dentoffs;
1973
+ }
1974
+
1975
+ if (EIO_CANCELLED (req))
1976
+ {
1977
+ errno = ECANCELED;
1978
+ break;
1979
+ }
1980
+
1981
+ #ifdef _WIN32
1982
+ if (!FindNextFile (dirp, &entp))
1983
+ {
1984
+ FindClose (dirp);
1985
+ dirp = 0;
1986
+ }
1987
+ #endif
1988
+ }
1989
+ }
1990
+
1991
+ /*****************************************************************************/
1992
+
1993
+ #define ALLOC(len) \
1994
+ if (!req->ptr2) \
1995
+ { \
1996
+ X_LOCK (wrklock); \
1997
+ req->flags |= EIO_FLAG_PTR2_FREE; \
1998
+ X_UNLOCK (wrklock); \
1999
+ req->ptr2 = malloc (len); \
2000
+ if (!req->ptr2) \
2001
+ { \
2002
+ errno = ENOMEM; \
2003
+ req->result = -1; \
2004
+ break; \
2005
+ } \
2006
+ }
2007
+
2008
+ X_THREAD_PROC (etp_proc)
2009
+ {
2010
+ ETP_REQ *req;
2011
+ struct timespec ts;
2012
+ etp_worker *self = (etp_worker *)thr_arg;
2013
+
2014
+ #if HAVE_PRCTL_SET_NAME
2015
+ prctl (PR_SET_NAME, (unsigned long)"eio_thread", 0, 0, 0);
2016
+ #endif
2017
+
2018
+ /* try to distribute timeouts somewhat evenly */
2019
+ ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL);
2020
+
2021
+ for (;;)
2022
+ {
2023
+ ts.tv_sec = 0;
2024
+
2025
+ X_LOCK (reqlock);
2026
+
2027
+ for (;;)
2028
+ {
2029
+ self->req = req = reqq_shift (&req_queue);
2030
+
2031
+ if (req)
2032
+ break;
2033
+
2034
+ if (ts.tv_sec == 1) /* no request, but timeout detected, let's quit */
2035
+ {
2036
+ X_UNLOCK (reqlock);
2037
+ X_LOCK (wrklock);
2038
+ --started;
2039
+ X_UNLOCK (wrklock);
2040
+ goto quit;
2041
+ }
2042
+
2043
+ ++idle;
2044
+
2045
+ if (idle <= max_idle)
2046
+ /* we are allowed to idle, so do so without any timeout */
2047
+ X_COND_WAIT (reqwait, reqlock);
2048
+ else
2049
+ {
2050
+ /* initialise timeout once */
2051
+ if (!ts.tv_sec)
2052
+ ts.tv_sec = time (0) + idle_timeout;
2053
+
2054
+ if (X_COND_TIMEDWAIT (reqwait, reqlock, ts) == ETIMEDOUT)
2055
+ ts.tv_sec = 1; /* assuming this is not a value computed above.,.. */
2056
+ }
2057
+
2058
+ --idle;
2059
+ }
2060
+
2061
+ --nready;
2062
+
2063
+ X_UNLOCK (reqlock);
2064
+
2065
+ if (req->type < 0)
2066
+ goto quit;
2067
+
2068
+ ETP_EXECUTE (self, req);
2069
+
2070
+ X_LOCK (reslock);
2071
+
2072
+ ++npending;
2073
+
2074
+ if (!reqq_push (&res_queue, req) && want_poll_cb)
2075
+ want_poll_cb ();
2076
+
2077
+ self->req = 0;
2078
+ etp_worker_clear (self);
2079
+
2080
+ X_UNLOCK (reslock);
2081
+ }
2082
+
2083
+ quit:
2084
+ X_LOCK (wrklock);
2085
+ etp_worker_free (self);
2086
+ X_UNLOCK (wrklock);
2087
+
2088
+ return 0;
2089
+ }
2090
+
2091
+ /*****************************************************************************/
2092
+
2093
+ int ecb_cold
2094
+ eio_init (void (*want_poll)(void), void (*done_poll)(void))
2095
+ {
2096
+ #if !HAVE_PREADWRITE
2097
+ X_MUTEX_CREATE (preadwritelock);
2098
+ #endif
2099
+
2100
+ return etp_init (want_poll, done_poll);
2101
+ }
2102
+
2103
+ ecb_inline void
2104
+ eio_api_destroy (eio_req *req)
2105
+ {
2106
+ free (req);
2107
+ }
2108
+
2109
+ #define REQ(rtype) \
2110
+ eio_req *req; \
2111
+ \
2112
+ req = (eio_req *)calloc (1, sizeof *req); \
2113
+ if (!req) \
2114
+ return 0; \
2115
+ \
2116
+ req->type = rtype; \
2117
+ req->pri = pri; \
2118
+ req->finish = cb; \
2119
+ req->data = data; \
2120
+ req->destroy = eio_api_destroy;
2121
+
2122
+ #define SEND eio_submit (req); return req
2123
+
2124
+ #define PATH \
2125
+ req->flags |= EIO_FLAG_PTR1_FREE; \
2126
+ req->ptr1 = strdup (path); \
2127
+ if (!req->ptr1) \
2128
+ { \
2129
+ eio_api_destroy (req); \
2130
+ return 0; \
2131
+ }
2132
+
2133
+ static void
2134
+ eio_execute (etp_worker *self, eio_req *req)
2135
+ {
2136
+ if (ecb_expect_false (EIO_CANCELLED (req)))
2137
+ {
2138
+ req->result = -1;
2139
+ req->errorno = ECANCELED;
2140
+ return;
2141
+ }
2142
+
2143
+ switch (req->type)
2144
+ {
2145
+ case EIO_READ: ALLOC (req->size);
2146
+ req->result = req->offs >= 0
2147
+ ? pread (req->int1, req->ptr2, req->size, req->offs)
2148
+ : read (req->int1, req->ptr2, req->size); break;
2149
+ case EIO_WRITE: req->result = req->offs >= 0
2150
+ ? pwrite (req->int1, req->ptr2, req->size, req->offs)
2151
+ : write (req->int1, req->ptr2, req->size); break;
2152
+
2153
+ case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break;
2154
+ case EIO_SENDFILE: req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size); break;
2155
+
2156
+ case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2157
+ req->result = stat (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break;
2158
+ case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2159
+ req->result = lstat (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break;
2160
+ case EIO_FSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2161
+ req->result = fstat (req->int1, (EIO_STRUCT_STAT *)req->ptr2); break;
2162
+
2163
+ case EIO_STATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS));
2164
+ req->result = statvfs (req->ptr1, (EIO_STRUCT_STATVFS *)req->ptr2); break;
2165
+ case EIO_FSTATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS));
2166
+ req->result = fstatvfs (req->int1, (EIO_STRUCT_STATVFS *)req->ptr2); break;
2167
+
2168
+ case EIO_CHOWN: req->result = chown (req->ptr1, req->int2, req->int3); break;
2169
+ case EIO_FCHOWN: req->result = fchown (req->int1, req->int2, req->int3); break;
2170
+ case EIO_CHMOD: req->result = chmod (req->ptr1, (eio_mode_t)req->int2); break;
2171
+ case EIO_FCHMOD: req->result = fchmod (req->int1, (eio_mode_t)req->int2); break;
2172
+ case EIO_TRUNCATE: req->result = truncate (req->ptr1, req->offs); break;
2173
+ case EIO_FTRUNCATE: req->result = ftruncate (req->int1, req->offs); break;
2174
+
2175
+ case EIO_OPEN: req->result = open (req->ptr1, req->int1, (eio_mode_t)req->int2); break;
2176
+ case EIO_CLOSE: req->result = close (req->int1); break;
2177
+ case EIO_DUP2: req->result = dup2 (req->int1, req->int2); break;
2178
+ case EIO_UNLINK: req->result = unlink (req->ptr1); break;
2179
+ case EIO_RMDIR: req->result = rmdir (req->ptr1); break;
2180
+ case EIO_MKDIR: req->result = mkdir (req->ptr1, (eio_mode_t)req->int2); break;
2181
+ case EIO_RENAME: req->result = rename (req->ptr1, req->ptr2); break;
2182
+ case EIO_LINK: req->result = link (req->ptr1, req->ptr2); break;
2183
+ case EIO_SYMLINK: req->result = symlink (req->ptr1, req->ptr2); break;
2184
+ case EIO_MKNOD: req->result = mknod (req->ptr1, (eio_mode_t)req->int2, (dev_t)req->offs); break;
2185
+
2186
+ case EIO_REALPATH: eio__realpath (req, self); break;
2187
+
2188
+ case EIO_READLINK: ALLOC (PATH_MAX);
2189
+ req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break;
2190
+
2191
+ case EIO_SYNC: req->result = 0; sync (); break;
2192
+ case EIO_FSYNC: req->result = fsync (req->int1); break;
2193
+ case EIO_FDATASYNC: req->result = fdatasync (req->int1); break;
2194
+ case EIO_SYNCFS: req->result = eio__syncfs (req->int1); break;
2195
+ case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break;
2196
+ case EIO_MSYNC: req->result = eio__msync (req->ptr2, req->size, req->int1); break;
2197
+ case EIO_MTOUCH: req->result = eio__mtouch (req); break;
2198
+ case EIO_MLOCK: req->result = eio__mlock (req->ptr2, req->size); break;
2199
+ case EIO_MLOCKALL: req->result = eio__mlockall (req->int1); break;
2200
+ case EIO_FALLOCATE: req->result = eio__fallocate (req->int1, req->int2, req->offs, req->size); break;
2201
+
2202
+ case EIO_READDIR: eio__scandir (req, self); break;
2203
+
2204
+ case EIO_BUSY:
2205
+ #ifdef _WIN32
2206
+ Sleep (req->nv1 * 1e3);
2207
+ #else
2208
+ {
2209
+ struct timeval tv;
2210
+
2211
+ tv.tv_sec = req->nv1;
2212
+ tv.tv_usec = (req->nv1 - tv.tv_sec) * 1e6;
2213
+
2214
+ req->result = select (0, 0, 0, 0, &tv);
2215
+ }
2216
+ #endif
2217
+ break;
2218
+
2219
+ case EIO_UTIME:
2220
+ case EIO_FUTIME:
2221
+ {
2222
+ struct timeval tv[2];
2223
+ struct timeval *times;
2224
+
2225
+ if (req->nv1 != -1. || req->nv2 != -1.)
2226
+ {
2227
+ tv[0].tv_sec = req->nv1;
2228
+ tv[0].tv_usec = (req->nv1 - tv[0].tv_sec) * 1000000.;
2229
+ tv[1].tv_sec = req->nv2;
2230
+ tv[1].tv_usec = (req->nv2 - tv[1].tv_sec) * 1000000.;
2231
+
2232
+ times = tv;
2233
+ }
2234
+ else
2235
+ times = 0;
2236
+
2237
+ req->result = req->type == EIO_FUTIME
2238
+ ? futimes (req->int1, times)
2239
+ : utimes (req->ptr1, times);
2240
+ }
2241
+ break;
2242
+
2243
+ case EIO_GROUP:
2244
+ abort (); /* handled in eio_request */
2245
+
2246
+ case EIO_NOP:
2247
+ req->result = 0;
2248
+ break;
2249
+
2250
+ case EIO_CUSTOM:
2251
+ req->feed (req);
2252
+ break;
2253
+
2254
+ default:
2255
+ errno = ENOSYS;
2256
+ req->result = -1;
2257
+ break;
2258
+ }
2259
+
2260
+ req->errorno = errno;
2261
+ }
2262
+
2263
+ #ifndef EIO_NO_WRAPPERS
2264
+
2265
+ eio_req *eio_nop (int pri, eio_cb cb, void *data)
2266
+ {
2267
+ REQ (EIO_NOP); SEND;
2268
+ }
2269
+
2270
+ eio_req *eio_busy (double delay, int pri, eio_cb cb, void *data)
2271
+ {
2272
+ REQ (EIO_BUSY); req->nv1 = delay; SEND;
2273
+ }
2274
+
2275
+ eio_req *eio_sync (int pri, eio_cb cb, void *data)
2276
+ {
2277
+ REQ (EIO_SYNC); SEND;
2278
+ }
2279
+
2280
+ eio_req *eio_fsync (int fd, int pri, eio_cb cb, void *data)
2281
+ {
2282
+ REQ (EIO_FSYNC); req->int1 = fd; SEND;
2283
+ }
2284
+
2285
+ eio_req *eio_msync (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data)
2286
+ {
2287
+ REQ (EIO_MSYNC); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND;
2288
+ }
2289
+
2290
+ eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data)
2291
+ {
2292
+ REQ (EIO_FDATASYNC); req->int1 = fd; SEND;
2293
+ }
2294
+
2295
+ eio_req *eio_syncfs (int fd, int pri, eio_cb cb, void *data)
2296
+ {
2297
+ REQ (EIO_SYNCFS); req->int1 = fd; SEND;
2298
+ }
2299
+
2300
+ eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data)
2301
+ {
2302
+ REQ (EIO_SYNC_FILE_RANGE); req->int1 = fd; req->offs = offset; req->size = nbytes; req->int2 = flags; SEND;
2303
+ }
2304
+
2305
+ eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data)
2306
+ {
2307
+ REQ (EIO_MTOUCH); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND;
2308
+ }
2309
+
2310
+ eio_req *eio_mlock (void *addr, size_t length, int pri, eio_cb cb, void *data)
2311
+ {
2312
+ REQ (EIO_MLOCK); req->ptr2 = addr; req->size = length; SEND;
2313
+ }
2314
+
2315
+ eio_req *eio_mlockall (int flags, int pri, eio_cb cb, void *data)
2316
+ {
2317
+ REQ (EIO_MLOCKALL); req->int1 = flags; SEND;
2318
+ }
2319
+
2320
+ eio_req *eio_fallocate (int fd, int mode, off_t offset, size_t len, int pri, eio_cb cb, void *data)
2321
+ {
2322
+ REQ (EIO_FALLOCATE); req->int1 = fd; req->int2 = mode; req->offs = offset; req->size = len; SEND;
2323
+ }
2324
+
2325
+ eio_req *eio_close (int fd, int pri, eio_cb cb, void *data)
2326
+ {
2327
+ REQ (EIO_CLOSE); req->int1 = fd; SEND;
2328
+ }
2329
+
2330
+ eio_req *eio_readahead (int fd, off_t offset, size_t length, int pri, eio_cb cb, void *data)
2331
+ {
2332
+ REQ (EIO_READAHEAD); req->int1 = fd; req->offs = offset; req->size = length; SEND;
2333
+ }
2334
+
2335
+ eio_req *eio_read (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data)
2336
+ {
2337
+ REQ (EIO_READ); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = buf; SEND;
2338
+ }
2339
+
2340
+ eio_req *eio_write (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data)
2341
+ {
2342
+ REQ (EIO_WRITE); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = buf; SEND;
2343
+ }
2344
+
2345
+ eio_req *eio_fstat (int fd, int pri, eio_cb cb, void *data)
2346
+ {
2347
+ REQ (EIO_FSTAT); req->int1 = fd; SEND;
2348
+ }
2349
+
2350
+ eio_req *eio_fstatvfs (int fd, int pri, eio_cb cb, void *data)
2351
+ {
2352
+ REQ (EIO_FSTATVFS); req->int1 = fd; SEND;
2353
+ }
2354
+
2355
+ eio_req *eio_futime (int fd, double atime, double mtime, int pri, eio_cb cb, void *data)
2356
+ {
2357
+ REQ (EIO_FUTIME); req->int1 = fd; req->nv1 = atime; req->nv2 = mtime; SEND;
2358
+ }
2359
+
2360
+ eio_req *eio_ftruncate (int fd, off_t offset, int pri, eio_cb cb, void *data)
2361
+ {
2362
+ REQ (EIO_FTRUNCATE); req->int1 = fd; req->offs = offset; SEND;
2363
+ }
2364
+
2365
+ eio_req *eio_fchmod (int fd, eio_mode_t mode, int pri, eio_cb cb, void *data)
2366
+ {
2367
+ REQ (EIO_FCHMOD); req->int1 = fd; req->int2 = (long)mode; SEND;
2368
+ }
2369
+
2370
+ eio_req *eio_fchown (int fd, eio_uid_t uid, eio_gid_t gid, int pri, eio_cb cb, void *data)
2371
+ {
2372
+ REQ (EIO_FCHOWN); req->int1 = fd; req->int2 = (long)uid; req->int3 = (long)gid; SEND;
2373
+ }
2374
+
2375
+ eio_req *eio_dup2 (int fd, int fd2, int pri, eio_cb cb, void *data)
2376
+ {
2377
+ REQ (EIO_DUP2); req->int1 = fd; req->int2 = fd2; SEND;
2378
+ }
2379
+
2380
+ eio_req *eio_sendfile (int out_fd, int in_fd, off_t in_offset, size_t length, int pri, eio_cb cb, void *data)
2381
+ {
2382
+ REQ (EIO_SENDFILE); req->int1 = out_fd; req->int2 = in_fd; req->offs = in_offset; req->size = length; SEND;
2383
+ }
2384
+
2385
+ eio_req *eio_open (const char *path, int flags, eio_mode_t mode, int pri, eio_cb cb, void *data)
2386
+ {
2387
+ REQ (EIO_OPEN); PATH; req->int1 = flags; req->int2 = (long)mode; SEND;
2388
+ }
2389
+
2390
+ eio_req *eio_utime (const char *path, double atime, double mtime, int pri, eio_cb cb, void *data)
2391
+ {
2392
+ REQ (EIO_UTIME); PATH; req->nv1 = atime; req->nv2 = mtime; SEND;
2393
+ }
2394
+
2395
+ eio_req *eio_truncate (const char *path, off_t offset, int pri, eio_cb cb, void *data)
2396
+ {
2397
+ REQ (EIO_TRUNCATE); PATH; req->offs = offset; SEND;
2398
+ }
2399
+
2400
+ eio_req *eio_chown (const char *path, eio_uid_t uid, eio_gid_t gid, int pri, eio_cb cb, void *data)
2401
+ {
2402
+ REQ (EIO_CHOWN); PATH; req->int2 = (long)uid; req->int3 = (long)gid; SEND;
2403
+ }
2404
+
2405
+ eio_req *eio_chmod (const char *path, eio_mode_t mode, int pri, eio_cb cb, void *data)
2406
+ {
2407
+ REQ (EIO_CHMOD); PATH; req->int2 = (long)mode; SEND;
2408
+ }
2409
+
2410
+ eio_req *eio_mkdir (const char *path, eio_mode_t mode, int pri, eio_cb cb, void *data)
2411
+ {
2412
+ REQ (EIO_MKDIR); PATH; req->int2 = (long)mode; SEND;
2413
+ }
2414
+
2415
+ static eio_req *
2416
+ eio__1path (int type, const char *path, int pri, eio_cb cb, void *data)
2417
+ {
2418
+ REQ (type); PATH; SEND;
2419
+ }
2420
+
2421
+ eio_req *eio_readlink (const char *path, int pri, eio_cb cb, void *data)
2422
+ {
2423
+ return eio__1path (EIO_READLINK, path, pri, cb, data);
2424
+ }
2425
+
2426
+ eio_req *eio_realpath (const char *path, int pri, eio_cb cb, void *data)
2427
+ {
2428
+ return eio__1path (EIO_REALPATH, path, pri, cb, data);
2429
+ }
2430
+
2431
+ eio_req *eio_stat (const char *path, int pri, eio_cb cb, void *data)
2432
+ {
2433
+ return eio__1path (EIO_STAT, path, pri, cb, data);
2434
+ }
2435
+
2436
+ eio_req *eio_lstat (const char *path, int pri, eio_cb cb, void *data)
2437
+ {
2438
+ return eio__1path (EIO_LSTAT, path, pri, cb, data);
2439
+ }
2440
+
2441
+ eio_req *eio_statvfs (const char *path, int pri, eio_cb cb, void *data)
2442
+ {
2443
+ return eio__1path (EIO_STATVFS, path, pri, cb, data);
2444
+ }
2445
+
2446
+ eio_req *eio_unlink (const char *path, int pri, eio_cb cb, void *data)
2447
+ {
2448
+ return eio__1path (EIO_UNLINK, path, pri, cb, data);
2449
+ }
2450
+
2451
+ eio_req *eio_rmdir (const char *path, int pri, eio_cb cb, void *data)
2452
+ {
2453
+ return eio__1path (EIO_RMDIR, path, pri, cb, data);
2454
+ }
2455
+
2456
+ eio_req *eio_readdir (const char *path, int flags, int pri, eio_cb cb, void *data)
2457
+ {
2458
+ REQ (EIO_READDIR); PATH; req->int1 = flags; SEND;
2459
+ }
2460
+
2461
+ eio_req *eio_mknod (const char *path, eio_mode_t mode, dev_t dev, int pri, eio_cb cb, void *data)
2462
+ {
2463
+ REQ (EIO_MKNOD); PATH; req->int2 = (long)mode; req->offs = (off_t)dev; SEND;
2464
+ }
2465
+
2466
+ static eio_req *
2467
+ eio__2path (int type, const char *path, const char *new_path, int pri, eio_cb cb, void *data)
2468
+ {
2469
+ REQ (type); PATH;
2470
+
2471
+ req->flags |= EIO_FLAG_PTR2_FREE;
2472
+ req->ptr2 = strdup (new_path);
2473
+ if (!req->ptr2)
2474
+ {
2475
+ eio_api_destroy (req);
2476
+ return 0;
2477
+ }
2478
+
2479
+ SEND;
2480
+ }
2481
+
2482
+ eio_req *eio_link (const char *path, const char *new_path, int pri, eio_cb cb, void *data)
2483
+ {
2484
+ return eio__2path (EIO_LINK, path, new_path, pri, cb, data);
2485
+ }
2486
+
2487
+ eio_req *eio_symlink (const char *path, const char *new_path, int pri, eio_cb cb, void *data)
2488
+ {
2489
+ return eio__2path (EIO_SYMLINK, path, new_path, pri, cb, data);
2490
+ }
2491
+
2492
+ eio_req *eio_rename (const char *path, const char *new_path, int pri, eio_cb cb, void *data)
2493
+ {
2494
+ return eio__2path (EIO_RENAME, path, new_path, pri, cb, data);
2495
+ }
2496
+
2497
+ eio_req *eio_custom (void (*execute)(eio_req *), int pri, eio_cb cb, void *data)
2498
+ {
2499
+ REQ (EIO_CUSTOM); req->feed = execute; SEND;
2500
+ }
2501
+
2502
+ #endif
2503
+
2504
+ eio_req *eio_grp (eio_cb cb, void *data)
2505
+ {
2506
+ const int pri = EIO_PRI_MAX;
2507
+
2508
+ REQ (EIO_GROUP); SEND;
2509
+ }
2510
+
2511
+ #undef REQ
2512
+ #undef PATH
2513
+ #undef SEND
2514
+
2515
+ /*****************************************************************************/
2516
+ /* grp functions */
2517
+
2518
+ void
2519
+ eio_grp_feed (eio_req *grp, void (*feed)(eio_req *req), int limit)
2520
+ {
2521
+ grp->int2 = limit;
2522
+ grp->feed = feed;
2523
+
2524
+ grp_try_feed (grp);
2525
+ }
2526
+
2527
+ void
2528
+ eio_grp_limit (eio_req *grp, int limit)
2529
+ {
2530
+ grp->int2 = limit;
2531
+
2532
+ grp_try_feed (grp);
2533
+ }
2534
+
2535
+ void
2536
+ eio_grp_add (eio_req *grp, eio_req *req)
2537
+ {
2538
+ assert (("cannot add requests to IO::AIO::GRP after the group finished", grp->int1 != 2));
2539
+
2540
+ grp->flags |= EIO_FLAG_GROUPADD;
2541
+
2542
+ ++grp->size;
2543
+ req->grp = grp;
2544
+
2545
+ req->grp_prev = 0;
2546
+ req->grp_next = grp->grp_first;
2547
+
2548
+ if (grp->grp_first)
2549
+ grp->grp_first->grp_prev = req;
2550
+
2551
+ grp->grp_first = req;
2552
+ }
2553
+
2554
+ /*****************************************************************************/
2555
+ /* misc garbage */
2556
+
2557
+ eio_ssize_t
2558
+ eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count)
2559
+ {
2560
+ return eio__sendfile (ofd, ifd, offset, count);
2561
+ }
2562
+