jutil.cpp 92 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #ifdef _WIN32
  14. #pragma warning(disable: 4996)
  15. #include "winprocess.hpp"
  16. #include <conio.h>
  17. #endif
  18. #include "platform.h"
  19. #include "jmisc.hpp"
  20. #include "jutil.hpp"
  21. #include "jexcept.hpp"
  22. #include "jmutex.hpp"
  23. #include "jfile.hpp"
  24. #include "jprop.hpp"
  25. #include "jerror.hpp"
  26. #include "jencrypt.hpp"
  27. #include "jerror.hpp"
  28. #ifdef _WIN32
  29. #include <mmsystem.h> // for timeGetTime
  30. #include <float.h> //for _isnan and _fpclass
  31. #else
  32. #include <unistd.h> // read()
  33. #include <sys/wait.h>
  34. #include <pwd.h>
  35. #ifdef __linux__
  36. #include <crypt.h>
  37. #include <shadow.h>
  38. #endif
  39. #include <time.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <termios.h>
  43. #include <signal.h>
  44. #include <paths.h>
  45. #include <cmath>
  46. #include <string>
  47. #endif
  48. #include <limits.h>
  49. #include "build-config.h"
  50. #include "portlist.h"
  51. static NonReentrantSpinLock * cvtLock;
  52. #ifdef _WIN32
  53. static IRandomNumberGenerator * protectedGenerator;
  54. static CriticalSection * protectedGeneratorCs;
  55. #endif
  56. #if defined (__APPLE__)
  57. #include <mach-o/dyld.h>
  58. #include <mach/mach_time.h> /* mach_absolute_time */
  59. mach_timebase_info_data_t timebase_info = { 1,1 };
  60. #endif
  61. HPCCBuildInfo hpccBuildInfo;
  62. #define stringify(x) # x
  63. #define estringify(x) stringify(x)
  64. static void initBuildVars()
  65. {
  66. /* NB: picking up HPCC_BUILD_TAG from an environment variable is mainly so variants (like internal)
  67. * can customize the buildtag, which is shown in Eclwatch and logging.
  68. */
  69. hpccBuildInfo.buildTag = getenv("HPCC_BUILD_TAG");
  70. if (isEmptyString(hpccBuildInfo.buildTag))
  71. hpccBuildInfo.buildTag = BUILD_TAG;
  72. hpccBuildInfo.buildVersionMajor = BUILD_VERSION_MAJOR;
  73. hpccBuildInfo.buildVersionMinor = BUILD_VERSION_MINOR;
  74. hpccBuildInfo.buildVersionPoint = BUILD_VERSION_POINT;
  75. hpccBuildInfo.buildVersion = estringify(BUILD_VERSION_MAJOR) "." estringify(BUILD_VERSION_MINOR) "." estringify(BUILD_VERSION_POINT);
  76. hpccBuildInfo.dirName = DIR_NAME;
  77. hpccBuildInfo.prefix = PREFIX;
  78. hpccBuildInfo.execPrefix = EXEC_PREFIX;
  79. hpccBuildInfo.configPrefix = CONFIG_PREFIX;
  80. hpccBuildInfo.installDir = INSTALL_DIR;
  81. hpccBuildInfo.libDir = LIB_DIR;
  82. hpccBuildInfo.execDir = EXEC_DIR;
  83. hpccBuildInfo.componentDir = COMPONENTFILES_DIR;
  84. hpccBuildInfo.configDir = CONFIG_DIR;
  85. hpccBuildInfo.configSourceDir = CONFIG_SOURCE_DIR;
  86. hpccBuildInfo.adminDir = ADMIN_DIR;
  87. hpccBuildInfo.pluginsDir = PLUGINS_DIR;
  88. hpccBuildInfo.runtimeDir = RUNTIME_DIR;
  89. hpccBuildInfo.lockDir = LOCK_DIR;
  90. hpccBuildInfo.pidDir = PID_DIR;
  91. hpccBuildInfo.logDir = LOG_DIR;
  92. hpccBuildInfo.envXmlFile = ENV_XML_FILE;
  93. hpccBuildInfo.envConfFile = ENV_CONF_FILE;
  94. }
  95. MODULE_INIT(INIT_PRIORITY_SYSTEM)
  96. {
  97. cvtLock = new NonReentrantSpinLock;
  98. #ifdef _WIN32
  99. protectedGenerator = createRandomNumberGenerator();
  100. protectedGeneratorCs = new CriticalSection;
  101. #endif
  102. #if defined (__APPLE__)
  103. if (mach_timebase_info(&timebase_info) != KERN_SUCCESS)
  104. return false;
  105. #endif
  106. initBuildVars();
  107. return true;
  108. }
  109. MODULE_EXIT()
  110. {
  111. delete cvtLock;
  112. #ifdef _WIN32
  113. protectedGenerator->Release();
  114. delete protectedGeneratorCs;
  115. #endif
  116. }
  117. //===========================================================================
  118. bool safe_ecvt(size_t len, char * buffer, double value, int numDigits, int * decimal, int * sign)
  119. {
  120. #ifdef _WIN32
  121. return _ecvt_s(buffer, len, value, numDigits, decimal, sign) == 0;
  122. #else
  123. NonReentrantSpinBlock block(*cvtLock);
  124. const char * result = ecvt(value, numDigits, decimal, sign);
  125. if (!result)
  126. return false;
  127. strncpy(buffer, result, len);
  128. return true;
  129. #endif
  130. }
  131. bool safe_fcvt(size_t len, char * buffer, double value, int numPlaces, int * decimal, int * sign)
  132. {
  133. #ifdef _WIN32
  134. return _fcvt_s(buffer, len, value, numPlaces, decimal, sign) == 0;
  135. #else
  136. NonReentrantSpinBlock block(*cvtLock);
  137. const char * result = fcvt(value, numPlaces, decimal, sign);
  138. if (!result)
  139. return false;
  140. strncpy(buffer, result, len);
  141. return true;
  142. #endif
  143. }
  144. //===========================================================================
  145. bool j_isnan(double x)
  146. {
  147. #ifdef _MSC_VER
  148. return _isnan(x)!=0;
  149. #else
  150. return std::isnan(x);
  151. #endif
  152. }
  153. bool j_isinf(double x)
  154. {
  155. #ifdef _MSC_VER
  156. int fpv = _fpclass(x);
  157. return (fpv==_FPCLASS_PINF || fpv==_FPCLASS_NINF);
  158. #else
  159. return std::isinf(x);
  160. #endif
  161. }
  162. #ifdef _WIN32
  163. void MilliSleep(unsigned milli)
  164. {
  165. Sleep(milli);
  166. }
  167. #else
  168. void MilliSleep(unsigned milli)
  169. {
  170. if (milli) {
  171. unsigned target = msTick()+milli;
  172. for (;;) {
  173. timespec sleepTime;
  174. if (milli>=1000)
  175. {
  176. sleepTime.tv_sec = milli/1000;
  177. milli %= 1000;
  178. }
  179. else
  180. sleepTime.tv_sec = 0;
  181. sleepTime.tv_nsec = milli * 1000000;
  182. if (nanosleep(&sleepTime, NULL)==0)
  183. break;
  184. if (errno!=EINTR) {
  185. PROGLOG("MilliSleep err %d",errno);
  186. break;
  187. }
  188. milli = target-msTick();
  189. if ((int)milli<=0)
  190. break;
  191. }
  192. }
  193. else
  194. ThreadYield(); // 0 means yield
  195. }
  196. #endif
  197. long atolong_l(const char * s,int l)
  198. {
  199. char t[32];
  200. memcpy(t,s,l);
  201. t[l]=0;
  202. return atol(t);
  203. }
  204. int atoi_l(const char * s,int l)
  205. {
  206. char t[32];
  207. memcpy(t,s,l);
  208. t[l]=0;
  209. return atoi(t);
  210. }
  211. __int64 atoi64_l(const char * s,int l)
  212. {
  213. __int64 result = 0;
  214. char sign = '+';
  215. while (l>0 && isspace(*s))
  216. {
  217. l--;
  218. s++;
  219. }
  220. if (l>0 && (*s == '-' || *s == '+'))
  221. {
  222. sign = *s;
  223. l--;
  224. s++;
  225. }
  226. while (l>0 && isdigit(*s))
  227. {
  228. result = 10 * result + ((*s) - '0');
  229. l--;
  230. s++;
  231. }
  232. if (sign == '-')
  233. return -result;
  234. else
  235. return result;
  236. }
  237. #ifndef _WIN32
  238. static char *_itoa(unsigned long n, char *str, int b, bool sign)
  239. {
  240. char *s = str;
  241. if (sign)
  242. n = -n;
  243. do
  244. {
  245. byte d = n % b;
  246. *(s++) = d+((d<10)?'0':('a'-10));
  247. }
  248. while ((n /= b) > 0);
  249. if (sign)
  250. *(s++) = '-';
  251. *s = '\0';
  252. // reverse
  253. char *s2 = str;
  254. s--;
  255. while (s2<s)
  256. {
  257. char tc = *s2;
  258. *(s2++) = *s;
  259. *(s--) = tc;
  260. }
  261. return str;
  262. }
  263. char *itoa(int n, char *str, int b)
  264. {
  265. return _itoa(n, str, b, (n<0));
  266. }
  267. char *ltoa(long n, char *str, int b)
  268. {
  269. return _itoa(n, str, b, (n<0));
  270. }
  271. char *ultoa(unsigned long n, char *str, int b)
  272. {
  273. return _itoa(n, str, b, false);
  274. }
  275. #endif
  276. void packNumber(char * target, const char * source, unsigned slen)
  277. {
  278. unsigned next = 0;
  279. while (slen)
  280. {
  281. unsigned c = *source++;
  282. if (c == ' ') c = '0';
  283. next = (next << 4) + (c - '0');
  284. slen--;
  285. if ((slen & 1) == 0)
  286. {
  287. *target++ = next;
  288. next = 0;
  289. }
  290. }
  291. }
  292. void unpackNumber(char * target, const char * source, unsigned tlen)
  293. {
  294. if (tlen & 1)
  295. {
  296. *target = '0' + *source++;
  297. tlen--;
  298. }
  299. while (tlen)
  300. {
  301. unsigned char next = *source++;
  302. *target++ = (next >> 4) + '0';
  303. *target++ = (next & 15) + '0';
  304. tlen -= 2;
  305. }
  306. }
  307. //-----------------------------------------------------------------------
  308. class jlib_thrown_decl CorruptDllException : public CInterfaceOf<ICorruptDllException>
  309. {
  310. public:
  311. CorruptDllException(int code, const char *_dllName, const char *_dlError)
  312. : errcode(code)
  313. {
  314. VStringBuffer s("Error loading %s: %s", _dllName, _dlError);
  315. msg.set(s.str());
  316. };
  317. int errorCode() const { return errcode; }
  318. StringBuffer & errorMessage(StringBuffer &str) const
  319. {
  320. return str.append(msg.get());
  321. }
  322. MessageAudience errorAudience() const
  323. {
  324. return MSGAUD_operator;
  325. }
  326. private:
  327. int errcode;
  328. StringAttr msg;
  329. };
  330. static bool isCorruptDll(const char *errorMessage)
  331. {
  332. // yuk.
  333. // Add other error strings for corrupt .so files as/when we encounter them
  334. if (strstr(errorMessage, "file too short") ||
  335. strstr(errorMessage, "ELF load command past end of file"))
  336. return true;
  337. return false;
  338. }
  339. //-----------------------------------------------------------------------
  340. #ifdef __APPLE__
  341. bool findLoadedModule(StringBuffer &ret, const char *match)
  342. {
  343. bool found = false;
  344. unsigned count = _dyld_image_count();
  345. for (unsigned i = 0; i<count; i++)
  346. {
  347. const char *ln = _dyld_get_image_name(i);
  348. if (ln)
  349. {
  350. if (strstr(ln, match))
  351. {
  352. ret.set(ln);
  353. found = true;
  354. break;
  355. }
  356. }
  357. }
  358. return found;
  359. }
  360. #elif !defined(WIN32)
  361. bool findLoadedModule(StringBuffer &ret, const char *match)
  362. {
  363. bool found = false;
  364. FILE *diskfp = fopen("/proc/self/maps", "r");
  365. if (diskfp)
  366. {
  367. char ln[_MAX_PATH];
  368. while (fgets(ln, sizeof(ln), diskfp))
  369. {
  370. if (strstr(ln, match))
  371. {
  372. const char *fullName = strchr(ln, '/');
  373. if (fullName)
  374. {
  375. char * lf = (char *) strchr(fullName, '\n');
  376. if (lf)
  377. {
  378. *lf = 0;
  379. ret.set(fullName);
  380. found = true;
  381. break;
  382. }
  383. }
  384. }
  385. }
  386. fclose(diskfp);
  387. }
  388. return found;
  389. }
  390. #endif
  391. HINSTANCE LoadSharedObject(const char *name, bool isGlobal, bool raiseOnError)
  392. {
  393. #if defined(_WIN32)
  394. UINT oldMode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
  395. #else
  396. // don't think anything to do here.
  397. #endif
  398. DynamicScopeCtx scope;
  399. StringBuffer tmp;
  400. if (name&&isPathSepChar(*name)&&isPathSepChar(name[1])) {
  401. RemoteFilename rfn;
  402. rfn.setRemotePath(name);
  403. if (!rfn.isLocal()) {
  404. // I guess could copy to a temporary location but currently just fail
  405. throw MakeStringException(-1,"LoadSharedObject: %s is not a local file",name);
  406. }
  407. name = rfn.getLocalPath(tmp).str();
  408. }
  409. #if defined(_WIN32)
  410. HINSTANCE h = LoadLibrary(name);
  411. if (!LoadSucceeded(h))
  412. {
  413. int errcode = GetLastError();
  414. StringBuffer errmsg;
  415. formatSystemError(errmsg, errcode);
  416. //Strip trailing newlines - makes output/errors messages cleaner
  417. unsigned len = errmsg.length();
  418. while (len)
  419. {
  420. char c = errmsg.charAt(len-1);
  421. if ((c != '\r') && (c != '\n'))
  422. break;
  423. len--;
  424. }
  425. errmsg.setLength(len);
  426. DBGLOG("Error loading %s: %d - %s", name, errcode, errmsg.str());
  427. if (raiseOnError)
  428. throw MakeStringException(0, "Error loading %s: %d - %s", name, errcode, errmsg.str());
  429. }
  430. #else
  431. HINSTANCE h = dlopen((char *)name, isGlobal ? RTLD_NOW|RTLD_GLOBAL : RTLD_NOW);
  432. if(h == NULL)
  433. {
  434. // Try again, with .so extension if necessary
  435. StringBuffer path, tail, ext;
  436. splitFilename(name, &path, &path, &tail, &ext, false);
  437. if (!streq(ext.str(), SharedObjectExtension))
  438. {
  439. // Assume if there's no .so, there may also be no lib at the beginning
  440. if (strncmp(tail.str(), SharedObjectPrefix, strlen(SharedObjectPrefix)) != 0)
  441. path.append(SharedObjectPrefix);
  442. path.append(tail).append(ext).append(SharedObjectExtension);
  443. name = path.str();
  444. h = dlopen((char *)name, isGlobal ? RTLD_NOW|RTLD_GLOBAL : RTLD_NOW);
  445. }
  446. if (h == NULL)
  447. {
  448. StringBuffer dlErrorMsg(dlerror());
  449. OWARNLOG("Warning: Could not load %s: %s", name, dlErrorMsg.str());
  450. if (raiseOnError)
  451. {
  452. if (isCorruptDll(dlErrorMsg.str()))
  453. throw new CorruptDllException(errno, name, dlErrorMsg.str());
  454. else
  455. throw MakeStringException(0, "Error loading %s: %s", name, dlErrorMsg.str());
  456. }
  457. }
  458. }
  459. #endif
  460. #if defined(_WIN32)
  461. SetErrorMode(oldMode);
  462. #else
  463. // don't think anything to do here.
  464. #endif
  465. scope.processInitialization(h);
  466. return h;
  467. }
  468. void FreeSharedObject(HINSTANCE h)
  469. {
  470. ExitModuleObjects(h);
  471. #if defined(_WIN32)
  472. FreeLibrary(h);
  473. #else
  474. dlclose(h);
  475. #endif
  476. }
  477. bool SharedObject::load(const char * dllName, bool isGlobal, bool raiseOnError)
  478. {
  479. unload();
  480. #ifdef _WIN32
  481. UINT oldMode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
  482. if (dllName)
  483. {
  484. h=LoadSharedObject(dllName, isGlobal, raiseOnError);
  485. bRefCounted = true;
  486. }
  487. else
  488. {
  489. h=GetModuleHandle(NULL);
  490. bRefCounted = false;
  491. }
  492. SetErrorMode(oldMode);
  493. #else
  494. h=LoadSharedObject(dllName, isGlobal, raiseOnError);
  495. bRefCounted = true;
  496. #endif
  497. if (!LoadSucceeded(h))
  498. {
  499. h = 0;
  500. return false;
  501. }
  502. return true;
  503. }
  504. bool SharedObject::loadCurrentExecutable()
  505. {
  506. unload();
  507. #ifdef _WIN32
  508. h=GetModuleHandle(NULL);
  509. bRefCounted = false;
  510. #else
  511. h=dlopen(NULL, RTLD_NOW);
  512. bRefCounted = true;
  513. #endif
  514. return true;
  515. }
  516. bool SharedObject::loadResources(const char * dllName)
  517. {
  518. #ifdef _WIN32
  519. UINT oldMode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
  520. h = LoadLibraryEx(dllName, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
  521. if (!LoadSucceeded(h))
  522. h = LoadLibraryEx(dllName, NULL, LOAD_LIBRARY_AS_DATAFILE); // the LOAD_LIBRARY_AS_IMAGE_RESOURCE flag is not supported on all versions of Windows
  523. SetErrorMode(oldMode);
  524. return LoadSucceeded(h);
  525. #else
  526. UNIMPLEMENTED;
  527. #endif
  528. }
  529. void *SharedObject::getEntry(const char * name) const
  530. {
  531. return GetSharedProcedure(getInstanceHandle(), name);
  532. }
  533. void SharedObject::unload()
  534. {
  535. if (h && bRefCounted) FreeSharedObject(h);
  536. h = 0;
  537. }
  538. //-----------------------------------------------------------------------
  539. IPluggableFactory *loadPlugin(const IPropertyTree *pluginInfo)
  540. {
  541. const char *pluginName = pluginInfo->queryProp("@pluginName");
  542. const char *entrypoint = pluginInfo->queryProp("@entrypoint");
  543. if (!pluginName || !entrypoint)
  544. throw makeStringException(0, "Plugin information missing plugin name or entrypoint");
  545. Owned<SharedObject> pluginDll = new SharedObject;
  546. if (!pluginDll->load(pluginName, false, true))
  547. throw makeStringExceptionV(0, "Failed to load plugin %s", pluginName);
  548. IPluggableFactoryFactory pf = (IPluggableFactoryFactory) pluginDll->getEntry(entrypoint);
  549. if (!pf)
  550. throw makeStringExceptionV(0, "Function %s not found in plugin %s", entrypoint, pluginName);
  551. IPluggableFactory *factory = pf(pluginDll, pluginInfo);
  552. if (!factory)
  553. throw makeStringExceptionV(0, "Factory function %s returned NULL in plugin %s", entrypoint, pluginName);
  554. return factory;
  555. }
  556. //-----------------------------------------------------------------------
  557. /*
  558. We use a 64 bit number for generating temporaries so that we are unlikely to get any
  559. clashes (being paranoid). This should mean if a temporary ID is allocated 1,000,000,000
  560. times a second, then we won't repeat until 400 years later - assuming the machine stays
  561. alive for that long.
  562. Using a 32 bit number we loop after about an hour if we allocated 1,000,000 a second -
  563. not an unreasonable estimate for the future.
  564. */
  565. static unique_id_t nextTemporaryId;
  566. StringBuffer & appendUniqueId(StringBuffer & target, unique_id_t value)
  567. {
  568. //Just generate a temporary name from the __int64 -
  569. //Don't care about the format, therfore use base 32 in reverse order.
  570. while (value)
  571. {
  572. unsigned next = ((unsigned)value) & 31;
  573. value = value >> 5;
  574. if (next < 10)
  575. target.append((char)(next+'0'));
  576. else
  577. target.append((char)(next+'A'-10));
  578. }
  579. return target;
  580. }
  581. unique_id_t getUniqueId()
  582. {
  583. return ++nextTemporaryId;
  584. }
  585. StringBuffer & getUniqueId(StringBuffer & target)
  586. {
  587. return appendUniqueId(target, ++nextTemporaryId);
  588. }
  589. void resetUniqueId()
  590. {
  591. nextTemporaryId = 0;
  592. }
  593. //-----------------------------------------------------------------------
  594. #define make_numtostr(VTYPE) \
  595. int numtostr(char *dst, signed VTYPE _value) \
  596. { \
  597. int c; \
  598. unsigned VTYPE value; \
  599. if (_value<0) \
  600. { \
  601. *(dst++) = '-'; \
  602. value = (unsigned VTYPE) -_value; \
  603. c = 1; \
  604. } \
  605. else \
  606. { \
  607. c = 0; \
  608. value = _value; \
  609. } \
  610. char temp[11], *end = temp+10; \
  611. char *tmp = end; \
  612. *tmp = '\0'; \
  613. \
  614. while (value>=10) \
  615. { \
  616. unsigned VTYPE next = value / 10; \
  617. *(--tmp) = ((char)(value-next*10))+'0'; \
  618. value = next; \
  619. } \
  620. *(--tmp) = ((char)value)+'0'; \
  621. \
  622. int diff = (int)(end-tmp); \
  623. int i=diff+1; \
  624. while (i--) *(dst++) = *(tmp++); \
  625. \
  626. return c+diff; \
  627. }
  628. #define make_unumtostr(VTYPE) \
  629. int numtostr(char *dst, unsigned VTYPE value) \
  630. { \
  631. char temp[11], *end = temp+10; \
  632. char *tmp = end; \
  633. *tmp = '\0'; \
  634. \
  635. while (value>=10) \
  636. { \
  637. unsigned VTYPE next = value / 10; \
  638. *(--tmp) = ((char)(value-next*10))+'0'; \
  639. value = next; \
  640. } \
  641. *(--tmp) = ((char)value)+'0'; \
  642. \
  643. int diff = (int)(end-tmp); \
  644. int i=diff+1; \
  645. while (i--) *(dst++) = *(tmp++); \
  646. \
  647. return diff; \
  648. }
  649. make_numtostr(char);
  650. make_numtostr(short);
  651. make_numtostr(int);
  652. make_numtostr(long);
  653. make_unumtostr(char);
  654. make_unumtostr(short);
  655. make_unumtostr(int);
  656. make_unumtostr(long);
  657. NO_SANITIZE("signed-integer-overflow") int numtostr(char *dst, __int64 _value)
  658. {
  659. int c;
  660. unsigned __int64 value;
  661. if (_value<0)
  662. {
  663. *(dst++) = '-';
  664. value = (unsigned __int64) -_value; // This can overflow and thus behaviour is theoretically undefined.
  665. c = 1;
  666. }
  667. else
  668. {
  669. value = _value;
  670. c = 0;
  671. }
  672. char temp[24], *end = temp+23, *tmp = end;
  673. *tmp = '\0';
  674. unsigned __int32 v3 = (unsigned __int32)(value / LLC(10000000000));
  675. unsigned __int64 vv = value - ((unsigned __int64)v3*LLC(10000000000));
  676. unsigned __int32 v2 = (unsigned __int32)(vv / 100000);
  677. unsigned __int32 v1 = (unsigned __int32) (vv - (v2 * 100000));
  678. unsigned __int32 next;
  679. while (v1>=10)
  680. {
  681. next = v1/10;
  682. *(--tmp) = ((char)(v1-next*10))+'0';
  683. v1 = next;
  684. }
  685. *(--tmp) = ((char)v1)+'0';
  686. if (v2)
  687. {
  688. char *d = end-5;
  689. while (d != tmp)
  690. *(--tmp) = '0';
  691. while (v2>=10)
  692. {
  693. next = v2/10;
  694. *(--tmp) = ((char)(v2-next*10))+'0';
  695. v2 = next;
  696. }
  697. *(--tmp) = ((char)v2)+'0';
  698. }
  699. if (v3)
  700. {
  701. char *d = end-10;
  702. while (d != tmp)
  703. *(--tmp) = '0';
  704. while (v3>=10)
  705. {
  706. next = v3/10;
  707. *(--tmp) = ((char)(v3-next*10))+'0';
  708. v3 = next;
  709. }
  710. *(--tmp) = ((char)v3)+'0';
  711. }
  712. int diff = (int)(end-tmp);
  713. #ifdef USEMEMCPY
  714. memcpy(dst, tmp, diff+1);
  715. #else
  716. int i=diff+1;
  717. while (i--)
  718. { *(dst++) = *(tmp++);
  719. }
  720. #endif
  721. return c+diff;
  722. }
  723. int numtostr(char *dst, unsigned __int64 value)
  724. {
  725. char temp[24], *end = temp+23, *tmp = end;
  726. *tmp = '\0';
  727. unsigned __int32 v3 = (unsigned __int32)(value / LLC(10000000000));
  728. unsigned __int64 vv = value - ((unsigned __int64)v3*LLC(10000000000));
  729. unsigned __int32 v2 = (unsigned __int32)(vv / 100000);
  730. unsigned __int32 v1 = (unsigned __int32) (vv - (v2 * 100000));
  731. unsigned __int32 next;
  732. while (v1>=10)
  733. {
  734. next = v1/10;
  735. *(--tmp) = ((char)(v1-next*10))+'0';
  736. v1 = next;
  737. }
  738. *(--tmp) = ((char)v1)+'0';
  739. if (v2)
  740. {
  741. char *d = end-5;
  742. while (d != tmp)
  743. *(--tmp) = '0';
  744. while (v2>=10)
  745. {
  746. next = v2/10;
  747. *(--tmp) = ((char)(v2-next*10))+'0';
  748. v2 = next;
  749. }
  750. *(--tmp) = ((char)v2)+'0';
  751. }
  752. if (v3)
  753. {
  754. char *d = end-10;
  755. while (d != tmp)
  756. *(--tmp) = '0';
  757. while (v3>=10)
  758. {
  759. next = v3/10;
  760. *(--tmp) = ((char)(v3-next*10))+'0';
  761. v3 = next;
  762. }
  763. *(--tmp) = ((char)v3)+'0';
  764. }
  765. int diff = (int)(end-tmp);
  766. #ifdef USEMEMCPY
  767. memcpy(dst, tmp, diff+1);
  768. #else
  769. int i=diff+1;
  770. while (i--)
  771. { *(dst++) = *(tmp++);
  772. }
  773. #endif
  774. return diff;
  775. }
  776. class CRandom: public IRandomNumberGenerator, public CInterface
  777. {
  778. // from Knuth if I remember correctly
  779. #define HISTORYSIZE 55
  780. #define HISTORYMAX (HISTORYSIZE-1)
  781. unsigned history[HISTORYSIZE];
  782. unsigned ptr;
  783. unsigned lower;
  784. public:
  785. IMPLEMENT_IINTERFACE;
  786. CRandom()
  787. {
  788. seed((unsigned)get_cycles_now());
  789. }
  790. void seed(unsigned su)
  791. {
  792. ptr = HISTORYMAX;
  793. lower = 23;
  794. double s = 91648253+su;
  795. double a = 1389796;
  796. double m = 2147483647;
  797. unsigned i;
  798. for (i=0;i<HISTORYSIZE;i++) { // just used for initialization
  799. s *= a;
  800. int q = (int)(s/m);
  801. s -= q*m;
  802. history[i] = (unsigned)s;
  803. }
  804. }
  805. unsigned next()
  806. {
  807. if (ptr==0) {
  808. ptr = HISTORYMAX;
  809. lower--;
  810. }
  811. else {
  812. ptr--;
  813. if (lower==0)
  814. lower = HISTORYMAX;
  815. else
  816. lower--;
  817. }
  818. unsigned ret = history[ptr]+history[lower];
  819. history[ptr] = ret;
  820. return ret;
  821. }
  822. } RandomMain;
  823. static CriticalSection gobalRandomSect;
  824. unsigned getRandom()
  825. {
  826. CriticalBlock block(gobalRandomSect); // this is a shame but it is not thread-safe without
  827. return RandomMain.next();
  828. }
  829. void seedRandom(unsigned seed)
  830. {
  831. CriticalBlock block(gobalRandomSect);
  832. RandomMain.seed(seed);
  833. }
  834. IRandomNumberGenerator *createRandomNumberGenerator()
  835. {
  836. return new CRandom();
  837. }
  838. void fillRandomData(size32_t writeSz, void *_writePtr)
  839. {
  840. static thread_local Owned<IRandomNumberGenerator> generator = createRandomNumberGenerator();
  841. unsigned *writePtr = (unsigned *)_writePtr;
  842. unsigned *bufEnd = (unsigned *)(((byte *)writePtr)+writeSz);
  843. while (true)
  844. {
  845. size32_t diff = (const byte *)bufEnd - (const byte *)writePtr;
  846. unsigned r = generator->next();
  847. if (diff<sizeof(unsigned))
  848. {
  849. // last few bytes
  850. byte *p = (byte *)writePtr;
  851. while (diff--)
  852. {
  853. *p++ = r & 0xff;
  854. r >>= 8;
  855. }
  856. break;
  857. }
  858. *writePtr++ = r;
  859. }
  860. }
  861. void fillRandomData(size32_t writeSz, MemoryBuffer &mb)
  862. {
  863. void *writePtr = mb.reserveTruncate(writeSz);
  864. fillRandomData(writeSz, writePtr);
  865. }
  866. #ifdef WIN32
  867. // This function has the same prototype for rand_r, but seed is ignored.
  868. jlib_decl int rand_r(unsigned int *seed)
  869. {
  870. CriticalBlock procedure(*protectedGeneratorCs);
  871. return (protectedGenerator->next() & RAND_R_MAX);
  872. }
  873. #if ((RAND_R_MAX & (RAND_R_MAX+1)) != 0)
  874. #error RAND_R_MAX expected to be 2^n-1
  875. #endif
  876. #endif
  877. class CShuffledIterator: implements IShuffledIterator, public CInterface
  878. {
  879. CRandom rand;
  880. unsigned *seq;
  881. unsigned idx;
  882. unsigned num;
  883. public:
  884. IMPLEMENT_IINTERFACE;
  885. CShuffledIterator(unsigned _num)
  886. {
  887. num = _num;
  888. idx = 0;
  889. seq = NULL;
  890. }
  891. ~CShuffledIterator()
  892. {
  893. delete [] seq;
  894. }
  895. bool first()
  896. {
  897. if (!seq)
  898. seq = new unsigned[num];
  899. idx = 0;
  900. if (!num)
  901. return false;
  902. unsigned i;
  903. for (i=0;i<num;i++)
  904. seq[i] = i;
  905. while (i>1) {
  906. unsigned j = rand.next()%i; // NB i is correct here
  907. i--;
  908. unsigned t = seq[j];
  909. seq[j] = seq[i];
  910. seq[i] = t;
  911. }
  912. return true;
  913. }
  914. bool isValid()
  915. {
  916. return idx<num;
  917. }
  918. bool next()
  919. {
  920. if (idx<num)
  921. idx++;
  922. return isValid();
  923. }
  924. unsigned get()
  925. {
  926. return lookup(idx);
  927. }
  928. unsigned lookup(unsigned i)
  929. {
  930. if (!seq)
  931. first();
  932. return seq[i%num];
  933. }
  934. void seed(unsigned su)
  935. {
  936. rand.seed(su);
  937. }
  938. };
  939. extern jlib_decl IShuffledIterator *createShuffledIterator(unsigned n)
  940. {
  941. return new CShuffledIterator(n);
  942. }
  943. /* Check whether a string is a valid C identifier. */
  944. bool isCIdentifier(const char* id)
  945. {
  946. if (id==NULL || *id==0)
  947. return false;
  948. if (!isalpha(*id) && *id!='_')
  949. return false;
  950. for (++id; *id != 0; id++)
  951. if (!isalnum(*id) && *id!='_')
  952. return false;
  953. return true;
  954. }
  955. //-------------------------------------------------------------------
  956. static const char BASE64_enc[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  957. "abcdefghijklmnopqrstuvwxyz"
  958. "0123456789+/";
  959. static const unsigned char BASE64_dec[256] =
  960. {
  961. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  962. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  963. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3f,
  964. 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  965. 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
  966. 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
  967. 0x00, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
  968. 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
  969. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  970. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  971. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  972. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  973. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  974. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  975. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  976. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  977. static const char pad = '=';
  978. //
  979. // Encode the input in a base64 format
  980. //
  981. // const void * data -> data to be encoded
  982. // long length -> length in bytes of this data
  983. // IIOStream &out -> Write the result into this stream
  984. //
  985. void JBASE64_Encode(const void *data, long length, IIOStream &out, bool addLineBreaks)
  986. {
  987. const unsigned char *in = static_cast<const unsigned char *>(data);
  988. unsigned char one;
  989. unsigned char two;
  990. unsigned char three;
  991. long i;
  992. for(i = 0; i < length && length - i >= 3;)
  993. {
  994. one = *(in + i++);
  995. two = *(in + i++);
  996. three = *(in + i++);
  997. // 0x30 -> 0011 0000 b
  998. // 0x3c -> 0011 1100 b
  999. // 0x3f -> 0011 1111 b
  1000. //
  1001. writeCharToStream(out, BASE64_enc[one >> 2]);
  1002. writeCharToStream(out, BASE64_enc[((one << 4) & 0x30) | (two >> 4)]);
  1003. writeCharToStream(out, BASE64_enc[((two << 2) & 0x3c) | (three >> 6)]);
  1004. writeCharToStream(out, BASE64_enc[three & 0x3f]);
  1005. if(addLineBreaks && (i % 54 == 0))
  1006. {
  1007. writeCharToStream(out, '\n');
  1008. }
  1009. }
  1010. switch(length - i)
  1011. {
  1012. case 2:
  1013. one = *(in + i++);
  1014. two = *(in + i++);
  1015. writeCharToStream(out, BASE64_enc[one >> 2]);
  1016. writeCharToStream(out, BASE64_enc[((one << 4) & 0x30) | (two >> 4)]);
  1017. writeCharToStream(out, BASE64_enc[(two << 2) & 0x3c]);
  1018. writeCharToStream(out, pad);
  1019. break;
  1020. case 1:
  1021. one = *(in + i++);
  1022. writeCharToStream(out, BASE64_enc[one >> 2]);
  1023. writeCharToStream(out, BASE64_enc[(one << 4) & 0x30]);
  1024. writeCharToStream(out, pad);
  1025. writeCharToStream(out, pad);
  1026. break;
  1027. }
  1028. }
  1029. // JCSMORE could have IIOStream StringBuffer adapter inplace of below.
  1030. void JBASE64_Encode(const void *data, long length, StringBuffer &out, bool addLineBreaks)
  1031. {
  1032. const unsigned char *in = static_cast<const unsigned char *>(data);
  1033. unsigned char one;
  1034. unsigned char two;
  1035. unsigned char three;
  1036. long i;
  1037. for(i = 0; i < length && length - i >= 3;)
  1038. {
  1039. one = *(in + i++);
  1040. two = *(in + i++);
  1041. three = *(in + i++);
  1042. // 0x30 -> 0011 0000 b
  1043. // 0x3c -> 0011 1100 b
  1044. // 0x3f -> 0011 1111 b
  1045. //
  1046. out.append(BASE64_enc[one >> 2]);
  1047. out.append(BASE64_enc[((one << 4) & 0x30) | (two >> 4)]);
  1048. out.append(BASE64_enc[((two << 2) & 0x3c) | (three >> 6)]);
  1049. out.append(BASE64_enc[three & 0x3f]);
  1050. if(addLineBreaks && (i % 54 == 0))
  1051. {
  1052. out.append('\n');
  1053. }
  1054. }
  1055. switch(length - i)
  1056. {
  1057. case 2:
  1058. one = *(in + i++);
  1059. two = *(in + i++);
  1060. out.append(BASE64_enc[one >> 2]);
  1061. out.append(BASE64_enc[((one << 4) & 0x30) | (two >> 4)]);
  1062. out.append(BASE64_enc[(two << 2) & 0x3c]);
  1063. out.append(pad);
  1064. break;
  1065. case 1:
  1066. one = *(in + i++);
  1067. out.append(BASE64_enc[one >> 2]);
  1068. out.append(BASE64_enc[(one << 4) & 0x30]);
  1069. out.append(pad);
  1070. out.append(pad);
  1071. break;
  1072. }
  1073. }
  1074. //
  1075. // Decode the input in a base64 format
  1076. //
  1077. // const char *in -> The string to be decoded
  1078. // StringBuffer & out -> Decoded string here
  1079. //
  1080. StringBuffer &JBASE64_Decode(ISimpleReadStream &in, StringBuffer &out)
  1081. {
  1082. unsigned char c1, cs[3];
  1083. unsigned char &c2 = *cs;
  1084. unsigned char &c3 = *(cs+1);
  1085. unsigned char &c4 = *(cs+2);
  1086. unsigned char d1, d2, d3, d4;
  1087. for(;;)
  1088. {
  1089. if (in.read(1, &c1))
  1090. break;
  1091. if (!c1)
  1092. break;
  1093. else if (!isspace(c1))
  1094. {
  1095. in.read(3, cs);
  1096. d1 = BASE64_dec[c1];
  1097. d2 = BASE64_dec[c2];
  1098. d3 = BASE64_dec[c3];
  1099. d4 = BASE64_dec[c4];
  1100. out.append((char)((d1 << 2) | (d2 >> 4)));
  1101. if(c3 == pad)
  1102. break;
  1103. out.append((char)((d2 << 4) | (d3 >> 2)));
  1104. if(c4 == pad)
  1105. break;
  1106. out.append((char)((d3 << 6) | d4));
  1107. }
  1108. }
  1109. return out;
  1110. }
  1111. MemoryBuffer &JBASE64_Decode(ISimpleReadStream &in, MemoryBuffer &out)
  1112. {
  1113. unsigned char c1, cs[3];
  1114. unsigned char &c2 = *cs;
  1115. unsigned char &c3 = *(cs+1);
  1116. unsigned char &c4 = *(cs+2);
  1117. unsigned char d1, d2, d3, d4;
  1118. for(;;)
  1119. {
  1120. if (in.read(1, &c1) != 1)
  1121. break;
  1122. if (!c1)
  1123. break;
  1124. else if (!isspace(c1))
  1125. {
  1126. in.read(3, cs);
  1127. d1 = BASE64_dec[c1];
  1128. d2 = BASE64_dec[c2];
  1129. d3 = BASE64_dec[c3];
  1130. d4 = BASE64_dec[c4];
  1131. out.append((char)((d1 << 2) | (d2 >> 4)));
  1132. if(c3 == pad)
  1133. break;
  1134. out.append((char)((d2 << 4) | (d3 >> 2)));
  1135. if(c4 == pad)
  1136. break;
  1137. out.append((char)((d3 << 6) | d4));
  1138. }
  1139. }
  1140. return out;
  1141. }
  1142. StringBuffer &JBASE64_Decode(const char *incs, StringBuffer &out)
  1143. {
  1144. unsigned char c1, c2, c3, c4;
  1145. unsigned char d1, d2, d3, d4;
  1146. for(;;)
  1147. {
  1148. c1 = *incs++;
  1149. if (!c1)
  1150. break;
  1151. else if (!isspace(c1))
  1152. {
  1153. c2 = *incs++;
  1154. c3 = *incs++;
  1155. c4 = *incs++;
  1156. d1 = BASE64_dec[c1];
  1157. d2 = BASE64_dec[c2];
  1158. d3 = BASE64_dec[c3];
  1159. d4 = BASE64_dec[c4];
  1160. out.append((char)((d1 << 2) | (d2 >> 4)));
  1161. if(c3 == pad)
  1162. break;
  1163. out.append((char)((d2 << 4) | (d3 >> 2)));
  1164. if(c4 == pad)
  1165. break;
  1166. out.append((char)((d3 << 6) | d4));
  1167. }
  1168. }
  1169. return out;
  1170. }
  1171. MemoryBuffer &JBASE64_Decode(const char *incs, MemoryBuffer &out)
  1172. {
  1173. unsigned char c1, c2, c3, c4;
  1174. unsigned char d1, d2, d3, d4;
  1175. for(;;)
  1176. {
  1177. c1 = *incs++;
  1178. if (!c1)
  1179. break;
  1180. else if (!isspace(c1))
  1181. {
  1182. c2 = *incs++;
  1183. c3 = *incs++;
  1184. c4 = *incs++;
  1185. d1 = BASE64_dec[c1];
  1186. d2 = BASE64_dec[c2];
  1187. d3 = BASE64_dec[c3];
  1188. d4 = BASE64_dec[c4];
  1189. out.append((char)((d1 << 2) | (d2 >> 4)));
  1190. if(c3 == pad)
  1191. break;
  1192. out.append((char)((d2 << 4) | (d3 >> 2)));
  1193. if(c4 == pad)
  1194. break;
  1195. out.append((char)((d3 << 6) | d4));
  1196. }
  1197. }
  1198. return out;
  1199. }
  1200. bool JBASE64_Decode(size32_t length, const char *incs, StringBuffer &out)
  1201. {
  1202. out.ensureCapacity(((length / 4) + 1) * 3);
  1203. const char * end = incs + length;
  1204. unsigned char c1;
  1205. unsigned char c[4];
  1206. unsigned cIndex = 0;
  1207. unsigned char d1, d2, d3, d4;
  1208. bool fullQuartetDecoded = false;
  1209. while (incs < end)
  1210. {
  1211. c1 = *incs++;
  1212. if (isspace(c1))
  1213. continue;
  1214. if (!BASE64_dec[c1] && ('A' != c1) && (pad != c1))
  1215. {
  1216. // Forbidden char
  1217. fullQuartetDecoded = false;
  1218. break;
  1219. }
  1220. c[cIndex++] = c1;
  1221. fullQuartetDecoded = false;
  1222. if (4 == cIndex)
  1223. {
  1224. d1 = BASE64_dec[c[0]];
  1225. d2 = BASE64_dec[c[1]];
  1226. d3 = BASE64_dec[c[2]];
  1227. d4 = BASE64_dec[c[3]];
  1228. out.append((char)((d1 << 2) | (d2 >> 4)));
  1229. fullQuartetDecoded = true;
  1230. if (pad == c[2])
  1231. break;
  1232. out.append((char)((d2 << 4) | (d3 >> 2)));
  1233. if( pad == c[3])
  1234. break;
  1235. out.append((char)((d3 << 6) | d4));
  1236. cIndex = 0;
  1237. }
  1238. }
  1239. return fullQuartetDecoded;
  1240. }
  1241. static const char enc32[33] =
  1242. "abcdefghijklmnopqrstuvwxyz"
  1243. "234567";
  1244. static inline void encode5_32(const byte *in,StringBuffer &out)
  1245. {
  1246. // 5 bytes in 8 out
  1247. out.append(enc32[(in[0] >> 3)]);
  1248. out.append(enc32[((in[0] & 0x07) << 2) | (in[1] >> 6)]);
  1249. out.append(enc32[(in[1] >> 1) & 0x1f]);
  1250. out.append(enc32[((in[1] & 0x01) << 4) | (in[2] >> 4)]);
  1251. out.append(enc32[((in[2] & 0x0f) << 1) | (in[3] >> 7)]);
  1252. out.append(enc32[(in[3] >> 2) & 0x1f]);
  1253. out.append(enc32[((in[3] & 0x03) << 3) | (in[4] >> 5)]);
  1254. out.append(enc32[in[4] & 0x1f]);
  1255. }
  1256. void JBASE32_Encode(const char *in,StringBuffer &out)
  1257. {
  1258. size32_t len = (size32_t)strlen(in);
  1259. while (len>=5) {
  1260. encode5_32((const byte *)in,out);
  1261. in += 5;
  1262. len -= 5;
  1263. }
  1264. byte rest[5];
  1265. memcpy(rest,in,len);
  1266. memset(rest+len,0,5-len);
  1267. encode5_32(rest,out);
  1268. }
  1269. static inline byte decode_32c(char c)
  1270. {
  1271. byte b = (byte)c;
  1272. if (b>=97) {
  1273. if (b<=122)
  1274. return b-97;
  1275. }
  1276. else if ((b>=50)&&(b<=55))
  1277. return b-24;
  1278. return 0;
  1279. }
  1280. void JBASE32_Decode(const char *bi,StringBuffer &out)
  1281. {
  1282. for (;;) {
  1283. byte b[8];
  1284. for (unsigned i=0;i<8;i++)
  1285. b[i] = decode_32c(*(bi++));
  1286. byte o;
  1287. o = ((b[0] & 0x1f) << 3) | ((b[1] & 0x1c) >> 2);
  1288. if (!o) return;
  1289. out.append(o);
  1290. o = ((b[1] & 0x03) << 6) | ((b[2] & 0x1f) << 1) | ((b[3] & 0x10) >> 4);
  1291. if (!o) return;
  1292. out.append(o);
  1293. o = ((b[3] & 0x0f) << 4) | ((b[4] & 0x1e) >> 1);
  1294. if (!o) return;
  1295. out.append(o);
  1296. o = ((b[4] & 0x01) << 7) | ((b[5] & 0x1f) << 2) | ((b[6] & 0x18) >> 3);
  1297. if (!o) return;
  1298. out.append(o);
  1299. o = ((b[6] & 0x07) << 5) | (b[7] & 0x1f);
  1300. if (!o) return;
  1301. out.append(o);
  1302. }
  1303. }
  1304. static void DelimToStringArray(const char *csl, StringArray &dst, const char *delim, bool deldup, bool trimSpaces)
  1305. {
  1306. if (!csl)
  1307. return;
  1308. const char *s = csl;
  1309. char c;
  1310. if (!delim)
  1311. c = ',';
  1312. else if (*delim&&!delim[1])
  1313. c = *delim;
  1314. else
  1315. c = 0;
  1316. StringBuffer str;
  1317. unsigned dstlen=dst.ordinality();
  1318. for (;;)
  1319. {
  1320. if (trimSpaces)
  1321. while (isspace(*s))
  1322. s++;
  1323. if (!*s&&(dst.ordinality()==dstlen)) // this check is to allow trailing separators (e.g. ",," is 3 (NULL) entries) but not generate an entry for ""
  1324. break;
  1325. const char *e = s;
  1326. while (*e) {
  1327. if (c) {
  1328. if (*e==c)
  1329. break;
  1330. }
  1331. else if (strchr(delim,*e))
  1332. break;
  1333. e++;
  1334. }
  1335. str.clear().append((size32_t)(e-s),s);
  1336. if (trimSpaces)
  1337. str.clip();
  1338. if (deldup) {
  1339. const char *s1 = str.str();
  1340. unsigned i;
  1341. for (i=0;i<dst.ordinality();i++)
  1342. if (strcmp(s1,dst.item(i))==0)
  1343. break;
  1344. if (i>=dst.ordinality())
  1345. dst.append(s1);
  1346. }
  1347. else
  1348. dst.append(str.str());
  1349. if (!*e)
  1350. break;
  1351. s = e+1;
  1352. }
  1353. }
  1354. void StringArray::appendList(const char *list, const char *delim, bool trimSpaces)
  1355. {
  1356. DelimToStringArray(list, *this, delim, false, trimSpaces);
  1357. }
  1358. void StringArray::appendListUniq(const char *list, const char *delim, bool trimSpaces)
  1359. {
  1360. DelimToStringArray(list, *this, delim, true, trimSpaces);
  1361. }
  1362. StringBuffer &StringArray::getString(StringBuffer &ret, const char *delim)
  1363. {
  1364. ForEachItemIn(i, *this)
  1365. {
  1366. const char *v = item(i);
  1367. ret.append(v);
  1368. if (i+1 != ordinality())
  1369. ret.append(delim);
  1370. }
  1371. return ret;
  1372. }
  1373. void StringArray::sortAscii(bool nocase)
  1374. {
  1375. PARENT::sort(nocase ? CCmp::compareNC : CCmp::compare);
  1376. }
  1377. void StringArray::sortAsciiReverse(bool nocase)
  1378. {
  1379. PARENT::sort(nocase ? CCmp::revCompareNC : CCmp::revCompare);
  1380. }
  1381. void StringArray::sortCompare(int (*compare)(const char * const * l, const char * const * r))
  1382. {
  1383. PARENT::sort(compare);
  1384. }
  1385. #ifdef _WIN32
  1386. unsigned msTick() { return timeGetTime(); }
  1387. unsigned usTick()
  1388. {
  1389. static __int64 freq=0;
  1390. LARGE_INTEGER v;
  1391. if (!freq) {
  1392. if (QueryPerformanceFrequency(&v))
  1393. freq=v.QuadPart;
  1394. if (!freq)
  1395. return 0;
  1396. }
  1397. if (!QueryPerformanceCounter(&v))
  1398. return 0;
  1399. return (unsigned) ((v.QuadPart*1000000)/freq); // hope dividend doesn't overflow though it might
  1400. }
  1401. extern jlib_decl unsigned __int64 nsTick()
  1402. {
  1403. static __int64 freq=0;
  1404. LARGE_INTEGER v;
  1405. if (!freq) {
  1406. if (QueryPerformanceFrequency(&v))
  1407. freq=v.QuadPart;
  1408. if (!freq)
  1409. return 0;
  1410. }
  1411. if (!QueryPerformanceCounter(&v))
  1412. return 0;
  1413. return (v.QuadPart*U64C(1000000000))/freq; // This is unlikely to cleanly wrap
  1414. }
  1415. #else
  1416. #ifdef CLOCK_MONOTONIC
  1417. static bool use_gettimeofday=false;
  1418. unsigned msTick()
  1419. {
  1420. if (!use_gettimeofday) {
  1421. timespec tm;
  1422. if (clock_gettime(CLOCK_MONOTONIC, &tm)>=0)
  1423. return tm.tv_sec*1000+(tm.tv_nsec/1000000);
  1424. use_gettimeofday = true;
  1425. fprintf(stderr,"clock_gettime CLOCK_MONOTONIC returns %d",errno); // don't use PROGLOG
  1426. }
  1427. struct timeval tm;
  1428. gettimeofday(&tm,NULL);
  1429. return tm.tv_sec*1000+(tm.tv_usec/1000);
  1430. }
  1431. unsigned usTick()
  1432. {
  1433. if (!use_gettimeofday) {
  1434. timespec tm;
  1435. if (clock_gettime(CLOCK_MONOTONIC, &tm)>=0)
  1436. return tm.tv_sec*1000000+(tm.tv_nsec/1000);
  1437. use_gettimeofday = true;
  1438. fprintf(stderr,"clock_gettime CLOCK_MONOTONIC returns %d",errno); // don't use PROGLOG
  1439. }
  1440. struct timeval tm;
  1441. gettimeofday(&tm,NULL);
  1442. return tm.tv_sec*1000000+tm.tv_usec;
  1443. }
  1444. unsigned __int64 nsTick()
  1445. {
  1446. if (!use_gettimeofday) {
  1447. timespec tm;
  1448. if (clock_gettime(CLOCK_MONOTONIC, &tm)>=0)
  1449. return ((unsigned __int64)tm.tv_sec)*U64C(1000000000)+tm.tv_nsec;
  1450. use_gettimeofday = true;
  1451. fprintf(stderr,"clock_gettime CLOCK_MONOTONIC returns %d",errno); // don't use PROGLOG
  1452. }
  1453. struct timeval tm;
  1454. gettimeofday(&tm,NULL);
  1455. return tm.tv_sec*U64C(1000000000)+tm.tv_usec*1000;
  1456. }
  1457. #elif __APPLE__
  1458. unsigned __int64 nsTick()
  1459. {
  1460. return mach_absolute_time() * (uint64_t)timebase_info.numer / (uint64_t)timebase_info.denom;
  1461. }
  1462. unsigned usTick()
  1463. {
  1464. __uint64 nano = mach_absolute_time() * (uint64_t)timebase_info.numer / (uint64_t)timebase_info.denom;
  1465. return nano / 1000;
  1466. }
  1467. unsigned msTick()
  1468. {
  1469. __uint64 nano = mach_absolute_time() * (uint64_t)timebase_info.numer / (uint64_t)timebase_info.denom;
  1470. return nano / 1000000;
  1471. }
  1472. #else
  1473. #warning "clock_gettime(CLOCK_MONOTONIC) not supported"
  1474. unsigned msTick()
  1475. {
  1476. struct timeval tm;
  1477. gettimeofday(&tm,NULL);
  1478. return tm.tv_sec*1000+(tm.tv_usec/1000);
  1479. }
  1480. unsigned usTick()
  1481. {
  1482. struct timeval tm;
  1483. gettimeofday(&tm,NULL);
  1484. return tm.tv_sec*1000000+tm.tv_usec;
  1485. }
  1486. unsigned __int64 nsTick()
  1487. {
  1488. struct timeval tm;
  1489. gettimeofday(&tm,NULL);
  1490. return tm.tv_sec*U64C(1000000000)+tm.tv_usec*1000;
  1491. }
  1492. #endif
  1493. #endif
  1494. int write_pidfile(const char * instance)
  1495. {
  1496. #ifndef _WIN32
  1497. StringBuffer path;
  1498. path.append(PID_DIR).append(PATHSEPCHAR).append(instance).append(".pid");
  1499. FILE * fd = fopen(path.str(),"w");
  1500. if (fd==NULL) {
  1501. perror("Unable to open pidfile for writing");
  1502. return(EXIT_FAILURE);
  1503. }
  1504. fprintf(fd,"%d",getpid());
  1505. fclose(fd);
  1506. return(EXIT_SUCCESS);
  1507. #endif
  1508. return 0;
  1509. }
  1510. //Calculate the greatest common divisor using Euclid's method
  1511. unsigned __int64 greatestCommonDivisor(unsigned __int64 left, unsigned __int64 right)
  1512. {
  1513. for (;;)
  1514. {
  1515. if (left > right)
  1516. {
  1517. if (right == 0)
  1518. return left;
  1519. left = left % right;
  1520. }
  1521. else
  1522. {
  1523. if (left == 0)
  1524. return right;
  1525. right = right % left;
  1526. }
  1527. }
  1528. }
  1529. //The whole point of this function is to force memory to be accessed on the stack to avoid page faults.
  1530. //Therefore disable the gcc warning.
  1531. #ifdef __GNUC__
  1532. #pragma GCC diagnostic push
  1533. #pragma GCC diagnostic ignored "-Wuninitialized"
  1534. #endif
  1535. //In a separate module to stop optimizer removing the surrounding catch.
  1536. int minus4096 = -4096; // Stops compiler being clever enough to report error
  1537. void doStackProbe()
  1538. {
  1539. byte local;
  1540. const volatile byte * x = (const byte *)&local;
  1541. byte forceload __attribute__((unused)) = x[minus4096];
  1542. }
  1543. #ifdef __GNUC__
  1544. #pragma GCC diagnostic pop
  1545. #endif
  1546. #ifdef _WIN32
  1547. DWORD dwTlsIndex = -1;
  1548. CriticalSection tlscrit;
  1549. void initThreadLocal(int len, void* val)
  1550. {
  1551. {
  1552. CriticalBlock b(tlscrit);
  1553. if(dwTlsIndex == -1)
  1554. {
  1555. if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
  1556. throw MakeStringException(-1, "TlsAlloc failed");
  1557. }
  1558. }
  1559. LPVOID lpvData;
  1560. lpvData = TlsGetValue(dwTlsIndex);
  1561. if (lpvData != 0)
  1562. LocalFree((HLOCAL) lpvData);
  1563. // Initialize the TLS index for this thread.
  1564. lpvData = (LPVOID) LocalAlloc(LPTR, len);
  1565. memcpy((char*)lpvData, val, len);
  1566. if (! TlsSetValue(dwTlsIndex, lpvData))
  1567. throw MakeStringException(-1, "TlsSetValue error");
  1568. }
  1569. void* getThreadLocalVal()
  1570. {
  1571. if(dwTlsIndex == -1)
  1572. return NULL;
  1573. return TlsGetValue(dwTlsIndex);
  1574. }
  1575. void clearThreadLocal()
  1576. {
  1577. if(dwTlsIndex == -1)
  1578. return;
  1579. LPVOID lpvData = TlsGetValue(dwTlsIndex);
  1580. if (lpvData != 0)
  1581. {
  1582. LocalFree((HLOCAL) lpvData);
  1583. if (! TlsSetValue(dwTlsIndex, NULL))
  1584. throw MakeStringException(-1, "TlsSetValue error");
  1585. }
  1586. }
  1587. #else
  1588. // Key for the thread-specific buffer
  1589. static pthread_key_t buffer_key;
  1590. // Once-only initialisation of the key
  1591. static pthread_once_t buffer_key_once = PTHREAD_ONCE_INIT;
  1592. // Free the thread-specific buffer
  1593. static void buffer_destroy(void * buf)
  1594. {
  1595. if(buf)
  1596. free(buf);
  1597. }
  1598. // Allocate the key
  1599. static void buffer_key_alloc()
  1600. {
  1601. pthread_key_create(&buffer_key, buffer_destroy);
  1602. }
  1603. // Allocate the thread-specific buffer
  1604. void initThreadLocal(int len, void* val)
  1605. {
  1606. pthread_once(&buffer_key_once, buffer_key_alloc);
  1607. void* valbuf = malloc(len);
  1608. memcpy(valbuf, val, len);
  1609. pthread_setspecific(buffer_key, valbuf);
  1610. }
  1611. // Return the thread-specific buffer
  1612. void* getThreadLocalVal()
  1613. {
  1614. return (char *) pthread_getspecific(buffer_key);
  1615. }
  1616. void clearThreadLocal()
  1617. {
  1618. }
  1619. #endif
  1620. StringBuffer &expandMask(StringBuffer &buf, const char *mask, unsigned p, unsigned n)
  1621. {
  1622. const char *s=mask;
  1623. if (s)
  1624. while (*s) {
  1625. char next = *(s++);
  1626. if (next=='$') {
  1627. char pc = toupper(s[0]);
  1628. if (pc&&(s[1]=='$')) {
  1629. if (pc=='P') {
  1630. buf.append(p+1);
  1631. next = 0;
  1632. s+=2;
  1633. }
  1634. else if (pc=='N') {
  1635. buf.append(n);
  1636. next = 0;
  1637. s+=2;
  1638. }
  1639. }
  1640. }
  1641. if (next)
  1642. buf.append(next);
  1643. }
  1644. return buf;
  1645. }
  1646. static const char *findExtension(const char *fn)
  1647. {
  1648. if (!fn)
  1649. return NULL;
  1650. const char *ret = strchr(fn,'.');
  1651. if (ret) {
  1652. for (;;) {
  1653. ret++;
  1654. const char *s = strchr(ret,'.');
  1655. if (!s)
  1656. break;
  1657. ret = s;
  1658. }
  1659. }
  1660. return ret;
  1661. }
  1662. unsigned runExternalCommand(StringBuffer &output, StringBuffer &error, const char *cmd, const char *input)
  1663. {
  1664. return runExternalCommand(cmd, output, error, cmd, input, ".", nullptr);
  1665. }
  1666. unsigned runExternalCommand(const char *title, StringBuffer &output, StringBuffer &error, const char *cmd, const char *input, const char * cwd, const EnvironmentVector * optEnvironment)
  1667. {
  1668. try
  1669. {
  1670. if (!cwd)
  1671. cwd = ".";
  1672. Owned<IPipeProcess> pipe = createPipeProcess();
  1673. if (optEnvironment)
  1674. {
  1675. for (const auto & cur : *optEnvironment)
  1676. pipe->setenv(cur.first.c_str(), cur.second.c_str());
  1677. }
  1678. int ret = START_FAILURE;
  1679. if (pipe->run(title, cmd, cwd, input != NULL, true, true, 1024*1024))
  1680. {
  1681. if (input)
  1682. {
  1683. pipe->write(strlen(input), input);
  1684. pipe->closeInput();
  1685. }
  1686. char buf[1024];
  1687. while (true)
  1688. {
  1689. size32_t read = pipe->read(sizeof(buf), buf);
  1690. if (!read)
  1691. break;
  1692. output.append(read, buf);
  1693. }
  1694. ret = pipe->wait();
  1695. while (true)
  1696. {
  1697. size32_t read = pipe->readError(sizeof(buf), buf);
  1698. if (!read)
  1699. break;
  1700. error.append(read, buf);
  1701. }
  1702. }
  1703. return ret;
  1704. }
  1705. catch (IException *E)
  1706. {
  1707. E->Release();
  1708. output.clear();
  1709. return START_FAILURE;
  1710. }
  1711. }
  1712. bool matchesMask(const char *fn, const char *mask, unsigned p, unsigned n)
  1713. {
  1714. StringBuffer match;
  1715. expandMask(match,mask,p,n);
  1716. return (stricmp(fn,match.str())==0);
  1717. }
  1718. bool constructMask(StringAttr &attr, const char *fn, unsigned p, unsigned n)
  1719. {
  1720. StringBuffer buf;
  1721. const char *ext = findExtension(fn);
  1722. if (!ext)
  1723. return false;
  1724. buf.append((size32_t)(ext-fn),fn).append("_$P$_of_$N$");
  1725. if (matchesMask(fn,buf.str(),p,n)) {
  1726. attr.set(buf.str());
  1727. return true;
  1728. }
  1729. return false;
  1730. }
  1731. bool deduceMask(const char *fn, bool expandN, StringAttr &mask, unsigned &pret, unsigned &nret)
  1732. {
  1733. const char *e = findExtension(fn);
  1734. if (!e)
  1735. return false;
  1736. for (;;) {
  1737. const char *s=e;
  1738. if (*s=='_') {
  1739. s++;
  1740. unsigned p = 0;
  1741. while (isdigit(*s))
  1742. p = p*10+*(s++)-'0';
  1743. if (p&&(memcmp(s,"_of_",4)==0)) {
  1744. s += 4;
  1745. pret = p-1;
  1746. p = 0;
  1747. while (isdigit(*s))
  1748. p = p*10+*(s++)-'0';
  1749. nret = p;
  1750. if (((*s==0)||(*s=='.'))&&(p>pret)) {
  1751. StringBuffer buf;
  1752. if (expandN)
  1753. buf.append((size32_t)(e-fn),fn).append("_$P$_of_").append(p);
  1754. else
  1755. buf.append((size32_t)(e-fn),fn).append("_$P$_of_$N$");
  1756. if (*s=='.')
  1757. buf.append(s);
  1758. mask.set(buf);
  1759. return true;
  1760. }
  1761. }
  1762. }
  1763. e--;
  1764. for (;;) {
  1765. if (e==fn)
  1766. return false;
  1767. if (*(e-1)=='.')
  1768. break;
  1769. e--;
  1770. }
  1771. }
  1772. return false;
  1773. }
  1774. //==============================================================
  1775. #ifdef _WIN32
  1776. class CWindowsAuthenticatedUser: implements IAuthenticatedUser, public CInterface
  1777. {
  1778. StringAttr name;
  1779. HANDLE usertoken;
  1780. public:
  1781. IMPLEMENT_IINTERFACE;
  1782. CWindowsAuthenticatedUser()
  1783. {
  1784. usertoken = (HANDLE)-1;
  1785. }
  1786. ~CWindowsAuthenticatedUser()
  1787. {
  1788. if (usertoken != (HANDLE)-1)
  1789. CloseHandle(usertoken);
  1790. }
  1791. bool login(const char *user, const char *passwd)
  1792. {
  1793. name.clear();
  1794. if (usertoken != (HANDLE)-1)
  1795. CloseHandle(usertoken);
  1796. StringBuffer domain("");
  1797. const char *ut = strchr(user,'\\');
  1798. if (ut) {
  1799. domain.clear().append((size32_t)(ut-user),user);
  1800. user = ut+1;
  1801. }
  1802. BOOL res = LogonUser((LPTSTR)user,(LPTSTR)(domain.length()==0?NULL:domain.str()),(LPTSTR)passwd,LOGON32_LOGON_NETWORK,LOGON32_PROVIDER_DEFAULT,&usertoken);
  1803. if (res==0)
  1804. return false;
  1805. name.set(user);
  1806. return true;
  1807. }
  1808. void impersonate()
  1809. {
  1810. if (!ImpersonateLoggedOnUser(usertoken))
  1811. throw makeOsException(GetLastError());
  1812. }
  1813. void revert()
  1814. {
  1815. RevertToSelf();
  1816. }
  1817. const char *username()
  1818. {
  1819. return name.get();
  1820. }
  1821. };
  1822. IAuthenticatedUser *createAuthenticatedUser() { return new CWindowsAuthenticatedUser; }
  1823. #elif defined(__linux__)
  1824. class CLinuxAuthenticatedUser: implements IAuthenticatedUser, public CInterface
  1825. {
  1826. StringAttr name;
  1827. uid_t uid;
  1828. gid_t gid;
  1829. uid_t saveuid;
  1830. gid_t savegid;
  1831. public:
  1832. IMPLEMENT_IINTERFACE;
  1833. bool login(const char *user, const char *passwd)
  1834. {
  1835. name.clear();
  1836. const char *ut = strchr(user,'\\');
  1837. if (ut)
  1838. user = ut+1; // remove windows domain
  1839. struct passwd *pw;
  1840. char *epasswd;
  1841. if ((pw = getpwnam(user)) == NULL)
  1842. return false;
  1843. struct spwd *spwd = getspnam(user);
  1844. if (spwd)
  1845. epasswd = spwd->sp_pwdp;
  1846. else
  1847. epasswd = pw->pw_passwd;
  1848. if (!epasswd||!*epasswd)
  1849. return false;
  1850. if (strcmp(crypt(passwd,epasswd),epasswd)!=0)
  1851. return false;
  1852. uid = pw->pw_uid;
  1853. gid = pw->pw_gid;
  1854. name.set(pw->pw_name);
  1855. return true;
  1856. }
  1857. void impersonate()
  1858. {
  1859. saveuid = geteuid();
  1860. savegid = getegid();
  1861. if (setegid(gid) == -1)
  1862. throw makeOsException(errno, "Failed to set effective group id");
  1863. if (seteuid(uid) == -1)
  1864. throw makeOsException(errno, "Failed to set effective user id");
  1865. }
  1866. void revert()
  1867. {
  1868. if (seteuid(saveuid) == -1)
  1869. throw makeOsException(errno, "Failed to restore effective group id");
  1870. if (setegid(savegid) == -1)
  1871. throw makeOsException(errno, "Failed to restore effective user id");
  1872. }
  1873. const char *username()
  1874. {
  1875. return name.get();
  1876. }
  1877. };
  1878. IAuthenticatedUser *createAuthenticatedUser() { return new CLinuxAuthenticatedUser; }
  1879. #elif defined(__FreeBSD__) || defined (__APPLE__)
  1880. IAuthenticatedUser *createAuthenticatedUser() { UNIMPLEMENTED; }
  1881. #endif
  1882. extern jlib_decl void serializeAtom(MemoryBuffer & target, IAtom * name)
  1883. {
  1884. StringBuffer lower(str(name));
  1885. lower.toLowerCase();
  1886. serialize(target, lower.str());
  1887. }
  1888. extern jlib_decl IAtom * deserializeAtom(MemoryBuffer & source)
  1889. {
  1890. StringAttr text;
  1891. deserialize(source, text);
  1892. if (text)
  1893. return createAtom(text);
  1894. return NULL;
  1895. }
  1896. //==============================================================
  1897. static const char enc64[65] =
  1898. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  1899. "abcdefghijklmnopqrstuvwxyz"
  1900. "0123456789-_";
  1901. static inline void encode3_64(byte *in,StringBuffer &out)
  1902. {
  1903. // 3 bytes in 4 out
  1904. out.append(enc64[in[0]>>2]);
  1905. out.append(enc64[((in[0] << 4) & 0x30) | (in[1] >> 4)]);
  1906. out.append(enc64[((in[1] << 2) & 0x3c) | (in[2] >> 6)]);
  1907. out.append(enc64[in[2] & 0x3f]);
  1908. }
  1909. static NonReentrantSpinLock lock;
  1910. static unsigned uuidbin[5] = {0,0,0,0,0};
  1911. StringBuffer &genUUID(StringBuffer &out, bool nocase)
  1912. { // returns a 24 char UUID for nocase=false or 32 char for nocase=true
  1913. lock.enter();
  1914. // could be quicker using statics
  1915. if (uuidbin[0]==0) {
  1916. queryHostIP().getNetAddress(sizeof(uuidbin[0]),uuidbin);
  1917. uuidbin[1] = (unsigned)GetCurrentProcessId();
  1918. }
  1919. time_t t;
  1920. time(&t);
  1921. uuidbin[2] = (unsigned)t;
  1922. uuidbin[3] = msTick();
  1923. uuidbin[4]++;
  1924. byte *in = (byte *)uuidbin;
  1925. if (nocase) {
  1926. encode5_32(in,out);
  1927. encode5_32(in+5,out);
  1928. encode5_32(in+10,out);
  1929. encode5_32(in+15,out);
  1930. }
  1931. else {
  1932. encode3_64(in,out);
  1933. encode3_64(in+3,out);
  1934. encode3_64(in+6,out);
  1935. encode3_64(in+9,out);
  1936. byte tmp[3]; // drop two msb bytes from msec time
  1937. tmp[0] = in[12];
  1938. tmp[1] = in[13];
  1939. tmp[2] = in[16];
  1940. encode3_64(tmp,out);
  1941. encode3_64(in+17,out);
  1942. }
  1943. lock.leave();
  1944. return out;
  1945. }
  1946. //==============================================================
  1947. class jlib_decl CNameCountTable : public AtomRefTable
  1948. {
  1949. public:
  1950. CNameCountTable(bool _nocase=false) : AtomRefTable(_nocase) { }
  1951. StringBuffer &dump(StringBuffer &str)
  1952. {
  1953. SuperHashIteratorOf<HashKeyElement> iter(*this);
  1954. CriticalBlock b(crit);
  1955. ForEach (iter)
  1956. {
  1957. HashKeyElement &elem = iter.query();
  1958. str.append(elem.get()).append(", count = ").append(elem.queryReferences()).newline();
  1959. }
  1960. return str;
  1961. }
  1962. };
  1963. static CNameCountTable *namedCountHT;
  1964. MODULE_INIT(INIT_PRIORITY_SYSTEM)
  1965. {
  1966. namedCountHT = new CNameCountTable;
  1967. return true;
  1968. }
  1969. MODULE_EXIT()
  1970. {
  1971. delete namedCountHT;
  1972. }
  1973. NamedCount::NamedCount()
  1974. {
  1975. ht = NULL;
  1976. }
  1977. NamedCount::~NamedCount()
  1978. {
  1979. if (ht) namedCountHT->releaseKey(ht);
  1980. }
  1981. void NamedCount::set(const char *name)
  1982. {
  1983. ht = namedCountHT->queryCreate(name);
  1984. }
  1985. StringBuffer &dumpNamedCounts(StringBuffer &str)
  1986. {
  1987. return namedCountHT->dump(str);
  1988. }
  1989. //==============================================================
  1990. // class OffsetToString
  1991. OffsetToString::OffsetToString(offset_t offset)
  1992. {
  1993. #if defined(_MSC_VER) && !defined (_POSIX_) && (__STDC__ || _INTEGRAL_MAX_BITS < 64)
  1994. // fpos_t is defined as struct (see <stdio.h> in VC)
  1995. __int64 v = offset.lopart + (offset.hipart<<32);
  1996. m_buffer.append(v);
  1997. #else
  1998. m_buffer.append(offset);
  1999. #endif
  2000. }
  2001. /* Gentoo libc version omits these symbols which are directly */
  2002. /* referenced by some 3rd party libraries (sybase, Hasp). Until these */
  2003. /* libs get updated, provide linkable symbols within jlib for these... */
  2004. #if defined(__linux__) && (__GNUC__ >= 3)
  2005. const jlib_decl unsigned short int *__ctype_b = *__ctype_b_loc ();
  2006. const jlib_decl __int32_t *__ctype_tolower = *__ctype_tolower_loc();
  2007. const jlib_decl __int32_t *__ctype_toupper = *__ctype_toupper_loc();
  2008. // There seems to be some debate about whether these are needed
  2009. //#elif (__GNUC__ >= 3)
  2010. //const unsigned short int *__ctype_b = *__ctype_b_loc ();
  2011. //const unsigned int *__ctype_tolower = *__ctype_tolower_loc();
  2012. //const unsigned int *__ctype_toupper = *__ctype_toupper_loc();
  2013. #endif
  2014. //==============================================================
  2015. // URL Password, username handling
  2016. /*
  2017. From ftp://ftp.isi.edu/in-notes/rfc1738.txt:
  2018. http://<user>:<password>@<host>:<port>/<url-path>
  2019. Some or all of the parts "<user>:<password>@", ":<password>",
  2020. ":<port>", and "/<url-path>" may be excluded.
  2021. The user name (and password), if present, are followed by a
  2022. commercial at-sign "@". Within the user and password field, any ":",
  2023. "@", or "/" must be encoded.
  2024. */
  2025. jlib_decl StringBuffer& encodeUrlUseridPassword(StringBuffer& out, const char* in)
  2026. {
  2027. for (const char* p = in; *p; p++)
  2028. {
  2029. switch(*p)
  2030. {
  2031. // mentioned in rfc1738
  2032. case ':': out.append("%3A"); break;
  2033. case '@': out.append("%40"); break;
  2034. case '/': out.append("%2F"); break;
  2035. // these are not in the spec, but IE/Firefox has trouble if left un-encoded
  2036. case '%': out.append("%25"); break;
  2037. // these are not necessary: both IE and firefox handle them correctly
  2038. /*
  2039. case '&': out.append("%26"); break;
  2040. case ' ': out.append("%20"); break;
  2041. */
  2042. default: out.append(*p); break;
  2043. }
  2044. }
  2045. return out;
  2046. }
  2047. inline bool isHexChar(char c)
  2048. {
  2049. return (c>='0' && c<='9')
  2050. || (c>='A' && c<='F')
  2051. || (c>='a' && c<='f');
  2052. }
  2053. int hexValue(char c)
  2054. {
  2055. return (c>='0' && c<='9') ? c-'0' :
  2056. ((c>='A' && (c<='F') ? c-'A'+10 : c-'a'+10));
  2057. }
  2058. jlib_decl StringBuffer& decodeUrlUseridPassword(StringBuffer& out, const char* in)
  2059. {
  2060. for (const char* p = in; *p; p++)
  2061. {
  2062. if (*p=='%' && isHexChar(*(p+1)) && isHexChar(*(p+2)) )
  2063. {
  2064. char c1 = *(p+1), c2 = *(p+2);
  2065. int x = (hexValue(c1)<<4) + hexValue(c2);
  2066. out.appendf("%c",x);
  2067. p += 2;
  2068. }
  2069. else
  2070. out.appendf("%c",*p);
  2071. }
  2072. return out;
  2073. }
  2074. jlib_decl StringBuffer & passwordInput(const char* prompt, StringBuffer& passwd)
  2075. {
  2076. #ifdef _WIN32
  2077. printf("%s", prompt);
  2078. size32_t entrylen = passwd.length();
  2079. for (;;) {
  2080. char c = getch();
  2081. if (c == '\r')
  2082. break;
  2083. if (c == '\b') {
  2084. if (passwd.length()>entrylen) {
  2085. printf("\b \b");
  2086. passwd.setLength(passwd.length()-1);
  2087. }
  2088. }
  2089. else {
  2090. passwd.append(c);
  2091. printf("*");
  2092. }
  2093. }
  2094. printf("\n");
  2095. #else
  2096. // Unfortunately Linux tty can't easily support using '*' hiding
  2097. sigset_t saved_signals;
  2098. sigset_t set_signals;
  2099. struct termios saved_term;
  2100. struct termios set_term;
  2101. FILE *term = fopen(_PATH_TTY, "w+");
  2102. if (!term)
  2103. term = stdin;
  2104. int termfd = fileno(term);
  2105. fprintf(stdout, "%s", prompt);
  2106. fflush(stdout);
  2107. sigemptyset(&set_signals);
  2108. sigaddset(&set_signals, SIGINT);
  2109. sigaddset(&set_signals, SIGTSTP);
  2110. sigprocmask(SIG_BLOCK, &set_signals, &saved_signals);
  2111. tcgetattr(termfd, &saved_term);
  2112. set_term = saved_term;
  2113. set_term.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL);
  2114. tcsetattr(termfd, TCSAFLUSH, &set_term);
  2115. char c = EOF;
  2116. int rd = ::read(termfd,&c,1);
  2117. while ((rd==1)&&(c!='\r')&&(c!='\n')) {
  2118. passwd.append(c);
  2119. rd = ::read(termfd,&c,1);
  2120. }
  2121. int err = (rd<0)?errno:0;
  2122. tcsetattr(termfd, TCSAFLUSH, &saved_term);
  2123. sigprocmask(SIG_SETMASK, &saved_signals, 0);
  2124. if (term!=stdin)
  2125. fclose(term);
  2126. fprintf(stdout, "\n");
  2127. fflush(stdout);
  2128. if (err)
  2129. throw makeOsException(err);
  2130. #endif
  2131. return passwd;
  2132. }
  2133. StringBuffer & fillConfigurationDirectoryEntry(const char *dir,const char *name, const char *component, const char *instance, StringBuffer &dirout)
  2134. {
  2135. while (*dir) {
  2136. if (*dir=='[') {
  2137. if (memicmp(dir+1,"NAME]",5)==0) {
  2138. dirout.append(name);
  2139. dir += 5;
  2140. }
  2141. else if (memicmp(dir+1,"COMPONENT]",10)==0) {
  2142. dirout.append(component);
  2143. dir += 10;
  2144. }
  2145. else if (memicmp(dir+1,"INST]",5)==0){
  2146. dirout.append(instance);
  2147. dir += 5;
  2148. }
  2149. else
  2150. dirout.append('[');
  2151. }
  2152. else
  2153. dirout.append(*dir);
  2154. dir++;
  2155. }
  2156. return dirout;
  2157. }
  2158. IPropertyTree *getHPCCEnvironment()
  2159. {
  2160. #ifdef _CONTAINERIZED
  2161. #ifdef _DEBUG
  2162. throwUnexpectedX("getHPCCEnvironment() called from container system");
  2163. #else
  2164. IERRLOG("getHPCCEnvironment() called from container system");
  2165. #endif
  2166. #endif
  2167. StringBuffer envfile;
  2168. if (queryEnvironmentConf().getProp("environment",envfile) && envfile.length())
  2169. {
  2170. if (!isAbsolutePath(envfile.str()))
  2171. {
  2172. envfile.insert(0, CONFIG_DIR PATHSEPSTR);
  2173. }
  2174. Owned<IFile> file = createIFile(envfile.str());
  2175. if (file)
  2176. {
  2177. Owned<IFileIO> fileio = file->open(IFOread);
  2178. if (fileio)
  2179. return createPTree(*fileio, ipt_lowmem);
  2180. }
  2181. }
  2182. return NULL;
  2183. }
  2184. static Owned<IProperties> envConfFile;
  2185. static CriticalSection envConfCrit;
  2186. jlib_decl const IProperties &queryEnvironmentConf()
  2187. {
  2188. #if defined(_CONTAINERIZED) && defined(_DEBUG)
  2189. //The following line is currently hit by too many examples. Re-enable the exception when more
  2190. //work has been done removing calls to getConfigurationDirectory() and other related functions.
  2191. //throwUnexpectedX("queryEnvironmentConf() callled from container system");
  2192. IERRLOG("queryEnvironmentConf() callled from container system");
  2193. #endif
  2194. CriticalBlock b(envConfCrit);
  2195. if (!envConfFile)
  2196. envConfFile.setown(createProperties(CONFIG_DIR PATHSEPSTR ENV_CONF_FILE, true));
  2197. return *envConfFile;
  2198. }
  2199. static StringBuffer DAFSpassPhraseDec;//deprecated
  2200. static CriticalSection DAFSpassPhraseCrit;
  2201. //Deprecated, please use queryHPCCPKIKeyFiles() instead
  2202. jlib_decl bool querySecuritySettings(DAFSConnectCfg *_connectMethod,
  2203. unsigned short *_port,
  2204. const char * * _certificate,
  2205. const char * * _privateKey,
  2206. const char * * _passPhrase)//decrypted passphrase
  2207. {
  2208. if (_connectMethod)
  2209. *_connectMethod = SSLNone;//default
  2210. if (_port)
  2211. *_port = DAFILESRV_PORT;//default
  2212. // TLS TODO: could share mtls setting and cert/config for secure dafilesrv
  2213. // but note remote cluster configs should then match this one
  2214. #ifdef _CONTAINERIZED
  2215. //MORE: If these come from the component configuration they will need to clone the strings
  2216. if (_certificate)
  2217. *_certificate = nullptr;
  2218. if (_privateKey)
  2219. *_privateKey = nullptr;
  2220. if (_passPhrase)
  2221. *_passPhrase = nullptr;
  2222. #else
  2223. const IProperties & conf = queryEnvironmentConf();
  2224. StringAttr sslMethod;
  2225. sslMethod.set(conf.queryProp("dfsUseSSL"));
  2226. if (!sslMethod.isEmpty())
  2227. {
  2228. DAFSConnectCfg tmpMethod;
  2229. // checking for true | false for backward compatibility
  2230. if ( strieq(sslMethod.str(), "SSLOnly") || strieq(sslMethod.str(), "true") )
  2231. tmpMethod = SSLOnly;
  2232. else if ( strieq(sslMethod.str(), "SSLFirst") )
  2233. tmpMethod = SSLFirst;
  2234. else if ( strieq(sslMethod.str(), "UnsecureFirst") )
  2235. tmpMethod = UnsecureFirst;
  2236. else // SSLNone or false or ...
  2237. tmpMethod = SSLNone;
  2238. if (_connectMethod)
  2239. *_connectMethod = tmpMethod;
  2240. if (_port)
  2241. {
  2242. if (tmpMethod == SSLOnly || tmpMethod == SSLFirst)
  2243. *_port = SECURE_DAFILESRV_PORT;
  2244. }
  2245. //Begin of deprecated code
  2246. bool dfsKeywords = false;
  2247. if (_certificate)
  2248. {
  2249. *_certificate = conf.queryProp("dfsSSLCertFile");
  2250. if (*_certificate)
  2251. dfsKeywords = true;
  2252. }
  2253. if (_privateKey)
  2254. {
  2255. *_privateKey = conf.queryProp("dfsSSLPrivateKeyFile");
  2256. if (*_privateKey)
  2257. dfsKeywords = true;
  2258. }
  2259. StringBuffer DAFSpassPhraseEnc;
  2260. if (_passPhrase)
  2261. {
  2262. CriticalBlock b(DAFSpassPhraseCrit);
  2263. if (DAFSpassPhraseDec.isEmpty())//previously retrieved/decrypted it?
  2264. {
  2265. const char *passPhrasePtr = conf.queryProp("dfsSSLPassPhrase");
  2266. if (!isEmptyString(passPhrasePtr))
  2267. {
  2268. DAFSpassPhraseEnc.append(passPhrasePtr);//got encrypted pwd
  2269. dfsKeywords = true;
  2270. }
  2271. }
  2272. }
  2273. if (!dfsKeywords && (_certificate || _privateKey || _passPhrase))
  2274. {
  2275. //end of deprecated code
  2276. const char *passPhrasePtr = nullptr;
  2277. queryHPCCPKIKeyFiles(_certificate, nullptr, _privateKey, _passPhrase ? &passPhrasePtr : nullptr);//use new keywords
  2278. if (!isEmptyString(passPhrasePtr))
  2279. {
  2280. CriticalBlock b(DAFSpassPhraseCrit);
  2281. if (DAFSpassPhraseEnc.isEmpty())
  2282. DAFSpassPhraseEnc.append(passPhrasePtr);//got encrypted pwd
  2283. }
  2284. }
  2285. if (_passPhrase)
  2286. {
  2287. CriticalBlock b(DAFSpassPhraseCrit);
  2288. if (DAFSpassPhraseDec.isEmpty() && !DAFSpassPhraseEnc.isEmpty())
  2289. decrypt(DAFSpassPhraseDec, DAFSpassPhraseEnc.str());
  2290. *_passPhrase = DAFSpassPhraseDec.str();//return decrypted password. Note the preferred queryHPCCPKIKeyFiles() method returns it encrypted
  2291. }
  2292. }
  2293. #endif
  2294. return true;
  2295. }
  2296. jlib_decl bool queryDafsSecSettings(DAFSConnectCfg *_connectMethod,
  2297. unsigned short *_port,
  2298. unsigned short *_sslport,
  2299. const char * * _certificate,
  2300. const char * * _privateKey,
  2301. const char * * _passPhrase)
  2302. {
  2303. bool ret = querySecuritySettings(_connectMethod, nullptr, _certificate, _privateKey, _passPhrase);
  2304. if (ret)
  2305. {
  2306. if (_port)
  2307. *_port = DAFILESRV_PORT;
  2308. if (_sslport)
  2309. *_sslport = SECURE_DAFILESRV_PORT;
  2310. }
  2311. return ret;
  2312. }
  2313. //query PKI values from environment.conf
  2314. jlib_decl bool queryHPCCPKIKeyFiles(const char * * _certificate,//HPCCCertificateFile
  2315. const char * * _publicKey, //HPCCPublicKeyFile
  2316. const char * * _privateKey, //HPCCPrivateKeyFile
  2317. const char * * _passPhrase) //HPCCPassPhrase
  2318. {
  2319. const IProperties & conf = queryEnvironmentConf();
  2320. if (_certificate)
  2321. *_certificate = conf.queryProp("HPCCCertificateFile");
  2322. if (_publicKey)
  2323. *_publicKey = conf.queryProp("HPCCPublicKeyFile");
  2324. if (_privateKey)
  2325. *_privateKey = conf.queryProp("HPCCPrivateKeyFile");
  2326. if (_passPhrase)
  2327. *_passPhrase = conf.queryProp("HPCCPassPhrase"); //return encrypted
  2328. return true;
  2329. }
  2330. #ifndef _CONTAINERIZED
  2331. jlib_decl bool queryMtlsBareMetalConfig()
  2332. {
  2333. const IProperties &conf = queryEnvironmentConf();
  2334. if (conf.queryProp("mtls"))
  2335. return conf.getPropBool("mtls", false);
  2336. // not in conf, check xml, since all other mp settings are checked there
  2337. Owned<IPropertyTree> env = getHPCCEnvironment();
  2338. if (env)
  2339. return env->getPropBool("EnvSettings/mtls", false);
  2340. return false;
  2341. }
  2342. #endif
  2343. #ifndef _CONTAINERIZED
  2344. static IPropertyTree *getOSSdirTree()
  2345. {
  2346. Owned<IPropertyTree> envtree = getHPCCEnvironment();
  2347. if (envtree) {
  2348. IPropertyTree *ret = envtree->queryPropTree("Software/Directories");
  2349. if (ret)
  2350. return createPTreeFromIPT(ret);
  2351. }
  2352. return NULL;
  2353. }
  2354. #endif
  2355. StringBuffer &getFileAccessUrl(StringBuffer &out)
  2356. {
  2357. Owned<IPropertyTree> envtree = getHPCCEnvironment();
  2358. if (envtree)
  2359. {
  2360. IPropertyTree *secureFileAccessInfo = envtree->queryPropTree("EnvSettings/SecureFileAccess");
  2361. if (secureFileAccessInfo)
  2362. {
  2363. const char *protocol = secureFileAccessInfo->queryProp("@protocol");
  2364. const char *host = secureFileAccessInfo->queryProp("@host");
  2365. unsigned port = secureFileAccessInfo->getPropInt("@port", (unsigned)-1);
  2366. if (isEmptyString(protocol))
  2367. OWARNLOG("Missing protocol from secure file access definition");
  2368. else if (isEmptyString(host))
  2369. OWARNLOG("Missing host from secure file access definition");
  2370. else if ((unsigned)-1 == port)
  2371. OWARNLOG("Missing port from secure file access definition");
  2372. else
  2373. out.appendf("%s://%s:%u/WsDfu", protocol, host, port);
  2374. }
  2375. }
  2376. return out;
  2377. }
  2378. #ifdef _CONTAINERIZED
  2379. bool getDefaultPlane(StringBuffer &ret, const char * componentOption, const char * category)
  2380. {
  2381. // If the plane is specified for the component, then use that
  2382. if (getComponentConfigSP()->getProp(componentOption, ret))
  2383. return true;
  2384. //Otherwise check what the default plane for data storage is configured to be
  2385. //Iterator needed because "storage/planes[@category='%s'][1]/@name" generates an ambiguous error
  2386. VStringBuffer xpath("storage/planes[@category='%s']", category);
  2387. Owned<IPropertyTreeIterator> iter = getGlobalConfigSP()->getElements(xpath);
  2388. if (iter->first())
  2389. {
  2390. iter->query().getProp("@name", ret);
  2391. return true;
  2392. }
  2393. return false;
  2394. }
  2395. static bool getDefaultPlaneDirectory(StringBuffer &ret, const char * componentOption, const char * category)
  2396. {
  2397. StringBuffer planeName;
  2398. if (!getDefaultPlane(planeName, componentOption, category))
  2399. return false;
  2400. Owned<IPropertyTree> storagePlane = getStoragePlane(planeName);
  2401. return storagePlane->getProp("@prefix", ret);
  2402. }
  2403. #endif
  2404. bool getConfigurationDirectory(const IPropertyTree *useTree, const char *category, const char *component, const char *instance, StringBuffer &dirout)
  2405. {
  2406. #ifdef _CONTAINERIZED
  2407. if (streq(category, "data"))
  2408. {
  2409. Owned<IPropertyTree> storagePlane = getStoragePlane(instance);
  2410. if (!storagePlane)
  2411. throw makeStringExceptionV(-1, "no default directory available for plane '%s'", instance);
  2412. return storagePlane->getProp("@prefix", dirout);
  2413. }
  2414. if (streq(category, "data2") || streq(category, "data3") || streq(category, "data4") || streq(category, "mirror"))
  2415. return false;
  2416. if (streq(category, "spill"))
  2417. {
  2418. return getDefaultPlaneDirectory(dirout, "@spillPlane", "spill");
  2419. }
  2420. if (streq(category, "temp"))
  2421. {
  2422. if (getDefaultPlaneDirectory(dirout, "@tempPlane", "temp"))
  2423. return true;
  2424. return getDefaultPlaneDirectory(dirout, "@spillPlane", "spill");
  2425. }
  2426. if (streq(category, "log"))
  2427. {
  2428. return false;
  2429. }
  2430. if (streq(category, "dali"))
  2431. {
  2432. //Not used... the dataPath configuration property is used instead
  2433. return getDefaultPlaneDirectory(dirout, "@daliPlane", "dali");
  2434. }
  2435. if (streq(category, "query"))
  2436. {
  2437. return getDefaultPlaneDirectory(dirout, "@dllPlane", "dll");
  2438. }
  2439. if (streq(category, "lock"))
  2440. {
  2441. //Called by NamedMutex. Currently unused in the containerized system.
  2442. dirout.append("/var/lib/HPCCSystems/lock");
  2443. return true;
  2444. }
  2445. if (streq(category, "key") || streq(category, "run"))
  2446. {
  2447. throw makeStringExceptionV(-1, "Unexpected category '%s' requested in containerized mode", category);
  2448. }
  2449. throw makeStringExceptionV(-1, "Unrecognised configuration category %s", category);
  2450. #else
  2451. Linked<const IPropertyTree> dirtree = useTree;
  2452. if (!dirtree)
  2453. dirtree.setown(getOSSdirTree());
  2454. if (dirtree && category && *category)
  2455. {
  2456. const char *name = dirtree->queryProp("@name");
  2457. if (name&&*name) {
  2458. StringBuffer q("Category[@name=\"");
  2459. q.append(category).append("\"]");
  2460. IPropertyTree *cat = dirtree->queryPropTree(q.str()); // assume only 1
  2461. if (cat) {
  2462. IPropertyTree *over = NULL;
  2463. if (instance&&*instance) {
  2464. q.clear().append("Override[@instance=\"").append(instance).append("\"]");
  2465. Owned<IPropertyTreeIterator> it1 = cat->getElements(q.str());
  2466. ForEach(*it1) {
  2467. IPropertyTree &o1 = it1->query();
  2468. if ((!component||!*component)) {
  2469. if (!over)
  2470. over = &o1;
  2471. }
  2472. else {
  2473. const char *comp = o1.queryProp("@component");
  2474. if (!comp||!*comp) {
  2475. if (!over)
  2476. over = &o1;
  2477. }
  2478. else if (strcmp(comp,component)==0) {
  2479. over = &o1;
  2480. break;
  2481. }
  2482. }
  2483. }
  2484. }
  2485. if (!over&&component&&*component) {
  2486. q.clear().append("Override[@component=\"").append(component).append("\"]");
  2487. Owned<IPropertyTreeIterator> it2 = cat->getElements(q.str());
  2488. ForEach(*it2) {
  2489. IPropertyTree &o2 = it2->query();
  2490. if ((!instance||!*instance)) {
  2491. over = &o2;
  2492. break;
  2493. }
  2494. else {
  2495. const char *inst = o2.queryProp("@instance");
  2496. if (!inst||!*inst) {
  2497. over = &o2;
  2498. break;
  2499. }
  2500. }
  2501. }
  2502. }
  2503. const char *dir = over?over->queryProp("@dir"):cat->queryProp("@dir");
  2504. if (dir&&*dir) {
  2505. fillConfigurationDirectoryEntry(dir,name,component,instance,dirout);
  2506. return true;
  2507. }
  2508. }
  2509. }
  2510. }
  2511. return false;
  2512. #endif
  2513. }
  2514. const char * matchConfigurationDirectoryEntry(const char *path,const char *mask,StringBuffer &name, StringBuffer &component, StringBuffer &instance)
  2515. {
  2516. // first check matches from (and set any values)
  2517. // only handles simple masks currently
  2518. StringBuffer var;
  2519. PointerArray val;
  2520. const char *m = mask;
  2521. const char *p = path;
  2522. for (;;) {
  2523. char c = *m;
  2524. if (!c)
  2525. break;
  2526. m++;
  2527. StringBuffer *out=NULL;
  2528. if (c=='[') {
  2529. if (memicmp(m,"NAME]",5)==0) {
  2530. out = &name;
  2531. m += 5;
  2532. }
  2533. else if (memicmp(m,"COMPONENT]",10)==0) {
  2534. out = &component;
  2535. m += 10;
  2536. }
  2537. else if (memicmp(m,"INST]",5)==0) {
  2538. out = &instance;
  2539. m += 5;
  2540. }
  2541. }
  2542. if (out) {
  2543. StringBuffer mtail;
  2544. while (*m&&!isPathSepChar(*m)&&(*m!='['))
  2545. mtail.append(*(m++));
  2546. StringBuffer ptail;
  2547. while (*p&&!isPathSepChar(*p))
  2548. ptail.append(*(p++));
  2549. if (ptail.length()<mtail.length())
  2550. return NULL;
  2551. size32_t l = ptail.length()-mtail.length();
  2552. if (l&&(memcmp(ptail.str()+l,mtail.str(),mtail.length())!=0))
  2553. return NULL;
  2554. out->clear().append(l,ptail.str());
  2555. }
  2556. else if (c!=*(p++))
  2557. return NULL;
  2558. }
  2559. if (!*p)
  2560. return p;
  2561. if (isPathSepChar(*p))
  2562. return p+1;
  2563. return NULL;
  2564. }
  2565. bool replaceConfigurationDirectoryEntry(const char *path,const char *frommask,const char *tomask,StringBuffer &out)
  2566. {
  2567. StringBuffer name;
  2568. StringBuffer comp;
  2569. StringBuffer inst;
  2570. const char *tail = matchConfigurationDirectoryEntry(path,frommask,name,comp,inst);
  2571. if (!tail)
  2572. return false;
  2573. fillConfigurationDirectoryEntry(tomask,name,comp,inst,out);
  2574. if (*tail)
  2575. addPathSepChar(out).append(tail);
  2576. return true;
  2577. }
  2578. bool validateConfigurationDirectory(const IPropertyTree* useTree, const char* category, const char* component, const char* instance, const char* dirToValidate)
  2579. {
  2580. if (isEmptyString(dirToValidate))
  2581. return false;
  2582. StringBuffer configDir;
  2583. if (!getConfigurationDirectory(useTree, category, component, instance, configDir))
  2584. return false;
  2585. addPathSepChar(configDir);
  2586. return hasPrefix(dirToValidate, configDir, true);
  2587. }
  2588. static CriticalSection sect;
  2589. static StringAttr processPath;
  2590. const char * queryCurrentProcessPath()
  2591. {
  2592. CriticalBlock block(sect);
  2593. if (processPath.isEmpty())
  2594. {
  2595. #if _WIN32
  2596. HMODULE hModule = GetModuleHandle(NULL);
  2597. char path[MAX_PATH];
  2598. if (GetModuleFileName(hModule, path, MAX_PATH) != 0)
  2599. processPath.set(path);
  2600. #elif defined (__APPLE__)
  2601. char path[PATH_MAX];
  2602. uint32_t size = sizeof(path);
  2603. ssize_t len = _NSGetExecutablePath(path, &size);
  2604. switch(len)
  2605. {
  2606. case -1:
  2607. {
  2608. char * biggerPath = new char[size];
  2609. if (_NSGetExecutablePath(biggerPath, &size) == 0)
  2610. processPath.set(biggerPath);
  2611. delete [] biggerPath;
  2612. }
  2613. break;
  2614. case 0:
  2615. processPath.set(path);
  2616. break;
  2617. default:
  2618. break;
  2619. }
  2620. const char *canon = realpath(processPath.str(), nullptr);
  2621. if (canon)
  2622. {
  2623. processPath.clear();
  2624. processPath.set(canon);
  2625. free((void *) canon);
  2626. }
  2627. #else
  2628. char path[PATH_MAX + 1];
  2629. ssize_t len = readlink("/proc/self/exe", path, PATH_MAX);
  2630. if (len != -1)
  2631. {
  2632. path[len] = 0;
  2633. processPath.set(path);
  2634. }
  2635. #endif
  2636. }
  2637. if (processPath.isEmpty())
  2638. return NULL;
  2639. return processPath.str();
  2640. }
  2641. bool getPackageFolder(StringBuffer & path)
  2642. {
  2643. StringBuffer folder;
  2644. splitDirTail(queryCurrentProcessPath(), folder);
  2645. removeTrailingPathSepChar(folder);
  2646. if (folder.length())
  2647. {
  2648. StringBuffer foldersFolder;
  2649. splitDirTail(folder.str(), foldersFolder);
  2650. if (foldersFolder.length())
  2651. {
  2652. path = foldersFolder;
  2653. return true;
  2654. }
  2655. }
  2656. return false;
  2657. }
  2658. inline bool isOctChar(char c)
  2659. {
  2660. return (c>='0' && c<'8');
  2661. }
  2662. inline int octValue(char c)
  2663. {
  2664. return c-'0';
  2665. }
  2666. int parseCommandLine(const char * cmdline, MemoryBuffer &mb, const char** &argvout)
  2667. {
  2668. mb.append((char)0);
  2669. size32_t arg[256];
  2670. int argc = 0;
  2671. arg[0] = 0;
  2672. char quotechar = 0;
  2673. for (;;) {
  2674. char c = *(cmdline++);
  2675. switch(c) {
  2676. case ' ':
  2677. case '\t':
  2678. if (quotechar)
  2679. break;
  2680. // fall through
  2681. case 0: {
  2682. if (arg[argc]) {
  2683. while (mb.length()>arg[argc]) {
  2684. size32_t l = mb.length()-1;
  2685. const byte * b = ((const byte *)mb.bufferBase())+l;
  2686. if ((*b!=' ')&&(*b!='\t'))
  2687. break;
  2688. mb.setLength(l);
  2689. }
  2690. if (mb.length()>arg[argc]) {
  2691. mb.append((char)0);
  2692. argc++;
  2693. }
  2694. if (c) {
  2695. if (argc==256)
  2696. throw makeStringException(-1, "parseCommandLine: too many arguments");
  2697. arg[argc] = 0;
  2698. }
  2699. }
  2700. if (c)
  2701. continue;
  2702. argvout = (const char **)mb.reserve(argc*sizeof(const char *));
  2703. for (int i=0;i<argc;i++)
  2704. argvout[i] = arg[i]+(const char *)mb.bufferBase();
  2705. return argc;
  2706. }
  2707. break;
  2708. case '\'':
  2709. case '"':
  2710. if (c==quotechar) {
  2711. quotechar = 0;
  2712. continue;
  2713. }
  2714. if (quotechar)
  2715. break;
  2716. quotechar = c;
  2717. continue;
  2718. case '\\': {
  2719. if (*cmdline&&!quotechar) {
  2720. c = *(cmdline++);
  2721. switch (c) {
  2722. case 'a': c = '\a'; break;
  2723. case 'b': c = '\b'; break;
  2724. case 'f': c = '\f'; break;
  2725. case 'n': c = '\n'; break;
  2726. case 'r': c = '\r'; break;
  2727. case 't': c = '\t'; break;
  2728. case 'v': c = '\v'; break;
  2729. case 'x': case 'X': {
  2730. c = 0;
  2731. if (isHexChar(*cmdline)) {
  2732. c = hexValue(*(cmdline++));
  2733. if (isHexChar(*cmdline))
  2734. c = ((byte)c*16)+hexValue(*(cmdline++));
  2735. }
  2736. }
  2737. break;
  2738. case '0': case '1': case '2': case '3':
  2739. case '4': case '5': case '6': case '7': {
  2740. c = octValue(c);
  2741. if (isOctChar(*cmdline)) {
  2742. c = ((byte)c*8)+octValue(*(cmdline++));
  2743. if (isOctChar(*cmdline))
  2744. c = ((byte)c*8)+octValue(*(cmdline++));
  2745. }
  2746. }
  2747. break;
  2748. }
  2749. }
  2750. }
  2751. break;
  2752. }
  2753. if (!arg[argc])
  2754. arg[argc] = mb.length();
  2755. mb.append(c);
  2756. }
  2757. return 0;
  2758. }
  2759. static StringBuffer &doGetTempFilePath(StringBuffer & target, const char *tempCategory, const char * component, IPropertyTree * pTree)
  2760. {
  2761. StringBuffer dir;
  2762. if (pTree)
  2763. getConfigurationDirectory(pTree->queryPropTree("Directories"),tempCategory,component,pTree->queryProp("@name"),dir);
  2764. bool ok = false;
  2765. if (!dir.isEmpty())
  2766. {
  2767. ok = recursiveCreateDirectory(dir.str());
  2768. if (ok)
  2769. {
  2770. #ifdef _WIN32
  2771. return target.set(dir);
  2772. #else
  2773. int srtn = access(dir.str(), R_OK|W_OK|X_OK);
  2774. if (!srtn)
  2775. return target.set(dir);
  2776. #endif
  2777. }
  2778. }
  2779. // runtime dir
  2780. dir.clear();
  2781. dir.append(RUNTIME_DIR);
  2782. dir.append(PATHSEPCHAR).append("hpcc-data").append(PATHSEPCHAR).append(component);
  2783. dir.append(PATHSEPCHAR).append("temp");
  2784. ok = recursiveCreateDirectory(dir.str());
  2785. if (ok)
  2786. {
  2787. #ifdef _WIN32
  2788. return target.set(dir);
  2789. #else
  2790. int srtn = access(dir.str(), R_OK|W_OK|X_OK);
  2791. if (!srtn)
  2792. return target.set(dir);
  2793. #endif
  2794. }
  2795. // tmp dir
  2796. StringBuffer tmpdir;
  2797. #ifdef _WIN32
  2798. char path[_MAX_PATH+1];
  2799. if(GetTempPath(sizeof(path),path))
  2800. tmpdir.append(path);
  2801. else
  2802. tmpdir.append("C:\\TEMP"); // or C:\\Windows\\TEMP ?
  2803. #else
  2804. tmpdir.append(getenv("TMPDIR"));
  2805. if (tmpdir.isEmpty())
  2806. tmpdir.append("/tmp");
  2807. #endif
  2808. dir.clear();
  2809. dir.append(tmpdir);
  2810. dir.append(PATHSEPCHAR).append("HPCCSystems");
  2811. dir.append(PATHSEPCHAR).append("hpcc-data").append(PATHSEPCHAR).append(component);
  2812. dir.append(PATHSEPCHAR).append("temp");
  2813. ok = recursiveCreateDirectory(dir.str());
  2814. if (ok)
  2815. {
  2816. #ifdef _WIN32
  2817. return target.set(dir);
  2818. #else
  2819. int srtn = access(dir.str(), R_OK|W_OK|X_OK);
  2820. if (!srtn)
  2821. return target.set(dir);
  2822. #endif
  2823. }
  2824. #ifdef _WIN32
  2825. throw MakeStringException(-1, "Unable to create temp directory");
  2826. #else
  2827. // uniq tmp - perhaps previous dirs above were owned by others ...
  2828. dir.clear();
  2829. dir.append(tmpdir);
  2830. dir.append(PATHSEPCHAR).append("HPCCSystems-XXXXXX");
  2831. char templt[256];
  2832. strcpy(templt, dir.str());
  2833. char *td = mkdtemp(templt);
  2834. if (!td)
  2835. throw MakeStringException(-1, "Unable to create temp directory");
  2836. return target.set(templt);
  2837. #endif
  2838. }
  2839. jlib_decl StringBuffer &getTempFilePath(StringBuffer & target, const char * component, IPropertyTree * pTree)
  2840. {
  2841. return doGetTempFilePath(target, "temp", component, pTree);
  2842. }
  2843. jlib_decl StringBuffer &getSpillFilePath(StringBuffer & target, const char * component, IPropertyTree * pTree)
  2844. {
  2845. return doGetTempFilePath(target, "spill", component, pTree);
  2846. }
  2847. const char *getEnumText(int value, const EnumMapping *map)
  2848. {
  2849. while (map->str)
  2850. {
  2851. if (value==map->val)
  2852. return map->str;
  2853. map++;
  2854. }
  2855. throwUnexpectedX("Unexpected value in getEnumText");
  2856. }
  2857. int getEnum(const char *v, const EnumMapping *map)
  2858. {
  2859. if (v && *v)
  2860. {
  2861. while (map->str)
  2862. {
  2863. if (stricmp(v, map->str)==0)
  2864. return map->val;
  2865. map++;
  2866. }
  2867. throwUnexpectedX("Unexpected value in getEnum");
  2868. }
  2869. return 0;
  2870. }
  2871. const char *getEnumText(int value, const EnumMapping *map, const char * defval)
  2872. {
  2873. while (map->str)
  2874. {
  2875. if (value==map->val)
  2876. return map->str;
  2877. map++;
  2878. }
  2879. return defval;
  2880. }
  2881. int getEnum(const char *v, const EnumMapping *map, int defval)
  2882. {
  2883. if (v && *v)
  2884. {
  2885. while (map->str)
  2886. {
  2887. if (stricmp(v, map->str)==0)
  2888. return map->val;
  2889. map++;
  2890. }
  2891. }
  2892. return defval;
  2893. }
  2894. //---------------------------------------------------------------------------------------------------------------------
  2895. extern jlib_decl offset_t friendlyStringToSize(const char *in)
  2896. {
  2897. char *tail;
  2898. offset_t result = strtoull(in, &tail, 10);
  2899. offset_t scale = 1;
  2900. if (*tail)
  2901. {
  2902. if (tail[1] == '\0')
  2903. {
  2904. switch (*tail)
  2905. {
  2906. case 'K': scale = 1000; break;
  2907. case 'M': scale = 1000000; break;
  2908. case 'G': scale = 1000000000; break;
  2909. case 'T': scale = 1000000000000; break;
  2910. case 'P': scale = 1000000000000000; break;
  2911. case 'E': scale = 1000000000000000000; break;
  2912. default:
  2913. throw makeStringExceptionV(0, "Invalid size suffix %s", tail);
  2914. }
  2915. }
  2916. else if (streq(tail+1, "i"))
  2917. {
  2918. switch (*tail)
  2919. {
  2920. case 'K': scale = 1llu<<10; break;
  2921. case 'M': scale = 1llu<<20; break;
  2922. case 'G': scale = 1llu<<30; break;
  2923. case 'T': scale = 1llu<<40; break;
  2924. case 'P': scale = 1llu<<50; break;
  2925. case 'E': scale = 1llu<<60; break;
  2926. default:
  2927. throw makeStringExceptionV(0, "Invalid size suffix %s", tail);
  2928. }
  2929. }
  2930. else
  2931. throw makeStringExceptionV(0, "Invalid size suffix %s", tail);
  2932. }
  2933. return result * scale;
  2934. }
  2935. void jlib_decl atomicWriteFile(const char *fileName, const char *output)
  2936. {
  2937. recursiveCreateDirectoryForFile(fileName);
  2938. #ifdef _WIN32
  2939. StringBuffer newFileName;
  2940. makeTempCopyName(newFileName, fileName);
  2941. Owned<IFile> newFile = createIFile(newFileName);
  2942. Owned<IFile> file = createIFile(fileName);
  2943. {
  2944. OwnedIFileIO ifileio = newFile->open(IFOcreate);
  2945. if (!ifileio)
  2946. throw MakeStringException(0, "atomicWriteFile: could not create output file %s", newFileName.str());
  2947. ifileio->write(0, strlen(output), output);
  2948. }
  2949. #else
  2950. VStringBuffer newFileName("%s.XXXXXX", fileName);
  2951. int fh = mkstemp(const_cast<char *>(newFileName.str()));
  2952. if (fh==-1)
  2953. throw MakeStringException(0, "atomicWriteFile: could not create output file for %s", fileName);
  2954. Owned<IFile> newFile = createIFile(newFileName);
  2955. Owned<IFile> file = createIFile(fileName);
  2956. {
  2957. OwnedIFileIO ifileio = createIFileIO(fh, IFOwrite);
  2958. if (!ifileio)
  2959. throw MakeStringException(0, "atomicWriteFile: could not create output file %s", newFileName.str());
  2960. ifileio->write(0, strlen(output), output);
  2961. }
  2962. #endif
  2963. if (file->exists())
  2964. file->remove();
  2965. newFile->rename(fileName);
  2966. }
  2967. //---------------------------------------------------------------------------------------------------------------------
  2968. const char * generatePassword(StringBuffer &pwd, int pwdLen)
  2969. {
  2970. if (pwdLen < 8)
  2971. throw makeStringException(0, "Generated Passwords must be at least 8 characters in length");
  2972. #define NUM_GROUPS 4 //4 character groups follow
  2973. const char alphaUC[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  2974. const char alphaLC[] = "abcdefghijklmnopqrstuvwxyz";
  2975. const char numeric[] = "0123456789";
  2976. const char symbol[] = "~`!@#$%^&*()_-+={[}]|:;<,>.?/";
  2977. //Ensures each character group used at least once
  2978. srand(time(0));
  2979. pwd.append(alphaUC[rand() % sizeof(alphaUC)]);
  2980. pwd.append(alphaLC[rand() % sizeof(alphaLC)]);
  2981. pwd.append(numeric[rand() % sizeof(numeric)]);
  2982. pwd.append(symbol[rand() % sizeof(symbol)]);
  2983. for (int i = 4; i < pwdLen; i++)
  2984. {
  2985. switch(rand() % NUM_GROUPS)//select a random character group
  2986. {
  2987. case 0:
  2988. pwd.append(alphaUC[rand() % sizeof(alphaUC)]); break;
  2989. case 1:
  2990. pwd.append(alphaLC[rand() % sizeof(alphaLC)]); break;
  2991. case 2:
  2992. pwd.append(numeric[rand() % sizeof(numeric)]); break;
  2993. case 3:
  2994. pwd.append(symbol[rand() % sizeof(symbol)]); break;
  2995. }
  2996. }
  2997. return pwd.str();
  2998. }
  2999. //---------------------------------------------------------------------------------------------------------------------
  3000. bool checkCreateDaemon(unsigned argc, const char * * argv)
  3001. {
  3002. #ifndef _CONTAINERIZED
  3003. for (unsigned i=0;i<(unsigned)argc;i++) {
  3004. if (streq(argv[i],"--daemon") || streq(argv[i],"-d")) {
  3005. if (daemon(1,0) || write_pidfile(argv[++i])) {
  3006. perror("Failed to daemonize");
  3007. return false;
  3008. }
  3009. break;
  3010. }
  3011. }
  3012. #endif
  3013. return true;
  3014. }
  3015. //#define TESTURL
  3016. #ifdef TESTURL
  3017. static int doTests()
  3018. {
  3019. const char* ps[] = {
  3020. "ABCD", "@BCD", "%BCD","&BCD","A CD","A/CD", "A@@%%A","A&%/@"
  3021. };
  3022. const int N = sizeof(ps)/sizeof(char*);
  3023. for (int i=0; i<N; i++)
  3024. {
  3025. StringBuffer raw, encoded;
  3026. encodeUrlUseridPassword(encoded,ps[i]);
  3027. printf("Encoded: %s\n", encoded.str());
  3028. decodeUrlUseridPassword(raw,encoded);
  3029. if (strcmp(raw.str(),ps[i])!=0)
  3030. assert(!"decoding error");
  3031. }
  3032. return 0;
  3033. }
  3034. int gDummy = doTests();
  3035. #endif