1
0

util.c 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /* util.c -- utility functions -- functions available form libslapd */
  13. #include <sys/socket.h>
  14. #include <sys/param.h>
  15. #include <unistd.h>
  16. #include <pwd.h>
  17. #include <stdint.h>
  18. #include <fcntl.h>
  19. #include <libgen.h>
  20. #include <pk11func.h>
  21. #include "slap.h"
  22. #include "prtime.h"
  23. #include "prinrval.h"
  24. #include "snmp_collator.h"
  25. #include <sys/time.h>
  26. #include <sys/resource.h>
  27. #define UTIL_ESCAPE_NONE 0
  28. #define UTIL_ESCAPE_HEX 1
  29. #define UTIL_ESCAPE_BACKSLASH 2
  30. #define _PSEP "/"
  31. #define _PSEP2 "//"
  32. #define _CSEP '/'
  33. /* slapi_filter_sprintf macros */
  34. #define ATTRSIZE 256 /* size allowed for an attr name */
  35. #define FILTER_BUF 128 /* initial buffer size for attr value */
  36. #define BUF_INCR 16 /* the amount to increase the FILTER_BUF once it fills up */
  37. /* Used by our util_info_sys_pages function
  38. *
  39. * platforms supported so far:
  40. * Solaris, Linux, Windows
  41. */
  42. #ifdef OS_solaris
  43. #include <sys/procfs.h>
  44. #endif
  45. #ifdef LINUX
  46. #include <linux/kernel.h>
  47. #endif
  48. #if defined ( hpux )
  49. #include <sys/pstat.h>
  50. #endif
  51. static int special_np(unsigned char c)
  52. {
  53. if (c == '\\') {
  54. return UTIL_ESCAPE_BACKSLASH;
  55. }
  56. if (c < 32 || c > 126 || c == '"') {
  57. return UTIL_ESCAPE_HEX;
  58. }
  59. return UTIL_ESCAPE_NONE;
  60. }
  61. static int special_np_and_punct(unsigned char c)
  62. {
  63. if (c == '\\') {
  64. return UTIL_ESCAPE_BACKSLASH;
  65. }
  66. if (c < 32 || c > 126 || c == '"' || c == '*') {
  67. return UTIL_ESCAPE_HEX;
  68. }
  69. return UTIL_ESCAPE_NONE;
  70. }
  71. #ifndef USE_OPENLDAP
  72. static int special_filter(unsigned char c)
  73. {
  74. /*
  75. * Escape all non-printing chars and double-quotes in addition
  76. * to those required by RFC 2254 so that we can use the string
  77. * in log files.
  78. */
  79. return (c < 32 ||
  80. c > 126 ||
  81. c == '*' ||
  82. c == '(' ||
  83. c == ')' ||
  84. c == '\\' ||
  85. c == '"') ? UTIL_ESCAPE_HEX : UTIL_ESCAPE_NONE;
  86. }
  87. #endif
  88. /*
  89. * Used by filter_stuff_func to help extract an attribute so we know
  90. * how to normalize the value.
  91. */
  92. static int
  93. special_attr_char(unsigned char c)
  94. {
  95. return (c < 32 ||
  96. c > 126 ||
  97. c == '*' ||
  98. c == '|' ||
  99. c == '&' ||
  100. c == '!' ||
  101. c == '(' ||
  102. c == ')' ||
  103. c == '\\' ||
  104. c == '=' ||
  105. c == '"');
  106. }
  107. static const char*
  108. do_escape_string (
  109. const char* str,
  110. int len, /* -1 means str is nul-terminated */
  111. char buf[BUFSIZ],
  112. int (*special)(unsigned char)
  113. )
  114. {
  115. const char* s;
  116. const char* last;
  117. int esc;
  118. if (str == NULL) {
  119. *buf = '\0';
  120. return buf;
  121. }
  122. if (len == -1) len = strlen (str);
  123. if (len == 0) return str;
  124. last = str + len - 1;
  125. for (s = str; s <= last; ++s) {
  126. if ( (esc = (*special)((unsigned char)*s))) {
  127. const char* first = str;
  128. char* bufNext = buf;
  129. int bufSpace = BUFSIZ - 4;
  130. while (1) {
  131. if (bufSpace < (s - first)) s = first + bufSpace - 1;
  132. if (s > first) {
  133. memcpy (bufNext, first, s - first);
  134. bufNext += (s - first);
  135. bufSpace -= (s - first);
  136. }
  137. if (s > last) {
  138. break;
  139. }
  140. do {
  141. if (esc == UTIL_ESCAPE_BACKSLASH) {
  142. /* *s is '\\' */
  143. /* If *(s+1) and *(s+2) are both hex digits,
  144. * the char is already escaped. */
  145. if (isxdigit(*(s+1)) && isxdigit(*(s+2))) {
  146. memcpy(bufNext, s, 3);
  147. bufNext += 3;
  148. bufSpace -= 3;
  149. s += 2;
  150. } else {
  151. *bufNext++ = *s; --bufSpace;
  152. }
  153. } else { /* UTIL_ESCAPE_HEX */
  154. *bufNext++ = '\\'; --bufSpace;
  155. if (bufSpace < 3) {
  156. memcpy(bufNext, "..", 2);
  157. bufNext += 2;
  158. goto bail;
  159. }
  160. PR_snprintf(bufNext, 3, "%02x", *(unsigned char*)s);
  161. bufNext += 2; bufSpace -= 2;
  162. }
  163. } while (++s <= last &&
  164. (esc = (*special)((unsigned char)*s)));
  165. if (s > last) break;
  166. first = s;
  167. while ( (esc = (*special)((unsigned char)*s)) == UTIL_ESCAPE_NONE && s <= last) ++s;
  168. }
  169. bail:
  170. *bufNext = '\0';
  171. return buf;
  172. }
  173. }
  174. return str;
  175. }
  176. /*
  177. * Function: escape_string
  178. * Arguments: str: string
  179. * buf: a char array of BUFSIZ length, in which the escaped string will
  180. * be returned.
  181. * Returns: a pointer to buf, if str==NULL or it needed to be escaped, or
  182. * str itself otherwise.
  183. *
  184. * This function should only be used for generating loggable strings.
  185. */
  186. const char*
  187. escape_string (const char* str, char buf[BUFSIZ])
  188. {
  189. return do_escape_string(str,-1,buf,special_np);
  190. }
  191. const char*
  192. escape_string_with_punctuation(const char* str, char buf[BUFSIZ])
  193. {
  194. return do_escape_string(str,-1,buf,special_np_and_punct);
  195. }
  196. #define ESCAPE_FILTER 1
  197. #define NORM_FILTER 2
  198. struct filter_ctx {
  199. char *buf;
  200. char attr[ATTRSIZE];
  201. int attr_position;
  202. int attr_found;
  203. int buf_size;
  204. int buf_len;
  205. int next_arg_needs_esc_norm;
  206. int skip_escape;
  207. };
  208. /*
  209. * This function is called by slapi_filter_sprintf to escape/normalize certain values
  210. */
  211. static PRIntn
  212. filter_stuff_func(void *arg, const char *val, PRUint32 slen)
  213. {
  214. struct filter_ctx *ctx = (struct filter_ctx *)arg;
  215. #if defined (USE_OPENLDAP)
  216. struct berval escaped_filter;
  217. struct berval raw_filter;
  218. #endif
  219. char *buf = (char *)val;
  220. int extra_space;
  221. int filter_len = slen;
  222. /* look at val - if val is one of our special keywords, and make a note of it for the next pass */
  223. if (strcmp(val, ESC_NEXT_VAL) == 0){
  224. ctx->next_arg_needs_esc_norm |= ESCAPE_FILTER;
  225. return 0;
  226. }
  227. if (strcmp(val, NORM_NEXT_VAL) == 0){
  228. ctx->next_arg_needs_esc_norm |= NORM_FILTER;
  229. return 0;
  230. }
  231. if (strcmp(val, ESC_AND_NORM_NEXT_VAL) == 0){
  232. ctx->next_arg_needs_esc_norm = NORM_FILTER | ESCAPE_FILTER;
  233. return 0;
  234. }
  235. /*
  236. * Start collecting the attribute name so we can use the correct
  237. * syntax normalization func.
  238. */
  239. if(ctx->attr_found == 0 && ctx->attr_position < (ATTRSIZE - 1)){
  240. if(ctx->attr[0] == '\0'){
  241. if(strstr(val,"=")){
  242. /* we have an attr we need to record */
  243. if(!special_attr_char(val[0])){
  244. memcpy(ctx->attr, val, 1);
  245. ctx->attr_position++;
  246. }
  247. } else {
  248. /*
  249. * We have passed in an attribute as a arg - so we can just set the
  250. * attr with val. The next pass should be '=', otherwise we will
  251. * reset it.
  252. */
  253. memcpy(ctx->attr, val, slen);
  254. ctx->attr_position = slen;
  255. }
  256. } else {
  257. if(val[0] == '='){ /* hit the end of the attribute name */
  258. ctx->attr_found = 1;
  259. } else {
  260. if(special_attr_char(val[0])){
  261. /* this is not an attribute, we should not be collecting this, reset everything */
  262. memset(ctx->attr, '\0', ATTRSIZE);
  263. ctx->attr_position = 0;
  264. } else {
  265. memcpy(ctx->attr + ctx->attr_position, val, 1);
  266. ctx->attr_position++;
  267. }
  268. }
  269. }
  270. }
  271. if (ctx->next_arg_needs_esc_norm && !ctx->skip_escape){
  272. /*
  273. * Normalize the filter value first
  274. */
  275. if(ctx->next_arg_needs_esc_norm & NORM_FILTER){
  276. char *norm_val = NULL;
  277. if(ctx->attr_found){
  278. slapi_attr_value_normalize(NULL, NULL, ctx->attr , buf, 1, &norm_val );
  279. if(norm_val){
  280. buf = norm_val;
  281. filter_len = strlen(buf);
  282. }
  283. }
  284. }
  285. /*
  286. * Escape the filter value
  287. */
  288. if(ctx->next_arg_needs_esc_norm & ESCAPE_FILTER){
  289. #if defined (USE_OPENLDAP)
  290. raw_filter.bv_val = (char *)buf;
  291. raw_filter.bv_len = filter_len;
  292. if(ldap_bv2escaped_filter_value(&raw_filter, &escaped_filter) != 0){
  293. LDAPDebug(LDAP_DEBUG_TRACE, "slapi_filter_sprintf: failed to escape filter value(%s)\n",val,0,0);
  294. ctx->next_arg_needs_esc_norm = 0;
  295. return -1;
  296. } else {
  297. filter_len = escaped_filter.bv_len;
  298. buf = escaped_filter.bv_val;
  299. }
  300. #else
  301. char *val2 = NULL;
  302. buf = slapi_ch_calloc(sizeof(char), filter_len*3 + 1);
  303. val2 = (char *)do_escape_string(val, filter_len, buf, special_filter);
  304. if(val2 == NULL){
  305. LDAPDebug(LDAP_DEBUG_TRACE, "slapi_filter_sprintf: failed to escape filter value(%s)\n",val,0,0);
  306. ctx->next_arg_needs_esc_norm = 0;
  307. slapi_ch_free_string(&buf);
  308. return -1;
  309. } else if (val == val2) { /* value did not need escaping and was just returned */
  310. strcpy(buf, val); /* just use value as-is - len did not change */
  311. } else {
  312. filter_len = strlen(buf);
  313. }
  314. #endif
  315. }
  316. /*
  317. * Now add the new value to the buffer, and allocate more memory if needed
  318. */
  319. if (ctx->buf_size + filter_len >= ctx->buf_len){
  320. /* increase buffer for this filter */
  321. extra_space = (ctx->buf_len + filter_len + BUF_INCR);
  322. ctx->buf = slapi_ch_realloc(ctx->buf, sizeof(char) * extra_space);
  323. ctx->buf_len = extra_space;
  324. }
  325. /* append the escaped value */
  326. memcpy(ctx->buf + ctx->buf_size, buf, filter_len);
  327. ctx->buf_size += filter_len;
  328. /* done with the value, reset everything */
  329. ctx->next_arg_needs_esc_norm = 0;
  330. ctx->attr_found = 0;
  331. ctx->attr_position = 0;
  332. memset(ctx->attr, '\0', ATTRSIZE);
  333. slapi_ch_free_string(&buf);
  334. return filter_len;
  335. } else { /* process arg as is */
  336. /* check if we have enough room in our buffer */
  337. if (ctx->buf_size + slen >= ctx->buf_len){
  338. /* increase buffer for this filter */
  339. extra_space = (ctx->buf_len + slen + BUF_INCR);
  340. ctx->buf = slapi_ch_realloc((char *)ctx->buf, sizeof(char) * extra_space);
  341. ctx->buf_len = extra_space;
  342. }
  343. memcpy(ctx->buf + ctx->buf_size, buf, slen);
  344. ctx->buf_size += slen;
  345. return slen;
  346. }
  347. }
  348. /*
  349. * This is basically like slapi_ch_smprintf() except it can handle special
  350. * keywords that will cause the next value to be escaped and/or normalized.
  351. *
  352. * ESC_NEXT_VAL - escape the next value
  353. * NORM_NEXT_VAL - normalize the next value
  354. * ESC_AND_NORM_NEXT_VAL - escape and normalize the next value
  355. *
  356. * Example:
  357. *
  358. * slapi_filter_sprintf("cn=%s%s", ESC_NEXT_VAL, value);
  359. * slapi_filter_sprintf("(|(cn=%s%s)(sn=%s%s))", ESC_NEXT_VAL, value, NORM_NEXT_VAL, value);
  360. *
  361. * Note: you need a string format specifier(%s) for each keyword
  362. */
  363. char*
  364. slapi_filter_sprintf(const char *fmt, ...)
  365. {
  366. struct filter_ctx ctx;
  367. va_list args;
  368. char *buf;
  369. int rc;
  370. buf = slapi_ch_calloc(sizeof(char), FILTER_BUF + 1);
  371. ctx.buf = buf;
  372. memset(ctx.attr,'\0', ATTRSIZE);
  373. ctx.attr_position = 0;
  374. ctx.attr_found = 0;
  375. ctx.buf_len = FILTER_BUF;
  376. ctx.buf_size = 0;
  377. ctx.next_arg_needs_esc_norm = 0;
  378. ctx.skip_escape = 0;
  379. va_start(args, fmt);
  380. rc = PR_vsxprintf(filter_stuff_func, &ctx, fmt, args);
  381. if(rc == -1){
  382. /* transformation failed, just return non-normalized/escaped string */
  383. ctx.skip_escape = 1;
  384. PR_vsxprintf(filter_stuff_func, &ctx, fmt, args);
  385. }
  386. va_end(args);
  387. return ctx.buf;
  388. }
  389. /*
  390. * escape special characters in values used in search filters
  391. *
  392. * caller must free the returned value
  393. */
  394. char*
  395. slapi_escape_filter_value(char* filter_str, int len)
  396. {
  397. #if defined (USE_OPENLDAP)
  398. struct berval escaped_filter;
  399. struct berval raw_filter;
  400. #endif
  401. int filter_len;
  402. /*
  403. * Check the length for special cases
  404. */
  405. if(len == -1){
  406. /* filter str is null terminated */
  407. filter_len = strlen(filter_str);
  408. } else if (len == 0){
  409. /* return the filter as is */
  410. return slapi_ch_strdup(filter_str);
  411. } else {
  412. /* the len is the length */
  413. filter_len = len;
  414. }
  415. #if defined (USE_OPENLDAP)
  416. /*
  417. * Construct the berval and escape it
  418. */
  419. raw_filter.bv_val = filter_str;
  420. raw_filter.bv_len = filter_len;
  421. if(ldap_bv2escaped_filter_value(&raw_filter, &escaped_filter) != 0){
  422. LDAPDebug(LDAP_DEBUG_TRACE, "slapi_escape_filter_value: failed to escape filter value(%s)\n",filter_str,0,0);
  423. return NULL;
  424. } else {
  425. return escaped_filter.bv_val;
  426. }
  427. #else
  428. char *buf = slapi_ch_calloc(sizeof(char), filter_len*3+1);
  429. char *esc_str = (char *)do_escape_string(filter_str, filter_len, buf, special_filter);
  430. if(esc_str != buf){
  431. slapi_ch_free_string(&buf);
  432. return slapi_ch_strdup(esc_str);
  433. } else {
  434. return buf;
  435. }
  436. #endif
  437. }
  438. /*
  439. ** This function takes a quoted attribute value of the form "abc",
  440. ** and strips off the enclosing quotes. It also deals with quoted
  441. ** characters by removing the preceeding '\' character.
  442. **
  443. */
  444. void
  445. strcpy_unescape_value( char *d, const char *s )
  446. {
  447. int gotesc = 0;
  448. const char *end = s + strlen(s);
  449. for ( ; *s; s++ )
  450. {
  451. switch ( *s )
  452. {
  453. case '"':
  454. break;
  455. case '\\':
  456. gotesc = 1;
  457. if ( s+2 < end ) {
  458. int n = slapi_hexchar2int( s[1] );
  459. if ( n >= 0 && n < 16 ) {
  460. int n2 = slapi_hexchar2int( s[2] );
  461. if ( n2 >= 0 ) {
  462. n = (n << 4) + n2;
  463. if (n == 0) { /* don't change \00 */
  464. *d++ = *s++;
  465. *d++ = *s++;
  466. *d++ = *s;
  467. } else { /* change \xx to a single char */
  468. *d++ = (char)n;
  469. s += 2;
  470. }
  471. gotesc = 0;
  472. }
  473. }
  474. }
  475. /* This is an escaped single character (like \"), so
  476. * just copy the special character and not the escape.
  477. * We need to be careful to not go past the end of
  478. * the string when the loop increments s. */
  479. if (gotesc && (s+1 < end)) {
  480. s++;
  481. *d++ = *s;
  482. gotesc = 0;
  483. }
  484. break;
  485. default:
  486. *d++ = *s;
  487. break;
  488. }
  489. }
  490. *d = '\0';
  491. }
  492. /* functions to convert between an entry and a set of mods */
  493. int slapi_mods2entry (Slapi_Entry **e, const char *idn, LDAPMod **iattrs)
  494. {
  495. int i, rc = LDAP_SUCCESS;
  496. LDAPMod **attrs= NULL;
  497. PR_ASSERT (idn);
  498. PR_ASSERT (iattrs);
  499. PR_ASSERT (e);
  500. attrs = normalize_mods2bvals((const LDAPMod **)iattrs);
  501. PR_ASSERT (attrs);
  502. /* Construct an entry */
  503. *e = slapi_entry_alloc();
  504. PR_ASSERT (*e);
  505. slapi_entry_init(*e, slapi_ch_strdup(idn), NULL);
  506. for (i = 0; rc==LDAP_SUCCESS && attrs[ i ]!=NULL; i++)
  507. {
  508. char *normtype;
  509. Slapi_Value **vals;
  510. /*
  511. * slapi_entry_apply_mod_extension applys mod and stores
  512. * the result in the extension
  513. * return value: 1 - mod is applied and stored in extension
  514. * -1 - mod is applied and failed
  515. * 0 - mod is nothing to do with extension
  516. */
  517. rc = slapi_entry_apply_mod_extension(*e, attrs[i], -1);
  518. if (rc) {
  519. if (1 == rc) {
  520. rc = LDAP_SUCCESS;
  521. } else {
  522. rc = LDAP_OPERATIONS_ERROR;
  523. }
  524. #if !defined(USE_OLD_UNHASHED)
  525. /* In case USE_OLD_UNHASHED,
  526. * unhashed pw needs to be in attr, too. */
  527. continue;
  528. #endif
  529. }
  530. normtype = slapi_attr_syntax_normalize(attrs[ i ]->mod_type);
  531. valuearray_init_bervalarray(attrs[ i ]->mod_bvalues, &vals);
  532. if (strcasecmp(normtype, SLAPI_USERPWD_ATTR) == 0)
  533. {
  534. pw_encodevals(vals);
  535. }
  536. /* set entry uniqueid - also adds attribute to the list */
  537. if (strcasecmp(normtype, SLAPI_ATTR_UNIQUEID) == 0) {
  538. if (vals) {
  539. slapi_entry_set_uniqueid (*e,
  540. slapi_ch_strdup (slapi_value_get_string(vals[0])));
  541. } else {
  542. rc = LDAP_NO_SUCH_ATTRIBUTE;
  543. }
  544. } else {
  545. rc = slapi_entry_add_values_sv(*e, normtype, vals);
  546. }
  547. valuearray_free(&vals);
  548. if (rc != LDAP_SUCCESS)
  549. {
  550. LDAPDebug2Args(LDAP_DEBUG_ANY,
  551. "slapi_mods2entry: add_values for type %s failed (rc: %d)\n",
  552. normtype, rc );
  553. slapi_entry_free (*e);
  554. *e = NULL;
  555. }
  556. slapi_ch_free((void **) &normtype);
  557. }
  558. freepmods(attrs);
  559. return rc;
  560. }
  561. int
  562. slapi_entry2mods (const Slapi_Entry *e, char **dn, LDAPMod ***attrs)
  563. {
  564. Slapi_Mods smods;
  565. Slapi_Attr *attr;
  566. Slapi_Value **va;
  567. char *type;
  568. int rc;
  569. PR_ASSERT (e && attrs);
  570. if (dn)
  571. *dn = slapi_ch_strdup (slapi_entry_get_dn ((Slapi_Entry *)e));
  572. slapi_mods_init (&smods, 0);
  573. rc = slapi_entry_first_attr(e, &attr);
  574. while (rc == 0)
  575. {
  576. if ( NULL != ( va = attr_get_present_values( attr ))) {
  577. slapi_attr_get_type(attr, &type);
  578. slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD, type, va );
  579. }
  580. rc = slapi_entry_next_attr(e, attr, &attr);
  581. }
  582. #if !defined(USE_OLD_UNHASHED)
  583. if (SLAPD_UNHASHED_PW_ON == config_get_unhashed_pw_switch()) {
  584. /* store unhashed passwd is enabled */
  585. /* In case USE_OLD_UNHASHED, unhashed pw is already in mods */
  586. /* add extension to mods */
  587. rc = slapi_pw_get_entry_ext((Slapi_Entry *)e, &va);
  588. if (LDAP_SUCCESS == rc) {
  589. /* va is copied and set to smods */
  590. slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD,
  591. PSEUDO_ATTR_UNHASHEDUSERPASSWORD, va);
  592. }
  593. }
  594. #endif
  595. *attrs = slapi_mods_get_ldapmods_passout (&smods);
  596. slapi_mods_done (&smods);
  597. return 0;
  598. }
  599. /******************************************************************************
  600. *
  601. * normalize_mods2bvals
  602. *
  603. * Return value: normalized mods
  604. * The values/bvals are all duplicated in this function since
  605. * the normalized mods are freed with ldap_mods_free by the caller.
  606. *
  607. *******************************************************************************/
  608. LDAPMod **
  609. normalize_mods2bvals(const LDAPMod **mods)
  610. {
  611. int w, x, vlen, num_values, num_mods;
  612. LDAPMod **normalized_mods;
  613. if (mods == NULL)
  614. {
  615. return NULL;
  616. }
  617. /* first normalize the mods so they are bvalues */
  618. /* count the number of mods -- sucks but should be small */
  619. num_mods = 1;
  620. for (w=0; mods[w] != NULL; w++) num_mods++;
  621. normalized_mods = (LDAPMod **) slapi_ch_calloc(num_mods, sizeof(LDAPMod *));
  622. for (w = 0; mods[w] != NULL; w++)
  623. {
  624. Slapi_Attr a = {0};
  625. slapi_attr_init(&a, mods[w]->mod_type);
  626. int is_dn_syntax = 0;
  627. struct berval **normmbvp = NULL;
  628. /* Check if the type of the to-be-added values has DN syntax
  629. * or not. */
  630. if (slapi_attr_is_dn_syntax_attr(&a)) {
  631. is_dn_syntax = 1;
  632. }
  633. attr_done(&a);
  634. /* copy each mod into a normalized modbvalue */
  635. normalized_mods[w] = (LDAPMod *) slapi_ch_calloc(1, sizeof(LDAPMod));
  636. normalized_mods[w]->mod_op = mods[w]->mod_op | LDAP_MOD_BVALUES;
  637. normalized_mods[w]->mod_type = slapi_ch_strdup(mods[w]->mod_type);
  638. /*
  639. * count the number of values -- kinda sucks but probably
  640. * less expensive then reallocing, and num_values
  641. * should typically be very small
  642. */
  643. num_values = 0;
  644. if (mods[w]->mod_op & LDAP_MOD_BVALUES)
  645. {
  646. for (x = 0; mods[w]->mod_bvalues != NULL &&
  647. mods[w]->mod_bvalues[x] != NULL; x++)
  648. {
  649. num_values++;
  650. }
  651. } else {
  652. for (x = 0; mods[w]->mod_values != NULL &&
  653. mods[w]->mod_values[x] != NULL; x++)
  654. {
  655. num_values++;
  656. }
  657. }
  658. if (num_values > 0)
  659. {
  660. normalized_mods[w]->mod_bvalues = (struct berval **)
  661. slapi_ch_calloc(num_values + 1, sizeof(struct berval *));
  662. } else {
  663. normalized_mods[w]->mod_bvalues = NULL;
  664. }
  665. if (mods[w]->mod_op & LDAP_MOD_BVALUES)
  666. {
  667. struct berval **mbvp = NULL;
  668. for (mbvp = mods[w]->mod_bvalues,
  669. normmbvp = normalized_mods[w]->mod_bvalues;
  670. mbvp && *mbvp; mbvp++, normmbvp++)
  671. {
  672. if (is_dn_syntax) {
  673. Slapi_DN *sdn = slapi_sdn_new_dn_byref((*mbvp)->bv_val);
  674. if (slapi_sdn_get_dn(sdn)) {
  675. *normmbvp =
  676. (struct berval *)slapi_ch_malloc(sizeof(struct berval));
  677. (*normmbvp)->bv_val =
  678. slapi_ch_strdup(slapi_sdn_get_dn(sdn));
  679. (*normmbvp)->bv_len = slapi_sdn_get_ndn_len(sdn);
  680. } else {
  681. /* normalization failed; use the original */
  682. *normmbvp = ber_bvdup(*mbvp);
  683. }
  684. slapi_sdn_free(&sdn);
  685. } else {
  686. *normmbvp = ber_bvdup(*mbvp);
  687. }
  688. }
  689. } else {
  690. char **mvp = NULL;
  691. for (mvp = mods[w]->mod_values,
  692. normmbvp = normalized_mods[w]->mod_bvalues;
  693. mvp && *mvp; mvp++, normmbvp++)
  694. {
  695. vlen = strlen(*mvp);
  696. *normmbvp =
  697. (struct berval *)slapi_ch_malloc(sizeof(struct berval));
  698. if (is_dn_syntax) {
  699. Slapi_DN *sdn = slapi_sdn_new_dn_byref(*mvp);
  700. if (slapi_sdn_get_dn(sdn)) {
  701. (*normmbvp)->bv_val =
  702. slapi_ch_strdup(slapi_sdn_get_dn(sdn));
  703. (*normmbvp)->bv_len = slapi_sdn_get_ndn_len(sdn);
  704. } else {
  705. /* normalization failed; use the original */
  706. (*normmbvp)->bv_val = slapi_ch_malloc(vlen + 1);
  707. memcpy((*normmbvp)->bv_val, *mvp, vlen);
  708. (*normmbvp)->bv_val[vlen] = '\0';
  709. (*normmbvp)->bv_len = vlen;
  710. }
  711. slapi_sdn_free(&sdn);
  712. } else {
  713. (*normmbvp)->bv_val = slapi_ch_malloc(vlen + 1);
  714. memcpy((*normmbvp)->bv_val, *mvp, vlen);
  715. (*normmbvp)->bv_val[vlen] = '\0';
  716. (*normmbvp)->bv_len = vlen;
  717. }
  718. }
  719. }
  720. PR_ASSERT(normmbvp - normalized_mods[w]->mod_bvalues <= num_values);
  721. /* don't forget to null terminate it */
  722. if (num_values > 0)
  723. {
  724. *normmbvp = NULL;
  725. }
  726. }
  727. /* don't forget to null terminate the normalize list of mods */
  728. normalized_mods[w] = NULL;
  729. return(normalized_mods);
  730. }
  731. /*
  732. * Return true if the given path is an absolute path, false otherwise
  733. */
  734. int
  735. is_abspath(const char *path)
  736. {
  737. if (path == NULL || *path == '\0') {
  738. return 0; /* empty path is not absolute? */
  739. }
  740. if (path[0] == '/') {
  741. return 1; /* unix abs path */
  742. }
  743. return 0; /* not an abs path */
  744. }
  745. static void
  746. clean_path(char **norm_path)
  747. {
  748. char **np;
  749. for (np = norm_path; np && *np; np++)
  750. slapi_ch_free_string(np);
  751. slapi_ch_free((void **)&norm_path);
  752. }
  753. static char **
  754. normalize_path(char *path)
  755. {
  756. char *dname = NULL;
  757. char *dnamep = NULL;
  758. char **dirs = NULL;
  759. char **rdirs = NULL;
  760. char **dp = NULL;
  761. char **rdp;
  762. int elimdots = 0;
  763. if (NULL == path || '\0' == *path) {
  764. return NULL;
  765. }
  766. dirs = (char **)slapi_ch_calloc(strlen(path), sizeof(char *));
  767. rdirs = (char **)slapi_ch_calloc(strlen(path), sizeof(char *));
  768. dp = dirs;
  769. dname = slapi_ch_strdup(path);
  770. do {
  771. dnamep = strrchr(dname, _CSEP);
  772. if (NULL == dnamep) {
  773. dnamep = dname;
  774. } else {
  775. *dnamep = '\0';
  776. dnamep++;
  777. }
  778. if (0 != strcmp(dnamep, ".") && strlen(dnamep) > 0) {
  779. *dp++ = slapi_ch_strdup(dnamep); /* rm "/./" and "//" in the path */
  780. }
  781. } while ( dnamep > dname /* == -> no more _CSEP */ );
  782. slapi_ch_free_string(&dname);
  783. /* remove "xxx/.." in the path */
  784. for (dp = dirs, rdp = rdirs; dp && *dp; dp++) {
  785. while (*dp && 0 == strcmp(*dp, "..")) {
  786. dp++;
  787. elimdots++;
  788. }
  789. if (elimdots > 0) {
  790. elimdots--;
  791. } else if (*dp) {
  792. *rdp++ = slapi_ch_strdup(*dp);
  793. }
  794. }
  795. /* reverse */
  796. for (--rdp, dp = rdirs; rdp >= dp && rdp >= rdirs; --rdp, dp++) {
  797. char *tmpp = *dp;
  798. *dp = *rdp;
  799. *rdp = tmpp;
  800. }
  801. clean_path(dirs);
  802. return rdirs;
  803. }
  804. /*
  805. * Take "relpath" and prepend the current working directory to it
  806. * if it isn't an absolute pathname already. The caller is responsible
  807. * for freeing the returned string.
  808. */
  809. char *
  810. rel2abspath( char *relpath )
  811. {
  812. return rel2abspath_ext( relpath, NULL );
  813. }
  814. char *
  815. rel2abspath_ext( char *relpath, char *cwd )
  816. {
  817. char abspath[ MAXPATHLEN + 1 ];
  818. char *retpath = NULL;
  819. if ( relpath == NULL ) {
  820. return NULL;
  821. }
  822. if ( relpath[ 0 ] == _CSEP ) { /* absolute path */
  823. PR_snprintf(abspath, sizeof(abspath), "%s", relpath);
  824. } else { /* relative path */
  825. if ( NULL == cwd ) {
  826. if ( getcwd( abspath, MAXPATHLEN ) == NULL ) {
  827. perror( "getcwd" );
  828. LDAPDebug( LDAP_DEBUG_ANY, "Cannot determine current directory\n",
  829. 0, 0, 0 );
  830. exit( 1 );
  831. }
  832. } else {
  833. PR_snprintf(abspath, sizeof(abspath), "%s", cwd);
  834. }
  835. if ( strlen( relpath ) + strlen( abspath ) + 1 > MAXPATHLEN ) {
  836. LDAPDebug( LDAP_DEBUG_ANY, "Pathname \"%s" _PSEP "%s\" too long\n",
  837. abspath, relpath, 0 );
  838. exit( 1 );
  839. }
  840. if ( strcmp( relpath, "." )) {
  841. if ( abspath[ 0 ] != '\0' &&
  842. abspath[ strlen( abspath ) - 1 ] != _CSEP )
  843. {
  844. PL_strcatn( abspath, sizeof(abspath), _PSEP );
  845. }
  846. PL_strcatn( abspath, sizeof(abspath), relpath );
  847. }
  848. }
  849. retpath = slapi_ch_strdup(abspath);
  850. /* if there's no '.' or separators, no need to call normalize_path */
  851. if (NULL != strchr(abspath, '.') || NULL != strstr(abspath, _PSEP))
  852. {
  853. char **norm_path = normalize_path(abspath);
  854. char **np, *rp;
  855. int pathlen = strlen(abspath) + 1;
  856. int usedlen = 0;
  857. for (np = norm_path, rp = retpath; np && *np; np++) {
  858. int thislen = strlen(*np) + 1;
  859. if (0 != strcmp(*np, _PSEP))
  860. PR_snprintf(rp, pathlen - usedlen, "%c%s", _CSEP, *np);
  861. rp += thislen;
  862. usedlen += thislen;
  863. }
  864. clean_path(norm_path);
  865. }
  866. return retpath;
  867. }
  868. /*
  869. * Allocate a buffer large enough to hold a berval's
  870. * value and a terminating null byte. The returned buffer
  871. * is null-terminated. Returns NULL if bval is NULL or if
  872. * bval->bv_val is NULL.
  873. */
  874. char *
  875. slapi_berval_get_string_copy(const struct berval *bval)
  876. {
  877. char *return_value = NULL;
  878. if (NULL != bval && NULL != bval->bv_val)
  879. {
  880. return_value = slapi_ch_malloc(bval->bv_len + 1);
  881. memcpy(return_value, bval->bv_val, bval->bv_len);
  882. return_value[bval->bv_len] = '\0';
  883. }
  884. return return_value;
  885. }
  886. /* Takes a return code supposed to be errno or from a plugin
  887. which we don't expect to see and prints a handy log message */
  888. void slapd_nasty(char* str, int c, int err)
  889. {
  890. char *msg = NULL;
  891. char buffer[100];
  892. PR_snprintf(buffer,sizeof(buffer), "%s BAD %d",str,c);
  893. LDAPDebug(LDAP_DEBUG_ANY,"%s, err=%d %s\n",buffer,err,(msg = strerror( err )) ? msg : "");
  894. }
  895. /* ***************************************************
  896. Random function (very similar to rand_r())
  897. *************************************************** */
  898. int
  899. slapi_rand_r(unsigned int *randx)
  900. {
  901. if (*randx)
  902. {
  903. PK11_RandomUpdate(randx, sizeof(*randx));
  904. }
  905. PK11_GenerateRandom((unsigned char *)randx, (int)sizeof(*randx));
  906. return (int)(*randx & 0x7FFFFFFF);
  907. }
  908. /* ***************************************************
  909. Random function (very similar to rand_r() but takes and returns an array)
  910. Note: there is an identical function in plugins/pwdstorage/ssha_pwd.c.
  911. That module can't use a libslapd function because the module is included
  912. in libds_admin, which doesn't link to libslapd. Eventually, shared
  913. functions should be moved to a shared library.
  914. *************************************************** */
  915. void
  916. slapi_rand_array(void *randx, size_t len)
  917. {
  918. PK11_RandomUpdate(randx, len);
  919. PK11_GenerateRandom((unsigned char *)randx, (int)len);
  920. }
  921. /* ***************************************************
  922. Random function (very similar to rand()...)
  923. *************************************************** */
  924. int
  925. slapi_rand()
  926. {
  927. unsigned int randx = 0;
  928. return slapi_rand_r(&randx);
  929. }
  930. /************************************************************************
  931. Function: DS_Sleep(PRIntervalTime ticks)
  932. Purpose: To replace PR_Sleep()
  933. Author: Scott Hopson <[email protected]>
  934. Description:
  935. Causes the current thread to wait for ticks number of intervals.
  936. In UNIX this is accomplished by using select()
  937. which should be supported across all UNIX platforms.
  938. ************************************************************************/
  939. void
  940. DS_Sleep(PRIntervalTime ticks)
  941. {
  942. long mSecs = PR_IntervalToMilliseconds(ticks);
  943. struct timeval tm;
  944. tm.tv_sec = mSecs / 1000;
  945. tm.tv_usec = (mSecs % 1000) * 1000;
  946. select(0,NULL,NULL,NULL,&tm);
  947. }
  948. /*****************************************************************************
  949. * strarray2str(): convert the array of strings in "a" into a single
  950. * space-separated string like:
  951. * str1 str2 str3
  952. * If buf is too small, the result will be truncated and end with "...".
  953. * If include_quotes is non-zero, double quote marks are included around
  954. * the string, e.g.,
  955. * "str2 str2 str3"
  956. *
  957. * Returns: 0 if completely successful and -1 if result is truncated.
  958. */
  959. int
  960. strarray2str( char **a, char *buf, size_t buflen, int include_quotes )
  961. {
  962. int rc = 0; /* optimistic */
  963. char *p = buf;
  964. size_t totlen = 0;
  965. if ( include_quotes ) {
  966. if ( buflen < 3 ) {
  967. return -1; /* not enough room for the quote marks! */
  968. }
  969. *p++ = '"';
  970. ++totlen;
  971. }
  972. if ( NULL != a ) {
  973. int ii;
  974. size_t len = 0;
  975. for ( ii = 0; a[ ii ] != NULL; ii++ ) {
  976. if ( ii > 0 ) {
  977. *p++ = ' ';
  978. totlen++;
  979. }
  980. len = strlen( a[ ii ]);
  981. if ( totlen + len > buflen - 5 ) {
  982. strcpy ( p, "..." );
  983. p += 3;
  984. totlen += 3;
  985. rc = -1;
  986. break; /* result truncated */
  987. } else {
  988. strcpy( p, a[ ii ]);
  989. p += len;
  990. totlen += len;
  991. }
  992. }
  993. }
  994. if ( include_quotes ) {
  995. *p++ = '"';
  996. ++totlen;
  997. }
  998. buf[ totlen ] = '\0';
  999. return( rc );
  1000. }
  1001. /*****************************************************************************/
  1002. /* Changes the ownership of the given file/directory if not
  1003. already the owner
  1004. Returns 0 upon success or non-zero otherwise, usually -1 if
  1005. some system error occurred
  1006. */
  1007. int
  1008. slapd_chown_if_not_owner(const char *filename, uid_t uid, gid_t gid)
  1009. {
  1010. int fd = -1;
  1011. struct stat statbuf;
  1012. int result = 1;
  1013. if (!filename)
  1014. return result;
  1015. fd = open(filename, O_RDONLY);
  1016. if (fd == -1) {
  1017. return result;
  1018. }
  1019. memset(&statbuf, '\0', sizeof(statbuf));
  1020. if (!(result = fstat(fd, &statbuf)))
  1021. {
  1022. if (((uid != -1) && (uid != statbuf.st_uid)) ||
  1023. ((gid != -1) && (gid != statbuf.st_gid)))
  1024. {
  1025. result = fchown(fd, uid, gid);
  1026. }
  1027. }
  1028. close(fd);
  1029. return result;
  1030. }
  1031. /*
  1032. * Compare 2 pathes
  1033. * Paths could contain ".", "..", "//" in the path, thus normalize them first.
  1034. * One or two of the paths could be a relative path.
  1035. */
  1036. int
  1037. slapd_comp_path(char *p0, char *p1)
  1038. {
  1039. int rval = 0;
  1040. char *norm_p0 = rel2abspath(p0);
  1041. char *norm_p1 = rel2abspath(p1);
  1042. rval = strcmp(norm_p0, norm_p1);
  1043. slapi_ch_free_string(&norm_p0);
  1044. slapi_ch_free_string(&norm_p1);
  1045. return rval;
  1046. }
  1047. /*
  1048. Takes an unsigned char value and converts it to a hex string.
  1049. The string s is written, and the caller must ensure s has enough
  1050. space. For hex numbers, the upper argument says to use a-f or A-F.
  1051. The return value is the address of the next char after the last one written.
  1052. */
  1053. char *
  1054. slapi_u8_to_hex(uint8_t val, char *s, uint8_t upper) {
  1055. static char ldigits[] = "0123456789abcdef";
  1056. static char udigits[] = "0123456789ABCDEF";
  1057. char *digits;
  1058. if (upper) {
  1059. digits = udigits;
  1060. } else {
  1061. digits = ldigits;
  1062. }
  1063. s[0] = digits[val >> 4];
  1064. s[1] = digits[val & 0xf];
  1065. return &s[2];
  1066. }
  1067. char *
  1068. slapi_u16_to_hex(uint16_t val, char *s, uint8_t upper) {
  1069. static char ldigits[] = "0123456789abcdef";
  1070. static char udigits[] = "0123456789ABCDEF";
  1071. char *digits;
  1072. if (upper) {
  1073. digits = udigits;
  1074. } else {
  1075. digits = ldigits;
  1076. }
  1077. s[0] = digits[val >> 12];
  1078. s[1] = digits[(val >> 8) & 0xf];
  1079. s[2] = digits[(val >> 4) & 0xf];
  1080. s[3] = digits[val & 0xf];
  1081. return &s[4];
  1082. }
  1083. char *
  1084. slapi_u32_to_hex(uint32_t val, char *s, uint8_t upper) {
  1085. static char ldigits[] = "0123456789abcdef";
  1086. static char udigits[] = "0123456789ABCDEF";
  1087. char *digits;
  1088. if (upper) {
  1089. digits = udigits;
  1090. } else {
  1091. digits = ldigits;
  1092. }
  1093. s[0] = digits[val >> 28];
  1094. s[1] = digits[(val >> 24) & 0xf];
  1095. s[2] = digits[(val >> 20) & 0xf];
  1096. s[3] = digits[(val >> 16) & 0xf];
  1097. s[4] = digits[(val >> 12) & 0xf];
  1098. s[5] = digits[(val >> 8) & 0xf];
  1099. s[6] = digits[(val >> 4) & 0xf];
  1100. s[7] = digits[val & 0xf];
  1101. return &s[8];
  1102. }
  1103. char *
  1104. slapi_u64_to_hex(uint64_t val, char *s, uint8_t upper) {
  1105. static char ldigits[] = "0123456789abcdef";
  1106. static char udigits[] = "0123456789ABCDEF";
  1107. char *digits;
  1108. if (upper) {
  1109. digits = udigits;
  1110. } else {
  1111. digits = ldigits;
  1112. }
  1113. s[0] = digits[val >> 60];
  1114. s[1] = digits[(val >> 56) & 0xf];
  1115. s[2] = digits[(val >> 52) & 0xf];
  1116. s[3] = digits[(val >> 48) & 0xf];
  1117. s[4] = digits[(val >> 44) & 0xf];
  1118. s[5] = digits[(val >> 40) & 0xf];
  1119. s[6] = digits[(val >> 36) & 0xf];
  1120. s[7] = digits[(val >> 32) & 0xf];
  1121. s[8] = digits[(val >> 28) & 0xf];
  1122. s[9] = digits[(val >> 24) & 0xf];
  1123. s[10] = digits[(val >> 20) & 0xf];
  1124. s[11] = digits[(val >> 16) & 0xf];
  1125. s[12] = digits[(val >> 12) & 0xf];
  1126. s[13] = digits[(val >> 8) & 0xf];
  1127. s[14] = digits[(val >> 4) & 0xf];
  1128. s[15] = digits[val & 0xf];
  1129. return &s[16];
  1130. }
  1131. static const int char2intarray[] = {
  1132. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1133. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1134. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1135. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
  1136. -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1137. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1138. -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1139. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1140. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1141. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1142. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1143. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1144. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1145. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1146. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1147. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
  1148. };
  1149. int
  1150. slapi_hexchar2int(char c)
  1151. {
  1152. return char2intarray[(unsigned char)c];
  1153. }
  1154. uint8_t
  1155. slapi_str_to_u8(const char *s)
  1156. {
  1157. uint8_t v0 = (uint8_t)slapi_hexchar2int(s[0]);
  1158. uint8_t v1 = (uint8_t)slapi_hexchar2int(s[1]);
  1159. return (v0 << 4) | v1;
  1160. }
  1161. uint16_t
  1162. slapi_str_to_u16(const char *s)
  1163. {
  1164. uint16_t v0 = (uint16_t)slapi_hexchar2int(s[0]);
  1165. uint16_t v1 = (uint16_t)slapi_hexchar2int(s[1]);
  1166. uint16_t v2 = (uint16_t)slapi_hexchar2int(s[2]);
  1167. uint16_t v3 = (uint16_t)slapi_hexchar2int(s[3]);
  1168. return (v0 << 12) | (v1 << 8) | (v2 << 4) | v3;
  1169. }
  1170. uint32_t
  1171. slapi_str_to_u32(const char *s)
  1172. {
  1173. uint32_t v0 = (uint32_t)slapi_hexchar2int(s[0]);
  1174. uint32_t v1 = (uint32_t)slapi_hexchar2int(s[1]);
  1175. uint32_t v2 = (uint32_t)slapi_hexchar2int(s[2]);
  1176. uint32_t v3 = (uint32_t)slapi_hexchar2int(s[3]);
  1177. uint32_t v4 = (uint32_t)slapi_hexchar2int(s[4]);
  1178. uint32_t v5 = (uint32_t)slapi_hexchar2int(s[5]);
  1179. uint32_t v6 = (uint32_t)slapi_hexchar2int(s[6]);
  1180. uint32_t v7 = (uint32_t)slapi_hexchar2int(s[7]);
  1181. return (v0 << 28) | (v1 << 24) | (v2 << 20) | (v3 << 16) | (v4 << 12) | (v5 << 8) | (v6 << 4) | v7;
  1182. }
  1183. uint64_t
  1184. slapi_str_to_u64(const char *s)
  1185. {
  1186. uint64_t v0 = (uint64_t)slapi_hexchar2int(s[0]);
  1187. uint64_t v1 = (uint64_t)slapi_hexchar2int(s[1]);
  1188. uint64_t v2 = (uint64_t)slapi_hexchar2int(s[2]);
  1189. uint64_t v3 = (uint64_t)slapi_hexchar2int(s[3]);
  1190. uint64_t v4 = (uint64_t)slapi_hexchar2int(s[4]);
  1191. uint64_t v5 = (uint64_t)slapi_hexchar2int(s[5]);
  1192. uint64_t v6 = (uint64_t)slapi_hexchar2int(s[6]);
  1193. uint64_t v7 = (uint64_t)slapi_hexchar2int(s[7]);
  1194. uint64_t v8 = (uint64_t)slapi_hexchar2int(s[8]);
  1195. uint64_t v9 = (uint64_t)slapi_hexchar2int(s[9]);
  1196. uint64_t v10 = (uint64_t)slapi_hexchar2int(s[10]);
  1197. uint64_t v11 = (uint64_t)slapi_hexchar2int(s[11]);
  1198. uint64_t v12 = (uint64_t)slapi_hexchar2int(s[12]);
  1199. uint64_t v13 = (uint64_t)slapi_hexchar2int(s[13]);
  1200. uint64_t v14 = (uint64_t)slapi_hexchar2int(s[14]);
  1201. uint64_t v15 = (uint64_t)slapi_hexchar2int(s[15]);
  1202. return (v0 << 60) | (v1 << 56) | (v2 << 52) | (v3 << 48) | (v4 << 44) | (v5 << 40) |
  1203. (v6 << 36) | (v7 << 32) | (v8 << 28) | (v9 << 24) | (v10 << 20) | (v11 << 16) |
  1204. (v12 << 12) | (v13 << 8) | (v14 << 4) | v15;
  1205. }
  1206. /* PR_GetLibraryName does almost everything we need, and unfortunately
  1207. a little bit more - it adds "lib" to be beginning of the library
  1208. name if the library name does not end with the current platform
  1209. DLL suffix - so
  1210. foo.so -> /path/foo.so
  1211. libfoo.so -> /path/libfoo.so
  1212. BUT
  1213. foo -> /path/libfoo.so
  1214. libfoo -> /path/liblibfoo.so
  1215. /path/libfoo -> lib/path/libfoo.so
  1216. */
  1217. char *
  1218. slapi_get_plugin_name(const char *path, const char *lib)
  1219. {
  1220. const char *libstr = "/lib";
  1221. size_t libstrlen = 4;
  1222. char *fullname = PR_GetLibraryName(path, lib);
  1223. char *ptr = PL_strrstr(fullname, lib);
  1224. /* see if /lib was added */
  1225. if (ptr && ((ptr - fullname) >= libstrlen)) {
  1226. /* ptr is at the libname in fullname, and there is something before it */
  1227. ptr -= libstrlen; /* ptr now points at the "/" in "/lib" if it is there */
  1228. if (0 == PL_strncmp(ptr, libstr, libstrlen)) {
  1229. /* just copy the remainder of the string on top of here */
  1230. ptr++; /* ptr now points at the "l" in "/lib" - keep the "/" */
  1231. memmove(ptr, ptr+3, strlen(ptr+3)+1);
  1232. }
  1233. } else if ((NULL == path) && (0 == strncmp(fullname, "lib", 3))) {
  1234. /*
  1235. * case: /path/libfoo -> lib/path/libfoo.so
  1236. * remove "lib".
  1237. */
  1238. memmove(fullname, fullname+3, strlen(fullname)-2);
  1239. }
  1240. return fullname;
  1241. }
  1242. /*
  1243. * Check if rdn is a slecial rdn/dn or not.
  1244. * If flag is IS_TOMBSTONE, returns 1 if rdn is a tombstone rdn/dn.
  1245. * If flag is IS_CONFLICT, returns 1 if rdn is a conflict rdn/dn.
  1246. * Otherwise returns 0.
  1247. */
  1248. static int util_uniqueidlen = 0;
  1249. int
  1250. slapi_is_special_rdn(const char *rdn, int flag)
  1251. {
  1252. char *rp;
  1253. int plus = 0;
  1254. if (!util_uniqueidlen) {
  1255. util_uniqueidlen = SLAPI_ATTR_UNIQUEID_LENGTH + slapi_uniqueIDSize() + 1/*=*/;
  1256. }
  1257. if ((RDN_IS_TOMBSTONE != flag) && (RDN_IS_CONFLICT != flag)) {
  1258. LDAPDebug1Arg(LDAP_DEBUG_ANY, "slapi_is_special_rdn: invalid flag %d\n", flag);
  1259. return 0; /* not a special rdn/dn */
  1260. }
  1261. if (!rdn) {
  1262. LDAPDebug0Args(LDAP_DEBUG_ANY, "slapi_is_special_rdn: NULL rdn\n");
  1263. return 0; /* not a special rdn/dn */
  1264. }
  1265. if (strlen(rdn) < util_uniqueidlen) {
  1266. return 0; /* not a special rdn/dn */
  1267. }
  1268. rp = (char *)rdn;
  1269. while (rp) {
  1270. char *endp = NULL;
  1271. if (!PL_strncasecmp(rp, SLAPI_ATTR_UNIQUEID, SLAPI_ATTR_UNIQUEID_LENGTH) &&
  1272. (*(rp + SLAPI_ATTR_UNIQUEID_LENGTH) == '=')) {
  1273. if (RDN_IS_TOMBSTONE == flag) {
  1274. if ((*(rp + util_uniqueidlen) == ',') ||
  1275. (*(rp + util_uniqueidlen) == '\0')) {
  1276. return 1;
  1277. } else {
  1278. return 0;
  1279. }
  1280. } else {
  1281. if ((*(rp + util_uniqueidlen) == '+') ||
  1282. (plus && ((*(rp + util_uniqueidlen) == ',') ||
  1283. (*(rp + util_uniqueidlen) == '\0')))) {
  1284. return 1;
  1285. }
  1286. }
  1287. } else if (RDN_IS_TOMBSTONE == flag) {
  1288. /* If the first part of rdn does not start with SLAPI_ATTR_UNIQUEID,
  1289. * it's not a tombstone RDN. */
  1290. return 0;
  1291. }
  1292. endp = PL_strchr(rp, ',');
  1293. if (!endp) {
  1294. endp = rp + strlen(rp);
  1295. }
  1296. rp = PL_strchr(rp, '+');
  1297. if (rp && (rp < endp)) {
  1298. plus = 1;
  1299. rp++;
  1300. }
  1301. }
  1302. return 0;
  1303. }
  1304. int
  1305. slapi_uniqueIDRdnSize()
  1306. {
  1307. if (!util_uniqueidlen) {
  1308. util_uniqueidlen = SLAPI_ATTR_UNIQUEID_LENGTH + slapi_uniqueIDSize() + 1/*=*/;
  1309. }
  1310. return util_uniqueidlen;
  1311. }
  1312. /**
  1313. * Get the virtual memory size as defined by system rlimits.
  1314. *
  1315. * \return size_t bytes available
  1316. */
  1317. static size_t util_getvirtualmemsize()
  1318. {
  1319. struct rlimit rl;
  1320. /* the maximum size of a process's total available memory, in bytes */
  1321. if (getrlimit(RLIMIT_AS, &rl) != 0) {
  1322. /* We received an error condition. There are a number of possible
  1323. * reasons we have have gotten here, but most likely is EINVAL, where
  1324. * rlim->rlim_cur was greater than rlim->rlim_max.
  1325. * As a result, we should return a 0, to tell the system we can't alloc
  1326. * memory.
  1327. */
  1328. int errsrv = errno;
  1329. slapi_log_error(SLAPI_LOG_FATAL,"util_getvirtualmemsize", "ERROR: getrlimit returned non-zero. errno=%u\n", errsrv);
  1330. return 0;
  1331. }
  1332. return rl.rlim_cur;
  1333. }
  1334. /* pages = number of pages of physical ram on the machine (corrected for 32-bit build on 64-bit machine).
  1335. * procpages = pages currently used by this process (or working set size, sometimes)
  1336. * availpages = some notion of the number of pages 'free'. Typically this number is not useful.
  1337. */
  1338. int util_info_sys_pages(size_t *pagesize, size_t *pages, size_t *procpages, size_t *availpages)
  1339. {
  1340. *pagesize = 0;
  1341. *pages = 0;
  1342. *availpages = 0;
  1343. if (procpages)
  1344. *procpages = 0;
  1345. #ifdef OS_solaris
  1346. *pagesize = (int)sysconf(_SC_PAGESIZE);
  1347. *pages = (int)sysconf(_SC_PHYS_PAGES);
  1348. *availpages = util_getvirtualmemsize() / *pagesize;
  1349. /* solaris has THE most annoying way to get this info */
  1350. if (procpages) {
  1351. struct prpsinfo psi;
  1352. char fn[40];
  1353. int fd;
  1354. sprintf(fn, "/proc/%d", getpid());
  1355. fd = open(fn, O_RDONLY);
  1356. if (fd >= 0) {
  1357. memset(&psi, 0, sizeof(psi));
  1358. if (ioctl(fd, PIOCPSINFO, (void *)&psi) == 0)
  1359. *procpages = psi.pr_size;
  1360. close(fd);
  1361. }
  1362. }
  1363. #endif
  1364. #ifdef LINUX
  1365. {
  1366. /*
  1367. * On linux because of the way that the virtual memory system works, we
  1368. * don't really need to think about other processes, or fighting them.
  1369. * But that's not without quirks.
  1370. *
  1371. * We are given a virtual memory space, represented by vsize (man 5 proc)
  1372. * This space is a "funny number". It's a best effort based system
  1373. * where linux instead of telling us how much memory *actually* exists
  1374. * for us to use, gives us a virtual memory allocation which is the
  1375. * value of ram + swap.
  1376. *
  1377. * But none of these pages even exist or belong to us on the real system
  1378. * until will malloc them AND write a non-zero to them.
  1379. *
  1380. * The biggest issue with this is that vsize does NOT consider the
  1381. * effect other processes have on the system. So a process can malloc
  1382. * 2 Gig from the host, and our vsize doesn't reflect that until we
  1383. * suddenly can't malloc anything.
  1384. *
  1385. * We can see exactly what we are using inside of the vmm by
  1386. * looking at rss (man 5 proc). This shows us the current actual
  1387. * allocation of memory we are using. This is a good thing.
  1388. *
  1389. * We obviously don't want to have any pages in swap, but sometimes we
  1390. * can't help that: And there is also no guarantee that while we have
  1391. * X bytes in vsize, that we can even allocate any of them. Plus, we
  1392. * don't know if we are about to allocate to swap or not .... or get us
  1393. * killed in a blaze of oom glory.
  1394. *
  1395. * So there are now two strategies avaliable in this function.
  1396. * The first is to blindly accept what the VMM tells us about vsize
  1397. * while we hope and pray that we don't get nailed because we used
  1398. * too much.
  1399. *
  1400. * The other is a more conservative approach: We check vsize from
  1401. * proc/pid/status, and we check /proc/meminfo for freemem
  1402. * Which ever value is "lower" is the upper bound on pages we could
  1403. * potentially allocate: generally, this will be MemAvailable.
  1404. */
  1405. size_t vmsize = 0;
  1406. size_t freesize = 0;
  1407. *pagesize = getpagesize();
  1408. /* Get the amount of freeram, rss, and the vmsize */
  1409. FILE *f;
  1410. char fn[40], s[80];
  1411. sprintf(fn, "/proc/%d/status", getpid());
  1412. f = fopen(fn, "r");
  1413. if (!f) { /* fopen failed */
  1414. /* We should probably make noise here! */
  1415. int errsrv = errno;
  1416. slapi_log_error(SLAPI_LOG_FATAL,"util_info_sys_pages", "ERROR: Unable to open file /proc/%d/status. errno=%u\n", getpid(), errsrv);
  1417. return 1;
  1418. }
  1419. while (! feof(f)) {
  1420. fgets(s, 79, f);
  1421. if (feof(f)) {
  1422. break;
  1423. }
  1424. /* VmRSS shows us what we are ACTUALLY using for proc pages
  1425. * Rather than "funny" pages.
  1426. */
  1427. if (strncmp(s, "VmSize:", 7) == 0) {
  1428. sscanf(s+7, "%lu", (long unsigned int *)&vmsize);
  1429. }
  1430. if (strncmp(s, "VmRSS:", 6) == 0) {
  1431. sscanf(s+6, "%lu", (long unsigned int *)procpages);
  1432. }
  1433. }
  1434. fclose(f);
  1435. FILE *fm;
  1436. char *fmn = "/proc/meminfo";
  1437. fm = fopen(fmn, "r");
  1438. if (!fm) {
  1439. int errsrv = errno;
  1440. slapi_log_error(SLAPI_LOG_FATAL,"util_info_sys_pages", "ERROR: Unable to open file /proc/meminfo. errno=%u\n", errsrv);
  1441. return 1;
  1442. }
  1443. while (! feof(fm)) {
  1444. fgets(s, 79, fm);
  1445. /* Is this really needed? */
  1446. if (feof(fm)) {
  1447. break;
  1448. }
  1449. if (strncmp(s, "MemTotal:", 9) == 0) {
  1450. sscanf(s+9, "%lu", (long unsigned int *)pages);
  1451. }
  1452. if (strncmp(s, "MemAvailable:", 13) == 0) {
  1453. sscanf(s+13, "%lu", (long unsigned int *)&freesize);
  1454. }
  1455. }
  1456. fclose(fm);
  1457. *pages /= (*pagesize / 1024);
  1458. freesize /= (*pagesize / 1024);
  1459. /* procpages is now in kb not pages... */
  1460. *procpages /= (*pagesize / 1024);
  1461. /* This is in bytes, make it pages */
  1462. *availpages = util_getvirtualmemsize() / *pagesize;
  1463. /* Now we have vmsize, the availpages from getrlimit, our freesize */
  1464. vmsize /= (*pagesize / 1024);
  1465. /* Pages is the total ram on the system. We should smaller of:
  1466. * - vmsize
  1467. * - pages
  1468. */
  1469. LDAPDebug(LDAP_DEBUG_TRACE,"util_info_sys_pages pages=%lu, vmsize=%lu, \n",
  1470. (unsigned long) *pages, (unsigned long) vmsize,0);
  1471. if (vmsize < *pages) {
  1472. LDAPDebug(LDAP_DEBUG_TRACE,"util_info_sys_pages using vmsize for pages \n",0,0,0);
  1473. *pages = vmsize;
  1474. } else {
  1475. LDAPDebug(LDAP_DEBUG_TRACE,"util_info_sys_pages using pages for pages \n",0,0,0);
  1476. }
  1477. /* Availpages is how much we *could* alloc. We should take the smallest:
  1478. * - pages
  1479. * - getrlimit (availpages)
  1480. * - freesize
  1481. */
  1482. LDAPDebug(LDAP_DEBUG_TRACE,"util_info_sys_pages pages=%lu, getrlim=%lu, freesize=%lu\n",
  1483. (unsigned long)*pages, (unsigned long)*availpages, (unsigned long)freesize);
  1484. if (*pages < *availpages && *pages < freesize) {
  1485. LDAPDebug(LDAP_DEBUG_TRACE,"util_info_sys_pages using pages for availpages \n",0,0,0);
  1486. *availpages = *pages;
  1487. } else if ( freesize < *pages && freesize < *availpages ) {
  1488. LDAPDebug(LDAP_DEBUG_TRACE,"util_info_sys_pages using freesize for availpages \n",0,0,0);
  1489. *availpages = freesize;
  1490. } else {
  1491. LDAPDebug(LDAP_DEBUG_TRACE,"util_info_sys_pages using getrlim for availpages \n",0,0,0);
  1492. }
  1493. }
  1494. #endif /* linux */
  1495. #if defined ( hpux )
  1496. {
  1497. struct pst_static pst;
  1498. int rval = pstat_getstatic(&pst, sizeof(pst), (size_t)1, 0);
  1499. if (rval < 0) { /* pstat_getstatic failed */
  1500. return 1;
  1501. }
  1502. *pagesize = pst.page_size;
  1503. *pages = pst.physical_memory;
  1504. *availpages = util_getvirtualmemsize() / *pagesize;
  1505. if (procpages)
  1506. {
  1507. #define BURST (size_t)32 /* get BURST proc info at one time... */
  1508. struct pst_status psts[BURST];
  1509. int i, count;
  1510. int idx = 0; /* index within the context */
  1511. int mypid = getpid();
  1512. *procpages = 0;
  1513. /* loop until count == 0, will occur all have been returned */
  1514. while ((count = pstat_getproc(psts, sizeof(psts[0]), BURST, idx)) > 0) {
  1515. /* got count (max of BURST) this time. process them */
  1516. for (i = 0; i < count; i++) {
  1517. if (psts[i].pst_pid == mypid)
  1518. {
  1519. *procpages = (size_t)(psts[i].pst_dsize + psts[i].pst_tsize + psts[i].pst_ssize);
  1520. break;
  1521. }
  1522. }
  1523. if (i < count)
  1524. break;
  1525. /*
  1526. * now go back and do it again, using the next index after
  1527. * the current 'burst'
  1528. */
  1529. idx = psts[count-1].pst_idx + 1;
  1530. }
  1531. }
  1532. }
  1533. #endif
  1534. /* If this is a 32-bit build, it might be running on a 64-bit machine,
  1535. * in which case, if the box has tons of ram, we can end up telling
  1536. * the auto cache code to use more memory than the process can address.
  1537. * so we cap the number returned here.
  1538. */
  1539. #if defined(__LP64__) || defined (_LP64)
  1540. #else
  1541. {
  1542. #define GIGABYTE (1024*1024*1024)
  1543. size_t one_gig_pages = GIGABYTE / *pagesize;
  1544. if (*pages > (2 * one_gig_pages) ) {
  1545. LDAPDebug(LDAP_DEBUG_TRACE,"More than 2Gbytes physical memory detected. Since this is a 32-bit process, truncating memory size used for auto cache calculations to 2Gbytes\n",
  1546. 0, 0, 0);
  1547. *pages = (2 * one_gig_pages);
  1548. }
  1549. }
  1550. #endif
  1551. /* This is stupid. If you set %u to %zu to print a size_t, you get literal %zu in your logs
  1552. * So do the filthy cast instead.
  1553. */
  1554. slapi_log_error(SLAPI_LOG_FATAL,"util_info_sys_pages", "USING pages=%lu, procpages=%lu, availpages=%lu \n",
  1555. (unsigned long)*pages, (unsigned long)*procpages, (unsigned long)*availpages);
  1556. return 0;
  1557. }
  1558. int util_is_cachesize_sane(size_t *cachesize)
  1559. {
  1560. size_t pages = 0;
  1561. size_t pagesize = 0;
  1562. size_t procpages = 0;
  1563. size_t availpages = 0;
  1564. size_t cachepages = 0;
  1565. int issane = 1;
  1566. if (util_info_sys_pages(&pagesize, &pages, &procpages, &availpages) != 0) {
  1567. goto out;
  1568. }
  1569. #ifdef LINUX
  1570. /* Linux we calculate availpages correctly, so USE IT */
  1571. if (!pagesize || !availpages) {
  1572. goto out;
  1573. }
  1574. #else
  1575. if (!pagesize || !pages) {
  1576. goto out;
  1577. }
  1578. #endif
  1579. /* do nothing when we can't get the avail mem */
  1580. /* If the requested cache size is larger than the remaining physical memory
  1581. * after the current working set size for this process has been subtracted,
  1582. * then we say that's insane and try to correct.
  1583. */
  1584. cachepages = *cachesize / pagesize;
  1585. LDAPDebug(LDAP_DEBUG_TRACE,"util_is_cachesize_sane cachesize=%lu / pagesize=%lu \n",
  1586. (unsigned long)*cachesize,(unsigned long)pagesize,0);
  1587. #ifdef LINUX
  1588. /* Linux we calculate availpages correctly, so USE IT */
  1589. issane = (int)(cachepages <= availpages);
  1590. LDAPDebug(LDAP_DEBUG_TRACE,"util_is_cachesize_sane cachepages=%lu <= availpages=%lu\n",
  1591. (unsigned long)cachepages,(unsigned long)availpages,0);
  1592. if (!issane) {
  1593. /* Since we are ask for more than what's available, we give half of
  1594. * the remaining system mem to the cachesize instead, and log a warning
  1595. */
  1596. *cachesize = (size_t)((availpages / 2) * pagesize);
  1597. slapi_log_error(SLAPI_LOG_FATAL, "util_is_cachesize_sane", "WARNING adjusted cachesize to %lu\n", (unsigned long)*cachesize);
  1598. }
  1599. #else
  1600. size_t freepages = 0;
  1601. freepages = pages - procpages;
  1602. LDAPDebug(LDAP_DEBUG_TRACE,"util_is_cachesize_sane pages=%lu - procpages=%lu\n",
  1603. (unsigned long)pages,(unsigned long)procpages,0);
  1604. issane = (int)(cachepages <= freepages);
  1605. LDAPDebug(LDAP_DEBUG_TRACE,"util_is_cachesize_sane cachepages=%lu <= freepages=%lu\n",
  1606. (unsigned long)cachepages,(unsigned long)freepages,0);
  1607. if (!issane) {
  1608. *cachesize = (size_t)((pages - procpages) * pagesize);
  1609. slapi_log_error(SLAPI_LOG_FATAL, "util_is_cachesize_sane", "util_is_cachesize_sane WARNING adjusted cachesize to %lu\n",
  1610. (unsigned long )*cachesize);
  1611. }
  1612. #endif
  1613. out:
  1614. if (!issane) {
  1615. slapi_log_error(SLAPI_LOG_FATAL,"util_is_cachesize_sane", "WARNING: Cachesize not sane \n");
  1616. }
  1617. return issane;
  1618. }