log.c 104 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. /*
  39. **
  40. ** log.c
  41. **
  42. ** Routines for writing access and error/debug logs
  43. **
  44. **
  45. ** History:
  46. ** As of DS 4.0, we support log rotation for the ACCESS/ERROR/AUDIT log.
  47. */
  48. #include "log.h"
  49. #include "fe.h"
  50. #if defined( XP_WIN32 )
  51. #include <fcntl.h>
  52. #include "ntslapdmessages.h"
  53. #include "proto-ntutil.h"
  54. extern HANDLE hSlapdEventSource;
  55. extern LPTSTR pszServerName;
  56. #endif
  57. /**************************************************************************
  58. * GLOBALS, defines, and ...
  59. *************************************************************************/
  60. /* main struct which contains all the information about logging */
  61. PRUintn logbuf_tsdindex;
  62. struct logbufinfo *logbuf_accum;
  63. static struct logging_opts loginfo;
  64. static int detached=0;
  65. /* used to lock the timestamp info used by vslapd_log_access */
  66. static PRLock *ts_time_lock = NULL;
  67. /*
  68. * Note: the order of the values in the slapi_log_map array must exactly
  69. * match that of the SLAPI_LOG_XXX #defines found in slapi-plugin.h (this is
  70. * so we can use the SLAPI_LOG_XXX values to index directly into the array).
  71. */
  72. static int slapi_log_map[] = {
  73. LDAP_DEBUG_ANY, /* SLAPI_LOG_FATAL */
  74. LDAP_DEBUG_TRACE, /* SLAPI_LOG_TRACE */
  75. LDAP_DEBUG_PACKETS, /* SLAPI_LOG_PACKETS */
  76. LDAP_DEBUG_ARGS, /* SLAPI_LOG_ARGS */
  77. LDAP_DEBUG_CONNS, /* SLAPI_LOG_CONNS */
  78. LDAP_DEBUG_BER, /* SLAPI_LOG_BER */
  79. LDAP_DEBUG_FILTER, /* SLAPI_LOG_FILTER */
  80. LDAP_DEBUG_CONFIG, /* SLAPI_LOG_CONFIG */
  81. LDAP_DEBUG_ACL, /* SLAPI_LOG_ACL */
  82. LDAP_DEBUG_SHELL, /* SLAPI_LOG_SHELL */
  83. LDAP_DEBUG_PARSE, /* SLAPI_LOG_PARSE */
  84. LDAP_DEBUG_HOUSE, /* SLAPI_LOG_HOUSE */
  85. LDAP_DEBUG_REPL, /* SLAPI_LOG_REPL */
  86. LDAP_DEBUG_CACHE, /* SLAPI_LOG_CACHE */
  87. LDAP_DEBUG_PLUGIN, /* SLAPI_LOG_PLUGIN */
  88. LDAP_DEBUG_TIMING, /* SLAPI_LOG_TIMING */
  89. LDAP_DEBUG_ACLSUMMARY, /* SLAPI_LOG_ACLSUMMARY */
  90. };
  91. #define SLAPI_LOG_MIN SLAPI_LOG_FATAL /* from slapi-plugin.h */
  92. #define SLAPI_LOG_MAX SLAPI_LOG_ACLSUMMARY /* from slapi-plugin.h */
  93. #define TBUFSIZE 50 /* size for time buffers */
  94. #define SLAPI_LOG_BUFSIZ 2048 /* size for data buffers */
  95. /**************************************************************************
  96. * PROTOTYPES
  97. *************************************************************************/
  98. static int log__open_accesslogfile(int logfile_type, int locked);
  99. static int log__open_errorlogfile(int logfile_type, int locked);
  100. static int log__open_auditlogfile(int logfile_type, int locked);
  101. static int log__needrotation(LOGFD fp, int logtype);
  102. static int log__delete_access_logfile();
  103. static int log__delete_error_logfile();
  104. static int log__delete_audit_logfile();
  105. static int log__access_rotationinfof(char *pathname);
  106. static int log__error_rotationinfof(char *pathname);
  107. static int log__audit_rotationinfof(char *pathname);
  108. static int log__extract_logheader (FILE *fp, long *f_ctime, int *f_size);
  109. static int log__getfilesize(LOGFD fp);
  110. static int log__enough_freespace(char *path);
  111. static int vslapd_log_error(LOGFD fp, char *subsystem, char *fmt, va_list ap );
  112. static int vslapd_log_access(char *fmt, va_list ap );
  113. static void log_convert_time (time_t ctime, char *tbuf, int type);
  114. static LogBufferInfo *log_create_buffer(size_t sz);
  115. static void log_append_buffer2(time_t tnl, LogBufferInfo *lbi, char *msg1, size_t size1, char *msg2, size_t size2);
  116. static void log_flush_buffer(LogBufferInfo *lbi, int type, int sync_now);
  117. static void log_write_title(LOGFD fp);
  118. static int
  119. slapd_log_error_proc_internal(
  120. char *subsystem, /* omitted if NULL */
  121. char *fmt,
  122. va_list ap_err,
  123. va_list ap_file);
  124. /*
  125. * these macros are used for opening a log file, closing a log file, and
  126. * writing out to a log file. we have to do this because currently NSPR
  127. * is extremely under-performant on NT, while fopen/fwrite fail on several
  128. * unix platforms if there are more than 128 files open.
  129. *
  130. * LOG_OPEN_APPEND(fd, filename, mode) returns true if successful. 'fd' should
  131. * be of type LOGFD (check log.h). the file is open for appending to.
  132. * LOG_OPEN_WRITE(fd, filename, mode) is the same but truncates the file and
  133. * starts writing at the beginning of the file.
  134. * LOG_WRITE(fd, buffer, size, headersize) writes into a LOGFD
  135. * LOG_WRITE_NOW(fd, buffer, size, headersize) writes into a LOGFD and flushes the
  136. * buffer if necessary
  137. * LOG_CLOSE(fd) closes the logfile
  138. */
  139. #ifdef XP_WIN32
  140. #define LOG_OPEN_APPEND(fd, filename, mode) \
  141. (((fd) = fopen((filename), "a")) != NULL)
  142. #define LOG_OPEN_WRITE(fd, filename, mode) \
  143. (((fd) = fopen((filename), "w")) != NULL)
  144. #define LOG_WRITE(fd, buffer, size, headersize) \
  145. if ( fwrite((buffer), (size), 1, (fd)) != 1 ) \
  146. {\
  147. ReportSlapdEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVER_FAILED_TO_WRITE_LOG, 1, (buffer)); \
  148. }
  149. #define LOG_WRITE_NOW(fd, buffer, size, headersize) do {\
  150. if ( fwrite((buffer), (size), 1, (fd)) != 1 ) \
  151. { \
  152. ReportSlapdEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVER_FAILED_TO_WRITE_LOG, 1, (buffer)); \
  153. }; \
  154. fflush((fd)); \
  155. } while (0)
  156. #define LOG_CLOSE(fd) \
  157. fclose((fd))
  158. #else /* xp_win32 */
  159. #define LOG_OPEN_APPEND(fd, filename, mode) \
  160. (((fd) = PR_Open((filename), PR_WRONLY | PR_APPEND | PR_CREATE_FILE , \
  161. mode)) != NULL)
  162. #define LOG_OPEN_WRITE(fd, filename, mode) \
  163. (((fd) = PR_Open((filename), PR_WRONLY | PR_TRUNCATE | \
  164. PR_CREATE_FILE, mode)) != NULL)
  165. #define LOG_WRITE(fd, buffer, size, headersize) \
  166. if ( slapi_write_buffer((fd), (buffer), (size)) != (size) ) \
  167. { \
  168. PRErrorCode prerr = PR_GetError(); \
  169. syslog(LOG_ERR, "Failed to write log, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s): %s\n", prerr, slapd_pr_strerror(prerr), (buffer)+(headersize) ); \
  170. }
  171. #define LOG_WRITE_NOW(fd, buffer, size, headersize) do {\
  172. if ( slapi_write_buffer((fd), (buffer), (size)) != (size) ) \
  173. { \
  174. PRErrorCode prerr = PR_GetError(); \
  175. syslog(LOG_ERR, "Failed to write log, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s): %s\n", prerr, slapd_pr_strerror(prerr), (buffer)+(headersize) ); \
  176. } \
  177. /* Should be a flush in here ?? Yes because PR_SYNC doesn't work ! */ \
  178. PR_Sync(fd); \
  179. } while (0)
  180. #define LOG_CLOSE(fd) \
  181. PR_Close((fd))
  182. #endif
  183. /******************************************************************************
  184. * Set the access level
  185. ******************************************************************************/
  186. void g_set_accesslog_level(int val)
  187. {
  188. LOG_ACCESS_LOCK_WRITE( );
  189. loginfo.log_access_level = val;
  190. LOG_ACCESS_UNLOCK_WRITE();
  191. }
  192. /******************************************************************************
  193. * Set whether the process is alive or dead
  194. * If it is detached, then we write the error in 'stderr'
  195. ******************************************************************************/
  196. void g_set_detached(int val)
  197. {
  198. detached = val;
  199. }
  200. /******************************************************************************
  201. * Tell me whether logging begins or not
  202. ******************************************************************************/
  203. void g_log_init(int log_enabled)
  204. {
  205. slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
  206. #if defined( XP_WIN32 )
  207. char * instancedir = NULL;
  208. #endif
  209. ts_time_lock = PR_NewLock();
  210. if (! ts_time_lock)
  211. exit(-1);
  212. #if defined( XP_WIN32 )
  213. pszServerName = slapi_ch_malloc( MAX_SERVICE_NAME );
  214. instancedir = config_get_instancedir();
  215. unixtodospath(instancedir);
  216. if( !SlapdGetServerNameFromCmdline(pszServerName, instancedir, 1) )
  217. {
  218. MessageBox(GetDesktopWindow(), "Failed to get the Directory"
  219. " Server name from the command-line argument.",
  220. " ", MB_ICONEXCLAMATION | MB_OK);
  221. exit( 1 );
  222. }
  223. slapi_ch_free((void **)&instancedir);
  224. /* Register with the NT EventLog */
  225. hSlapdEventSource = RegisterEventSource(NULL, pszServerName );
  226. if( !hSlapdEventSource )
  227. {
  228. char szMessage[256];
  229. PR_snprintf( szMessage, sizeof(szMessage), "Directory Server %s is terminating. Failed "
  230. "to set the EventLog source.", pszServerName);
  231. MessageBox(GetDesktopWindow(), szMessage, " ",
  232. MB_ICONEXCLAMATION | MB_OK);
  233. exit( 1 );
  234. }
  235. #endif
  236. /* ACCESS LOG */
  237. loginfo.log_access_state = 0;
  238. loginfo.log_access_mode = SLAPD_DEFAULT_FILE_MODE;
  239. loginfo.log_access_maxnumlogs = 1;
  240. loginfo.log_access_maxlogsize = -1;
  241. loginfo.log_access_rotationsync_enabled = 0;
  242. loginfo.log_access_rotationsynchour = -1;
  243. loginfo.log_access_rotationsyncmin = -1;
  244. loginfo.log_access_rotationsyncclock = -1;
  245. loginfo.log_access_rotationtime = -1;
  246. loginfo.log_access_rotationunit = -1;
  247. loginfo.log_access_rotationtime_secs = -1;
  248. loginfo.log_access_maxdiskspace = -1;
  249. loginfo.log_access_minfreespace = -1;
  250. loginfo.log_access_exptime = -1;
  251. loginfo.log_access_exptimeunit = -1;
  252. loginfo.log_access_exptime_secs = -1;
  253. loginfo.log_access_level = LDAP_DEBUG_STATS;
  254. loginfo.log_access_ctime = 0L;
  255. loginfo.log_access_fdes = NULL;
  256. loginfo.log_access_file = NULL;
  257. loginfo.log_numof_access_logs = 1;
  258. loginfo.log_access_logchain = NULL;
  259. loginfo.log_access_buffer = log_create_buffer(LOG_BUFFER_MAXSIZE);
  260. if (loginfo.log_access_buffer == NULL)
  261. exit(-1);
  262. if ((loginfo.log_access_buffer->lock = PR_NewLock())== NULL )
  263. exit (-1);
  264. slapdFrontendConfig->accessloglevel = LDAP_DEBUG_STATS;
  265. /* ERROR LOG */
  266. loginfo.log_error_state = 0;
  267. loginfo.log_error_mode = SLAPD_DEFAULT_FILE_MODE;
  268. loginfo.log_error_maxnumlogs = 1;
  269. loginfo.log_error_maxlogsize = -1;
  270. loginfo.log_error_rotationsync_enabled = 0;
  271. loginfo.log_error_rotationsynchour = -1;
  272. loginfo.log_error_rotationsyncmin = -1;
  273. loginfo.log_error_rotationsyncclock = -1;
  274. loginfo.log_error_rotationtime = -1;
  275. loginfo.log_error_rotationunit = -1;
  276. loginfo.log_error_rotationtime_secs = -1;
  277. loginfo.log_error_maxdiskspace = -1;
  278. loginfo.log_error_minfreespace = -1;
  279. loginfo.log_error_exptime = -1;
  280. loginfo.log_error_exptimeunit = -1;
  281. loginfo.log_error_exptime_secs = -1;
  282. loginfo.log_error_ctime = 0L;
  283. loginfo.log_error_file = NULL;
  284. loginfo.log_error_fdes = NULL;
  285. loginfo.log_numof_error_logs = 1;
  286. loginfo.log_error_logchain = NULL;
  287. if ((loginfo.log_error_rwlock =rwl_new())== NULL ) {
  288. exit (-1);
  289. }
  290. /* AUDIT LOG */
  291. loginfo.log_audit_state = 0;
  292. loginfo.log_audit_mode = SLAPD_DEFAULT_FILE_MODE;
  293. loginfo.log_audit_maxnumlogs = 1;
  294. loginfo.log_audit_maxlogsize = -1;
  295. loginfo.log_audit_rotationsync_enabled = 0;
  296. loginfo.log_audit_rotationsynchour = -1;
  297. loginfo.log_audit_rotationsyncmin = -1;
  298. loginfo.log_audit_rotationsyncclock = -1;
  299. loginfo.log_audit_rotationtime = -1;
  300. loginfo.log_audit_rotationunit = -1;
  301. loginfo.log_audit_rotationtime_secs = -1;
  302. loginfo.log_audit_maxdiskspace = -1;
  303. loginfo.log_audit_minfreespace = -1;
  304. loginfo.log_audit_exptime = -1;
  305. loginfo.log_audit_exptimeunit = -1;
  306. loginfo.log_audit_exptime_secs = -1;
  307. loginfo.log_audit_ctime = 0L;
  308. loginfo.log_audit_file = NULL;
  309. loginfo.log_numof_audit_logs = 1;
  310. loginfo.log_audit_fdes = NULL;
  311. loginfo.log_audit_logchain = NULL;
  312. if ((loginfo.log_audit_rwlock =rwl_new())== NULL ) {
  313. exit (-1);
  314. }
  315. }
  316. /******************************************************************************
  317. * Tell me if log is enabled or disabled
  318. ******************************************************************************/
  319. int
  320. log_set_logging(const char *attrname, char *value, int logtype, char *errorbuf, int apply)
  321. {
  322. int v;
  323. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  324. if ( NULL == value ) {
  325. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  326. "%s: NULL value; valid values "
  327. "are \"on\" or \"off\"", attrname );
  328. return LDAP_OPERATIONS_ERROR;
  329. }
  330. if (strcasecmp(value, "on") == 0) {
  331. v = LOGGING_ENABLED;
  332. }
  333. else if (strcasecmp(value, "off") == 0 ) {
  334. v = 0;
  335. }
  336. else {
  337. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  338. "%s: invalid value \"%s\", valid values "
  339. "are \"on\" or \"off\"", attrname, value );
  340. return LDAP_OPERATIONS_ERROR;
  341. }
  342. if ( !apply ){
  343. return LDAP_SUCCESS;
  344. }
  345. switch (logtype) {
  346. case SLAPD_ACCESS_LOG:
  347. LOG_ACCESS_LOCK_WRITE( );
  348. fe_cfg->accesslog_logging_enabled = v;
  349. if(v) {
  350. loginfo.log_access_state |= LOGGING_ENABLED;
  351. }
  352. else {
  353. loginfo.log_access_state &= ~LOGGING_ENABLED;
  354. }
  355. LOG_ACCESS_UNLOCK_WRITE();
  356. break;
  357. case SLAPD_ERROR_LOG:
  358. LOG_ERROR_LOCK_WRITE( );
  359. fe_cfg->errorlog_logging_enabled = v;
  360. if (v) {
  361. loginfo.log_error_state |= LOGGING_ENABLED;
  362. }
  363. else {
  364. loginfo.log_error_state &= ~LOGGING_ENABLED;
  365. }
  366. LOG_ERROR_UNLOCK_WRITE();
  367. break;
  368. case SLAPD_AUDIT_LOG:
  369. LOG_AUDIT_LOCK_WRITE( );
  370. fe_cfg->auditlog_logging_enabled = v;
  371. if (v) {
  372. loginfo.log_audit_state |= LOGGING_ENABLED;
  373. }
  374. else {
  375. loginfo.log_audit_state &= ~LOGGING_ENABLED;
  376. }
  377. LOG_AUDIT_UNLOCK_WRITE();
  378. break;
  379. }
  380. return LDAP_SUCCESS;
  381. }
  382. /******************************************************************************
  383. * Tell me the access log file name inc path
  384. ******************************************************************************/
  385. char *
  386. g_get_access_log () {
  387. char *logfile = NULL;
  388. LOG_ACCESS_LOCK_READ();
  389. if ( loginfo.log_access_file)
  390. logfile = slapi_ch_strdup (loginfo.log_access_file);
  391. LOG_ACCESS_UNLOCK_READ();
  392. return logfile;
  393. }
  394. /******************************************************************************
  395. * Point to a new access logdir
  396. *
  397. * Returns:
  398. * LDAP_SUCCESS -- success
  399. * LDAP_UNWILLING_TO_PERFORM -- when trying to open a invalid log file
  400. * LDAP_LOCAL_ERRO -- some error
  401. ******************************************************************************/
  402. int
  403. log_update_accesslogdir(char *pathname, int apply)
  404. {
  405. int rv = LDAP_SUCCESS;
  406. LOGFD fp;
  407. /* try to open the file, we may have a incorrect path */
  408. if (! LOG_OPEN_APPEND(fp, pathname, loginfo.log_access_mode)) {
  409. LDAPDebug(LDAP_DEBUG_ANY, "WARNING: can't open file %s. "
  410. "errno %d (%s)\n",
  411. pathname, errno, slapd_system_strerror(errno));
  412. /* stay with the current log file */
  413. return LDAP_UNWILLING_TO_PERFORM;
  414. }
  415. LOG_CLOSE(fp);
  416. /* skip the rest if we aren't doing this for real */
  417. if ( !apply ) {
  418. return LDAP_SUCCESS;
  419. }
  420. /*
  421. ** The user has changed the access log directory. That means we
  422. ** need to start fresh.
  423. */
  424. LOG_ACCESS_LOCK_WRITE ();
  425. if (loginfo.log_access_fdes) {
  426. LogFileInfo *logp, *d_logp;
  427. LDAPDebug(LDAP_DEBUG_TRACE,
  428. "LOGINFO:Closing the access log file. "
  429. "Moving to a new access log file (%s)\n", pathname,0,0);
  430. LOG_CLOSE(loginfo.log_access_fdes);
  431. loginfo.log_access_fdes = 0;
  432. loginfo.log_access_ctime = 0;
  433. logp = loginfo.log_access_logchain;
  434. while (logp) {
  435. d_logp = logp;
  436. logp = logp->l_next;
  437. slapi_ch_free((void**)&d_logp);
  438. }
  439. loginfo.log_access_logchain = NULL;
  440. slapi_ch_free((void**)&loginfo.log_access_file);
  441. loginfo.log_access_file = NULL;
  442. loginfo.log_numof_access_logs = 1;
  443. }
  444. /* Now open the new access log file */
  445. if ( access_log_openf (pathname, 1 /* locked */)) {
  446. rv = LDAP_LOCAL_ERROR; /* error Unable to use the new dir */
  447. }
  448. LOG_ACCESS_UNLOCK_WRITE();
  449. return rv;
  450. }
  451. /******************************************************************************
  452. * Tell me the error log file name inc path
  453. ******************************************************************************/
  454. char *
  455. g_get_error_log() {
  456. char *logfile = NULL;
  457. LOG_ERROR_LOCK_READ();
  458. if ( loginfo.log_error_file)
  459. logfile = slapi_ch_strdup (loginfo.log_error_file);
  460. LOG_ERROR_UNLOCK_READ();
  461. return logfile;
  462. }
  463. /******************************************************************************
  464. * Point to a new error logdir
  465. *
  466. * Returns:
  467. * LDAP_SUCCESS -- success
  468. * LDAP_UNWILLING_TO_PERFORM -- when trying to open a invalid log file
  469. * LDAP_LOCAL_ERRO -- some error
  470. ******************************************************************************/
  471. int
  472. log_update_errorlogdir(char *pathname, int apply)
  473. {
  474. int rv = LDAP_SUCCESS;
  475. LOGFD fp;
  476. /* try to open the file, we may have a incorrect path */
  477. if (! LOG_OPEN_APPEND(fp, pathname, loginfo.log_error_mode)) {
  478. LDAPDebug(LDAP_DEBUG_ANY, "WARNING: can't open file %s. "
  479. "errno %d (%s)\n",
  480. pathname, errno, slapd_system_strerror(errno));
  481. /* stay with the current log file */
  482. return LDAP_UNWILLING_TO_PERFORM;
  483. }
  484. /* skip the rest if we aren't doing this for real */
  485. if ( !apply ) {
  486. return LDAP_SUCCESS;
  487. }
  488. LOG_CLOSE(fp);
  489. /*
  490. ** The user has changed the error log directory. That means we
  491. ** need to start fresh.
  492. */
  493. LOG_ERROR_LOCK_WRITE ();
  494. if (loginfo.log_error_fdes) {
  495. LogFileInfo *logp, *d_logp;
  496. LOG_CLOSE(loginfo.log_error_fdes);
  497. loginfo.log_error_fdes = 0;
  498. loginfo.log_error_ctime = 0;
  499. logp = loginfo.log_error_logchain;
  500. while (logp) {
  501. d_logp = logp;
  502. logp = logp->l_next;
  503. slapi_ch_free((void**)&d_logp);
  504. }
  505. loginfo.log_error_logchain = NULL;
  506. slapi_ch_free((void**)&loginfo.log_error_file);
  507. loginfo.log_error_file = NULL;
  508. loginfo.log_numof_error_logs = 1;
  509. }
  510. /* Now open the new errorlog */
  511. if ( error_log_openf (pathname, 1 /* obtained lock */)) {
  512. rv = LDAP_LOCAL_ERROR; /* error: Unable to use the new dir */
  513. }
  514. LOG_ERROR_UNLOCK_WRITE();
  515. return rv;
  516. }
  517. /******************************************************************************
  518. * Tell me the audit log file name inc path
  519. ******************************************************************************/
  520. char *
  521. g_get_audit_log() {
  522. char *logfile = NULL;
  523. LOG_AUDIT_LOCK_READ();
  524. if ( loginfo.log_audit_file)
  525. logfile = slapi_ch_strdup (loginfo.log_audit_file);
  526. LOG_AUDIT_UNLOCK_READ();
  527. return logfile;
  528. }
  529. /******************************************************************************
  530. * Point to a new audit logdir
  531. *
  532. * Returns:
  533. * LDAP_SUCCESS -- success
  534. * LDAP_UNWILLING_TO_PERFORM -- when trying to open a invalid log file
  535. * LDAP_LOCAL_ERRO -- some error
  536. ******************************************************************************/
  537. int
  538. log_update_auditlogdir(char *pathname, int apply)
  539. {
  540. int rv = LDAP_SUCCESS;
  541. LOGFD fp;
  542. /* try to open the file, we may have a incorrect path */
  543. if (! LOG_OPEN_APPEND(fp, pathname, loginfo.log_audit_mode)) {
  544. LDAPDebug(LDAP_DEBUG_ANY, "WARNING: can't open file %s. "
  545. "errno %d (%s)\n",
  546. pathname, errno, slapd_system_strerror(errno));
  547. /* stay with the current log file */
  548. return LDAP_UNWILLING_TO_PERFORM;
  549. }
  550. /* skip the rest if we aren't doing this for real */
  551. if ( !apply ) {
  552. return LDAP_SUCCESS;
  553. }
  554. LOG_CLOSE(fp);
  555. /*
  556. ** The user has changed the audit log directory. That means we
  557. ** need to start fresh.
  558. */
  559. LOG_AUDIT_LOCK_WRITE ();
  560. if (loginfo.log_audit_fdes) {
  561. LogFileInfo *logp, *d_logp;
  562. LDAPDebug(LDAP_DEBUG_TRACE,
  563. "LOGINFO:Closing the audit log file. "
  564. "Moving to a new audit file (%s)\n", pathname,0,0);
  565. LOG_CLOSE(loginfo.log_audit_fdes);
  566. loginfo.log_audit_fdes = 0;
  567. loginfo.log_audit_ctime = 0;
  568. logp = loginfo.log_audit_logchain;
  569. while (logp) {
  570. d_logp = logp;
  571. logp = logp->l_next;
  572. slapi_ch_free((void**)&d_logp);
  573. }
  574. loginfo.log_audit_logchain = NULL;
  575. slapi_ch_free((void**)&loginfo.log_audit_file);
  576. loginfo.log_audit_file = NULL;
  577. loginfo.log_numof_audit_logs = 1;
  578. }
  579. /* Now open the new errorlog */
  580. if ( audit_log_openf (pathname, 1 /* locked */)) {
  581. rv = LDAP_LOCAL_ERROR; /* error: Unable to use the new dir */
  582. }
  583. LOG_AUDIT_UNLOCK_WRITE();
  584. return rv;
  585. }
  586. int
  587. log_set_mode (const char *attrname, char *value, int logtype, char *errorbuf, int apply)
  588. {
  589. int v = 0;
  590. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  591. if ( NULL == value ) {
  592. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  593. "%s: null value; valid values "
  594. "are are of the format \"yz-yz-yz-\" where y could be 'r' or '-',"
  595. " and z could be 'w' or '-'", attrname );
  596. return LDAP_OPERATIONS_ERROR;
  597. }
  598. if ( !apply ){
  599. return LDAP_SUCCESS;
  600. }
  601. v = strtol (value, NULL, 8);
  602. switch (logtype) {
  603. case SLAPD_ACCESS_LOG:
  604. LOG_ACCESS_LOCK_WRITE( );
  605. slapi_ch_free ( (void **) &fe_cfg->accesslog_mode );
  606. fe_cfg->accesslog_mode = slapi_ch_strdup (value);
  607. loginfo.log_access_mode = v;
  608. LOG_ACCESS_UNLOCK_WRITE();
  609. break;
  610. case SLAPD_ERROR_LOG:
  611. LOG_ERROR_LOCK_WRITE( );
  612. slapi_ch_free ( (void **) &fe_cfg->errorlog_mode );
  613. fe_cfg->errorlog_mode = slapi_ch_strdup (value);
  614. loginfo.log_error_mode = v;
  615. LOG_ERROR_UNLOCK_WRITE();
  616. break;
  617. case SLAPD_AUDIT_LOG:
  618. LOG_AUDIT_LOCK_WRITE( );
  619. slapi_ch_free ( (void **) &fe_cfg->auditlog_mode );
  620. fe_cfg->auditlog_mode = slapi_ch_strdup (value);
  621. loginfo.log_audit_mode = v;
  622. LOG_AUDIT_UNLOCK_WRITE();
  623. break;
  624. }
  625. return LDAP_SUCCESS;
  626. }
  627. /******************************************************************************
  628. * MAX NUMBER OF LOGS
  629. ******************************************************************************/
  630. int
  631. log_set_numlogsperdir(const char *attrname, char *numlogs_str, int logtype, char *returntext, int apply)
  632. {
  633. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  634. int rv = LDAP_SUCCESS;
  635. int numlogs;
  636. if ( logtype != SLAPD_ACCESS_LOG &&
  637. logtype != SLAPD_ERROR_LOG &&
  638. logtype != SLAPD_AUDIT_LOG ) {
  639. rv = LDAP_OPERATIONS_ERROR;
  640. PR_snprintf( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
  641. "%s: invalid log type %d", attrname, logtype );
  642. }
  643. if ( !apply || !numlogs_str || !*numlogs_str) {
  644. return rv;
  645. }
  646. numlogs = atoi(numlogs_str);
  647. if (numlogs >= 1) {
  648. switch (logtype) {
  649. case SLAPD_ACCESS_LOG:
  650. LOG_ACCESS_LOCK_WRITE( );
  651. loginfo.log_access_maxnumlogs = numlogs;
  652. fe_cfg->accesslog_maxnumlogs = numlogs;
  653. LOG_ACCESS_UNLOCK_WRITE();
  654. break;
  655. case SLAPD_ERROR_LOG:
  656. LOG_ERROR_LOCK_WRITE( );
  657. loginfo.log_error_maxnumlogs = numlogs;
  658. fe_cfg->errorlog_maxnumlogs = numlogs;
  659. LOG_ERROR_UNLOCK_WRITE();
  660. break;
  661. case SLAPD_AUDIT_LOG:
  662. LOG_AUDIT_LOCK_WRITE( );
  663. loginfo.log_audit_maxnumlogs = numlogs;
  664. fe_cfg->auditlog_maxnumlogs = numlogs;
  665. LOG_AUDIT_UNLOCK_WRITE();
  666. break;
  667. default:
  668. rv = LDAP_OPERATIONS_ERROR;
  669. LDAPDebug( LDAP_DEBUG_ANY,
  670. "log_set_numlogsperdir: invalid log type %d", logtype,0,0 );
  671. }
  672. }
  673. return rv;
  674. }
  675. /******************************************************************************
  676. * LOG SIZE
  677. * Return Values:
  678. * LDAP_OPERATIONS_ERROR -- fail
  679. * LDAP_SUCCESS -- success
  680. *
  681. * NOTE: The config struct should contain the maxlogsize in MB and not in bytes.
  682. ******************************************************************************/
  683. int
  684. log_set_logsize(const char *attrname, char *logsize_str, int logtype, char *returntext, int apply)
  685. {
  686. int rv = LDAP_SUCCESS;
  687. int mdiskspace= 0;
  688. int max_logsize;
  689. int logsize;
  690. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  691. if (!apply || !logsize_str || !*logsize_str)
  692. return rv;
  693. logsize = atoi(logsize_str);
  694. /* convert it to bytes */
  695. max_logsize = logsize * LOG_MB_IN_BYTES;
  696. if (max_logsize <= 0) {
  697. max_logsize = -1;
  698. }
  699. switch (logtype) {
  700. case SLAPD_ACCESS_LOG:
  701. LOG_ACCESS_LOCK_WRITE( );
  702. mdiskspace = loginfo.log_access_maxdiskspace;
  703. break;
  704. case SLAPD_ERROR_LOG:
  705. LOG_ERROR_LOCK_WRITE( );
  706. mdiskspace = loginfo.log_error_maxdiskspace;
  707. break;
  708. case SLAPD_AUDIT_LOG:
  709. LOG_AUDIT_LOCK_WRITE( );
  710. mdiskspace = loginfo.log_audit_maxdiskspace;
  711. break;
  712. default:
  713. PR_snprintf( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
  714. "%s: invalid logtype %d", attrname, logtype );
  715. rv = LDAP_OPERATIONS_ERROR;
  716. }
  717. if ((max_logsize > mdiskspace) && (mdiskspace != -1))
  718. rv = 2;
  719. switch (logtype) {
  720. case SLAPD_ACCESS_LOG:
  721. if (!rv && apply) {
  722. loginfo.log_access_maxlogsize = max_logsize;
  723. fe_cfg->accesslog_maxlogsize = logsize;
  724. }
  725. LOG_ACCESS_UNLOCK_WRITE();
  726. break;
  727. case SLAPD_ERROR_LOG:
  728. if (!rv && apply) {
  729. loginfo.log_error_maxlogsize = max_logsize;
  730. fe_cfg->errorlog_maxlogsize = logsize;
  731. }
  732. LOG_ERROR_UNLOCK_WRITE();
  733. break;
  734. case SLAPD_AUDIT_LOG:
  735. if (!rv && apply) {
  736. loginfo.log_audit_maxlogsize = max_logsize;
  737. fe_cfg->auditlog_maxlogsize = logsize;
  738. }
  739. LOG_AUDIT_UNLOCK_WRITE();
  740. break;
  741. default:
  742. rv = 1;
  743. }
  744. /* logsize will be in n MB. Convert it to bytes */
  745. if (rv == 2) {
  746. LDAPDebug (LDAP_DEBUG_ANY,
  747. "Invalid value for Maximum log size:"
  748. "Maxlogsize:%d MB Maxdisksize:%d MB\n",
  749. logsize, mdiskspace/LOG_MB_IN_BYTES,0);
  750. rv = LDAP_OPERATIONS_ERROR;
  751. }
  752. return rv;
  753. }
  754. time_t
  755. log_get_rotationsyncclock(int synchour, int syncmin)
  756. {
  757. struct tm *currtm;
  758. time_t currclock;
  759. time_t syncclock;
  760. int hours, minutes;
  761. time( &currclock);
  762. currtm = localtime( &currclock );
  763. if ( syncmin < currtm->tm_min ) {
  764. minutes = syncmin + 60 - currtm->tm_min;
  765. hours = synchour - 1 - currtm->tm_hour;
  766. } else {
  767. minutes = syncmin - currtm->tm_min;
  768. hours = synchour - currtm->tm_hour;
  769. }
  770. if ( hours < 0 ) hours += 24;
  771. syncclock = currclock + hours * 3600 + minutes * 60;
  772. return syncclock;
  773. }
  774. int
  775. log_set_rotationsync_enabled(const char *attrname, char *value, int logtype, char *errorbuf, int apply)
  776. {
  777. int v;
  778. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  779. if ( NULL == value ) {
  780. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  781. "%s: NULL value; valid values "
  782. "are \"on\" or \"off\"", attrname );
  783. return LDAP_OPERATIONS_ERROR;
  784. }
  785. if (strcasecmp(value, "on") == 0) {
  786. v = LDAP_ON;
  787. }
  788. else if (strcasecmp(value, "off") == 0 ) {
  789. v = LDAP_OFF;
  790. }
  791. else {
  792. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  793. "%s: invalid value \"%s\", valid values "
  794. "are \"on\" or \"off\"", attrname, value );
  795. return LDAP_OPERATIONS_ERROR;
  796. }
  797. if ( !apply ){
  798. return LDAP_SUCCESS;
  799. }
  800. switch (logtype) {
  801. case SLAPD_ACCESS_LOG:
  802. LOG_ACCESS_LOCK_WRITE( );
  803. fe_cfg->accesslog_rotationsync_enabled = v;
  804. loginfo.log_access_rotationsync_enabled = v;
  805. LOG_ACCESS_UNLOCK_WRITE();
  806. break;
  807. case SLAPD_ERROR_LOG:
  808. LOG_ERROR_LOCK_WRITE( );
  809. fe_cfg->errorlog_rotationsync_enabled = v;
  810. loginfo.log_error_rotationsync_enabled = v;
  811. LOG_ERROR_UNLOCK_WRITE();
  812. break;
  813. case SLAPD_AUDIT_LOG:
  814. LOG_AUDIT_LOCK_WRITE( );
  815. fe_cfg->auditlog_rotationsync_enabled = v;
  816. loginfo.log_audit_rotationsync_enabled = v;
  817. LOG_AUDIT_UNLOCK_WRITE();
  818. break;
  819. }
  820. return LDAP_SUCCESS;
  821. }
  822. int
  823. log_set_rotationsynchour(const char *attrname, char *rhour_str, int logtype, char *returntext, int apply)
  824. {
  825. int rhour = -1;
  826. int rv = LDAP_SUCCESS;
  827. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  828. if ( logtype != SLAPD_ACCESS_LOG &&
  829. logtype != SLAPD_ERROR_LOG &&
  830. logtype != SLAPD_AUDIT_LOG ) {
  831. PR_snprintf( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
  832. "%s: invalid log type: %d", attrname, logtype );
  833. return LDAP_OPERATIONS_ERROR;
  834. }
  835. /* return if we aren't doing this for real */
  836. if ( !apply ) {
  837. return rv;
  838. }
  839. if ( rhour_str && *rhour_str != '\0' )
  840. rhour = atol( rhour_str );
  841. if ( rhour > 23 )
  842. rhour = rhour % 24;
  843. switch (logtype) {
  844. case SLAPD_ACCESS_LOG:
  845. LOG_ACCESS_LOCK_WRITE( );
  846. loginfo.log_access_rotationsynchour = rhour;
  847. loginfo.log_access_rotationsyncclock = log_get_rotationsyncclock( rhour, loginfo.log_access_rotationsyncmin );
  848. fe_cfg->accesslog_rotationsynchour = rhour;
  849. LOG_ACCESS_UNLOCK_WRITE();
  850. break;
  851. case SLAPD_ERROR_LOG:
  852. LOG_ERROR_LOCK_WRITE( );
  853. loginfo.log_error_rotationsynchour = rhour;
  854. loginfo.log_error_rotationsyncclock = log_get_rotationsyncclock( rhour, loginfo.log_error_rotationsyncmin );
  855. fe_cfg->errorlog_rotationsynchour = rhour;
  856. LOG_ERROR_UNLOCK_WRITE();
  857. break;
  858. case SLAPD_AUDIT_LOG:
  859. LOG_AUDIT_LOCK_WRITE( );
  860. loginfo.log_audit_rotationsynchour = rhour;
  861. loginfo.log_audit_rotationsyncclock = log_get_rotationsyncclock( rhour, loginfo.log_audit_rotationsyncmin );
  862. fe_cfg->auditlog_rotationsynchour = rhour;
  863. LOG_AUDIT_UNLOCK_WRITE();
  864. break;
  865. default:
  866. rv = 1;
  867. }
  868. return rv;
  869. }
  870. int
  871. log_set_rotationsyncmin(const char *attrname, char *rmin_str, int logtype, char *returntext, int apply)
  872. {
  873. int rmin = -1;
  874. int rv = LDAP_SUCCESS;
  875. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  876. if ( logtype != SLAPD_ACCESS_LOG &&
  877. logtype != SLAPD_ERROR_LOG &&
  878. logtype != SLAPD_AUDIT_LOG ) {
  879. PR_snprintf( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
  880. "%s: invalid log type: %d", attrname, logtype );
  881. return LDAP_OPERATIONS_ERROR;
  882. }
  883. /* return if we aren't doing this for real */
  884. if ( !apply ) {
  885. return rv;
  886. }
  887. if ( rmin_str && *rmin_str != '\0' )
  888. rmin = atol( rmin_str );
  889. if ( rmin > 59 )
  890. rmin = rmin % 60;
  891. switch (logtype) {
  892. case SLAPD_ACCESS_LOG:
  893. LOG_ACCESS_LOCK_WRITE( );
  894. loginfo.log_access_rotationsyncmin = rmin;
  895. fe_cfg->accesslog_rotationsyncmin = rmin;
  896. loginfo.log_access_rotationsyncclock = log_get_rotationsyncclock( loginfo.log_access_rotationsynchour, rmin );
  897. LOG_ACCESS_UNLOCK_WRITE();
  898. break;
  899. case SLAPD_ERROR_LOG:
  900. LOG_ERROR_LOCK_WRITE( );
  901. loginfo.log_error_rotationsyncmin = rmin;
  902. loginfo.log_error_rotationsyncclock = log_get_rotationsyncclock( loginfo.log_error_rotationsynchour, rmin );
  903. fe_cfg->errorlog_rotationsyncmin = rmin;
  904. LOG_ERROR_UNLOCK_WRITE();
  905. break;
  906. case SLAPD_AUDIT_LOG:
  907. LOG_AUDIT_LOCK_WRITE( );
  908. loginfo.log_audit_rotationsyncmin = rmin;
  909. fe_cfg->auditlog_rotationsyncmin = rmin;
  910. loginfo.log_audit_rotationsyncclock = log_get_rotationsyncclock( loginfo.log_audit_rotationsynchour, rmin );
  911. LOG_AUDIT_UNLOCK_WRITE();
  912. break;
  913. default:
  914. rv = 1;
  915. }
  916. return rv;
  917. }
  918. /******************************************************************************
  919. * ROTATION TIME
  920. * Return Values:
  921. * 1 -- fail
  922. * 0 -- success
  923. ******************************************************************************/
  924. int
  925. log_set_rotationtime(const char *attrname, char *rtime_str, int logtype, char *returntext, int apply)
  926. {
  927. int runit= 0;
  928. int value, rtime;
  929. int rv = LDAP_SUCCESS;
  930. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  931. if ( logtype != SLAPD_ACCESS_LOG &&
  932. logtype != SLAPD_ERROR_LOG &&
  933. logtype != SLAPD_AUDIT_LOG ) {
  934. PR_snprintf( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
  935. "%s: invalid log type: %d", attrname, logtype );
  936. return LDAP_OPERATIONS_ERROR;
  937. }
  938. /* return if we aren't doing this for real */
  939. if ( !apply || !rtime_str || !*rtime_str) {
  940. return rv;
  941. }
  942. rtime = atoi(rtime_str);
  943. switch (logtype) {
  944. case SLAPD_ACCESS_LOG:
  945. LOG_ACCESS_LOCK_WRITE( );
  946. loginfo.log_access_rotationtime = rtime;
  947. runit = loginfo.log_access_rotationunit;
  948. break;
  949. case SLAPD_ERROR_LOG:
  950. LOG_ERROR_LOCK_WRITE( );
  951. loginfo.log_error_rotationtime = rtime;
  952. runit = loginfo.log_error_rotationunit;
  953. break;
  954. case SLAPD_AUDIT_LOG:
  955. LOG_AUDIT_LOCK_WRITE( );
  956. loginfo.log_audit_rotationtime = rtime;
  957. runit = loginfo.log_audit_rotationunit;
  958. break;
  959. default:
  960. rv = 1;
  961. }
  962. /* find out the rotation unit we have se right now */
  963. if (runit == LOG_UNIT_MONTHS) {
  964. value = 31 * 24 * 60 * 60 * rtime;
  965. } else if (runit == LOG_UNIT_WEEKS) {
  966. value = 7 * 24 * 60 * 60 * rtime;
  967. } else if (runit == LOG_UNIT_DAYS ) {
  968. value = 24 * 60 * 60 * rtime;
  969. } else if (runit == LOG_UNIT_HOURS) {
  970. value = 3600 * rtime;
  971. } else if (runit == LOG_UNIT_MINS) {
  972. value = 60 * rtime;
  973. } else {
  974. /* In this case we don't rotate */
  975. value = -1;
  976. }
  977. switch (logtype) {
  978. case SLAPD_ACCESS_LOG:
  979. fe_cfg->accesslog_rotationtime = rtime;
  980. loginfo.log_access_rotationtime_secs = value;
  981. LOG_ACCESS_UNLOCK_WRITE();
  982. break;
  983. case SLAPD_ERROR_LOG:
  984. fe_cfg->errorlog_rotationtime = rtime;
  985. loginfo.log_error_rotationtime_secs = value;
  986. LOG_ERROR_UNLOCK_WRITE();
  987. break;
  988. case SLAPD_AUDIT_LOG:
  989. fe_cfg->auditlog_rotationtime = rtime;
  990. loginfo.log_audit_rotationtime_secs = value;
  991. LOG_AUDIT_UNLOCK_WRITE();
  992. break;
  993. default:
  994. rv = 1;
  995. }
  996. return rv;
  997. }
  998. /******************************************************************************
  999. * ROTATION TIME UNIT
  1000. * Return Values:
  1001. * 1 -- fail
  1002. * 0 -- success
  1003. ******************************************************************************/
  1004. int log_set_rotationtimeunit(const char *attrname, char *runit, int logtype, char *errorbuf, int apply)
  1005. {
  1006. int value= 0;
  1007. int runitType;
  1008. int rv = 0;
  1009. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  1010. if ( logtype != SLAPD_ACCESS_LOG &&
  1011. logtype != SLAPD_ERROR_LOG &&
  1012. logtype != SLAPD_AUDIT_LOG ) {
  1013. PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  1014. "%s: invalid log type: %d", attrname, logtype );
  1015. return LDAP_OPERATIONS_ERROR;
  1016. }
  1017. if ( (strcasecmp(runit, "month") == 0) ||
  1018. (strcasecmp(runit, "week") == 0) ||
  1019. (strcasecmp(runit, "day") == 0) ||
  1020. (strcasecmp(runit, "hour") == 0) ||
  1021. (strcasecmp(runit, "minute") == 0)) {
  1022. /* all good values */
  1023. } else {
  1024. PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  1025. "%s: unknown unit \"%s\"", attrname, runit );
  1026. rv = LDAP_OPERATIONS_ERROR;
  1027. }
  1028. /* return if we aren't doing this for real */
  1029. if ( !apply ) {
  1030. return rv;
  1031. }
  1032. switch (logtype) {
  1033. case SLAPD_ACCESS_LOG:
  1034. LOG_ACCESS_LOCK_WRITE( );
  1035. value = loginfo.log_access_rotationtime;
  1036. break;
  1037. case SLAPD_ERROR_LOG:
  1038. LOG_ERROR_LOCK_WRITE( );
  1039. value = loginfo.log_error_rotationtime;
  1040. break;
  1041. case SLAPD_AUDIT_LOG:
  1042. LOG_AUDIT_LOCK_WRITE( );
  1043. value = loginfo.log_audit_rotationtime;
  1044. break;
  1045. default:
  1046. rv = 1;
  1047. }
  1048. if (strcasecmp(runit, "month") == 0) {
  1049. runitType = LOG_UNIT_MONTHS;
  1050. value *= 31 * 24 * 60 * 60;
  1051. } else if (strcasecmp(runit, "week") == 0) {
  1052. runitType = LOG_UNIT_WEEKS;
  1053. value *= 7 * 24 * 60 * 60;
  1054. } else if (strcasecmp(runit, "day") == 0) {
  1055. runitType = LOG_UNIT_DAYS;
  1056. value *= 24 * 60 * 60;
  1057. } else if (strcasecmp(runit, "hour") == 0) {
  1058. runitType = LOG_UNIT_HOURS;
  1059. value *= 3600;
  1060. } else if (strcasecmp(runit, "minute") == 0) {
  1061. runitType = LOG_UNIT_MINS;
  1062. value *= 60;
  1063. } else {
  1064. /* In this case we don't rotate */
  1065. runitType = LOG_UNIT_UNKNOWN;
  1066. value = -1;
  1067. }
  1068. switch (logtype) {
  1069. case SLAPD_ACCESS_LOG:
  1070. loginfo.log_access_rotationtime_secs = value;
  1071. loginfo.log_access_rotationunit = runitType;
  1072. slapi_ch_free ( (void **) &fe_cfg->accesslog_rotationunit);
  1073. fe_cfg->accesslog_rotationunit = slapi_ch_strdup ( runit );
  1074. LOG_ACCESS_UNLOCK_WRITE();
  1075. break;
  1076. case SLAPD_ERROR_LOG:
  1077. loginfo.log_error_rotationtime_secs = value;
  1078. loginfo.log_error_rotationunit = runitType;
  1079. slapi_ch_free ( (void **) &fe_cfg->errorlog_rotationunit) ;
  1080. fe_cfg->errorlog_rotationunit = slapi_ch_strdup ( runit );
  1081. LOG_ERROR_UNLOCK_WRITE();
  1082. break;
  1083. case SLAPD_AUDIT_LOG:
  1084. loginfo.log_audit_rotationtime_secs = value;
  1085. loginfo.log_audit_rotationunit = runitType;
  1086. slapi_ch_free ( (void **) &fe_cfg->auditlog_rotationunit);
  1087. fe_cfg->auditlog_rotationunit = slapi_ch_strdup ( runit );
  1088. LOG_AUDIT_UNLOCK_WRITE();
  1089. break;
  1090. default:
  1091. rv = 1;
  1092. }
  1093. return rv;
  1094. }
  1095. /******************************************************************************
  1096. * MAXIMUM DISK SPACE
  1097. * Return Values:
  1098. * 1 -- fail
  1099. * 0 -- success
  1100. *
  1101. * NOTE:
  1102. * The config struct should contain the value in MB and not in bytes.
  1103. ******************************************************************************/
  1104. int
  1105. log_set_maxdiskspace(const char *attrname, char *maxdiskspace_str, int logtype, char *errorbuf, int apply)
  1106. {
  1107. int rv = 0;
  1108. int mlogsize;
  1109. int maxdiskspace;
  1110. int s_maxdiskspace;
  1111. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  1112. if ( logtype != SLAPD_ACCESS_LOG &&
  1113. logtype != SLAPD_ERROR_LOG &&
  1114. logtype != SLAPD_AUDIT_LOG ) {
  1115. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  1116. "%s: invalid log type: %d", attrname, logtype );
  1117. return LDAP_OPERATIONS_ERROR;
  1118. }
  1119. if (!apply || !maxdiskspace_str || !*maxdiskspace_str)
  1120. return rv;
  1121. maxdiskspace = atoi(maxdiskspace_str);
  1122. s_maxdiskspace = maxdiskspace;
  1123. /* Disk space are in MB but store in bytes */
  1124. switch (logtype) {
  1125. case SLAPD_ACCESS_LOG:
  1126. LOG_ACCESS_LOCK_WRITE( );
  1127. mlogsize = loginfo.log_access_maxlogsize;
  1128. break;
  1129. case SLAPD_ERROR_LOG:
  1130. LOG_ERROR_LOCK_WRITE( );
  1131. mlogsize = loginfo.log_error_maxlogsize;
  1132. break;
  1133. case SLAPD_AUDIT_LOG:
  1134. LOG_AUDIT_LOCK_WRITE( );
  1135. mlogsize = loginfo.log_audit_maxlogsize;
  1136. break;
  1137. default:
  1138. rv = 1;
  1139. mlogsize = -1;
  1140. }
  1141. maxdiskspace *= LOG_MB_IN_BYTES;
  1142. if (maxdiskspace < 0) {
  1143. maxdiskspace = -1;
  1144. }
  1145. else if (maxdiskspace < mlogsize) {
  1146. rv = LDAP_OPERATIONS_ERROR;
  1147. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  1148. "%s: maxdiskspace \"%d\" is less than max log size \"%d\"",
  1149. attrname, maxdiskspace, mlogsize );
  1150. }
  1151. switch (logtype) {
  1152. case SLAPD_ACCESS_LOG:
  1153. if (rv== 0 && apply) {
  1154. loginfo.log_access_maxdiskspace = maxdiskspace;
  1155. fe_cfg->accesslog_maxdiskspace = s_maxdiskspace ;
  1156. }
  1157. LOG_ACCESS_UNLOCK_WRITE();
  1158. break;
  1159. case SLAPD_ERROR_LOG:
  1160. if (rv== 0 && apply) {
  1161. loginfo.log_error_maxdiskspace = maxdiskspace;
  1162. fe_cfg->errorlog_maxdiskspace = s_maxdiskspace;
  1163. }
  1164. LOG_ERROR_UNLOCK_WRITE();
  1165. break;
  1166. case SLAPD_AUDIT_LOG:
  1167. if (rv== 0 && apply) {
  1168. loginfo.log_audit_maxdiskspace = maxdiskspace;
  1169. fe_cfg->auditlog_maxdiskspace = s_maxdiskspace;
  1170. }
  1171. LOG_AUDIT_UNLOCK_WRITE();
  1172. break;
  1173. default:
  1174. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  1175. "%s: invalid maximum log disk size:"
  1176. "Maxdiskspace:%d MB Maxlogsize:%d MB \n",
  1177. attrname, maxdiskspace, mlogsize);
  1178. rv = LDAP_OPERATIONS_ERROR;
  1179. }
  1180. return rv;
  1181. }
  1182. /******************************************************************************
  1183. * MINIMUM FREE SPACE
  1184. * Return Values:
  1185. * 1 -- fail
  1186. * 0 -- success
  1187. ******************************************************************************/
  1188. int
  1189. log_set_mindiskspace(const char *attrname, char *minfreespace_str, int logtype, char *errorbuf, int apply)
  1190. {
  1191. int rv=LDAP_SUCCESS;
  1192. int minfreespaceB;
  1193. int minfreespace;
  1194. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  1195. if ( logtype != SLAPD_ACCESS_LOG &&
  1196. logtype != SLAPD_ERROR_LOG &&
  1197. logtype != SLAPD_AUDIT_LOG ) {
  1198. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  1199. "%s: invalid log type: %d", attrname, logtype );
  1200. rv = LDAP_OPERATIONS_ERROR;
  1201. }
  1202. /* return if we aren't doing this for real */
  1203. if ( !apply || !minfreespace_str || !*minfreespace_str) {
  1204. return rv;
  1205. }
  1206. minfreespace = atoi(minfreespace_str);
  1207. /* Disk space are in MB but store in bytes */
  1208. if (minfreespace >= 1 ) {
  1209. minfreespaceB = minfreespace * LOG_MB_IN_BYTES;
  1210. switch (logtype) {
  1211. case SLAPD_ACCESS_LOG:
  1212. LOG_ACCESS_LOCK_WRITE( );
  1213. loginfo.log_access_minfreespace = minfreespaceB;
  1214. fe_cfg->accesslog_minfreespace = minfreespace;
  1215. LOG_ACCESS_UNLOCK_WRITE();
  1216. break;
  1217. case SLAPD_ERROR_LOG:
  1218. LOG_ERROR_LOCK_WRITE( );
  1219. loginfo.log_error_minfreespace = minfreespaceB;
  1220. fe_cfg->errorlog_minfreespace = minfreespace;
  1221. LOG_ERROR_UNLOCK_WRITE();
  1222. break;
  1223. case SLAPD_AUDIT_LOG:
  1224. LOG_AUDIT_LOCK_WRITE( );
  1225. loginfo.log_audit_minfreespace = minfreespaceB;
  1226. fe_cfg->auditlog_minfreespace = minfreespace;
  1227. LOG_AUDIT_UNLOCK_WRITE();
  1228. break;
  1229. default:
  1230. rv = 1;
  1231. }
  1232. }
  1233. return rv;
  1234. }
  1235. /******************************************************************************
  1236. * LOG EXPIRATION TIME
  1237. * Return Values:
  1238. * 1 -- fail
  1239. * 0 -- success
  1240. ******************************************************************************/
  1241. int
  1242. log_set_expirationtime(const char *attrname, char *exptime_str, int logtype, char *errorbuf, int apply)
  1243. {
  1244. int eunit, value, exptime;
  1245. int rsec=0;
  1246. int rv = 0;
  1247. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  1248. if ( logtype != SLAPD_ACCESS_LOG &&
  1249. logtype != SLAPD_ERROR_LOG &&
  1250. logtype != SLAPD_AUDIT_LOG ) {
  1251. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  1252. "%s: invalid log type: %d", attrname, logtype );
  1253. rv = LDAP_OPERATIONS_ERROR;
  1254. }
  1255. /* return if we aren't doing this for real */
  1256. if ( !apply || !exptime_str || !*exptime_str) {
  1257. return rv;
  1258. }
  1259. exptime = atoi(exptime_str);
  1260. switch (logtype) {
  1261. case SLAPD_ACCESS_LOG:
  1262. LOG_ACCESS_LOCK_WRITE( );
  1263. loginfo.log_access_exptime = exptime;
  1264. eunit = loginfo.log_access_exptimeunit;
  1265. rsec = loginfo.log_access_rotationtime_secs;
  1266. break;
  1267. case SLAPD_ERROR_LOG:
  1268. LOG_ERROR_LOCK_WRITE( );
  1269. loginfo.log_error_exptime = exptime;
  1270. eunit = loginfo.log_error_exptimeunit;
  1271. rsec = loginfo.log_error_rotationtime_secs;
  1272. break;
  1273. case SLAPD_AUDIT_LOG:
  1274. LOG_AUDIT_LOCK_WRITE( );
  1275. loginfo.log_audit_exptime = exptime;
  1276. eunit = loginfo.log_audit_exptimeunit;
  1277. rsec = loginfo.log_audit_rotationtime_secs;
  1278. break;
  1279. default:
  1280. rv = 1;
  1281. eunit = -1;
  1282. }
  1283. if (eunit == LOG_UNIT_MONTHS) {
  1284. value = 31 * 24 * 60 * 60 * exptime;
  1285. } else if (eunit == LOG_UNIT_WEEKS) {
  1286. value = 7 * 24 * 60 * 60 * exptime;
  1287. } else if (eunit == LOG_UNIT_DAYS) {
  1288. value = 24 * 60 * 60 * exptime;
  1289. } else {
  1290. /* In this case we don't expire */
  1291. value = -1;
  1292. }
  1293. if (value < rsec) {
  1294. value = rsec;
  1295. }
  1296. switch (logtype) {
  1297. case SLAPD_ACCESS_LOG:
  1298. loginfo.log_access_exptime_secs = value;
  1299. fe_cfg->accesslog_exptime = exptime;
  1300. LOG_ACCESS_UNLOCK_WRITE();
  1301. break;
  1302. case SLAPD_ERROR_LOG:
  1303. loginfo.log_error_exptime_secs = value;
  1304. fe_cfg->errorlog_exptime = exptime;
  1305. LOG_ERROR_UNLOCK_WRITE();
  1306. break;
  1307. case SLAPD_AUDIT_LOG:
  1308. loginfo.log_audit_exptime_secs = value;
  1309. fe_cfg->auditlog_exptime = exptime;
  1310. LOG_AUDIT_UNLOCK_WRITE();
  1311. break;
  1312. default:
  1313. rv = 1;
  1314. }
  1315. return rv;
  1316. }
  1317. /******************************************************************************
  1318. * LOG EXPIRATION TIME UNIT
  1319. * Return Values:
  1320. * 1 -- fail
  1321. * 0 -- success
  1322. ******************************************************************************/
  1323. int
  1324. log_set_expirationtimeunit(const char *attrname, char *expunit, int logtype, char *errorbuf, int apply)
  1325. {
  1326. int value = 0;
  1327. int rv = 0;
  1328. int eunit, etimeunit, rsecs;
  1329. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  1330. if ( logtype != SLAPD_ACCESS_LOG &&
  1331. logtype != SLAPD_ERROR_LOG &&
  1332. logtype != SLAPD_AUDIT_LOG ) {
  1333. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  1334. "%s: invalid log type: %d", attrname, logtype );
  1335. return LDAP_OPERATIONS_ERROR;
  1336. }
  1337. if ( NULL == expunit ) {
  1338. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  1339. "%s: NULL value", attrname );
  1340. return LDAP_OPERATIONS_ERROR;
  1341. }
  1342. if ( (strcasecmp(expunit, "month") == 0) ||
  1343. (strcasecmp(expunit, "week") == 0) ||
  1344. (strcasecmp(expunit, "day") == 0)) {
  1345. /* we have good values */
  1346. } else {
  1347. PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
  1348. "%s: invalid time unit \"%s\"", attrname, expunit );
  1349. rv = LDAP_OPERATIONS_ERROR;;
  1350. }
  1351. /* return if we aren't doing this for real */
  1352. if ( !apply ) {
  1353. return rv;
  1354. }
  1355. switch (logtype) {
  1356. case SLAPD_ACCESS_LOG:
  1357. LOG_ACCESS_LOCK_WRITE( );
  1358. etimeunit = loginfo.log_access_exptime;
  1359. rsecs = loginfo.log_access_rotationtime_secs;
  1360. break;
  1361. case SLAPD_ERROR_LOG:
  1362. LOG_ERROR_LOCK_WRITE( );
  1363. etimeunit = loginfo.log_error_exptime;
  1364. rsecs = loginfo.log_error_rotationtime_secs;
  1365. break;
  1366. case SLAPD_AUDIT_LOG:
  1367. LOG_AUDIT_LOCK_WRITE( );
  1368. etimeunit = loginfo.log_audit_exptime;
  1369. rsecs = loginfo.log_audit_rotationtime_secs;
  1370. break;
  1371. default:
  1372. rv = 1;
  1373. etimeunit = -1;
  1374. rsecs = -1;
  1375. }
  1376. if (strcasecmp(expunit, "month") == 0) {
  1377. eunit = LOG_UNIT_MONTHS;
  1378. value = 31 * 24 * 60 * 60 * etimeunit;
  1379. } else if (strcasecmp(expunit, "week") == 0) {
  1380. eunit = LOG_UNIT_WEEKS;
  1381. value = 7 * 24 * 60 * 60 * etimeunit;
  1382. } else if (strcasecmp(expunit, "day") == 0) {
  1383. eunit = LOG_UNIT_DAYS;
  1384. value = 24 * 60 * 60 * etimeunit;
  1385. } else {
  1386. eunit = LOG_UNIT_UNKNOWN;
  1387. value = -1;
  1388. }
  1389. if ((value> 0) && value < rsecs ) {
  1390. value = rsecs;
  1391. }
  1392. switch (logtype) {
  1393. case SLAPD_ACCESS_LOG:
  1394. loginfo.log_access_exptime_secs = value;
  1395. slapi_ch_free ( (void **) &(fe_cfg->accesslog_exptimeunit) );
  1396. fe_cfg->accesslog_exptimeunit = slapi_ch_strdup ( expunit );
  1397. LOG_ACCESS_UNLOCK_WRITE();
  1398. break;
  1399. case SLAPD_ERROR_LOG:
  1400. loginfo.log_error_exptime_secs = value;
  1401. slapi_ch_free ( (void **) &(fe_cfg->errorlog_exptimeunit) );
  1402. fe_cfg->errorlog_exptimeunit = slapi_ch_strdup ( expunit );
  1403. LOG_ERROR_UNLOCK_WRITE();
  1404. break;
  1405. case SLAPD_AUDIT_LOG:
  1406. loginfo.log_audit_exptime_secs = value;
  1407. slapi_ch_free ( (void **) &(fe_cfg->auditlog_exptimeunit) );
  1408. fe_cfg->auditlog_exptimeunit = slapi_ch_strdup ( expunit );
  1409. LOG_AUDIT_UNLOCK_WRITE();
  1410. break;
  1411. default:
  1412. rv = 1;
  1413. }
  1414. return rv;
  1415. }
  1416. /******************************************************************************
  1417. * Write title line in log file
  1418. *****************************************************************************/
  1419. static void
  1420. log_write_title (LOGFD fp)
  1421. {
  1422. slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
  1423. char *buildnum = config_get_buildnum();
  1424. char buff[512];
  1425. int bufflen = sizeof(buff);
  1426. PR_snprintf(buff, bufflen, "\t%s B%s\n",
  1427. fe_cfg->versionstring ? fe_cfg->versionstring : "Fedora-Directory",
  1428. buildnum ? buildnum : "");
  1429. LOG_WRITE_NOW(fp, buff, strlen(buff), 0);
  1430. if (fe_cfg->localhost) {
  1431. PR_snprintf(buff, bufflen, "\t%s:%d (%s)\n\n",
  1432. fe_cfg->localhost,
  1433. fe_cfg->security ? fe_cfg->secureport : fe_cfg->port,
  1434. fe_cfg->instancedir ? fe_cfg->instancedir : "");
  1435. }
  1436. else {
  1437. /* If fe_cfg->localhost is not set, ignore fe_cfg->port since
  1438. * it is the default and might be misleading.
  1439. */
  1440. PR_snprintf(buff, bufflen, "\t<host>:<port> (%s)\n\n",
  1441. fe_cfg->instancedir ? fe_cfg->instancedir : "");
  1442. }
  1443. LOG_WRITE_NOW(fp, buff, strlen(buff), 0);
  1444. slapi_ch_free((void **)&buildnum);
  1445. }
  1446. /******************************************************************************
  1447. * init function for the error log
  1448. * Returns:
  1449. * 0 - success
  1450. * 1 - fail
  1451. ******************************************************************************/
  1452. int error_log_openf( char *pathname, int locked)
  1453. {
  1454. int rv = 0;
  1455. int logfile_type =0;
  1456. char buf[BUFSIZ];
  1457. if (!locked) LOG_ERROR_LOCK_WRITE ();
  1458. /* save the file name */
  1459. slapi_ch_free ((void**)&loginfo.log_error_file);
  1460. loginfo.log_error_file = slapi_ch_strdup(pathname);
  1461. /* store the rotation info fiel path name */
  1462. PR_snprintf (buf, sizeof(buf), "%s.rotationinfo",pathname);
  1463. slapi_ch_free ((void**)&loginfo.log_errorinfo_file);
  1464. loginfo.log_errorinfo_file = slapi_ch_strdup ( buf );
  1465. /*
  1466. ** Check if we have a log file already. If we have it then
  1467. ** we need to parse the header info and update the loginfo
  1468. ** struct.
  1469. */
  1470. logfile_type = log__error_rotationinfof(loginfo.log_errorinfo_file);
  1471. if (log__open_errorlogfile(logfile_type, 1/* got lock*/) != LOG_SUCCESS) {
  1472. rv = 1;
  1473. }
  1474. if (!locked) LOG_ERROR_UNLOCK_WRITE();
  1475. return rv;
  1476. }
  1477. /******************************************************************************
  1478. * init function for the audit log
  1479. * Returns:
  1480. * 0 - success
  1481. * 1 - fail
  1482. ******************************************************************************/
  1483. int
  1484. audit_log_openf( char *pathname, int locked)
  1485. {
  1486. int rv=0;
  1487. int logfile_type = 0;
  1488. char buf[BUFSIZ];
  1489. if (!locked) LOG_AUDIT_LOCK_WRITE( );
  1490. /* store the path name */
  1491. loginfo.log_audit_file = slapi_ch_strdup ( pathname );
  1492. /* store the rotation info file path name */
  1493. PR_snprintf (buf, sizeof(buf), "%s.rotationinfo",pathname);
  1494. loginfo.log_auditinfo_file = slapi_ch_strdup ( buf );
  1495. /*
  1496. ** Check if we have a log file already. If we have it then
  1497. ** we need to parse the header info and update the loginfo
  1498. ** struct.
  1499. */
  1500. logfile_type = log__audit_rotationinfof(loginfo.log_auditinfo_file);
  1501. if (log__open_auditlogfile(logfile_type, 1/* got lock*/) != LOG_SUCCESS) {
  1502. rv = 1;
  1503. }
  1504. if (!locked) LOG_AUDIT_UNLOCK_WRITE();
  1505. return rv;
  1506. }
  1507. /******************************************************************************
  1508. * write in the audit log
  1509. ******************************************************************************/
  1510. int
  1511. slapd_log_audit_proc (
  1512. char *buffer,
  1513. int buf_len)
  1514. {
  1515. if ( (loginfo.log_audit_state & LOGGING_ENABLED) && (loginfo.log_audit_file != NULL) ){
  1516. LOG_AUDIT_LOCK_WRITE( );
  1517. if (log__needrotation(loginfo.log_audit_fdes,
  1518. SLAPD_AUDIT_LOG) == LOG_ROTATE) {
  1519. if (log__open_auditlogfile(LOGFILE_NEW, 1) != LOG_SUCCESS) {
  1520. LDAPDebug(LDAP_DEBUG_ANY,
  1521. "LOGINFO: Unable to open audit file:%s\n",
  1522. loginfo.log_audit_file,0,0);
  1523. LOG_AUDIT_UNLOCK_WRITE();
  1524. return 0;
  1525. }
  1526. while (loginfo.log_audit_rotationsyncclock <= loginfo.log_audit_ctime) {
  1527. loginfo.log_audit_rotationsyncclock += loginfo.log_audit_rotationtime_secs;
  1528. }
  1529. }
  1530. if (loginfo.log_audit_state & LOGGING_NEED_TITLE) {
  1531. log_write_title( loginfo.log_audit_fdes);
  1532. loginfo.log_audit_state &= ~LOGGING_NEED_TITLE;
  1533. }
  1534. LOG_WRITE_NOW(loginfo.log_audit_fdes, buffer, buf_len, 0);
  1535. LOG_AUDIT_UNLOCK_WRITE();
  1536. return 0;
  1537. }
  1538. return 0;
  1539. }
  1540. /******************************************************************************
  1541. * write in the error log
  1542. ******************************************************************************/
  1543. int
  1544. slapd_log_error_proc(
  1545. char *subsystem, /* omitted if NULL */
  1546. char *fmt,
  1547. ... )
  1548. {
  1549. va_list ap_err;
  1550. va_list ap_file;
  1551. va_start( ap_err, fmt );
  1552. va_start( ap_file, fmt );
  1553. slapd_log_error_proc_internal(subsystem, fmt, ap_err, ap_file);
  1554. va_end(ap_err);
  1555. va_end(ap_file);
  1556. return 0;
  1557. }
  1558. static int
  1559. slapd_log_error_proc_internal(
  1560. char *subsystem, /* omitted if NULL */
  1561. char *fmt,
  1562. va_list ap_err,
  1563. va_list ap_file)
  1564. {
  1565. int rc = 0;
  1566. if ( (loginfo.log_error_state & LOGGING_ENABLED) && (loginfo.log_error_file != NULL) ) {
  1567. LOG_ERROR_LOCK_WRITE( );
  1568. if (log__needrotation(loginfo.log_error_fdes,
  1569. SLAPD_ERROR_LOG) == LOG_ROTATE) {
  1570. if (log__open_errorlogfile(LOGFILE_NEW, 1) != LOG_SUCCESS) {
  1571. LOG_ERROR_UNLOCK_WRITE();
  1572. return 0;
  1573. }
  1574. while (loginfo.log_error_rotationsyncclock <= loginfo.log_error_ctime) {
  1575. loginfo.log_error_rotationsyncclock += loginfo.log_error_rotationtime_secs;
  1576. }
  1577. }
  1578. if (!(detached)) {
  1579. rc = vslapd_log_error( NULL, subsystem, fmt, ap_err );
  1580. }
  1581. if ( loginfo.log_error_fdes != NULL ) {
  1582. if (loginfo.log_error_state & LOGGING_NEED_TITLE) {
  1583. log_write_title(loginfo.log_error_fdes);
  1584. loginfo.log_error_state &= ~LOGGING_NEED_TITLE;
  1585. }
  1586. rc = vslapd_log_error( loginfo.log_error_fdes, subsystem, fmt, ap_file );
  1587. }
  1588. LOG_ERROR_UNLOCK_WRITE();
  1589. } else {
  1590. /* log the problem in the stderr */
  1591. rc = vslapd_log_error( NULL, subsystem, fmt, ap_err );
  1592. }
  1593. return( rc );
  1594. }
  1595. static int
  1596. vslapd_log_error(
  1597. LOGFD fp,
  1598. char *subsystem, /* omitted if NULL */
  1599. char *fmt,
  1600. va_list ap )
  1601. {
  1602. time_t tnl;
  1603. long tz;
  1604. struct tm *tmsp, tms;
  1605. char tbuf[ TBUFSIZE ];
  1606. char sign;
  1607. char buffer[SLAPI_LOG_BUFSIZ];
  1608. int blen;
  1609. char *vbuf;
  1610. int header_len = 0;
  1611. tnl = current_time();
  1612. #ifdef _WIN32
  1613. {
  1614. struct tm *pt = localtime( &tnl );
  1615. tmsp = &tms;
  1616. memcpy(&tms, pt, sizeof(struct tm) );
  1617. }
  1618. #else
  1619. (void)localtime_r( &tnl, &tms );
  1620. tmsp = &tms;
  1621. #endif
  1622. #ifdef BSD_TIME
  1623. tz = tmsp->tm_gmtoff;
  1624. #else /* BSD_TIME */
  1625. tz = - timezone;
  1626. if ( tmsp->tm_isdst ) {
  1627. tz += 3600;
  1628. }
  1629. #endif /* BSD_TIME */
  1630. sign = ( tz >= 0 ? '+' : '-' );
  1631. if ( tz < 0 ) {
  1632. tz = -tz;
  1633. }
  1634. (void)strftime( tbuf, (size_t)TBUFSIZE, "%d/%b/%Y:%H:%M:%S", tmsp);
  1635. sprintf( buffer, "[%s %c%02d%02d]%s%s - ", tbuf, sign,
  1636. (int)( tz / 3600 ), (int)( tz % 3600 ),
  1637. subsystem ? " " : "",
  1638. subsystem ? subsystem : "");
  1639. /* Bug 561525: to be able to remove timestamp to not over pollute syslog, we may need
  1640. to skip the timestamp part of the message.
  1641. The size of the header is:
  1642. the size of the time string
  1643. + size of space
  1644. + size of one char (sign)
  1645. + size of 2 char
  1646. + size of 2 char
  1647. + size of [
  1648. + size of ]
  1649. */
  1650. header_len = strlen(tbuf) + 8;
  1651. if ((vbuf = PR_vsmprintf(fmt, ap)) == NULL) {
  1652. return -1;
  1653. }
  1654. blen = strlen(buffer);
  1655. if ((unsigned int)(SLAPI_LOG_BUFSIZ - blen ) < strlen(vbuf)) {
  1656. free (vbuf);
  1657. return -1;
  1658. }
  1659. sprintf (buffer+blen, "%s", vbuf);
  1660. if (fp)
  1661. LOG_WRITE_NOW(fp, buffer, strlen(buffer), header_len);
  1662. else /* stderr is always unbuffered */
  1663. fprintf(stderr, "%s", buffer);
  1664. PR_smprintf_free (vbuf);
  1665. return( 0 );
  1666. }
  1667. int
  1668. slapi_log_error( int severity, char *subsystem, char *fmt, ... )
  1669. {
  1670. va_list ap1;
  1671. va_list ap2;
  1672. int rc;
  1673. if ( severity < SLAPI_LOG_MIN || severity > SLAPI_LOG_MAX ) {
  1674. (void)slapd_log_error_proc( subsystem,
  1675. "slapi_log_error: invalid severity %d (message %s)\n",
  1676. severity, fmt );
  1677. return( -1 );
  1678. }
  1679. #ifdef _WIN32
  1680. if ( *module_ldap_debug
  1681. #else
  1682. if ( slapd_ldap_debug
  1683. #endif
  1684. & slapi_log_map[ severity ] ) {
  1685. va_start( ap1, fmt );
  1686. va_start( ap2, fmt );
  1687. rc = slapd_log_error_proc_internal( subsystem, fmt, ap1, ap2 );
  1688. va_end( ap1 );
  1689. va_end( ap2 );
  1690. } else {
  1691. rc = 0; /* nothing to be logged --> always return success */
  1692. }
  1693. return( rc );
  1694. }
  1695. int
  1696. slapi_is_loglevel_set ( const int loglevel )
  1697. {
  1698. return (
  1699. #ifdef _WIN32
  1700. *module_ldap_debug
  1701. #else
  1702. slapd_ldap_debug
  1703. #endif
  1704. & slapi_log_map[ loglevel ] ? 1 : 0);
  1705. }
  1706. /******************************************************************************
  1707. * write in the access log
  1708. ******************************************************************************/
  1709. static int vslapd_log_access(char *fmt, va_list ap)
  1710. {
  1711. time_t tnl;
  1712. long tz;
  1713. struct tm *tmsp, tms;
  1714. char tbuf[ TBUFSIZE ];
  1715. char sign;
  1716. char buffer[SLAPI_LOG_BUFSIZ];
  1717. char vbuf[SLAPI_LOG_BUFSIZ];
  1718. int blen, vlen;
  1719. /* info needed to keep us from calling localtime/strftime so often: */
  1720. static time_t old_time = 0;
  1721. static char old_tbuf[TBUFSIZE];
  1722. static int old_blen = 0;
  1723. tnl = current_time();
  1724. /* check if we can use the old strftime buffer */
  1725. PR_Lock(ts_time_lock);
  1726. if (tnl == old_time) {
  1727. strcpy(buffer, old_tbuf);
  1728. blen = old_blen;
  1729. PR_Unlock(ts_time_lock);
  1730. } else {
  1731. /* nope... painstakingly create the new strftime buffer */
  1732. #ifdef _WIN32
  1733. {
  1734. struct tm *pt = localtime( &tnl );
  1735. tmsp = &tms;
  1736. memcpy(&tms, pt, sizeof(struct tm) );
  1737. }
  1738. #else
  1739. (void)localtime_r( &tnl, &tms );
  1740. tmsp = &tms;
  1741. #endif
  1742. #ifdef BSD_TIME
  1743. tz = tmsp->tm_gmtoff;
  1744. #else /* BSD_TIME */
  1745. tz = - timezone;
  1746. if ( tmsp->tm_isdst ) {
  1747. tz += 3600;
  1748. }
  1749. #endif /* BSD_TIME */
  1750. sign = ( tz >= 0 ? '+' : '-' );
  1751. if ( tz < 0 ) {
  1752. tz = -tz;
  1753. }
  1754. (void)strftime( tbuf, (size_t)TBUFSIZE, "%d/%b/%Y:%H:%M:%S", tmsp);
  1755. sprintf( buffer, "[%s %c%02d%02d] ", tbuf, sign,
  1756. (int)( tz / 3600 ), (int)( tz % 3600));
  1757. old_time = tnl;
  1758. strcpy(old_tbuf, buffer);
  1759. blen = strlen(buffer);
  1760. old_blen = blen;
  1761. PR_Unlock(ts_time_lock);
  1762. }
  1763. vlen = PR_vsnprintf(vbuf, SLAPI_LOG_BUFSIZ, fmt, ap);
  1764. if (! vlen) {
  1765. return -1;
  1766. }
  1767. if (SLAPI_LOG_BUFSIZ - blen < vlen) {
  1768. return -1;
  1769. }
  1770. log_append_buffer2(tnl, loginfo.log_access_buffer, buffer, blen, vbuf, vlen);
  1771. return( 0 );
  1772. }
  1773. int
  1774. slapi_log_access( int level,
  1775. char *fmt,
  1776. ... )
  1777. {
  1778. va_list ap;
  1779. int rc=0;
  1780. if (!(loginfo.log_access_state & LOGGING_ENABLED)) {
  1781. return 0;
  1782. }
  1783. va_start( ap, fmt );
  1784. if (( level & loginfo.log_access_level ) &&
  1785. ( loginfo.log_access_fdes != NULL ) && (loginfo.log_access_file != NULL) ) {
  1786. rc = vslapd_log_access(fmt, ap);
  1787. }
  1788. va_end( ap );
  1789. return( rc );
  1790. }
  1791. /******************************************************************************
  1792. * access_log_openf
  1793. *
  1794. * Open the access log file
  1795. *
  1796. * Returns:
  1797. * 0 -- success
  1798. * 1 -- fail
  1799. ******************************************************************************/
  1800. int access_log_openf(char *pathname, int locked)
  1801. {
  1802. int rv=0;
  1803. int logfile_type = 0;
  1804. char buf[BUFSIZ];
  1805. if (!locked) LOG_ACCESS_LOCK_WRITE( );
  1806. /* store the path name */
  1807. loginfo.log_access_file = slapi_ch_strdup ( pathname );
  1808. /* store the rotation info fiel path name */
  1809. PR_snprintf (buf, sizeof(buf), "%s.rotationinfo",pathname);
  1810. loginfo.log_accessinfo_file = slapi_ch_strdup ( buf );
  1811. /*
  1812. ** Check if we have a log file already. If we have it then
  1813. ** we need to parse the header info and update the loginfo
  1814. ** struct.
  1815. */
  1816. logfile_type = log__access_rotationinfof(loginfo.log_accessinfo_file);
  1817. if (log__open_accesslogfile(logfile_type, 1/* got lock*/) != LOG_SUCCESS) {
  1818. rv = 1;
  1819. }
  1820. if (!locked) LOG_ACCESS_UNLOCK_WRITE();
  1821. return rv;
  1822. }
  1823. /******************************************************************************
  1824. * log__open_accesslogfile
  1825. *
  1826. * Open a new log file. If we have run out of the max logs we can have
  1827. * then delete the oldest file.
  1828. ******************************************************************************/
  1829. static int
  1830. log__open_accesslogfile(int logfile_state, int locked)
  1831. {
  1832. time_t now;
  1833. LOGFD fp;
  1834. LOGFD fpinfo = NULL;
  1835. char tbuf[TBUFSIZE];
  1836. struct logfileinfo *logp;
  1837. char buffer[BUFSIZ];
  1838. if (!locked) LOG_ACCESS_LOCK_WRITE( );
  1839. /*
  1840. ** Here we are trying to create a new log file.
  1841. ** If we alredy have one, then we need to rename it as
  1842. ** "filename.time", close it and update it's information
  1843. ** in the array stack.
  1844. */
  1845. if (loginfo.log_access_fdes != NULL) {
  1846. struct logfileinfo *log;
  1847. char newfile[BUFSIZ];
  1848. int f_size;
  1849. /* get rid of the old one */
  1850. if ((f_size = log__getfilesize(loginfo.log_access_fdes)) == -1) {
  1851. /* Then assume that we have the max size */
  1852. f_size = loginfo.log_access_maxlogsize;
  1853. }
  1854. /* Check if I have to delete any old file, delete it if it is required.
  1855. ** If there is just one file, then access and access.rotation files
  1856. ** are deleted. After that we start fresh
  1857. */
  1858. while (log__delete_access_logfile());
  1859. /* close the file */
  1860. LOG_CLOSE(loginfo.log_access_fdes);
  1861. /*
  1862. * loginfo.log_access_fdes is not set to NULL here, otherwise
  1863. * slapi_log_access() will not send a message to the access log
  1864. * if it is called between this point and where this field is
  1865. * set again after calling LOG_OPEN_APPEND.
  1866. */
  1867. if ( loginfo.log_access_maxnumlogs > 1 ) {
  1868. log = (struct logfileinfo *) slapi_ch_malloc (sizeof (struct logfileinfo));
  1869. log->l_ctime = loginfo.log_access_ctime;
  1870. log->l_size = f_size;
  1871. log_convert_time (log->l_ctime, tbuf, 1 /*short */);
  1872. PR_snprintf(newfile, sizeof(newfile), "%s.%s", loginfo.log_access_file, tbuf);
  1873. if (PR_Rename (loginfo.log_access_file, newfile) != PR_SUCCESS) {
  1874. loginfo.log_access_fdes = NULL;
  1875. if (!locked) LOG_ACCESS_UNLOCK_WRITE();
  1876. return LOG_UNABLE_TO_OPENFILE;
  1877. }
  1878. /* add the log to the chain */
  1879. log->l_next = loginfo.log_access_logchain;
  1880. loginfo.log_access_logchain = log;
  1881. loginfo.log_numof_access_logs++;
  1882. }
  1883. }
  1884. /* open a new log file */
  1885. if (! LOG_OPEN_APPEND(fp, loginfo.log_access_file, loginfo.log_access_mode)) {
  1886. int oserr = errno;
  1887. loginfo.log_access_fdes = NULL;
  1888. if (!locked) LOG_ACCESS_UNLOCK_WRITE();
  1889. LDAPDebug( LDAP_DEBUG_ANY, "access file open %s failed errno %d (%s)\n",
  1890. loginfo.log_access_file,
  1891. oserr, slapd_system_strerror(oserr));
  1892. return LOG_UNABLE_TO_OPENFILE;
  1893. }
  1894. loginfo.log_access_fdes = fp;
  1895. if (logfile_state == LOGFILE_REOPENED) {
  1896. /* we have all the information */
  1897. if (!locked) LOG_ACCESS_UNLOCK_WRITE( );
  1898. return LOG_SUCCESS;
  1899. }
  1900. loginfo.log_access_state |= LOGGING_NEED_TITLE;
  1901. if (! LOG_OPEN_WRITE(fpinfo, loginfo.log_accessinfo_file, loginfo.log_access_mode)) {
  1902. int oserr = errno;
  1903. if (!locked) LOG_ACCESS_UNLOCK_WRITE();
  1904. LDAPDebug( LDAP_DEBUG_ANY, "accessinfo file open %s failed errno %d (%s)\n",
  1905. loginfo.log_accessinfo_file,
  1906. oserr, slapd_system_strerror(oserr));
  1907. return LOG_UNABLE_TO_OPENFILE;
  1908. }
  1909. /* write the header in the log */
  1910. now = current_time();
  1911. log_convert_time (now, tbuf, 2 /* long */);
  1912. PR_snprintf (buffer,sizeof(buffer),"LOGINFO:Log file created at: %s (%lu)\n", tbuf, now);
  1913. LOG_WRITE(fpinfo, buffer, strlen(buffer), 0);
  1914. logp = loginfo.log_access_logchain;
  1915. while ( logp) {
  1916. log_convert_time (logp->l_ctime, tbuf, 1 /*short*/);
  1917. PR_snprintf(buffer, sizeof(buffer), "LOGINFO:Previous Log File:%s.%s (%lu) (%u)\n",
  1918. loginfo.log_access_file, tbuf, logp->l_ctime, logp->l_size);
  1919. LOG_WRITE(fpinfo, buffer, strlen(buffer), 0);
  1920. logp = logp->l_next;
  1921. }
  1922. /* Close the info file. We need only when we need to rotate to the
  1923. ** next log file.
  1924. */
  1925. if (fpinfo) LOG_CLOSE(fpinfo);
  1926. /* This is now the current access log */
  1927. loginfo.log_access_ctime = now;
  1928. if (!locked) LOG_ACCESS_UNLOCK_WRITE( );
  1929. return LOG_SUCCESS;
  1930. }
  1931. /******************************************************************************
  1932. * log__needrotation
  1933. *
  1934. * Do we need to rotate the log file ?
  1935. * Find out based on rotation time and the max log size;
  1936. *
  1937. * Return:
  1938. * LOG_CONTINUE -- Use the same one
  1939. * LOG_ROTATE -- log need to be rotated
  1940. *
  1941. * Note:
  1942. * A READ LOCK is obtained.
  1943. ********************************************************************************/
  1944. #define LOG_SIZE_EXCEEDED 1
  1945. #define LOG_EXPIRED 2
  1946. static int
  1947. log__needrotation(LOGFD fp, int logtype)
  1948. {
  1949. time_t curr_time;
  1950. time_t log_createtime= 0;
  1951. time_t syncclock;
  1952. int type = LOG_CONTINUE;
  1953. int f_size = 0;
  1954. int maxlogsize, nlogs;
  1955. int rotationtime_secs = -1;
  1956. int sync_enabled, synchour, syncmin, timeunit;
  1957. if (fp == NULL) {
  1958. return LOG_ROTATE;
  1959. }
  1960. switch (logtype) {
  1961. case SLAPD_ACCESS_LOG:
  1962. nlogs = loginfo.log_access_maxnumlogs;
  1963. maxlogsize = loginfo.log_access_maxlogsize;
  1964. sync_enabled = loginfo.log_access_rotationsync_enabled;
  1965. synchour = loginfo.log_access_rotationsynchour;
  1966. syncmin = loginfo.log_access_rotationsyncmin;
  1967. syncclock = loginfo.log_access_rotationsyncclock;
  1968. timeunit = loginfo.log_access_rotationunit;
  1969. rotationtime_secs = loginfo.log_access_rotationtime_secs;
  1970. log_createtime = loginfo.log_access_ctime;
  1971. break;
  1972. case SLAPD_ERROR_LOG:
  1973. nlogs = loginfo.log_error_maxnumlogs;
  1974. maxlogsize = loginfo.log_error_maxlogsize;
  1975. sync_enabled = loginfo.log_error_rotationsync_enabled;
  1976. synchour = loginfo.log_error_rotationsynchour;
  1977. syncmin = loginfo.log_error_rotationsyncmin;
  1978. syncclock = loginfo.log_error_rotationsyncclock;
  1979. timeunit = loginfo.log_error_rotationunit;
  1980. rotationtime_secs = loginfo.log_error_rotationtime_secs;
  1981. log_createtime = loginfo.log_error_ctime;
  1982. break;
  1983. case SLAPD_AUDIT_LOG:
  1984. nlogs = loginfo.log_audit_maxnumlogs;
  1985. maxlogsize = loginfo.log_audit_maxlogsize;
  1986. sync_enabled = loginfo.log_audit_rotationsync_enabled;
  1987. synchour = loginfo.log_audit_rotationsynchour;
  1988. syncmin = loginfo.log_audit_rotationsyncmin;
  1989. syncclock = loginfo.log_audit_rotationsyncclock;
  1990. timeunit = loginfo.log_audit_rotationunit;
  1991. rotationtime_secs = loginfo.log_audit_rotationtime_secs;
  1992. log_createtime = loginfo.log_audit_ctime;
  1993. break;
  1994. default: /* error */
  1995. maxlogsize = -1;
  1996. nlogs = 1;
  1997. }
  1998. /* If we have one log then can't rotate at all */
  1999. if (nlogs == 1)
  2000. return LOG_CONTINUE;
  2001. if ((f_size = log__getfilesize(fp)) == -1) {
  2002. /* The next option is to rotate based on the rotation time */
  2003. f_size = 0;
  2004. }
  2005. /* If the log size is more than the limit, then it's time to rotate. */
  2006. if ((maxlogsize > 0) && (f_size >= maxlogsize)) {
  2007. type = LOG_SIZE_EXCEEDED;
  2008. goto log_rotate;
  2009. }
  2010. /* If rotation interval <= 0 then can't rotate by time */
  2011. if (rotationtime_secs <= 0)
  2012. return LOG_CONTINUE;
  2013. /*
  2014. ** If the log is older than the time allowed to be active,
  2015. ** then it's time to move on (i.e., rotate).
  2016. */
  2017. time (&curr_time);
  2018. if ( !sync_enabled || timeunit == LOG_UNIT_HOURS || timeunit == LOG_UNIT_MINS ) {
  2019. if (curr_time - log_createtime > rotationtime_secs) {
  2020. type = LOG_EXPIRED;
  2021. goto log_rotate;
  2022. }
  2023. } else if (curr_time > syncclock) {
  2024. type = LOG_EXPIRED;
  2025. goto log_rotate;
  2026. }
  2027. log_rotate:
  2028. /*
  2029. ** Don't send messages to the error log whilst we're rotating it.
  2030. ** This'll lead to a recursive call to the logging function, and
  2031. ** an assertion trying to relock the write lock.
  2032. */
  2033. if (logtype!=SLAPD_ERROR_LOG)
  2034. {
  2035. if (type == LOG_SIZE_EXCEEDED) {
  2036. LDAPDebug (LDAP_DEBUG_TRACE,
  2037. "LOGINFO:End of Log because size exceeded(Max:%d bytes) (Is:%d bytes)\n", maxlogsize, f_size, 0);
  2038. } else if ( type == LOG_EXPIRED) {
  2039. LDAPDebug(LDAP_DEBUG_TRACE,
  2040. "LOGINFO:End of Log because time exceeded(Max:%d secs) (Is:%d secs)\n",
  2041. rotationtime_secs, curr_time - log_createtime,0);
  2042. }
  2043. }
  2044. return (type == LOG_CONTINUE) ? LOG_CONTINUE : LOG_ROTATE;
  2045. }
  2046. /******************************************************************************
  2047. * log__delete_access_logfile
  2048. *
  2049. * Do we need to delete a logfile. Find out if we need to delete the log
  2050. * file based on expiration time, max diskspace, and minfreespace.
  2051. * Delete the file if we need to.
  2052. *
  2053. * Assumption: A WRITE lock has been acquired for the ACCESS
  2054. ******************************************************************************/
  2055. static int
  2056. log__delete_access_logfile()
  2057. {
  2058. struct logfileinfo *logp = NULL;
  2059. struct logfileinfo *delete_logp = NULL;
  2060. struct logfileinfo *p_delete_logp = NULL;
  2061. struct logfileinfo *prev_logp = NULL;
  2062. int total_size=0;
  2063. time_t cur_time;
  2064. int f_size;
  2065. int numoflogs=loginfo.log_numof_access_logs;
  2066. int rv = 0;
  2067. char *logstr;
  2068. char buffer[BUFSIZ];
  2069. char tbuf[TBUFSIZE];
  2070. /* If we have only one log, then will delete this one */
  2071. if (loginfo.log_access_maxnumlogs == 1) {
  2072. LOG_CLOSE(loginfo.log_access_fdes);
  2073. loginfo.log_access_fdes = NULL;
  2074. PR_snprintf (buffer, sizeof(buffer), "%s", loginfo.log_access_file);
  2075. if (PR_Delete(buffer) != PR_SUCCESS) {
  2076. LDAPDebug(LDAP_DEBUG_TRACE,
  2077. "LOGINFO:Unable to remove file:%s\n", loginfo.log_access_file,0,0);
  2078. }
  2079. /* Delete the rotation file also. */
  2080. PR_snprintf (buffer, sizeof(buffer), "%s.rotationinfo", loginfo.log_access_file);
  2081. if (PR_Delete(buffer) != PR_SUCCESS) {
  2082. LDAPDebug(LDAP_DEBUG_TRACE,
  2083. "LOGINFO:Unable to remove file:%s.rotationinfo\n", loginfo.log_access_file,0,0);
  2084. }
  2085. return 0;
  2086. }
  2087. /* If we have already the maximum number of log files, we
  2088. ** have to delete one any how.
  2089. */
  2090. if (++numoflogs > loginfo.log_access_maxnumlogs) {
  2091. logstr = "Exceeded max number of logs allowed";
  2092. goto delete_logfile;
  2093. }
  2094. /* Now check based on the maxdiskspace */
  2095. if (loginfo.log_access_maxdiskspace > 0) {
  2096. logp = loginfo.log_access_logchain;
  2097. while (logp) {
  2098. total_size += logp->l_size;
  2099. logp = logp->l_next;
  2100. }
  2101. if ((f_size = log__getfilesize(loginfo.log_access_fdes)) == -1) {
  2102. /* then just assume the max size */
  2103. total_size += loginfo.log_access_maxlogsize;
  2104. } else {
  2105. total_size += f_size;
  2106. }
  2107. /* If we have exceeded the max disk space or we have less than the
  2108. ** minimum, then we have to delete a file.
  2109. */
  2110. if (total_size >= loginfo.log_access_maxdiskspace) {
  2111. logstr = "exceeded maximum log disk space";
  2112. goto delete_logfile;
  2113. }
  2114. }
  2115. /* Now check based on the free space */
  2116. if ( loginfo.log_access_minfreespace > 0) {
  2117. rv = log__enough_freespace(loginfo.log_access_file);
  2118. if ( rv == 0) {
  2119. /* Not enough free space */
  2120. logstr = "Not enough free disk space";
  2121. goto delete_logfile;
  2122. }
  2123. }
  2124. /* Now check based on the expiration time */
  2125. if ( loginfo.log_access_exptime_secs > 0 ) {
  2126. /* is the file old enough */
  2127. time (&cur_time);
  2128. prev_logp = logp = loginfo.log_access_logchain;
  2129. while (logp) {
  2130. if ((cur_time - logp->l_ctime) > loginfo.log_access_exptime_secs) {
  2131. delete_logp = logp;
  2132. p_delete_logp = prev_logp;
  2133. logstr = "The file is older than the log expiration time";
  2134. goto delete_logfile;
  2135. }
  2136. prev_logp = logp;
  2137. logp = logp->l_next;
  2138. }
  2139. }
  2140. /* No log files to delete */
  2141. return 0;
  2142. delete_logfile:
  2143. if (delete_logp == NULL) {
  2144. time_t oldest;
  2145. time(&oldest);
  2146. prev_logp = logp = loginfo.log_access_logchain;
  2147. while (logp) {
  2148. if (logp->l_ctime <= oldest) {
  2149. oldest = logp->l_ctime;
  2150. delete_logp = logp;
  2151. p_delete_logp = prev_logp;
  2152. }
  2153. prev_logp = logp;
  2154. logp = logp->l_next;
  2155. }
  2156. /* We might face this case if we have only one log file and
  2157. ** trying to delete it because of deletion requirement.
  2158. */
  2159. if (!delete_logp) {
  2160. return 0;
  2161. }
  2162. }
  2163. if (p_delete_logp == delete_logp) {
  2164. /* then we are deleteing the first one */
  2165. loginfo.log_access_logchain = delete_logp->l_next;
  2166. } else {
  2167. p_delete_logp->l_next = delete_logp->l_next;
  2168. }
  2169. /* Delete the access file */
  2170. log_convert_time (delete_logp->l_ctime, tbuf, 1 /*short */);
  2171. PR_snprintf (buffer, sizeof(buffer), "%s.%s", loginfo.log_access_file, tbuf);
  2172. if (PR_Delete(buffer) != PR_SUCCESS) {
  2173. LDAPDebug(LDAP_DEBUG_TRACE,
  2174. "LOGINFO:Unable to remove file:%s.%s\n",
  2175. loginfo.log_access_file,tbuf,0);
  2176. } else {
  2177. LDAPDebug(LDAP_DEBUG_TRACE,
  2178. "LOGINFO:Removed file:%s.%s because of (%s)\n",
  2179. loginfo.log_access_file, tbuf,
  2180. logstr);
  2181. }
  2182. slapi_ch_free((void**)&delete_logp);
  2183. loginfo.log_numof_access_logs--;
  2184. return 1;
  2185. }
  2186. /******************************************************************************
  2187. * log__access_rotationinfof
  2188. *
  2189. * Try to open the log file. If we have one already, then try to read the
  2190. * header and update the information.
  2191. *
  2192. * Assumption: Lock has been acquired already
  2193. ******************************************************************************/
  2194. static int
  2195. log__access_rotationinfof( char *pathname)
  2196. {
  2197. long f_ctime;
  2198. int f_size;
  2199. int main_log = 1;
  2200. time_t now;
  2201. FILE *fp;
  2202. /*
  2203. ** Okay -- I confess, we want to use NSPR calls but I want to
  2204. ** use fgets and not use PR_Read() and implement a complicated
  2205. ** parsing module. Since this will be called only during the startup
  2206. ** and never aftre that, we can live by it.
  2207. */
  2208. if ((fp = fopen (pathname, "r")) == NULL) {
  2209. return LOGFILE_NEW;
  2210. }
  2211. loginfo.log_numof_access_logs = 0;
  2212. /*
  2213. ** We have reopened the log access file. Now we need to read the
  2214. ** log file info and update the values.
  2215. */
  2216. while (log__extract_logheader(fp, &f_ctime, &f_size) == LOG_CONTINUE) {
  2217. /* first we would get the main log info */
  2218. if (f_ctime == 0 && f_size == 0)
  2219. continue;
  2220. time (&now);
  2221. if (main_log) {
  2222. if (f_ctime > 0L)
  2223. loginfo.log_access_ctime = f_ctime;
  2224. else {
  2225. loginfo.log_access_ctime = now;
  2226. }
  2227. main_log = 0;
  2228. } else {
  2229. struct logfileinfo *logp;
  2230. logp = (struct logfileinfo *) slapi_ch_malloc (sizeof (struct logfileinfo));
  2231. if (f_ctime > 0L)
  2232. logp->l_ctime = f_ctime;
  2233. else
  2234. logp->l_ctime = now;
  2235. if (f_size > 0)
  2236. logp->l_size = f_size;
  2237. else {
  2238. /* make it the max log size */
  2239. logp->l_size = loginfo.log_access_maxlogsize;
  2240. }
  2241. logp->l_next = loginfo.log_access_logchain;
  2242. loginfo.log_access_logchain = logp;
  2243. }
  2244. loginfo.log_numof_access_logs++;
  2245. }
  2246. /* Check if there is a rotation overdue */
  2247. if (loginfo.log_access_rotationsync_enabled &&
  2248. loginfo.log_access_rotationunit != LOG_UNIT_HOURS &&
  2249. loginfo.log_access_rotationunit != LOG_UNIT_MINS &&
  2250. loginfo.log_access_ctime < loginfo.log_access_rotationsyncclock - loginfo.log_access_rotationtime_secs) {
  2251. loginfo.log_access_rotationsyncclock -= loginfo.log_access_rotationtime_secs;
  2252. }
  2253. fclose (fp);
  2254. return LOGFILE_REOPENED;
  2255. }
  2256. /******************************************************************************
  2257. * log__extract_logheader
  2258. *
  2259. * Extract each LOGINFO heder line. From there extract the time and
  2260. * size info of all the old log files.
  2261. ******************************************************************************/
  2262. static int
  2263. log__extract_logheader (FILE *fp, long *f_ctime, int *f_size)
  2264. {
  2265. char buf[BUFSIZ];
  2266. char *p, *s, *next;
  2267. *f_ctime = 0L;
  2268. *f_size = 0;
  2269. if ( fp == NULL)
  2270. return LOG_ERROR;
  2271. if (fgets(buf, BUFSIZ, fp) == NULL) {
  2272. return LOG_ERROR;
  2273. }
  2274. if ((p=strstr(buf, "LOGINFO")) == NULL) {
  2275. return LOG_ERROR;
  2276. }
  2277. s = p;
  2278. if ((p = strchr(p, '(')) == NULL) {
  2279. return LOG_CONTINUE;
  2280. }
  2281. if ((next= strchr(p, ')')) == NULL) {
  2282. return LOG_CONTINUE;
  2283. }
  2284. p++;
  2285. s = next;
  2286. next++;
  2287. *s = '\0';
  2288. /* Now p must hold the ctime value */
  2289. *f_ctime = atoi(p);
  2290. if ((p = strchr(next, '(')) == NULL) {
  2291. /* that's fine -- it means we have no size info */
  2292. *f_size = 0;
  2293. return LOG_CONTINUE;
  2294. }
  2295. if ((next= strchr(p, ')')) == NULL) {
  2296. return LOG_CONTINUE;
  2297. }
  2298. p++;
  2299. *next = '\0';
  2300. /* Now p must hold the size value */
  2301. *f_size = atoi(p);
  2302. return LOG_CONTINUE;
  2303. }
  2304. /******************************************************************************
  2305. * log__getfilesize
  2306. * Get the file size
  2307. *
  2308. * Assumption: Lock has been acquired already.
  2309. ******************************************************************************/
  2310. /* this kinda has to be diff't on each platform :( */
  2311. /* using an int implies that all logfiles will be under 2G. this is
  2312. * probably a safe assumption for now.
  2313. */
  2314. #ifdef XP_WIN32
  2315. static int
  2316. log__getfilesize(LOGFD fp)
  2317. {
  2318. struct stat info;
  2319. int rv;
  2320. if ((rv = fstat(fileno(fp), &info)) != 0) {
  2321. return -1;
  2322. }
  2323. return info.st_size;
  2324. }
  2325. #else
  2326. static int
  2327. log__getfilesize(LOGFD fp)
  2328. {
  2329. PRFileInfo info;
  2330. int rv;
  2331. if ((rv = PR_GetOpenFileInfo (fp, &info)) == PR_FAILURE) {
  2332. return -1;
  2333. }
  2334. return info.size;
  2335. }
  2336. #endif
  2337. /******************************************************************************
  2338. * log__enough_freespace
  2339. *
  2340. * Returns:
  2341. * 1 - we have enough space
  2342. * 0 - No the avialable space is less than recomended
  2343. * Assumption: Lock has been acquired already.
  2344. ******************************************************************************/
  2345. static int
  2346. log__enough_freespace(char *path)
  2347. {
  2348. #ifdef _WIN32
  2349. DWORD sectorsPerCluster, bytesPerSector, freeClusters, totalClusters;
  2350. char rootpath[4];
  2351. #else
  2352. #ifdef LINUX
  2353. struct statfs buf;
  2354. #else
  2355. struct statvfs buf;
  2356. #endif /* LINUX */
  2357. #endif
  2358. PRInt64 freeBytes;
  2359. PRInt64 tmpval;
  2360. #ifdef _WIN32
  2361. strncpy(rootpath, path, 3);
  2362. rootpath[3] = '\0';
  2363. /* we should consider using GetDiskFreeSpaceEx here someday */
  2364. if ( !GetDiskFreeSpace(rootpath, &sectorsPerCluster, &bytesPerSector,
  2365. &freeClusters, &totalClusters)) {
  2366. LDAPDebug(LDAP_DEBUG_ANY,
  2367. "log__enough_freespace: Unable to get the free space\n",0,0,0);
  2368. return 1;
  2369. } else {
  2370. LL_UI2L(freeBytes, freeClusters);
  2371. LL_UI2L(tmpval, sectorsPerCluster);
  2372. LL_MUL(freeBytes, freeBytes, tmpval);
  2373. LL_UI2L(tmpval, bytesPerSector);
  2374. LL_MUL(freeBytes, freeBytes, tmpval);
  2375. /* freeBytes = freeClusters * sectorsPerCluster * bytesPerSector; */
  2376. }
  2377. #else
  2378. #ifdef LINUX
  2379. if (statfs(path, &buf) == -1)
  2380. #else
  2381. if (statvfs(path, &buf) == -1)
  2382. #endif
  2383. {
  2384. int oserr = errno;
  2385. LDAPDebug(LDAP_DEBUG_ANY,
  2386. "log__enough_freespace: Unable to get the free space (errno:%d)\n",
  2387. oserr,0,0);
  2388. return 1;
  2389. } else {
  2390. LL_UI2L(freeBytes, buf.f_bavail);
  2391. LL_UI2L(tmpval, buf.f_bsize);
  2392. LL_MUL(freeBytes, freeBytes, tmpval);
  2393. /* freeBytes = buf.f_bavail * buf.f_bsize; */
  2394. }
  2395. #endif
  2396. LL_UI2L(tmpval, loginfo.log_access_minfreespace);
  2397. if (LL_UCMP(freeBytes, <, tmpval)) {
  2398. /* if (freeBytes < loginfo.log_access_minfreespace) { */
  2399. return 0;
  2400. }
  2401. return 1;
  2402. }
  2403. /******************************************************************************
  2404. * log__getaccesslist
  2405. * Update the previous access files in the slapdFrontendConfig_t.
  2406. * Returns:
  2407. * num > 1 -- how many are there
  2408. * 0 -- otherwise
  2409. ******************************************************************************/
  2410. char **
  2411. log_get_loglist(int logtype)
  2412. {
  2413. char **list=NULL;
  2414. int num, i;
  2415. LogFileInfo *logp = NULL;
  2416. char buf[BUFSIZ];
  2417. char tbuf[TBUFSIZE];
  2418. char *file;
  2419. switch (logtype) {
  2420. case SLAPD_ACCESS_LOG:
  2421. LOG_ACCESS_LOCK_READ( );
  2422. num = loginfo.log_numof_access_logs;
  2423. logp = loginfo.log_access_logchain;
  2424. file = loginfo.log_access_file;
  2425. break;
  2426. case SLAPD_ERROR_LOG:
  2427. LOG_ERROR_LOCK_READ( );
  2428. num = loginfo.log_numof_error_logs;
  2429. logp = loginfo.log_error_logchain;
  2430. file = loginfo.log_error_file;
  2431. break;
  2432. case SLAPD_AUDIT_LOG:
  2433. LOG_AUDIT_LOCK_READ( );
  2434. num = loginfo.log_numof_audit_logs;
  2435. logp = loginfo.log_audit_logchain;
  2436. file = loginfo.log_audit_file;
  2437. break;
  2438. default:
  2439. return NULL;
  2440. }
  2441. list = (char **) slapi_ch_calloc(1, num * sizeof(char *));
  2442. i = 0;
  2443. while (logp) {
  2444. log_convert_time (logp->l_ctime, tbuf, 1 /*short */);
  2445. PR_snprintf(buf, sizeof(buf), "%s.%s", file, tbuf);
  2446. list[i] = slapi_ch_strdup(buf);
  2447. i++;
  2448. logp = logp->l_next;
  2449. }
  2450. list[i] = NULL;
  2451. switch (logtype) {
  2452. case SLAPD_ACCESS_LOG:
  2453. LOG_ACCESS_UNLOCK_READ();
  2454. break;
  2455. case SLAPD_ERROR_LOG:
  2456. LOG_ERROR_UNLOCK_READ();
  2457. break;
  2458. case SLAPD_AUDIT_LOG:
  2459. LOG_AUDIT_UNLOCK_READ();
  2460. break;
  2461. }
  2462. return list;
  2463. }
  2464. /******************************************************************************
  2465. * log__delete_error_logfile
  2466. *
  2467. * Do we need to delete a logfile. Find out if we need to delete the log
  2468. * file based on expiration time, max diskspace, and minfreespace.
  2469. * Delete the file if we need to.
  2470. *
  2471. * Assumption: A WRITE lock has been acquired for the error log.
  2472. ******************************************************************************/
  2473. static int
  2474. log__delete_error_logfile()
  2475. {
  2476. struct logfileinfo *logp = NULL;
  2477. struct logfileinfo *delete_logp = NULL;
  2478. struct logfileinfo *p_delete_logp = NULL;
  2479. struct logfileinfo *prev_logp = NULL;
  2480. int total_size=0;
  2481. time_t cur_time;
  2482. int f_size;
  2483. int numoflogs=loginfo.log_numof_error_logs;
  2484. int rv = 0;
  2485. char *logstr;
  2486. char buffer[BUFSIZ];
  2487. char tbuf[TBUFSIZE];
  2488. /* If we have only one log, then will delete this one */
  2489. if (loginfo.log_error_maxnumlogs == 1) {
  2490. LOG_CLOSE(loginfo.log_error_fdes);
  2491. loginfo.log_error_fdes = NULL;
  2492. PR_snprintf (buffer, sizeof(buffer), "%s", loginfo.log_error_file);
  2493. if (PR_Delete(buffer) != PR_SUCCESS) {
  2494. LDAPDebug(LDAP_DEBUG_TRACE,
  2495. "LOGINFO:Unable to remove file:%s\n", loginfo.log_error_file,0,0);
  2496. }
  2497. /* Delete the rotation file also. */
  2498. PR_snprintf (buffer, sizeof(buffer), "%s.rotationinfo", loginfo.log_error_file);
  2499. if (PR_Delete(buffer) != PR_SUCCESS) {
  2500. LDAPDebug(LDAP_DEBUG_TRACE,
  2501. "LOGINFO:Unable to remove file:%s.rotationinfo\n", loginfo.log_error_file,0,0);
  2502. }
  2503. return 0;
  2504. }
  2505. /* If we have already the maximum number of log files, we
  2506. ** have to delete one any how.
  2507. */
  2508. if (++numoflogs > loginfo.log_error_maxnumlogs) {
  2509. logstr = "Exceeded max number of logs allowed";
  2510. goto delete_logfile;
  2511. }
  2512. /* Now check based on the maxdiskspace */
  2513. if (loginfo.log_error_maxdiskspace > 0) {
  2514. logp = loginfo.log_error_logchain;
  2515. while (logp) {
  2516. total_size += logp->l_size;
  2517. logp = logp->l_next;
  2518. }
  2519. if ((f_size = log__getfilesize(loginfo.log_error_fdes)) == -1) {
  2520. /* then just assume the max size */
  2521. total_size += loginfo.log_error_maxlogsize;
  2522. } else {
  2523. total_size += f_size;
  2524. }
  2525. /* If we have exceeded the max disk space or we have less than the
  2526. ** minimum, then we have to delete a file.
  2527. */
  2528. if (total_size >= loginfo.log_error_maxdiskspace) {
  2529. logstr = "exceeded maximum log disk space";
  2530. goto delete_logfile;
  2531. }
  2532. }
  2533. /* Now check based on the free space */
  2534. if ( loginfo.log_error_minfreespace > 0) {
  2535. rv = log__enough_freespace(loginfo.log_error_file);
  2536. if ( rv == 0) {
  2537. /* Not enough free space */
  2538. logstr = "Not enough free disk space";
  2539. goto delete_logfile;
  2540. }
  2541. }
  2542. /* Now check based on the expiration time */
  2543. if ( loginfo.log_error_exptime_secs > 0 ) {
  2544. /* is the file old enough */
  2545. time (&cur_time);
  2546. prev_logp = logp = loginfo.log_error_logchain;
  2547. while (logp) {
  2548. if ((cur_time - logp->l_ctime) > loginfo.log_error_exptime_secs) {
  2549. delete_logp = logp;
  2550. p_delete_logp = prev_logp;
  2551. logstr = "The file is older than the log expiration time";
  2552. goto delete_logfile;
  2553. }
  2554. prev_logp = logp;
  2555. logp = logp->l_next;
  2556. }
  2557. }
  2558. /* No log files to delete */
  2559. return 0;
  2560. delete_logfile:
  2561. if (delete_logp == NULL) {
  2562. time_t oldest;
  2563. time(&oldest);
  2564. prev_logp = logp = loginfo.log_error_logchain;
  2565. while (logp) {
  2566. if (logp->l_ctime <= oldest) {
  2567. oldest = logp->l_ctime;
  2568. delete_logp = logp;
  2569. p_delete_logp = prev_logp;
  2570. }
  2571. prev_logp = logp;
  2572. logp = logp->l_next;
  2573. }
  2574. /* We might face this case if we have only one log file and
  2575. ** trying to delete it because of deletion requirement.
  2576. */
  2577. if (!delete_logp) {
  2578. return 0;
  2579. }
  2580. }
  2581. if (p_delete_logp == delete_logp) {
  2582. /* then we are deleteing the first one */
  2583. loginfo.log_error_logchain = delete_logp->l_next;
  2584. } else {
  2585. p_delete_logp->l_next = delete_logp->l_next;
  2586. }
  2587. /* Delete the error file */
  2588. log_convert_time (delete_logp->l_ctime, tbuf, 1 /*short */);
  2589. PR_snprintf (buffer, sizeof(buffer), "%s.%s", loginfo.log_error_file, tbuf);
  2590. PR_Delete(buffer);
  2591. slapi_ch_free((void**)&delete_logp);
  2592. loginfo.log_numof_error_logs--;
  2593. return 1;
  2594. }
  2595. /******************************************************************************
  2596. * log__delete_audit_logfile
  2597. *
  2598. * Do we need to delete a logfile. Find out if we need to delete the log
  2599. * file based on expiration time, max diskspace, and minfreespace.
  2600. * Delete the file if we need to.
  2601. *
  2602. * Assumption: A WRITE lock has been acquired for the audit
  2603. ******************************************************************************/
  2604. static int
  2605. log__delete_audit_logfile()
  2606. {
  2607. struct logfileinfo *logp = NULL;
  2608. struct logfileinfo *delete_logp = NULL;
  2609. struct logfileinfo *p_delete_logp = NULL;
  2610. struct logfileinfo *prev_logp = NULL;
  2611. int total_size=0;
  2612. time_t cur_time;
  2613. int f_size;
  2614. int numoflogs=loginfo.log_numof_audit_logs;
  2615. int rv = 0;
  2616. char *logstr;
  2617. char buffer[BUFSIZ];
  2618. char tbuf[TBUFSIZE];
  2619. /* If we have only one log, then will delete this one */
  2620. if (loginfo.log_audit_maxnumlogs == 1) {
  2621. LOG_CLOSE(loginfo.log_audit_fdes);
  2622. loginfo.log_audit_fdes = NULL;
  2623. PR_snprintf(buffer, sizeof(buffer), "%s", loginfo.log_audit_file);
  2624. if (PR_Delete(buffer) != PR_SUCCESS) {
  2625. LDAPDebug(LDAP_DEBUG_TRACE,
  2626. "LOGINFO:Unable to remove file:%s\n", loginfo.log_audit_file,0,0);
  2627. }
  2628. /* Delete the rotation file also. */
  2629. PR_snprintf(buffer, sizeof(buffer), "%s.rotationinfo", loginfo.log_audit_file);
  2630. if (PR_Delete(buffer) != PR_SUCCESS) {
  2631. LDAPDebug(LDAP_DEBUG_TRACE,
  2632. "LOGINFO:Unable to remove file:%s.rotationinfo\n", loginfo.log_audit_file,0,0);
  2633. }
  2634. return 0;
  2635. }
  2636. /* If we have already the maximum number of log files, we
  2637. ** have to delete one any how.
  2638. */
  2639. if (++numoflogs > loginfo.log_audit_maxnumlogs) {
  2640. logstr = "Exceeded max number of logs allowed";
  2641. goto delete_logfile;
  2642. }
  2643. /* Now check based on the maxdiskspace */
  2644. if (loginfo.log_audit_maxdiskspace > 0) {
  2645. logp = loginfo.log_audit_logchain;
  2646. while (logp) {
  2647. total_size += logp->l_size;
  2648. logp = logp->l_next;
  2649. }
  2650. if ((f_size = log__getfilesize(loginfo.log_audit_fdes)) == -1) {
  2651. /* then just assume the max size */
  2652. total_size += loginfo.log_audit_maxlogsize;
  2653. } else {
  2654. total_size += f_size;
  2655. }
  2656. /* If we have exceeded the max disk space or we have less than the
  2657. ** minimum, then we have to delete a file.
  2658. */
  2659. if (total_size >= loginfo.log_audit_maxdiskspace) {
  2660. logstr = "exceeded maximum log disk space";
  2661. goto delete_logfile;
  2662. }
  2663. }
  2664. /* Now check based on the free space */
  2665. if ( loginfo.log_audit_minfreespace > 0) {
  2666. rv = log__enough_freespace(loginfo.log_audit_file);
  2667. if ( rv == 0) {
  2668. /* Not enough free space */
  2669. logstr = "Not enough free disk space";
  2670. goto delete_logfile;
  2671. }
  2672. }
  2673. /* Now check based on the expiration time */
  2674. if ( loginfo.log_audit_exptime_secs > 0 ) {
  2675. /* is the file old enough */
  2676. time (&cur_time);
  2677. prev_logp = logp = loginfo.log_audit_logchain;
  2678. while (logp) {
  2679. if ((cur_time - logp->l_ctime) > loginfo.log_audit_exptime_secs) {
  2680. delete_logp = logp;
  2681. p_delete_logp = prev_logp;
  2682. logstr = "The file is older than the log expiration time";
  2683. goto delete_logfile;
  2684. }
  2685. prev_logp = logp;
  2686. logp = logp->l_next;
  2687. }
  2688. }
  2689. /* No log files to delete */
  2690. return 0;
  2691. delete_logfile:
  2692. if (delete_logp == NULL) {
  2693. time_t oldest;
  2694. time(&oldest);
  2695. prev_logp = logp = loginfo.log_audit_logchain;
  2696. while (logp) {
  2697. if (logp->l_ctime <= oldest) {
  2698. oldest = logp->l_ctime;
  2699. delete_logp = logp;
  2700. p_delete_logp = prev_logp;
  2701. }
  2702. prev_logp = logp;
  2703. logp = logp->l_next;
  2704. }
  2705. /* We might face this case if we have only one log file and
  2706. ** trying to delete it because of deletion requirement.
  2707. */
  2708. if (!delete_logp) {
  2709. return 0;
  2710. }
  2711. }
  2712. if (p_delete_logp == delete_logp) {
  2713. /* then we are deleteing the first one */
  2714. loginfo.log_audit_logchain = delete_logp->l_next;
  2715. } else {
  2716. p_delete_logp->l_next = delete_logp->l_next;
  2717. }
  2718. /* Delete the audit file */
  2719. log_convert_time (delete_logp->l_ctime, tbuf, 1 /*short */);
  2720. PR_snprintf(buffer, sizeof(buffer), "%s.%s", loginfo.log_audit_file, tbuf );
  2721. if (PR_Delete(buffer) != PR_SUCCESS) {
  2722. LDAPDebug(LDAP_DEBUG_TRACE,
  2723. "LOGINFO:Unable to remove file:%s.%s\n",
  2724. loginfo.log_audit_file, tbuf,0);
  2725. } else {
  2726. LDAPDebug(LDAP_DEBUG_TRACE,
  2727. "LOGINFO:Removed file:%s.%s because of (%s)\n",
  2728. loginfo.log_audit_file, tbuf,
  2729. logstr);
  2730. }
  2731. slapi_ch_free((void**)&delete_logp);
  2732. loginfo.log_numof_audit_logs--;
  2733. return 1;
  2734. }
  2735. /******************************************************************************
  2736. * log__error_rotationinfof
  2737. *
  2738. * Try to open the log file. If we have one already, then try to read the
  2739. * header and update the information.
  2740. *
  2741. * Assumption: Lock has been acquired already
  2742. ******************************************************************************/
  2743. static int
  2744. log__error_rotationinfof( char *pathname)
  2745. {
  2746. long f_ctime;
  2747. int f_size;
  2748. int main_log = 1;
  2749. time_t now;
  2750. FILE *fp;
  2751. /*
  2752. ** Okay -- I confess, we want to use NSPR calls but I want to
  2753. ** use fgets and not use PR_Read() and implement a complicated
  2754. ** parsing module. Since this will be called only during the startup
  2755. ** and never aftre that, we can live by it.
  2756. */
  2757. if ((fp = fopen (pathname, "r")) == NULL) {
  2758. return LOGFILE_NEW;
  2759. }
  2760. loginfo.log_numof_error_logs = 0;
  2761. /*
  2762. ** We have reopened the log error file. Now we need to read the
  2763. ** log file info and update the values.
  2764. */
  2765. while (log__extract_logheader(fp, &f_ctime, &f_size) == LOG_CONTINUE) {
  2766. /* first we would get the main log info */
  2767. if (f_ctime == 0 && f_size == 0)
  2768. continue;
  2769. time (&now);
  2770. if (main_log) {
  2771. if (f_ctime > 0L)
  2772. loginfo.log_error_ctime = f_ctime;
  2773. else {
  2774. loginfo.log_error_ctime = now;
  2775. }
  2776. main_log = 0;
  2777. } else {
  2778. struct logfileinfo *logp;
  2779. logp = (struct logfileinfo *) slapi_ch_malloc (sizeof (struct logfileinfo));
  2780. if (f_ctime > 0L)
  2781. logp->l_ctime = f_ctime;
  2782. else
  2783. logp->l_ctime = now;
  2784. if (f_size > 0)
  2785. logp->l_size = f_size;
  2786. else {
  2787. /* make it the max log size */
  2788. logp->l_size = loginfo.log_error_maxlogsize;
  2789. }
  2790. logp->l_next = loginfo.log_error_logchain;
  2791. loginfo.log_error_logchain = logp;
  2792. }
  2793. loginfo.log_numof_error_logs++;
  2794. }
  2795. /* Check if there is a rotation overdue */
  2796. if (loginfo.log_error_rotationsync_enabled &&
  2797. loginfo.log_error_rotationunit != LOG_UNIT_HOURS &&
  2798. loginfo.log_error_rotationunit != LOG_UNIT_MINS &&
  2799. loginfo.log_error_ctime < loginfo.log_error_rotationsyncclock - loginfo.log_error_rotationtime_secs) {
  2800. loginfo.log_error_rotationsyncclock -= loginfo.log_error_rotationtime_secs;
  2801. }
  2802. fclose (fp);
  2803. return LOGFILE_REOPENED;
  2804. }
  2805. /******************************************************************************
  2806. * log__audit_rotationinfof
  2807. *
  2808. * Try to open the log file. If we have one already, then try to read the
  2809. * header and update the information.
  2810. *
  2811. * Assumption: Lock has been acquired already
  2812. ******************************************************************************/
  2813. static int
  2814. log__audit_rotationinfof( char *pathname)
  2815. {
  2816. long f_ctime;
  2817. int f_size;
  2818. int main_log = 1;
  2819. time_t now;
  2820. FILE *fp;
  2821. /*
  2822. ** Okay -- I confess, we want to use NSPR calls but I want to
  2823. ** use fgets and not use PR_Read() and implement a complicated
  2824. ** parsing module. Since this will be called only during the startup
  2825. ** and never aftre that, we can live by it.
  2826. */
  2827. if ((fp = fopen (pathname, "r")) == NULL) {
  2828. return LOGFILE_NEW;
  2829. }
  2830. loginfo.log_numof_audit_logs = 0;
  2831. /*
  2832. ** We have reopened the log audit file. Now we need to read the
  2833. ** log file info and update the values.
  2834. */
  2835. while (log__extract_logheader(fp, &f_ctime, &f_size) == LOG_CONTINUE) {
  2836. /* first we would get the main log info */
  2837. if (f_ctime == 0 && f_size == 0)
  2838. continue;
  2839. time (&now);
  2840. if (main_log) {
  2841. if (f_ctime > 0L)
  2842. loginfo.log_audit_ctime = f_ctime;
  2843. else {
  2844. loginfo.log_audit_ctime = now;
  2845. }
  2846. main_log = 0;
  2847. } else {
  2848. struct logfileinfo *logp;
  2849. logp = (struct logfileinfo *) slapi_ch_malloc (sizeof (struct logfileinfo));
  2850. if (f_ctime > 0L)
  2851. logp->l_ctime = f_ctime;
  2852. else
  2853. logp->l_ctime = now;
  2854. if (f_size > 0)
  2855. logp->l_size = f_size;
  2856. else {
  2857. /* make it the max log size */
  2858. logp->l_size = loginfo.log_audit_maxlogsize;
  2859. }
  2860. logp->l_next = loginfo.log_audit_logchain;
  2861. loginfo.log_audit_logchain = logp;
  2862. }
  2863. loginfo.log_numof_audit_logs++;
  2864. }
  2865. /* Check if there is a rotation overdue */
  2866. if (loginfo.log_audit_rotationsync_enabled &&
  2867. loginfo.log_audit_rotationunit != LOG_UNIT_HOURS &&
  2868. loginfo.log_audit_rotationunit != LOG_UNIT_MINS &&
  2869. loginfo.log_audit_ctime < loginfo.log_audit_rotationsyncclock - loginfo.log_audit_rotationtime_secs) {
  2870. loginfo.log_audit_rotationsyncclock -= loginfo.log_audit_rotationtime_secs;
  2871. }
  2872. fclose (fp);
  2873. return LOGFILE_REOPENED;
  2874. }
  2875. /******************************************************************************
  2876. * log__open_errorlogfile
  2877. *
  2878. * Open a new log file. If we have run out of the max logs we can have
  2879. * then delete the oldest file.
  2880. ******************************************************************************/
  2881. static int
  2882. log__open_errorlogfile(int logfile_state, int locked)
  2883. {
  2884. time_t now;
  2885. LOGFD fp;
  2886. LOGFD fpinfo = NULL;
  2887. char tbuf[TBUFSIZE];
  2888. struct logfileinfo *logp;
  2889. char buffer[BUFSIZ];
  2890. if (!locked) LOG_ERROR_LOCK_WRITE( );
  2891. /*
  2892. ** Here we are trying to create a new log file.
  2893. ** If we alredy have one, then we need to rename it as
  2894. ** "filename.time", close it and update it's information
  2895. ** in the array stack.
  2896. */
  2897. if (loginfo.log_error_fdes != NULL) {
  2898. struct logfileinfo *log;
  2899. char newfile[BUFSIZ];
  2900. int f_size;
  2901. /* get rid of the old one */
  2902. if ((f_size = log__getfilesize(loginfo.log_error_fdes)) == -1) {
  2903. /* Then assume that we have the max size */
  2904. f_size = loginfo.log_error_maxlogsize;
  2905. }
  2906. /* Check if I have to delete any old file, delete it if it is required.*/
  2907. while (log__delete_error_logfile());
  2908. /* close the file */
  2909. if ( loginfo.log_error_fdes != NULL ) {
  2910. LOG_CLOSE(loginfo.log_error_fdes);
  2911. }
  2912. loginfo.log_error_fdes = NULL;
  2913. if ( loginfo.log_error_maxnumlogs > 1 ) {
  2914. log = (struct logfileinfo *) slapi_ch_malloc (sizeof (struct logfileinfo));
  2915. log->l_ctime = loginfo.log_error_ctime;
  2916. log->l_size = f_size;
  2917. log_convert_time (log->l_ctime, tbuf, 1/*short */);
  2918. PR_snprintf(newfile, sizeof(newfile), "%s.%s", loginfo.log_error_file, tbuf);
  2919. if (PR_Rename (loginfo.log_error_file, newfile) != PR_SUCCESS) {
  2920. return LOG_UNABLE_TO_OPENFILE;
  2921. }
  2922. /* add the log to the chain */
  2923. log->l_next = loginfo.log_error_logchain;
  2924. loginfo.log_error_logchain = log;
  2925. loginfo.log_numof_error_logs++;
  2926. }
  2927. }
  2928. /* open a new log file */
  2929. if (! LOG_OPEN_APPEND(fp, loginfo.log_error_file, loginfo.log_error_mode)) {
  2930. LDAPDebug(LDAP_DEBUG_ANY, "WARNING: can't open file %s. "
  2931. "errno %d (%s)\n",
  2932. loginfo.log_error_file, errno, slapd_system_strerror(errno));
  2933. if (!locked) LOG_ERROR_UNLOCK_WRITE();
  2934. /*if I have an old log file -- I should log a message
  2935. ** that I can't open the new file. Let the caller worry
  2936. ** about logging message.
  2937. */
  2938. return LOG_UNABLE_TO_OPENFILE;
  2939. }
  2940. loginfo.log_error_fdes = fp;
  2941. if (logfile_state == LOGFILE_REOPENED) {
  2942. /* we have all the information */
  2943. if (!locked) LOG_ERROR_UNLOCK_WRITE( );
  2944. return LOG_SUCCESS;
  2945. }
  2946. loginfo.log_error_state |= LOGGING_NEED_TITLE;
  2947. if (! LOG_OPEN_WRITE(fpinfo, loginfo.log_errorinfo_file, loginfo.log_error_mode)) {
  2948. LDAPDebug(LDAP_DEBUG_ANY, "WARNING: can't open file %s. "
  2949. "errno %d (%s)\n",
  2950. loginfo.log_errorinfo_file, errno, slapd_system_strerror(errno));
  2951. if (!locked) LOG_ERROR_UNLOCK_WRITE();
  2952. return LOG_UNABLE_TO_OPENFILE;
  2953. }
  2954. /* write the header in the log */
  2955. now = current_time();
  2956. log_convert_time (now, tbuf, 2 /*long */);
  2957. PR_snprintf(buffer, sizeof(buffer),"LOGINFO:Log file created at: %s (%lu)\n", tbuf, now);
  2958. LOG_WRITE(fpinfo, buffer, strlen(buffer), 0);
  2959. logp = loginfo.log_error_logchain;
  2960. while ( logp) {
  2961. log_convert_time (logp->l_ctime, tbuf, 1 /*short */);
  2962. PR_snprintf(buffer, sizeof(buffer), "LOGINFO:Previous Log File:%s.%s (%lu) (%u)\n",
  2963. loginfo.log_error_file, tbuf, logp->l_ctime, logp->l_size);
  2964. LOG_WRITE(fpinfo, buffer, strlen(buffer), 0);
  2965. logp = logp->l_next;
  2966. }
  2967. /* Close the info file. We need only when we need to rotate to the
  2968. ** next log file.
  2969. */
  2970. if (fpinfo) LOG_CLOSE(fpinfo);
  2971. /* This is now the current error log */
  2972. loginfo.log_error_ctime = now;
  2973. if (!locked) LOG_ERROR_UNLOCK_WRITE( );
  2974. return LOG_SUCCESS;
  2975. }
  2976. /******************************************************************************
  2977. * log__open_auditlogfile
  2978. *
  2979. * Open a new log file. If we have run out of the max logs we can have
  2980. * then delete the oldest file.
  2981. ******************************************************************************/
  2982. static int
  2983. log__open_auditlogfile(int logfile_state, int locked)
  2984. {
  2985. time_t now;
  2986. LOGFD fp;
  2987. LOGFD fpinfo = NULL;
  2988. char tbuf[TBUFSIZE];
  2989. struct logfileinfo *logp;
  2990. char buffer[BUFSIZ];
  2991. if (!locked) LOG_AUDIT_LOCK_WRITE( );
  2992. /*
  2993. ** Here we are trying to create a new log file.
  2994. ** If we alredy have one, then we need to rename it as
  2995. ** "filename.time", close it and update it's information
  2996. ** in the array stack.
  2997. */
  2998. if (loginfo.log_audit_fdes != NULL) {
  2999. struct logfileinfo *log;
  3000. char newfile[BUFSIZ];
  3001. int f_size;
  3002. /* get rid of the old one */
  3003. if ((f_size = log__getfilesize(loginfo.log_audit_fdes)) == -1) {
  3004. /* Then assume that we have the max size */
  3005. f_size = loginfo.log_audit_maxlogsize;
  3006. }
  3007. /* Check if I have to delete any old file, delete it if it is required. */
  3008. while (log__delete_audit_logfile());
  3009. /* close the file */
  3010. LOG_CLOSE(loginfo.log_audit_fdes);
  3011. loginfo.log_audit_fdes = NULL;
  3012. if ( loginfo.log_audit_maxnumlogs > 1 ) {
  3013. log = (struct logfileinfo *) slapi_ch_malloc (sizeof (struct logfileinfo));
  3014. log->l_ctime = loginfo.log_audit_ctime;
  3015. log->l_size = f_size;
  3016. log_convert_time (log->l_ctime, tbuf, 1 /*short */);
  3017. PR_snprintf(newfile, sizeof(newfile), "%s.%s", loginfo.log_audit_file, tbuf);
  3018. if (PR_Rename (loginfo.log_audit_file, newfile) != PR_SUCCESS) {
  3019. if (!locked) LOG_AUDIT_UNLOCK_WRITE();
  3020. return LOG_UNABLE_TO_OPENFILE;
  3021. }
  3022. /* add the log to the chain */
  3023. log->l_next = loginfo.log_audit_logchain;
  3024. loginfo.log_audit_logchain = log;
  3025. loginfo.log_numof_audit_logs++;
  3026. }
  3027. }
  3028. /* open a new log file */
  3029. if (! LOG_OPEN_APPEND(fp, loginfo.log_audit_file, loginfo.log_audit_mode)) {
  3030. LDAPDebug(LDAP_DEBUG_ANY, "WARNING: can't open file %s. "
  3031. "errno %d (%s)\n",
  3032. loginfo.log_audit_file, errno, slapd_system_strerror(errno));
  3033. if (!locked) LOG_AUDIT_UNLOCK_WRITE();
  3034. /*if I have an old log file -- I should log a message
  3035. ** that I can't open the new file. Let the caller worry
  3036. ** about logging message.
  3037. */
  3038. return LOG_UNABLE_TO_OPENFILE;
  3039. }
  3040. loginfo.log_audit_fdes = fp;
  3041. if (logfile_state == LOGFILE_REOPENED) {
  3042. /* we have all the information */
  3043. if (!locked) LOG_AUDIT_UNLOCK_WRITE();
  3044. return LOG_SUCCESS;
  3045. }
  3046. loginfo.log_audit_state |= LOGGING_NEED_TITLE;
  3047. if (! LOG_OPEN_WRITE(fpinfo, loginfo.log_auditinfo_file, loginfo.log_audit_mode)) {
  3048. LDAPDebug(LDAP_DEBUG_ANY, "WARNING: can't open file %s. "
  3049. "errno %d (%s)\n",
  3050. loginfo.log_auditinfo_file, errno, slapd_system_strerror(errno));
  3051. if (!locked) LOG_AUDIT_UNLOCK_WRITE();
  3052. return LOG_UNABLE_TO_OPENFILE;
  3053. }
  3054. /* write the header in the log */
  3055. now = current_time();
  3056. log_convert_time (now, tbuf, 2 /*long */);
  3057. PR_snprintf(buffer, sizeof(buffer), "LOGINFO:Log file created at: %s (%lu)\n", tbuf, now);
  3058. LOG_WRITE(fpinfo, buffer, strlen(buffer), 0);
  3059. logp = loginfo.log_audit_logchain;
  3060. while ( logp) {
  3061. log_convert_time (logp->l_ctime, tbuf, 1 /*short */);
  3062. PR_snprintf(buffer, sizeof(buffer), "LOGINFO:Previous Log File:%s.%s (%d) (%d)\n",
  3063. loginfo.log_audit_file, tbuf, (int)logp->l_ctime, logp->l_size);
  3064. LOG_WRITE(fpinfo, buffer, strlen(buffer), 0);
  3065. logp = logp->l_next;
  3066. }
  3067. /* Close the info file. We need only when we need to rotate to the
  3068. ** next log file.
  3069. */
  3070. if (fpinfo) LOG_CLOSE(fpinfo);
  3071. /* This is now the current audit log */
  3072. loginfo.log_audit_ctime = now;
  3073. if (!locked) LOG_AUDIT_UNLOCK_WRITE( );
  3074. return LOG_SUCCESS;
  3075. }
  3076. /*
  3077. ** Log Buffering
  3078. ** only supports access log at this time
  3079. */
  3080. static LogBufferInfo *log_create_buffer(size_t sz)
  3081. {
  3082. LogBufferInfo *lbi;
  3083. lbi = (LogBufferInfo *) slapi_ch_malloc(sizeof(LogBufferInfo));
  3084. lbi->top = (char *) slapi_ch_malloc(sz);
  3085. lbi->current = lbi->top;
  3086. lbi->maxsize = sz;
  3087. lbi->refcount = 0;
  3088. return lbi;
  3089. }
  3090. #if 0
  3091. /* for some reason, we never call this. */
  3092. static void log_destroy_buffer(LogBufferInfo *lbi)
  3093. {
  3094. slapi_ch_free((void *)&(lbi->top));
  3095. slapi_ch_free((void *)&lbi);
  3096. }
  3097. #endif
  3098. /*
  3099. Some notes about this function. It is written the
  3100. way it is for performance reasons.
  3101. Tests showed that on 4 processor systems, there is
  3102. significant contention for the
  3103. lbi->lock. This is because the lock was held for
  3104. the duration of the copy of the
  3105. log message into the buffer. Therefore the routine
  3106. was re-written to avoid holding
  3107. the lock for that time. Instead we gain the lock,
  3108. take a copy of the buffer pointer
  3109. where we need to copy our message, increase the
  3110. size, move the current pointer beyond
  3111. our portion of the buffer, then increment a reference
  3112. count.
  3113. Then we release the lock and do the actual copy
  3114. in to the reserved buffer area.
  3115. We then atomically decrement the reference count.
  3116. The reference count is used to ensure that when
  3117. the buffer is flushed to the
  3118. filesystem, there are no threads left copying
  3119. data into the buffer.
  3120. The wait on zero reference count is implemented
  3121. in the flush routine because
  3122. it is also called from log_access_flush().
  3123. Tests show this speeds up searches by 10% on 4-way systems.
  3124. */
  3125. static void log_append_buffer2(time_t tnl, LogBufferInfo *lbi, char *msg1, size_t size1, char *msg2, size_t size2)
  3126. {
  3127. slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
  3128. size_t size = size1 + size2;
  3129. char* insert_point = NULL;
  3130. /* While holding the lock, we determine if there is space in the buffer for our payload,
  3131. and if we need to flush.
  3132. */
  3133. PR_Lock(lbi->lock);
  3134. if ( ((lbi->current - lbi->top) + size > lbi->maxsize) ||
  3135. (tnl >= loginfo.log_access_rotationsyncclock &&
  3136. loginfo.log_access_rotationsync_enabled) ) {
  3137. log_flush_buffer(lbi, SLAPD_ACCESS_LOG,
  3138. 0 /* do not sync to disk right now */ );
  3139. }
  3140. insert_point = lbi->current;
  3141. lbi->current += size;
  3142. /* Increment the copy refcount */
  3143. PR_AtomicIncrement(&(lbi->refcount));
  3144. PR_Unlock(lbi->lock);
  3145. /* Now we can copy without holding the lock */
  3146. memcpy(insert_point, msg1, size1);
  3147. memcpy(insert_point + size1, msg2, size2);
  3148. /* Decrement the copy refcount */
  3149. PR_AtomicDecrement(&(lbi->refcount));
  3150. /* If we are asked to sync to disk immediately, do so */
  3151. if (!slapdFrontendConfig->accesslogbuffering) {
  3152. PR_Lock(lbi->lock);
  3153. log_flush_buffer(lbi, SLAPD_ACCESS_LOG, 1 /* sync to disk now */ );
  3154. PR_Unlock(lbi->lock);
  3155. }
  3156. }
  3157. /* this function assumes the lock is already acquired */
  3158. /* if sync_now is non-zero, data is flushed to physical storage */
  3159. static void log_flush_buffer(LogBufferInfo *lbi, int type, int sync_now)
  3160. {
  3161. slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
  3162. if (type == SLAPD_ACCESS_LOG) {
  3163. /* It is only safe to flush once any other threads which are copying are finished */
  3164. while (lbi->refcount > 0) {
  3165. /* It's ok to sleep for a while because we only flush every second or so */
  3166. DS_Sleep (PR_MillisecondsToInterval(1));
  3167. }
  3168. if ((lbi->current - lbi->top) == 0) return;
  3169. if (log__needrotation(loginfo.log_access_fdes,
  3170. SLAPD_ACCESS_LOG) == LOG_ROTATE) {
  3171. if (log__open_accesslogfile(LOGFILE_NEW, 1) != LOG_SUCCESS) {
  3172. LDAPDebug(LDAP_DEBUG_ANY,
  3173. "LOGINFO: Unable to open access file:%s\n",
  3174. loginfo.log_access_file,0,0);
  3175. lbi->current = lbi->top; /* reset counter to prevent overwriting rest of lbi struct */
  3176. return;
  3177. }
  3178. while (loginfo.log_access_rotationsyncclock <= loginfo.log_access_ctime) {
  3179. loginfo.log_access_rotationsyncclock += loginfo.log_access_rotationtime_secs;
  3180. }
  3181. }
  3182. if (loginfo.log_access_state & LOGGING_NEED_TITLE) {
  3183. log_write_title(loginfo.log_access_fdes);
  3184. loginfo.log_access_state &= ~LOGGING_NEED_TITLE;
  3185. }
  3186. if (!sync_now && slapdFrontendConfig->accesslogbuffering) {
  3187. LOG_WRITE(loginfo.log_access_fdes, lbi->top, lbi->current - lbi->top, 0);
  3188. } else {
  3189. LOG_WRITE_NOW(loginfo.log_access_fdes, lbi->top, lbi->current - lbi->top, 0);
  3190. }
  3191. lbi->current = lbi->top;
  3192. }
  3193. }
  3194. void log_access_flush()
  3195. {
  3196. LOG_ACCESS_LOCK_WRITE();
  3197. log_flush_buffer(loginfo.log_access_buffer, SLAPD_ACCESS_LOG,
  3198. 1 /* sync to disk now */ );
  3199. LOG_ACCESS_UNLOCK_WRITE();
  3200. }
  3201. /*
  3202. *
  3203. * log_convert_time
  3204. * returns the time converted into the string format.
  3205. *
  3206. */
  3207. static void
  3208. log_convert_time (time_t ctime, char *tbuf, int type)
  3209. {
  3210. struct tm *tmsp, tms;
  3211. #ifdef _WIN32
  3212. {
  3213. struct tm *pt = localtime( &ctime );
  3214. tmsp = &tms;
  3215. memcpy(&tms, pt, sizeof(struct tm) );
  3216. }
  3217. #else
  3218. (void)localtime_r( &ctime, &tms );
  3219. tmsp = &tms;
  3220. #endif
  3221. if (type == 1) /* get the short form */
  3222. (void) strftime (tbuf, (size_t) TBUFSIZE, "%Y%m%d-%H%M%S",tmsp);
  3223. else /* wants the long form */
  3224. (void) strftime (tbuf, (size_t) TBUFSIZE, "%d/%b/%Y:%H:%M:%S",tmsp);
  3225. }
  3226. int
  3227. check_log_max_size( char *maxdiskspace_str,
  3228. char *mlogsize_str,
  3229. int maxdiskspace,
  3230. int mlogsize,
  3231. char * returntext,
  3232. int logtype)
  3233. {
  3234. slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
  3235. int rc = LDAP_SUCCESS;
  3236. int current_mlogsize = -1;
  3237. int current_maxdiskspace = -1;
  3238. switch (logtype)
  3239. {
  3240. case SLAPD_ACCESS_LOG:
  3241. current_mlogsize = slapdFrontendConfig->accesslog_maxlogsize;
  3242. current_maxdiskspace = slapdFrontendConfig->accesslog_maxdiskspace;
  3243. break;
  3244. case SLAPD_ERROR_LOG:
  3245. current_mlogsize = slapdFrontendConfig->errorlog_maxlogsize;
  3246. current_maxdiskspace = slapdFrontendConfig->errorlog_maxdiskspace;
  3247. break;
  3248. case SLAPD_AUDIT_LOG:
  3249. current_mlogsize = slapdFrontendConfig->auditlog_maxlogsize;
  3250. current_maxdiskspace = slapdFrontendConfig->auditlog_maxdiskspace;
  3251. break;
  3252. default:
  3253. current_mlogsize = -1;
  3254. current_maxdiskspace = -1;
  3255. }
  3256. if ( maxdiskspace == -1 )
  3257. maxdiskspace = current_maxdiskspace;
  3258. if ( mlogsize == -1 )
  3259. mlogsize = current_mlogsize;
  3260. if ( maxdiskspace < mlogsize )
  3261. {
  3262. /* fail */
  3263. PR_snprintf ( returntext, SLAPI_DSE_RETURNTEXT_SIZE,
  3264. "%s: maxdiskspace \"%d\" is less than max log size \"%d\"",
  3265. maxdiskspace_str, maxdiskspace*LOG_MB_IN_BYTES, mlogsize*LOG_MB_IN_BYTES );
  3266. rc = LDAP_OPERATIONS_ERROR;
  3267. }
  3268. switch (logtype)
  3269. {
  3270. case SLAPD_ACCESS_LOG:
  3271. loginfo.log_access_maxlogsize = mlogsize * LOG_MB_IN_BYTES;
  3272. loginfo.log_access_maxdiskspace = maxdiskspace * LOG_MB_IN_BYTES;
  3273. break;
  3274. case SLAPD_ERROR_LOG:
  3275. loginfo.log_error_maxlogsize = mlogsize * LOG_MB_IN_BYTES;
  3276. loginfo.log_error_maxdiskspace = maxdiskspace * LOG_MB_IN_BYTES;
  3277. break;
  3278. case SLAPD_AUDIT_LOG:
  3279. loginfo.log_audit_maxlogsize = mlogsize * LOG_MB_IN_BYTES;
  3280. loginfo.log_audit_maxdiskspace = maxdiskspace * LOG_MB_IN_BYTES;
  3281. break;
  3282. default:
  3283. break;
  3284. }
  3285. return rc;
  3286. }
  3287. /************************************************************************************/
  3288. /* E N D */
  3289. /************************************************************************************/