Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / sal / osl / unx / profile.cxx
blob15df5b5fba93e1e6081b174b4982e3c65ddd62c6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "system.h"
21 #include "readwrite_helper.h"
23 #include <osl/diagnose.h>
24 #include <osl/profile.h>
25 #include <osl/process.h>
26 #include <osl/thread.h>
27 #include <rtl/alloc.h>
28 #include <sal/log.hxx>
30 #define LINES_INI 32
31 #define LINES_ADD 10
32 #define SECTIONS_INI 5
33 #define SECTIONS_ADD 3
34 #define ENTRIES_INI 5
35 #define ENTRIES_ADD 3
37 #define STR_INI_BOOLYES "yes"
38 #define STR_INI_BOOLON "on"
39 #define STR_INI_BOOLONE "1"
40 #define STR_INI_BOOLNO "no"
41 #define STR_INI_BOOLOFF "off"
42 #define STR_INI_BOOLZERO "0"
44 #define FLG_USER 0x00FF
45 #define FLG_AUTOOPEN 0x0100
46 #define FLG_MODIFIED 0x0200
48 #define DEFAULT_PMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
50 /*#define DEBUG_OSL_PROFILE*/
51 /*#define TRACE_OSL_PROFILE*/
53 typedef time_t osl_TStamp;
55 typedef enum _osl_TLockMode
57 un_lock, read_lock, write_lock
58 } osl_TLockMode;
60 typedef struct _osl_TFile
62 int m_Handle;
63 sal_Char* m_pReadPtr;
64 sal_Char m_ReadBuf[512];
65 sal_Char* m_pWriteBuf;
66 sal_uInt32 m_nWriteBufLen;
67 sal_uInt32 m_nWriteBufFree;
68 } osl_TFile;
70 typedef struct _osl_TProfileEntry
72 sal_uInt32 m_Line;
73 sal_uInt32 m_Offset;
74 sal_uInt32 m_Len;
75 } osl_TProfileEntry;
77 typedef struct _osl_TProfileSection
79 sal_uInt32 m_Line;
80 sal_uInt32 m_Offset;
81 sal_uInt32 m_Len;
82 sal_uInt32 m_NoEntries;
83 sal_uInt32 m_MaxEntries;
84 osl_TProfileEntry* m_Entries;
85 } osl_TProfileSection;
87 /* Profile-data structure hidden behind oslProfile: */
88 typedef struct _osl_TProfileImpl
90 sal_uInt32 m_Flags;
91 osl_TFile* m_pFile;
92 osl_TStamp m_Stamp;
93 sal_Char m_FileName[PATH_MAX + 1];
94 sal_uInt32 m_NoLines;
95 sal_uInt32 m_MaxLines;
96 sal_uInt32 m_NoSections;
97 sal_uInt32 m_MaxSections;
98 sal_Char** m_Lines;
99 osl_TProfileSection* m_Sections;
100 pthread_mutex_t m_AccessLock;
101 bool m_bIsValid;
102 } osl_TProfileImpl;
104 static osl_TFile* openFileImpl(const sal_Char* pszFilename, oslProfileOption ProfileFlags);
105 static osl_TStamp closeFileImpl(osl_TFile* pFile, oslProfileOption Flags);
106 static bool OslProfile_lockFile(const osl_TFile* pFile, osl_TLockMode eMode);
107 static bool OslProfile_rewindFile(osl_TFile* pFile, bool bTruncate);
108 static osl_TStamp OslProfile_getFileStamp(osl_TFile* pFile);
110 static sal_Char* OslProfile_getLine(osl_TFile* pFile);
111 static bool OslProfile_putLine(osl_TFile* pFile, const sal_Char *pszLine);
112 static sal_Char* stripBlanks(sal_Char* String, sal_uInt32* pLen);
113 static sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line);
114 static sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo);
115 static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo);
116 static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
117 sal_uInt32 NoEntry, sal_uInt32 Line,
118 sal_Char* Entry, sal_uInt32 Len);
119 static bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
120 int Line, sal_Char* Entry, sal_uInt32 Len);
121 static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry);
122 static bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len);
123 static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection);
124 static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
125 const sal_Char* Entry, sal_uInt32 *pNoEntry);
126 static bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile);
127 static bool storeProfile(osl_TProfileImpl* pProfile, bool bCleanup);
128 static osl_TProfileImpl* acquireProfile(oslProfile Profile, bool bWriteable);
129 static bool releaseProfile(osl_TProfileImpl* pProfile);
131 static bool writeProfileImpl (osl_TFile* pFile);
132 static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl*);
133 static bool osl_ProfileSwapProfileNames(osl_TProfileImpl*);
134 static void osl_ProfileGenerateExtension(const sal_Char* pszFileName, const sal_Char* pszExtension, sal_Char* pszTmpName, int BufferMaxLen);
135 static oslProfile SAL_CALL osl_psz_openProfile(const sal_Char *pszProfileName, oslProfileOption Flags);
137 /* implemented in file.c */
138 extern "C" oslFileError FileURLToPath( char *, size_t, rtl_uString* );
140 oslProfile SAL_CALL osl_openProfile(rtl_uString *ustrProfileName, oslProfileOption Options)
142 char profilePath[PATH_MAX] = "";
144 if ( ustrProfileName != 0 && ustrProfileName->buffer[0] != 0 )
145 FileURLToPath( profilePath, PATH_MAX, ustrProfileName );
147 return osl_psz_openProfile( profilePath,Options );
150 static oslProfile SAL_CALL osl_psz_openProfile(const sal_Char *pszProfileName, oslProfileOption Flags)
152 osl_TFile* pFile;
153 osl_TProfileImpl* pProfile;
154 bool bRet = false;
156 #ifdef TRACE_OSL_PROFILE
157 OSL_TRACE("In osl_openProfile");
158 #endif
160 #ifdef DEBUG_OSL_PROFILE
161 Flags=osl_Profile_FLUSHWRITE;
163 OSL_TRACE("opening '%s'",pszProfileName);
164 if ( Flags == osl_Profile_DEFAULT )
166 OSL_TRACE("with osl_Profile_DEFAULT");
168 if ( Flags & osl_Profile_SYSTEM )
170 OSL_TRACE("with osl_Profile_SYSTEM");
172 if ( Flags & osl_Profile_READLOCK )
174 OSL_TRACE("with osl_Profile_READLOCK");
176 if ( Flags & osl_Profile_WRITELOCK )
178 OSL_TRACE("with osl_Profile_WRITELOCK");
180 if ( Flags & osl_Profile_FLUSHWRITE )
182 OSL_TRACE("with osl_Profile_FLUSHWRITE");
184 #endif
186 if ( ( pFile = openFileImpl(pszProfileName, Flags ) ) == NULL )
188 #ifdef TRACE_OSL_PROFILE
189 OSL_TRACE("Out osl_openProfile [not opened]");
190 #endif
191 return (NULL);
194 pProfile = (osl_TProfileImpl*)calloc(1, sizeof(osl_TProfileImpl));
196 if ( pProfile == 0 )
198 closeFileImpl(pFile, Flags);
199 return 0;
202 pProfile->m_Flags = Flags & FLG_USER;
204 if ( Flags & ( osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
206 pProfile->m_pFile = pFile;
209 pthread_mutex_init(&(pProfile->m_AccessLock),PTHREAD_MUTEXATTR_DEFAULT);
210 pProfile->m_bIsValid = true;
212 pProfile->m_Stamp = OslProfile_getFileStamp(pFile);
213 bRet=loadProfile(pFile, pProfile);
214 bRet &= realpath(pszProfileName, pProfile->m_FileName) != NULL;
215 OSL_ASSERT(bRet);
217 if (pProfile->m_pFile == NULL)
218 closeFileImpl(pFile,pProfile->m_Flags);
220 #ifdef TRACE_OSL_PROFILE
221 OSL_TRACE("Out osl_openProfile [ok]");
222 #endif
223 return (pProfile);
226 sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile)
228 osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
229 osl_TProfileImpl* pTmpProfile;
231 #ifdef TRACE_OSL_PROFILE
232 OSL_TRACE("In osl_closeProfile");
233 #endif
235 if ( Profile == 0 )
237 #ifdef TRACE_OSL_PROFILE
238 OSL_TRACE("Out osl_closeProfile [profile==0]");
239 #endif
240 return sal_False;
243 pthread_mutex_lock(&(pProfile->m_AccessLock));
245 if ( pProfile->m_bIsValid == false )
247 OSL_ASSERT(pProfile->m_bIsValid);
248 pthread_mutex_unlock(&(pProfile->m_AccessLock));
249 #ifdef TRACE_OSL_PROFILE
250 OSL_TRACE("Out osl_closeProfile [not valid]");
251 #endif
252 return sal_False;
255 pProfile->m_bIsValid = false;
257 if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) && ( pProfile->m_Flags & FLG_MODIFIED ) )
259 pTmpProfile = acquireProfile(Profile, true);
261 if ( pTmpProfile != 0 )
263 bool bRet = storeProfile(pTmpProfile, true);
264 OSL_ASSERT(bRet);
265 (void)bRet;
268 else
270 pTmpProfile = acquireProfile(Profile, false);
273 if ( pTmpProfile == 0 )
275 pthread_mutex_unlock(&(pProfile->m_AccessLock));
276 #ifdef TRACE_OSL_PROFILE
277 OSL_TRACE("Out osl_closeProfile [pProfile==0]");
278 #endif
279 return sal_False;
282 pProfile = pTmpProfile;
284 if (pProfile->m_pFile != NULL)
285 closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
287 pProfile->m_pFile = NULL;
288 pProfile->m_FileName[0] = '\0';
290 /* release whole profile data types memory */
291 if ( pProfile->m_NoLines > 0)
293 unsigned int idx=0;
294 if ( pProfile->m_Lines != 0 )
296 for ( idx = 0 ; idx < pProfile->m_NoLines ; ++idx)
298 if ( pProfile->m_Lines[idx] != 0 )
300 free(pProfile->m_Lines[idx]);
301 pProfile->m_Lines[idx]=0;
304 free(pProfile->m_Lines);
305 pProfile->m_Lines=0;
307 if ( pProfile->m_Sections != 0 )
309 /*osl_TProfileSection* pSections=pProfile->m_Sections;*/
310 for ( idx = 0 ; idx < pProfile->m_NoSections ; ++idx )
312 if ( pProfile->m_Sections[idx].m_Entries != 0 )
314 free(pProfile->m_Sections[idx].m_Entries);
315 pProfile->m_Sections[idx].m_Entries=0;
318 free(pProfile->m_Sections);
319 pProfile->m_Sections=0;
323 pthread_mutex_unlock(&(pProfile->m_AccessLock));
325 pthread_mutex_destroy(&(pProfile->m_AccessLock));
327 free(pProfile);
329 #ifdef TRACE_OSL_PROFILE
330 OSL_TRACE("Out osl_closeProfile [ok]");
331 #endif
332 return (sal_True);
335 sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile)
337 osl_TProfileImpl* pProfile = (osl_TProfileImpl*) Profile;
338 osl_TFile* pFile;
339 bool bRet = false;
341 #ifdef TRACE_OSL_PROFILE
342 OSL_TRACE("In osl_flushProfile()");
343 #endif
345 if ( pProfile == 0 )
347 #ifdef TRACE_OSL_PROFILE
348 OSL_TRACE("Out osl_flushProfile() [pProfile == 0]");
349 #endif
350 return sal_False;
353 pthread_mutex_lock(&(pProfile->m_AccessLock));
355 if ( pProfile->m_bIsValid == false )
357 OSL_ASSERT(pProfile->m_bIsValid);
358 pthread_mutex_unlock(&(pProfile->m_AccessLock));
359 #ifdef TRACE_OSL_PROFILE
360 OSL_TRACE("Out osl_flushProfile [not valid]");
361 #endif
362 return sal_False;
365 pFile = pProfile->m_pFile;
366 if ( !( pFile != 0 && pFile->m_Handle >= 0 ) )
368 pthread_mutex_unlock(&(pProfile->m_AccessLock));
369 #ifdef TRACE_OSL_PROFILE
370 OSL_TRACE("Out osl_flushProfile() [invalid file]");
371 #endif
372 return sal_False;
375 if ( pProfile->m_Flags & FLG_MODIFIED )
377 #ifdef DEBUG_OSL_PROFILE
378 OSL_TRACE("swapping to storeprofile");
379 #endif
380 bRet = storeProfile(pProfile, false);
381 OSL_ASSERT(bRet);
384 #ifdef TRACE_OSL_PROFILE
385 OSL_TRACE("Out osl_flushProfile() [ok]");
386 #endif
387 pthread_mutex_unlock(&(pProfile->m_AccessLock));
388 return bRet;
391 static bool writeProfileImpl(osl_TFile* pFile)
393 #if OSL_DEBUG_LEVEL > 1
394 unsigned int nLen=0;
395 #endif
397 #ifdef TRACE_OSL_PROFILE
398 OSL_TRACE("In osl_writeProfileImpl()");
399 #endif
401 if ( !( pFile != 0 && pFile->m_Handle >= 0 ) || ( pFile->m_pWriteBuf == 0 ) )
403 #ifdef TRACE_OSL_PROFILE
404 OSL_TRACE("Out osl_writeProfileImpl() [invalid args]");
405 #endif
406 return false;
409 #if OSL_DEBUG_LEVEL > 1
410 nLen=strlen(pFile->m_pWriteBuf);
411 OSL_ASSERT(nLen == (pFile->m_nWriteBufLen - pFile->m_nWriteBufFree));
412 #endif
414 if ( !safeWrite(pFile->m_Handle, pFile->m_pWriteBuf, pFile->m_nWriteBufLen - pFile->m_nWriteBufFree) )
416 OSL_TRACE("write failed '%s'",strerror(errno));
417 return false;
420 free(pFile->m_pWriteBuf);
421 pFile->m_pWriteBuf=0;
422 pFile->m_nWriteBufLen=0;
423 pFile->m_nWriteBufFree=0;
424 #ifdef TRACE_OSL_PROFILE
425 OSL_TRACE("Out osl_writeProfileImpl() [ok]");
426 #endif
427 return true;
430 sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile,
431 const sal_Char* pszSection,
432 const sal_Char* pszEntry,
433 sal_Char* pszString,
434 sal_uInt32 MaxLen,
435 const sal_Char* pszDefault)
437 sal_uInt32 NoEntry;
438 sal_Char* pStr=0;
439 osl_TProfileSection* pSec;
440 osl_TProfileImpl* pProfile=0;
441 osl_TProfileImpl* pTmpProfile=0;
442 bool bRet = false;
444 #ifdef TRACE_OSL_PROFILE
445 OSL_TRACE("In osl_readProfileString");
446 #endif
448 pTmpProfile = (osl_TProfileImpl*) Profile;
450 if ( pTmpProfile == 0 )
452 #ifdef TRACE_OSL_PROFILE
453 OSL_TRACE("Out osl_readProfileString [pTmpProfile==0]");
454 #endif
455 return sal_False;
458 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
460 if ( pTmpProfile->m_bIsValid == false )
462 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
463 #ifdef TRACE_OSL_PROFILE
464 OSL_TRACE("Out osl_readProfileString [not valid]");
465 #endif
466 return sal_False;
469 pProfile = acquireProfile(Profile, false);
471 if ( pProfile == NULL )
473 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
474 #ifdef TRACE_OSL_PROFILE
475 OSL_TRACE("Out osl_readProfileString [pProfile==0]");
476 #endif
477 return (sal_False);
480 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
482 if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
483 (NoEntry < pSec->m_NoEntries) &&
484 ((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line],
485 '=')) != NULL))
487 pStr++;
489 else
491 pStr=(sal_Char*)pszDefault;
494 if ( pStr != 0 )
496 pStr = stripBlanks(pStr, NULL);
497 MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr);
498 pStr = stripBlanks(pStr, &MaxLen);
499 strncpy(pszString, pStr, MaxLen);
500 pszString[MaxLen] = '\0';
503 else
504 { /* not implemented */ }
506 bRet=releaseProfile(pProfile);
507 OSL_ASSERT(bRet);
508 (void)bRet;
510 if ( pStr == 0 )
512 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
513 #ifdef TRACE_OSL_PROFILE
514 OSL_TRACE("Out osl_readProfileString [pStr==0]");
515 #endif
516 return sal_False;
519 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
521 #ifdef TRACE_OSL_PROFILE
522 OSL_TRACE("Out osl_readProfileString [ok]");
523 #endif
525 return (sal_True);
528 sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile,
529 const sal_Char* pszSection,
530 const sal_Char* pszEntry,
531 sal_Bool Default)
533 sal_Char Line[32];
534 Line[0] = '\0';
536 #ifdef TRACE_OSL_PROFILE
537 OSL_TRACE("In osl_readProfileBool");
538 #endif
540 if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
542 if ((strcasecmp(Line, STR_INI_BOOLYES) == 0) ||
543 (strcasecmp(Line, STR_INI_BOOLON) == 0) ||
544 (strcasecmp(Line, STR_INI_BOOLONE) == 0))
545 Default = sal_True;
546 else
547 if ((strcasecmp(Line, STR_INI_BOOLNO) == 0) ||
548 (strcasecmp(Line, STR_INI_BOOLOFF) == 0) ||
549 (strcasecmp(Line, STR_INI_BOOLZERO) == 0))
550 Default = sal_False;
553 #ifdef TRACE_OSL_PROFILE
554 OSL_TRACE("Out osl_readProfileBool [ok]");
555 #endif
557 return (Default);
560 sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile,
561 const sal_Char* pszSection,
562 const sal_Char* pszEntry,
563 sal_uInt32 FirstId,
564 const sal_Char* Strings[],
565 sal_uInt32 Default)
567 sal_uInt32 i;
568 sal_Char Line[256];
569 Line[0] = '\0';
571 #ifdef TRACE_OSL_PROFILE
572 OSL_TRACE("In osl_readProfileIdent");
573 #endif
575 if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
577 i = 0;
578 while (Strings[i] != NULL)
580 if (strcasecmp(Line, Strings[i]) == 0)
582 Default = i + FirstId;
583 break;
585 i++;
589 #ifdef TRACE_OSL_PROFILE
590 OSL_TRACE("Out osl_readProfileIdent [ok]");
591 #endif
592 return (Default);
595 sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile,
596 const sal_Char* pszSection,
597 const sal_Char* pszEntry,
598 const sal_Char* pszString)
600 sal_uInt32 i;
601 bool bRet = false;
602 sal_uInt32 NoEntry;
603 sal_Char* pStr;
604 sal_Char* Line = 0;
605 osl_TProfileSection* pSec;
606 osl_TProfileImpl* pProfile = 0;
607 osl_TProfileImpl* pTmpProfile = 0;
609 #ifdef TRACE_OSL_PROFILE
610 OSL_TRACE("In osl_writeProfileString");
611 #endif
613 pTmpProfile = (osl_TProfileImpl*) Profile;
615 if ( pTmpProfile == 0 )
617 #ifdef TRACE_OSL_PROFILE
618 OSL_TRACE("Out osl_writeProfileString [pTmpProfile==0]");
619 #endif
620 return sal_False;
623 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
625 if ( pTmpProfile->m_bIsValid == false )
627 OSL_ASSERT(pTmpProfile->m_bIsValid);
628 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
629 #ifdef TRACE_OSL_PROFILE
630 OSL_TRACE("Out osl_writeProfileString [not valid]");
631 #endif
632 return sal_False;
635 pProfile=acquireProfile(Profile, true);
637 if (pProfile == NULL)
639 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
640 #ifdef TRACE_OSL_PROFILE
641 OSL_TRACE("Out osl_writeProfileString [pProfile==0]");
642 #endif
643 return (sal_False);
646 Line = (sal_Char*) malloc(strlen(pszEntry)+strlen(pszString)+48);
648 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
650 if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == NULL)
652 Line[0] = '\0';
653 addLine(pProfile, Line);
655 Line[0] = '[';
656 strcpy(&Line[1], pszSection);
657 Line[1 + strlen(pszSection)] = ']';
658 Line[2 + strlen(pszSection)] = '\0';
660 if (((pStr = addLine(pProfile, Line)) == NULL) ||
661 (! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection))))
663 bRet=releaseProfile(pProfile);
664 OSL_ASSERT(bRet);
666 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
668 free(Line);
670 #ifdef TRACE_OSL_PROFILE
671 OSL_TRACE("Out osl_writeProfileString [not added]");
672 #endif
673 return (sal_False);
676 pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1];
677 NoEntry = pSec->m_NoEntries;
680 Line[0] = '\0';
681 strcpy(&Line[0], pszEntry);
682 Line[0 + strlen(pszEntry)] = '=';
683 strcpy(&Line[1 + strlen(pszEntry)], pszString);
685 if (NoEntry >= pSec->m_NoEntries)
687 if (pSec->m_NoEntries > 0)
688 i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1;
689 else
690 i = pSec->m_Line + 1;
692 if (((pStr = insertLine(pProfile, Line, i)) == NULL) ||
693 (! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry))))
695 bRet=releaseProfile(pProfile);
696 OSL_ASSERT(bRet);
698 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
699 free(Line);
701 #ifdef TRACE_OSL_PROFILE
702 OSL_TRACE("Out osl_writeProfileString [not inserted]");
703 #endif
704 return (sal_False);
707 pProfile->m_Flags |= FLG_MODIFIED;
709 else
711 i = pSec->m_Entries[NoEntry].m_Line;
712 free(pProfile->m_Lines[i]);
713 pProfile->m_Lines[i] = strdup(Line);
714 setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry));
716 pProfile->m_Flags |= FLG_MODIFIED;
719 else {
720 /* not implemented */
723 bRet = releaseProfile(pProfile);
724 OSL_ASSERT(bRet);
726 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
727 if ( Line!= 0 )
729 free(Line);
732 #ifdef TRACE_OSL_PROFILE
733 OSL_TRACE("Out osl_writeProfileString [ok]");
734 #endif
736 return bRet;
739 sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile,
740 const sal_Char* pszSection,
741 const sal_Char* pszEntry,
742 sal_Bool Value)
744 bool bRet = false;
746 #ifdef TRACE_OSL_PROFILE
747 OSL_TRACE("In osl_writeProfileBool");
748 #endif
750 if (Value)
751 bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE);
752 else
753 bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO);
755 #ifdef TRACE_OSL_PROFILE
756 OSL_TRACE("Out osl_writeProfileBool [ok]");
757 #endif
759 return bRet;
762 sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile,
763 const sal_Char* pszSection,
764 const sal_Char* pszEntry,
765 sal_uInt32 FirstId,
766 const sal_Char* Strings[],
767 sal_uInt32 Value)
769 int i, n = 0;
770 bool bRet = false;
772 #ifdef TRACE_OSL_PROFILE
773 OSL_TRACE("In osl_writeProfileIdent");
774 #endif
776 while (Strings[n] != NULL)
777 ++n;
779 if ((i = Value - FirstId) >= n)
780 bRet = false;
781 else
782 bRet = osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]);
784 #ifdef TRACE_OSL_PROFILE
785 OSL_TRACE("Out osl_writeProfileIdent");
786 #endif
787 return bRet;
790 sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile,
791 const sal_Char *pszSection,
792 const sal_Char *pszEntry)
794 sal_uInt32 NoEntry;
795 osl_TProfileSection* pSec;
796 osl_TProfileImpl* pProfile = 0;
797 osl_TProfileImpl* pTmpProfile = 0;
798 bool bRet = false;
800 #ifdef TRACE_OSL_PROFILE
801 OSL_TRACE("In osl_removeProfileEntry");
802 #endif
804 pTmpProfile = (osl_TProfileImpl*) Profile;
806 if ( pTmpProfile == 0 )
808 #ifdef TRACE_OSL_PROFILE
809 OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]");
810 #endif
811 return sal_False;
814 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
816 if ( pTmpProfile->m_bIsValid == false )
818 OSL_ASSERT(pTmpProfile->m_bIsValid);
819 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
820 #ifdef TRACE_OSL_PROFILE
821 OSL_TRACE("Out osl_removeProfileEntry [not valid]");
822 #endif
823 return sal_False;
826 pProfile = acquireProfile(Profile, true);
828 if (pProfile == NULL)
830 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
831 #ifdef TRACE_OSL_PROFILE
832 OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]");
833 #endif
834 return (sal_False);
837 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
839 if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
840 (NoEntry < pSec->m_NoEntries))
842 removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line);
843 removeEntry(pSec, NoEntry);
844 if (pSec->m_NoEntries == 0)
846 removeLine(pProfile, pSec->m_Line);
848 /* remove any empty separation line */
849 if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0'))
850 removeLine(pProfile, pSec->m_Line - 1);
852 removeSection(pProfile, pSec);
855 pProfile->m_Flags |= FLG_MODIFIED;
858 else
859 { /* not implemented */ }
861 bRet = releaseProfile(pProfile);
862 OSL_ASSERT(bRet);
864 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
866 #ifdef TRACE_OSL_PROFILE
867 OSL_TRACE("Out osl_removeProfileEntry [ok]");
868 #endif
869 return bRet;
872 sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile,
873 const sal_Char *pszSection,
874 sal_Char* pszBuffer,
875 sal_uInt32 MaxLen)
877 sal_uInt32 i, n = 0;
878 sal_uInt32 NoEntry;
879 osl_TProfileSection* pSec;
880 osl_TProfileImpl* pProfile = 0;
881 osl_TProfileImpl* pTmpProfile = 0;
882 bool bRet = false;
884 #ifdef TRACE_OSL_PROFILE
885 OSL_TRACE("In osl_getProfileSectionEntries");
886 #endif
888 pTmpProfile = (osl_TProfileImpl*) Profile;
890 if ( pTmpProfile == 0 )
892 #ifdef TRACE_OSL_PROFILE
893 OSL_TRACE("Out osl_getProfileSectionEntries [pTmpProfile==0]");
894 #endif
895 return sal_False;
899 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
901 if ( pTmpProfile->m_bIsValid == false )
903 OSL_ASSERT(pTmpProfile->m_bIsValid);
905 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
907 #ifdef TRACE_OSL_PROFILE
908 OSL_TRACE("Out osl_getProfileSectionEntries [not valid]");
909 #endif
911 return sal_False;
914 pProfile = acquireProfile(Profile, false);
916 if (pProfile == NULL)
918 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
920 #ifdef TRACE_OSL_PROFILE
921 OSL_TRACE("Out osl_getProfileSectionEntries [pProfile=0]");
922 #endif
924 return (0);
927 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
929 if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != NULL)
931 if (MaxLen != 0)
933 for (i = 0; i < pSec->m_NoEntries; i++)
935 if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen)
937 strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
938 [pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len);
939 n += pSec->m_Entries[i].m_Len;
940 pszBuffer[n++] = '\0';
942 else
943 break;
947 pszBuffer[n++] = '\0';
949 else
951 for (i = 0; i < pSec->m_NoEntries; i++)
952 n += pSec->m_Entries[i].m_Len + 1;
954 n += 1;
957 else
958 n = 0;
960 else {
961 /* not implemented */
964 bRet=releaseProfile(pProfile);
965 OSL_ASSERT(bRet);
966 (void)bRet;
968 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
970 #ifdef TRACE_OSL_PROFILE
971 OSL_TRACE("Out osl_getProfileSectionEntries [ok]");
972 #endif
974 return (n);
977 sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile,
978 sal_Char* pszBuffer,
979 sal_uInt32 MaxLen)
981 sal_uInt32 i, n = 0;
982 osl_TProfileSection* pSec;
983 osl_TProfileImpl* pProfile = 0;
984 osl_TProfileImpl* pTmpProfile = 0;
985 bool bRet = false;
987 #ifdef TRACE_OSL_PROFILE
988 OSL_TRACE("In osl_getProfileSections");
989 #endif
991 pTmpProfile = (osl_TProfileImpl*) Profile;
993 if ( pTmpProfile == 0 )
995 #ifdef TRACE_OSL_PROFILE
996 OSL_TRACE("Out osl_getProfileSections [pTmpProfile==0]");
997 #endif
998 return sal_False;
1001 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
1003 if ( pTmpProfile->m_bIsValid == false )
1005 OSL_ASSERT(pTmpProfile->m_bIsValid);
1006 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
1007 #ifdef TRACE_OSL_PROFILE
1008 OSL_TRACE("Out osl_getProfileSections [not valid]");
1009 #endif
1010 return sal_False;
1013 pProfile = acquireProfile(Profile, false);
1015 if (pProfile == NULL)
1017 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
1019 #ifdef TRACE_OSL_PROFILE
1020 OSL_TRACE("Out osl_getProfileSections [pProfile==0]");
1021 #endif
1022 return (0);
1025 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
1027 if (MaxLen != 0)
1029 for (i = 0; i < pProfile->m_NoSections; i++)
1031 pSec = &pProfile->m_Sections[i];
1033 if ((n + pSec->m_Len + 1) < MaxLen)
1035 strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset],
1036 pSec->m_Len);
1037 n += pSec->m_Len;
1038 pszBuffer[n++] = '\0';
1040 else
1041 break;
1044 pszBuffer[n++] = '\0';
1046 else
1048 for (i = 0; i < pProfile->m_NoSections; i++)
1049 n += pProfile->m_Sections[i].m_Len + 1;
1051 n += 1;
1054 else
1055 { /* not implemented */ }
1057 bRet=releaseProfile(pProfile);
1058 OSL_ASSERT(bRet);
1059 (void)bRet;
1061 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
1063 #ifdef TRACE_OSL_PROFILE
1064 OSL_TRACE("Out osl_getProfileSections [ok]");
1065 #endif
1067 return (n);
1070 static osl_TStamp OslProfile_getFileStamp(osl_TFile* pFile)
1072 struct stat status;
1074 if ( (pFile->m_Handle < 0) || (fstat(pFile->m_Handle, &status) < 0) )
1076 return (0);
1079 return (status.st_mtime);
1082 static bool OslProfile_lockFile(const osl_TFile* pFile, osl_TLockMode eMode)
1084 struct flock lock;
1085 /* boring hack, but initializers for static vars must be constant */
1086 static bool bIsInitialized = false;
1087 static bool bLockingDisabled;
1089 #ifdef TRACE_OSL_PROFILE
1090 OSL_TRACE("In OslProfile_lockFile");
1091 #endif
1093 if ( !bIsInitialized )
1095 sal_Char* pEnvValue;
1096 pEnvValue = getenv( "STAR_PROFILE_LOCKING_DISABLED" );
1098 if ( pEnvValue == 0 )
1100 bLockingDisabled = false;
1103 else
1105 bLockingDisabled = true;
1108 bIsInitialized = true;
1111 if (pFile->m_Handle < 0)
1113 #ifdef TRACE_OSL_PROFILE
1114 OSL_TRACE("Out OslProfile_lockFile [invalid file handle]");
1115 #endif
1116 return false;
1119 if ( bLockingDisabled )
1121 #ifdef TRACE_OSL_PROFILE
1122 OSL_TRACE("Out OslProfile_lockFile [locking disabled]");
1123 #endif
1124 return true;
1127 lock.l_start = 0;
1128 lock.l_whence = SEEK_SET;
1129 lock.l_len = 0;
1131 switch (eMode)
1133 case un_lock:
1134 lock.l_type = F_UNLCK;
1135 break;
1137 case read_lock:
1138 lock.l_type = F_RDLCK;
1139 break;
1141 case write_lock:
1142 lock.l_type = F_WRLCK;
1143 break;
1146 #ifndef MACOSX
1147 if ( fcntl(pFile->m_Handle, F_SETLKW, &lock) == -1 )
1148 #else
1149 /* Mac OSX will return ENOTSUP for webdav drives so we should ignore it */
1150 if ( fcntl(pFile->m_Handle, F_SETLKW, &lock) == -1 && errno != ENOTSUP )
1151 #endif
1153 OSL_TRACE("fcntl returned -1 (%s)",strerror(errno));
1154 #ifdef TRACE_OSL_PROFILE
1155 OSL_TRACE("Out OslProfile_lockFile [fcntl F_SETLKW]");
1156 #endif
1157 return false;
1160 #ifdef TRACE_OSL_PROFILE
1161 OSL_TRACE("Out OslProfile_lockFile [ok]");
1162 #endif
1163 return true;
1166 static osl_TFile* openFileImpl(const sal_Char* pszFilename, oslProfileOption ProfileFlags )
1168 int Flags;
1169 osl_TFile* pFile = (osl_TFile*) calloc(1, sizeof(osl_TFile));
1170 bool bWriteable = false;
1172 if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
1174 #ifdef DEBUG_OSL_PROFILE
1175 OSL_TRACE("setting bWriteable to TRUE");
1176 #endif
1177 bWriteable = true;
1180 if (! bWriteable)
1182 #ifdef DEBUG_OSL_PROFILE
1183 OSL_TRACE("opening '%s' read only",pszFilename);
1184 #endif
1186 pFile->m_Handle = open(pszFilename, O_RDONLY);
1187 /* mfe: argghh!!! do not check if the file could be openend */
1188 /* default mode expects it that way!!! */
1190 else
1192 #ifdef DEBUG_OSL_PROFILE
1193 OSL_TRACE("opening '%s' read/write",pszFilename);
1194 #endif
1195 if (((pFile->m_Handle = open(pszFilename, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PMODE)) < 0) &&
1196 ((pFile->m_Handle = open(pszFilename, O_RDWR)) < 0))
1198 free(pFile);
1199 #ifdef TRACE_OSL_PROFILE
1200 OSL_TRACE("Out openFileImpl [open read/write]");
1201 #endif
1202 return (NULL);
1206 /* set close-on-exec flag */
1207 if ((Flags = fcntl(pFile->m_Handle, F_GETFD, 0)) != -1)
1209 Flags |= FD_CLOEXEC;
1210 int e = fcntl(pFile->m_Handle, F_SETFD, Flags);
1211 SAL_INFO_IF(
1212 e != 0, "sal.osl",
1213 "fcntl to set FD_CLOEXEC failed for " << pszFilename);
1216 pFile->m_pWriteBuf=0;
1217 pFile->m_nWriteBufFree=0;
1218 pFile->m_nWriteBufLen=0;
1220 if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
1222 #ifdef DEBUG_OSL_PROFILE
1223 OSL_TRACE("locking '%s' file",pszFilename);
1224 #endif
1225 OslProfile_lockFile(pFile, bWriteable ? write_lock : read_lock);
1228 #ifdef TRACE_OSL_PROFILE
1229 OSL_TRACE("Out openFileImpl [ok]");
1230 #endif
1231 return (pFile);
1234 static osl_TStamp closeFileImpl(osl_TFile* pFile, oslProfileOption Flags)
1236 osl_TStamp stamp = 0;
1238 #ifdef TRACE_OSL_PROFILE
1239 OSL_TRACE("In closeFileImpl");
1240 #endif
1242 if ( pFile == 0 )
1244 #ifdef TRACE_OSL_PROFILE
1245 OSL_TRACE("Out closeFileImpl [pFile == 0]");
1246 #endif
1247 return stamp;
1250 if ( pFile->m_Handle >= 0 )
1252 stamp = OslProfile_getFileStamp(pFile);
1254 if ( Flags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
1256 OslProfile_lockFile(pFile, un_lock);
1259 close(pFile->m_Handle);
1260 pFile->m_Handle = -1;
1263 if ( pFile->m_pWriteBuf )
1265 free(pFile->m_pWriteBuf);
1268 free(pFile);
1270 #ifdef TRACE_OSL_PROFILE
1271 OSL_TRACE("Out closeFileImpl [ok]");
1272 #endif
1274 return(stamp);
1277 static bool OslProfile_rewindFile(osl_TFile* pFile, bool bTruncate)
1279 bool bRet = true;
1280 #ifdef TRACE_OSL_PROFILE
1281 OSL_TRACE("In osl_OslProfile_rewindFile");
1282 #endif
1284 if (pFile->m_Handle >= 0)
1286 pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1288 #ifdef DEBUG_OSL_PROFILE
1289 OSL_TRACE("rewinding");
1290 #endif
1291 bRet = (lseek(pFile->m_Handle, SEEK_SET, 0L) == 0L);
1293 if (bTruncate)
1295 #ifdef DEBUG_OSL_PROFILE
1296 OSL_TRACE("truncating");
1297 #endif
1298 bRet &= (ftruncate(pFile->m_Handle, 0L) == 0);
1303 #ifdef TRACE_OSL_PROFILE
1304 OSL_TRACE("Out osl_OslProfile_rewindFile [ok]");
1305 #endif
1306 return bRet;
1309 static sal_Char* OslProfile_getLine(osl_TFile* pFile)
1311 int Max, Free, Bytes, nLineBytes = 0;
1312 sal_Char* pChr;
1313 sal_Char* pLine = NULL;
1314 sal_Char* pNewLine;
1316 if ( pFile == 0 )
1318 return 0;
1321 if (pFile->m_Handle < 0)
1322 return NULL;
1326 Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf);
1328 if (Bytes <= 1)
1330 /* refill buffer */
1331 memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes);
1332 pFile->m_pReadPtr = pFile->m_ReadBuf;
1334 Free = sizeof(pFile->m_ReadBuf) - Bytes;
1336 if ((Max = read(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free)) < 0)
1338 OSL_TRACE("read failed '%s'",strerror(errno));
1340 if( pLine )
1341 rtl_freeMemory( pLine );
1342 pLine = NULL;
1343 break;
1346 if (Max < Free)
1348 if ((Max == 0) && ! pLine)
1349 break;
1351 pFile->m_ReadBuf[Bytes + Max] = '\0';
1355 for (pChr = pFile->m_pReadPtr;
1356 (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') &&
1357 (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1));
1358 pChr++);
1360 Max = pChr - pFile->m_pReadPtr;
1361 pNewLine = (sal_Char*) rtl_allocateMemory( nLineBytes + Max + 1 );
1362 if( pLine )
1364 memcpy( pNewLine, pLine, nLineBytes );
1365 rtl_freeMemory( pLine );
1367 memcpy(pNewLine+nLineBytes, pFile->m_pReadPtr, Max);
1368 nLineBytes += Max;
1369 pNewLine[ nLineBytes ] = 0;
1370 pLine = pNewLine;
1372 if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1))
1374 if (*pChr != '\0')
1376 if ((pChr[0] == '\r') && (pChr[1] == '\n'))
1377 pChr += 2;
1378 else
1379 pChr += 1;
1382 if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) &&
1383 (*pChr == '\0'))
1384 pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1386 /* setting Max to -1 indicates terminating read loop */
1387 Max = -1;
1390 pFile->m_pReadPtr = pChr;
1392 while (Max > 0);
1394 return pLine;
1397 static bool OslProfile_putLine(osl_TFile* pFile, const sal_Char *pszLine)
1399 unsigned int Len = strlen(pszLine);
1401 #ifdef DEBUG_OSL_PROFILE
1402 int strLen=0;
1403 #endif
1405 if ( pFile == 0 || pFile->m_Handle < 0 )
1407 return false;
1410 if ( pFile->m_pWriteBuf == 0 )
1412 pFile->m_pWriteBuf = (sal_Char*) malloc(Len+3);
1413 pFile->m_nWriteBufLen = Len+3;
1414 pFile->m_nWriteBufFree = Len+3;
1416 else
1418 if ( pFile->m_nWriteBufFree <= Len + 3 )
1420 sal_Char* pTmp;
1422 pTmp=(sal_Char*) realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) );
1423 if ( pTmp == 0 )
1425 return false;
1427 pFile->m_pWriteBuf = pTmp;
1428 pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len );
1429 pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2;
1430 memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree);
1434 memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1);
1435 #ifdef DEBUG_OSL_PROFILE
1436 strLen = strlen(pFile->m_pWriteBuf);
1437 #endif
1438 pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\n';
1439 pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\0';
1441 pFile->m_nWriteBufFree-=Len+1;
1443 return true;
1446 static sal_Char* stripBlanks(sal_Char* String, sal_uInt32* pLen)
1448 if ( ( pLen != NULL ) && ( *pLen != 0 ) )
1450 while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t'))
1451 (*pLen)--;
1453 while ( (*String == ' ') || (*String == '\t') )
1455 String++;
1456 (*pLen)--;
1459 else
1460 while ( (*String == ' ') || (*String == '\t') )
1461 String++;
1463 return (String);
1466 static sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line)
1468 if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1470 if (pProfile->m_Lines == NULL)
1472 pProfile->m_MaxLines = LINES_INI;
1473 pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
1474 memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
1476 else
1478 unsigned int idx=0;
1479 unsigned int oldmax=pProfile->m_MaxLines;
1481 pProfile->m_MaxLines += LINES_ADD;
1482 pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
1483 pProfile->m_MaxLines * sizeof(sal_Char *));
1484 for ( idx = oldmax ; idx < pProfile->m_MaxLines ; ++idx )
1486 pProfile->m_Lines[idx]=0;
1490 if (pProfile->m_Lines == NULL)
1492 pProfile->m_NoLines = 0;
1493 pProfile->m_MaxLines = 0;
1494 return (NULL);
1497 if ( pProfile->m_Lines[pProfile->m_NoLines] != 0 )
1499 free(pProfile->m_Lines[pProfile->m_NoLines]);
1501 pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line);
1503 return (pProfile->m_Lines[pProfile->m_NoLines - 1]);
1506 static sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo)
1508 if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1510 if (pProfile->m_Lines == NULL)
1512 pProfile->m_MaxLines = LINES_INI;
1513 pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
1514 memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
1516 else
1518 pProfile->m_MaxLines += LINES_ADD;
1519 pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
1520 pProfile->m_MaxLines * sizeof(sal_Char *));
1522 memset(&pProfile->m_Lines[pProfile->m_NoLines],
1524 (pProfile->m_MaxLines - pProfile->m_NoLines - 1) * sizeof(sal_Char*));
1527 if (pProfile->m_Lines == NULL)
1529 pProfile->m_NoLines = 0;
1530 pProfile->m_MaxLines = 0;
1531 return (NULL);
1535 LineNo = LineNo > pProfile->m_NoLines ? pProfile->m_NoLines : LineNo;
1537 if (LineNo < pProfile->m_NoLines)
1539 sal_uInt32 i, n;
1540 osl_TProfileSection* pSec;
1542 memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo],
1543 (pProfile->m_NoLines - LineNo) * sizeof(sal_Char *));
1545 /* adjust line references */
1546 for (i = 0; i < pProfile->m_NoSections; i++)
1548 pSec = &pProfile->m_Sections[i];
1550 if (pSec->m_Line >= LineNo)
1551 pSec->m_Line++;
1553 for (n = 0; n < pSec->m_NoEntries; n++)
1554 if (pSec->m_Entries[n].m_Line >= LineNo)
1555 pSec->m_Entries[n].m_Line++;
1559 pProfile->m_NoLines++;
1561 pProfile->m_Lines[LineNo] = strdup(Line);
1563 return (pProfile->m_Lines[LineNo]);
1566 static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo)
1568 if (LineNo < pProfile->m_NoLines)
1570 free(pProfile->m_Lines[LineNo]);
1571 pProfile->m_Lines[LineNo]=0;
1572 if (pProfile->m_NoLines - LineNo > 1)
1574 sal_uInt32 i, n;
1575 osl_TProfileSection* pSec;
1577 memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1],
1578 (pProfile->m_NoLines - LineNo - 1) * sizeof(sal_Char *));
1580 memset(&pProfile->m_Lines[pProfile->m_NoLines - 1],
1582 (pProfile->m_MaxLines - pProfile->m_NoLines) * sizeof(sal_Char*));
1584 /* adjust line references */
1585 for (i = 0; i < pProfile->m_NoSections; i++)
1587 pSec = &pProfile->m_Sections[i];
1589 if (pSec->m_Line > LineNo)
1590 pSec->m_Line--;
1592 for (n = 0; n < pSec->m_NoEntries; n++)
1593 if (pSec->m_Entries[n].m_Line > LineNo)
1594 pSec->m_Entries[n].m_Line--;
1597 else
1599 pProfile->m_Lines[LineNo] = 0;
1602 pProfile->m_NoLines--;
1605 return;
1608 static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
1609 sal_uInt32 NoEntry, sal_uInt32 Line,
1610 sal_Char* Entry, sal_uInt32 Len)
1612 Entry = stripBlanks(Entry, &Len);
1613 pSection->m_Entries[NoEntry].m_Line = Line;
1614 pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line];
1615 pSection->m_Entries[NoEntry].m_Len = Len;
1617 return;
1620 static bool addEntry(osl_TProfileImpl* pProfile,
1621 osl_TProfileSection *pSection,
1622 int Line, sal_Char* Entry,
1623 sal_uInt32 Len)
1625 if (pSection != NULL)
1627 if (pSection->m_NoEntries >= pSection->m_MaxEntries)
1629 if (pSection->m_Entries == NULL)
1631 pSection->m_MaxEntries = ENTRIES_INI;
1632 pSection->m_Entries = (osl_TProfileEntry *)malloc(
1633 pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
1635 else
1637 pSection->m_MaxEntries += ENTRIES_ADD;
1638 pSection->m_Entries = (osl_TProfileEntry *)realloc(pSection->m_Entries,
1639 pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
1642 if (pSection->m_Entries == NULL)
1644 pSection->m_NoEntries = 0;
1645 pSection->m_MaxEntries = 0;
1646 return false;
1650 pSection->m_NoEntries++;
1652 Entry = stripBlanks(Entry, &Len);
1653 setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line,
1654 Entry, Len);
1656 return true;
1659 return false;
1662 static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry)
1664 if (NoEntry < pSection->m_NoEntries)
1666 if (pSection->m_NoEntries - NoEntry > 1)
1668 memmove(&pSection->m_Entries[NoEntry],
1669 &pSection->m_Entries[NoEntry + 1],
1670 (pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry));
1671 pSection->m_Entries[pSection->m_NoEntries - 1].m_Line=0;
1672 pSection->m_Entries[pSection->m_NoEntries - 1].m_Offset=0;
1673 pSection->m_Entries[pSection->m_NoEntries - 1].m_Len=0;
1676 pSection->m_NoEntries--;
1679 return;
1682 static bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len)
1684 if (pProfile->m_NoSections >= pProfile->m_MaxSections)
1686 if (pProfile->m_Sections == NULL)
1688 pProfile->m_MaxSections = SECTIONS_INI;
1689 pProfile->m_Sections = (osl_TProfileSection *)malloc(pProfile->m_MaxSections * sizeof(osl_TProfileSection));
1690 memset(pProfile->m_Sections,0,pProfile->m_MaxSections * sizeof(osl_TProfileSection));
1692 else
1694 unsigned int idx=0;
1695 unsigned int oldmax=pProfile->m_MaxSections;
1697 pProfile->m_MaxSections += SECTIONS_ADD;
1698 pProfile->m_Sections = (osl_TProfileSection *)realloc(pProfile->m_Sections,
1699 pProfile->m_MaxSections * sizeof(osl_TProfileSection));
1700 for ( idx = oldmax ; idx < pProfile->m_MaxSections ; ++idx )
1702 pProfile->m_Sections[idx].m_Entries=0;
1706 if (pProfile->m_Sections == NULL)
1708 pProfile->m_NoSections = 0;
1709 pProfile->m_MaxSections = 0;
1710 return false;
1714 pProfile->m_NoSections++;
1716 if ( pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries != 0 )
1718 free(pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries);
1720 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = NULL;
1721 pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries = 0;
1722 pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0;
1724 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line;
1725 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line];
1726 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len;
1728 return true;
1731 static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection)
1733 sal_uInt32 Section;
1735 if ((Section = pSection - pProfile->m_Sections) < pProfile->m_NoSections)
1737 free (pSection->m_Entries);
1738 pSection->m_Entries=0;
1739 if (pProfile->m_NoSections - Section > 1)
1741 memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1],
1742 (pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection));
1744 memset(&pProfile->m_Sections[pProfile->m_NoSections - 1],
1746 (pProfile->m_MaxSections - pProfile->m_NoSections) * sizeof(osl_TProfileSection));
1747 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = 0;
1749 else
1751 pSection->m_Entries = 0;
1754 pProfile->m_NoSections--;
1757 return;
1760 static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile,
1761 const sal_Char* Section,
1762 const sal_Char* Entry,
1763 sal_uInt32 *pNoEntry)
1765 static sal_uInt32 Sect = 0;
1766 sal_uInt32 i, n;
1767 sal_uInt32 Len;
1768 const sal_Char* pStr;
1769 osl_TProfileSection* pSec=0;
1771 Len = strlen(Section);
1773 n = Sect;
1775 for (i = 0; i < pProfile->m_NoSections; i++)
1777 n %= pProfile->m_NoSections;
1778 pSec = &pProfile->m_Sections[n];
1779 if ((Len == pSec->m_Len) &&
1780 (strncasecmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len)
1781 == 0))
1782 break;
1783 n++;
1786 Sect = n;
1788 if (i < pProfile->m_NoSections)
1790 Len = strlen(Entry);
1792 *pNoEntry = pSec->m_NoEntries;
1794 for (i = 0; i < pSec->m_NoEntries; i++)
1796 pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
1797 [pSec->m_Entries[i].m_Offset];
1798 if ((Len == pSec->m_Entries[i].m_Len) &&
1799 (strncasecmp(Entry, pStr, pSec->m_Entries[i].m_Len)
1800 == 0))
1802 *pNoEntry = i;
1803 break;
1807 else
1808 pSec = NULL;
1810 return (pSec);
1813 static bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile)
1815 sal_uInt32 i;
1816 sal_Char* pStr;
1817 sal_Char* pChar;
1819 sal_Char* pLine;
1820 sal_Char* bWasAdded = NULL;
1822 if ( !pFile )
1824 return false;
1827 if ( !pProfile )
1829 return false;
1832 pProfile->m_NoLines = 0;
1833 pProfile->m_NoSections = 0;
1835 OSL_VERIFY(OslProfile_rewindFile(pFile, false));
1837 while ( ( pLine=OslProfile_getLine(pFile) ) != 0 )
1839 bWasAdded = addLine( pProfile, pLine );
1840 rtl_freeMemory( pLine );
1841 OSL_ASSERT(bWasAdded);
1842 if ( ! bWasAdded )
1843 return false;
1846 for (i = 0; i < pProfile->m_NoLines; i++)
1848 pStr = (sal_Char *)stripBlanks(pProfile->m_Lines[i], NULL);
1850 if ((*pStr == '\0') || (*pStr == ';'))
1851 continue;
1853 if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == NULL) ||
1854 ((pChar - pStr) <= 2))
1856 /* insert entry */
1858 if (pProfile->m_NoSections < 1)
1859 continue;
1861 if ((pChar = strchr(pStr, '=')) == NULL)
1862 pChar = pStr + strlen(pStr);
1864 if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1],
1865 i, pStr, pChar - pStr))
1867 OSL_ASSERT(false);
1868 continue;
1872 else
1874 /* new section */
1876 if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1))
1878 OSL_ASSERT(false);
1879 continue;
1885 return true;
1888 static bool storeProfile(osl_TProfileImpl* pProfile, bool bCleanup)
1890 #ifdef TRACE_OSL_PROFILE
1891 OSL_TRACE("In storeProfile");
1892 #endif
1894 if (pProfile->m_Lines != NULL)
1896 if (pProfile->m_Flags & FLG_MODIFIED)
1898 sal_uInt32 i;
1900 osl_TFile* pTmpFile = osl_openTmpProfileImpl(pProfile);
1902 if ( pTmpFile == 0 )
1904 return false;
1907 OSL_VERIFY(OslProfile_rewindFile(pTmpFile, true));
1909 for ( i = 0 ; i < pProfile->m_NoLines ; i++ )
1911 OSL_VERIFY(OslProfile_putLine(pTmpFile, pProfile->m_Lines[i]));
1914 if ( ! writeProfileImpl(pTmpFile) )
1916 if ( pTmpFile->m_pWriteBuf != 0 )
1918 free(pTmpFile->m_pWriteBuf);
1921 pTmpFile->m_pWriteBuf=0;
1922 pTmpFile->m_nWriteBufLen=0;
1923 pTmpFile->m_nWriteBufFree=0;
1925 #ifdef TRACE_OSL_PROFILE
1926 OSL_TRACE("Out storeProfile [not flushed]");
1927 #endif
1928 closeFileImpl(pTmpFile,pProfile->m_Flags);
1930 return false;
1933 pProfile->m_Flags &= ~FLG_MODIFIED;
1935 closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
1936 closeFileImpl(pTmpFile,pProfile->m_Flags);
1938 osl_ProfileSwapProfileNames(pProfile);
1940 pProfile->m_pFile = openFileImpl(pProfile->m_FileName,pProfile->m_Flags);
1944 if (bCleanup)
1946 while (pProfile->m_NoLines > 0)
1947 removeLine(pProfile, pProfile->m_NoLines - 1);
1949 free(pProfile->m_Lines);
1950 pProfile->m_Lines = NULL;
1951 pProfile->m_NoLines = 0;
1952 pProfile->m_MaxLines = 0;
1954 while (pProfile->m_NoSections > 0)
1955 removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]);
1957 free(pProfile->m_Sections);
1958 pProfile->m_Sections = NULL;
1959 pProfile->m_NoSections = 0;
1960 pProfile->m_MaxSections = 0;
1964 #ifdef TRACE_OSL_PROFILE
1965 OSL_TRACE("Out storeProfile [ok]");
1966 #endif
1967 return true;
1970 static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl* pProfile)
1972 osl_TFile* pFile=0;
1973 sal_Char const * pszExtension = "tmp";
1974 sal_Char pszTmpName[PATH_MAX];
1975 oslProfileOption PFlags=0;
1977 pszTmpName[0] = '\0';
1979 /* generate tmp profilename */
1980 osl_ProfileGenerateExtension(pProfile->m_FileName, pszExtension, pszTmpName, PATH_MAX);
1982 if ( pszTmpName[0] == 0 )
1984 return 0;
1987 if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) )
1989 PFlags |= osl_Profile_WRITELOCK;
1992 /* open this file */
1993 pFile = openFileImpl(pszTmpName,pProfile->m_Flags | PFlags);
1995 /* return new pFile */
1996 return pFile;
1999 static bool osl_ProfileSwapProfileNames(osl_TProfileImpl* pProfile)
2001 sal_Char pszBakFile[PATH_MAX];
2002 sal_Char pszTmpFile[PATH_MAX];
2004 pszBakFile[0] = '\0';
2005 pszTmpFile[0] = '\0';
2007 osl_ProfileGenerateExtension(pProfile->m_FileName, "bak", pszBakFile, PATH_MAX);
2008 osl_ProfileGenerateExtension(pProfile->m_FileName, "tmp", pszTmpFile, PATH_MAX);
2010 /* unlink bak */
2011 unlink( pszBakFile );
2013 // Rename ini -> bak, then tmp -> ini:
2014 return rename( pProfile->m_FileName, pszBakFile ) == 0
2015 && rename( pszTmpFile, pProfile->m_FileName ) == 0;
2018 static void osl_ProfileGenerateExtension(const sal_Char* pszFileName, const sal_Char* pszExtension, sal_Char* pszTmpName, int BufferMaxLen)
2020 sal_Char* cursor = pszTmpName;
2021 int len;
2023 /* concatenate filename + "." + extension, limited to the size of the
2024 * output buffer; in case of overrun, data is truncated at the end...
2025 * and the result is always 0-terminated.
2027 len = strlen(pszFileName);
2028 if(len < BufferMaxLen)
2030 memcpy(cursor, pszFileName, len);
2031 cursor += len;
2032 BufferMaxLen -= len;
2034 else
2036 memcpy(cursor, pszFileName, BufferMaxLen - 1);
2037 cursor += BufferMaxLen - 1;
2038 BufferMaxLen = 1;
2040 if(BufferMaxLen > 1)
2042 *cursor++ = '.';
2043 BufferMaxLen -= 1;
2045 len = strlen(pszExtension);
2046 if(len < BufferMaxLen)
2048 memcpy(cursor, pszExtension, len);
2049 cursor += len;
2051 else
2053 memcpy(cursor, pszExtension, BufferMaxLen - 1);
2054 cursor += BufferMaxLen - 1;
2055 BufferMaxLen = 1;
2057 *cursor = 0;
2059 return;
2062 static osl_TProfileImpl* acquireProfile(oslProfile Profile, bool bWriteable)
2064 osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
2065 oslProfileOption PFlags=0;
2067 if ( bWriteable )
2069 PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK;
2071 else
2073 PFlags = osl_Profile_DEFAULT;
2076 if (pProfile == NULL)
2078 #ifdef DEBUG_OSL_PROFILE
2079 OSL_TRACE("AUTOOPEN MODE");
2080 #endif
2082 if ( ( pProfile = (osl_TProfileImpl*) osl_openProfile(0, PFlags ) ) != NULL )
2084 pProfile->m_Flags |= FLG_AUTOOPEN;
2087 else
2089 #ifdef DEBUG_OSL_PROFILE
2090 OSL_TRACE("try to acquire");
2091 #endif
2093 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
2095 if (! (pProfile->m_Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE )))
2097 osl_TStamp Stamp;
2099 #ifdef DEBUG_OSL_PROFILE
2100 OSL_TRACE("Profile acquire DEFAULT MODE");
2101 #endif
2102 if (! (pProfile->m_pFile = openFileImpl(pProfile->m_FileName, pProfile->m_Flags | PFlags )))
2103 return NULL;
2105 Stamp = OslProfile_getFileStamp(pProfile->m_pFile);
2107 if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp)))
2109 bool bRet = false;
2111 pProfile->m_Stamp = Stamp;
2113 bRet=loadProfile(pProfile->m_pFile, pProfile);
2114 OSL_ASSERT(bRet);
2115 (void)bRet;
2118 else
2120 #ifdef DEBUG_OSL_PROFILE
2121 OSL_TRACE("Profile acquire READ/WRITELOCK MODE");
2122 #endif
2123 /* A readlock file could not be written */
2124 if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable)
2126 return (NULL);
2132 return (pProfile);
2135 static bool releaseProfile(osl_TProfileImpl* pProfile)
2137 #ifdef TRACE_OSL_PROFILE
2138 OSL_TRACE("In releaseProfile");
2139 #endif
2141 if ( pProfile == 0 )
2143 #ifdef TRACE_OSL_PROFILE
2144 OSL_TRACE("Out releaseProfile [profile==0]");
2145 #endif
2146 return false;
2149 if (pProfile->m_Flags & FLG_AUTOOPEN)
2151 #ifdef TRACE_OSL_PROFILE
2152 OSL_TRACE("Out releaseProfile [AUTOOPEN]");
2153 #endif
2154 return (osl_closeProfile((oslProfile)pProfile));
2156 else
2158 #ifdef DEBUG_OSL_PROFILE
2159 OSL_TRACE("DEFAULT MODE");
2160 #endif
2161 if (! (pProfile->m_Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE )))
2163 if (pProfile->m_Flags & FLG_MODIFIED)
2165 bool bRet = storeProfile(pProfile, false);
2166 OSL_ASSERT(bRet);
2167 (void)bRet;
2170 closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
2171 pProfile->m_pFile = NULL;
2175 #ifdef TRACE_OSL_PROFILE
2176 OSL_TRACE("Out releaseProfile [ok]");
2177 #endif
2178 return true;
2181 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */