Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / sal / osl / unx / profile.c
blobc9aca5e34730a2bf3a82eae291a61df5e1e3db21
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>
29 #define LINES_INI 32
30 #define LINES_ADD 10
31 #define SECTIONS_INI 5
32 #define SECTIONS_ADD 3
33 #define ENTRIES_INI 5
34 #define ENTRIES_ADD 3
36 #define STR_INI_BOOLYES "yes"
37 #define STR_INI_BOOLON "on"
38 #define STR_INI_BOOLONE "1"
39 #define STR_INI_BOOLNO "no"
40 #define STR_INI_BOOLOFF "off"
41 #define STR_INI_BOOLZERO "0"
43 #define FLG_USER 0x00FF
44 #define FLG_AUTOOPEN 0x0100
45 #define FLG_MODIFIED 0x0200
47 #define DEFAULT_PMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
49 /*#define DEBUG_OSL_PROFILE*/
50 /*#define TRACE_OSL_PROFILE*/
52 typedef time_t osl_TStamp;
54 typedef enum _osl_TLockMode
56 un_lock, read_lock, write_lock
57 } osl_TLockMode;
59 typedef struct _osl_TFile
61 int m_Handle;
62 sal_Char* m_pReadPtr;
63 sal_Char m_ReadBuf[512];
64 sal_Char* m_pWriteBuf;
65 sal_uInt32 m_nWriteBufLen;
66 sal_uInt32 m_nWriteBufFree;
67 } osl_TFile;
69 typedef struct _osl_TProfileEntry
71 sal_uInt32 m_Line;
72 sal_uInt32 m_Offset;
73 sal_uInt32 m_Len;
74 } osl_TProfileEntry;
76 typedef struct _osl_TProfileSection
78 sal_uInt32 m_Line;
79 sal_uInt32 m_Offset;
80 sal_uInt32 m_Len;
81 sal_uInt32 m_NoEntries;
82 sal_uInt32 m_MaxEntries;
83 osl_TProfileEntry* m_Entries;
84 } 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 sal_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 sal_Bool OslProfile_lockFile(const osl_TFile* pFile, osl_TLockMode eMode);
107 static sal_Bool OslProfile_rewindFile(osl_TFile* pFile, sal_Bool bTruncate);
108 static osl_TStamp OslProfile_getFileStamp(osl_TFile* pFile);
110 static sal_Char* OslProfile_getLine(osl_TFile* pFile);
111 static sal_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 sal_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 sal_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 sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile);
127 static sal_Bool storeProfile(osl_TProfileImpl* pProfile, sal_Bool bCleanup);
128 static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable);
129 static sal_Bool releaseProfile(osl_TProfileImpl* pProfile);
131 static sal_Bool writeProfileImpl (osl_TFile* pFile);
132 static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl*);
133 static sal_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 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 sal_Bool bRet = sal_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
187 if ( ( pFile = openFileImpl(pszProfileName, Flags ) ) == NULL )
189 #ifdef TRACE_OSL_PROFILE
190 OSL_TRACE("Out osl_openProfile [not opened]");
191 #endif
192 return (NULL);
196 pProfile = (osl_TProfileImpl*)calloc(1, sizeof(osl_TProfileImpl));
198 if ( pProfile == 0 )
200 closeFileImpl(pFile, Flags);
201 return 0;
204 pProfile->m_Flags = Flags & FLG_USER;
206 if ( Flags & ( osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
208 pProfile->m_pFile = pFile;
211 pthread_mutex_init(&(pProfile->m_AccessLock),PTHREAD_MUTEXATTR_DEFAULT);
212 pProfile->m_bIsValid=sal_True;
214 pProfile->m_Stamp = OslProfile_getFileStamp(pFile);
215 bRet=loadProfile(pFile, pProfile);
216 bRet &= realpath(pszProfileName, pProfile->m_FileName) != NULL;
217 OSL_ASSERT(bRet);
219 if (pProfile->m_pFile == NULL)
220 closeFileImpl(pFile,pProfile->m_Flags);
222 #ifdef TRACE_OSL_PROFILE
223 OSL_TRACE("Out osl_openProfile [ok]");
224 #endif
225 return (pProfile);
228 sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile)
230 osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
231 osl_TProfileImpl* pTmpProfile;
233 #ifdef TRACE_OSL_PROFILE
234 OSL_TRACE("In osl_closeProfile");
235 #endif
237 if ( Profile == 0 )
239 #ifdef TRACE_OSL_PROFILE
240 OSL_TRACE("Out osl_closeProfile [profile==0]");
241 #endif
242 return sal_False;
245 pthread_mutex_lock(&(pProfile->m_AccessLock));
247 if ( pProfile->m_bIsValid == sal_False )
249 OSL_ASSERT(pProfile->m_bIsValid);
250 pthread_mutex_unlock(&(pProfile->m_AccessLock));
251 #ifdef TRACE_OSL_PROFILE
252 OSL_TRACE("Out osl_closeProfile [not valid]");
253 #endif
254 return sal_False;
257 pProfile->m_bIsValid=sal_False;
259 if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) && ( pProfile->m_Flags & FLG_MODIFIED ) )
261 pTmpProfile = acquireProfile(Profile,sal_True);
263 if ( pTmpProfile != 0 )
265 sal_Bool bRet = storeProfile(pTmpProfile, sal_True);
266 OSL_ASSERT(bRet);
267 (void)bRet;
270 else
272 pTmpProfile = acquireProfile(Profile,sal_False);
276 if ( pTmpProfile == 0 )
278 pthread_mutex_unlock(&(pProfile->m_AccessLock));
279 #ifdef TRACE_OSL_PROFILE
280 OSL_TRACE("Out osl_closeProfile [pProfile==0]");
281 #endif
282 return sal_False;
285 pProfile = pTmpProfile;
287 if (pProfile->m_pFile != NULL)
288 closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
290 pProfile->m_pFile = NULL;
291 pProfile->m_FileName[0] = '\0';
293 /* release whole profile data types memory */
294 if ( pProfile->m_NoLines > 0)
296 unsigned int idx=0;
297 if ( pProfile->m_Lines != 0 )
299 for ( idx = 0 ; idx < pProfile->m_NoLines ; ++idx)
301 if ( pProfile->m_Lines[idx] != 0 )
303 free(pProfile->m_Lines[idx]);
304 pProfile->m_Lines[idx]=0;
307 free(pProfile->m_Lines);
308 pProfile->m_Lines=0;
310 if ( pProfile->m_Sections != 0 )
312 /*osl_TProfileSection* pSections=pProfile->m_Sections;*/
313 for ( idx = 0 ; idx < pProfile->m_NoSections ; ++idx )
315 if ( pProfile->m_Sections[idx].m_Entries != 0 )
317 free(pProfile->m_Sections[idx].m_Entries);
318 pProfile->m_Sections[idx].m_Entries=0;
321 free(pProfile->m_Sections);
322 pProfile->m_Sections=0;
326 pthread_mutex_unlock(&(pProfile->m_AccessLock));
328 pthread_mutex_destroy(&(pProfile->m_AccessLock));
330 free(pProfile);
332 #ifdef TRACE_OSL_PROFILE
333 OSL_TRACE("Out osl_closeProfile [ok]");
334 #endif
335 return (sal_True);
339 sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile)
341 osl_TProfileImpl* pProfile = (osl_TProfileImpl*) Profile;
342 osl_TFile* pFile;
343 sal_Bool bRet = sal_False;
345 #ifdef TRACE_OSL_PROFILE
346 OSL_TRACE("In osl_flushProfile()");
347 #endif
349 if ( pProfile == 0 )
351 #ifdef TRACE_OSL_PROFILE
352 OSL_TRACE("Out osl_flushProfile() [pProfile == 0]");
353 #endif
354 return sal_False;
357 pthread_mutex_lock(&(pProfile->m_AccessLock));
359 if ( pProfile->m_bIsValid == sal_False )
361 OSL_ASSERT(pProfile->m_bIsValid);
362 pthread_mutex_unlock(&(pProfile->m_AccessLock));
363 #ifdef TRACE_OSL_PROFILE
364 OSL_TRACE("Out osl_flushProfile [not valid]");
365 #endif
366 return sal_False;
369 pFile = pProfile->m_pFile;
370 if ( !( pFile != 0 && pFile->m_Handle >= 0 ) )
372 pthread_mutex_unlock(&(pProfile->m_AccessLock));
373 #ifdef TRACE_OSL_PROFILE
374 OSL_TRACE("Out osl_flushProfile() [invalid file]");
375 #endif
376 return sal_False;
379 if ( pProfile->m_Flags & FLG_MODIFIED )
381 #ifdef DEBUG_OSL_PROFILE
382 OSL_TRACE("swapping to storeprofile");
383 #endif
384 bRet = storeProfile(pProfile,sal_False);
385 OSL_ASSERT(bRet);
388 #ifdef TRACE_OSL_PROFILE
389 OSL_TRACE("Out osl_flushProfile() [ok]");
390 #endif
391 pthread_mutex_unlock(&(pProfile->m_AccessLock));
392 return bRet;
395 static sal_Bool writeProfileImpl(osl_TFile* pFile)
397 #if OSL_DEBUG_LEVEL > 1
398 unsigned int nLen=0;
399 #endif
401 #ifdef TRACE_OSL_PROFILE
402 OSL_TRACE("In osl_writeProfileImpl()");
403 #endif
405 if ( !( pFile != 0 && pFile->m_Handle >= 0 ) || ( pFile->m_pWriteBuf == 0 ) )
407 #ifdef TRACE_OSL_PROFILE
408 OSL_TRACE("Out osl_writeProfileImpl() [invalid args]");
409 #endif
410 return sal_False;
413 #if OSL_DEBUG_LEVEL > 1
414 nLen=strlen(pFile->m_pWriteBuf);
415 OSL_ASSERT(nLen == (pFile->m_nWriteBufLen - pFile->m_nWriteBufFree));
416 #endif
418 if ( !safeWrite(pFile->m_Handle, pFile->m_pWriteBuf, pFile->m_nWriteBufLen - pFile->m_nWriteBufFree) )
420 OSL_TRACE("write failed '%s'",strerror(errno));
421 return (sal_False);
424 free(pFile->m_pWriteBuf);
425 pFile->m_pWriteBuf=0;
426 pFile->m_nWriteBufLen=0;
427 pFile->m_nWriteBufFree=0;
428 #ifdef TRACE_OSL_PROFILE
429 OSL_TRACE("Out osl_writeProfileImpl() [ok]");
430 #endif
431 return sal_True;
435 sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile,
436 const sal_Char* pszSection,
437 const sal_Char* pszEntry,
438 sal_Char* pszString,
439 sal_uInt32 MaxLen,
440 const sal_Char* pszDefault)
442 sal_uInt32 NoEntry;
443 sal_Char* pStr=0;
444 osl_TProfileSection* pSec;
445 osl_TProfileImpl* pProfile=0;
446 osl_TProfileImpl* pTmpProfile=0;
447 sal_Bool bRet = sal_False;
449 #ifdef TRACE_OSL_PROFILE
450 OSL_TRACE("In osl_readProfileString");
451 #endif
453 pTmpProfile = (osl_TProfileImpl*) Profile;
455 if ( pTmpProfile == 0 )
457 #ifdef TRACE_OSL_PROFILE
458 OSL_TRACE("Out osl_readProfileString [pTmpProfile==0]");
459 #endif
460 return sal_False;
463 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
465 if ( pTmpProfile->m_bIsValid == sal_False )
467 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
468 #ifdef TRACE_OSL_PROFILE
469 OSL_TRACE("Out osl_readProfileString [not valid]");
470 #endif
471 return sal_False;
474 pProfile = acquireProfile(Profile, sal_False);
476 if ( pProfile == NULL )
478 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
479 #ifdef TRACE_OSL_PROFILE
480 OSL_TRACE("Out osl_readProfileString [pProfile==0]");
481 #endif
482 return (sal_False);
485 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
487 if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
488 (NoEntry < pSec->m_NoEntries) &&
489 ((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line],
490 '=')) != NULL))
492 pStr++;
494 else
496 pStr=(sal_Char*)pszDefault;
499 if ( pStr != 0 )
501 pStr = stripBlanks(pStr, NULL);
502 MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr);
503 pStr = stripBlanks(pStr, &MaxLen);
504 strncpy(pszString, pStr, MaxLen);
505 pszString[MaxLen] = '\0';
508 else
509 { /* not implemented */ }
512 bRet=releaseProfile(pProfile);
513 OSL_ASSERT(bRet);
514 (void)bRet;
516 if ( pStr == 0 )
518 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
519 #ifdef TRACE_OSL_PROFILE
520 OSL_TRACE("Out osl_readProfileString [pStr==0]");
521 #endif
522 return sal_False;
525 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
527 #ifdef TRACE_OSL_PROFILE
528 OSL_TRACE("Out osl_readProfileString [ok]");
529 #endif
531 return (sal_True);
534 sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile,
535 const sal_Char* pszSection,
536 const sal_Char* pszEntry,
537 sal_Bool Default)
539 sal_Char Line[32];
540 Line[0] = '\0';
542 #ifdef TRACE_OSL_PROFILE
543 OSL_TRACE("In osl_readProfileBool");
544 #endif
546 if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
548 if ((strcasecmp(Line, STR_INI_BOOLYES) == 0) ||
549 (strcasecmp(Line, STR_INI_BOOLON) == 0) ||
550 (strcasecmp(Line, STR_INI_BOOLONE) == 0))
551 Default = sal_True;
552 else
553 if ((strcasecmp(Line, STR_INI_BOOLNO) == 0) ||
554 (strcasecmp(Line, STR_INI_BOOLOFF) == 0) ||
555 (strcasecmp(Line, STR_INI_BOOLZERO) == 0))
556 Default = sal_False;
559 #ifdef TRACE_OSL_PROFILE
560 OSL_TRACE("Out osl_readProfileBool [ok]");
561 #endif
563 return (Default);
566 sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile,
567 const sal_Char* pszSection,
568 const sal_Char* pszEntry,
569 sal_uInt32 FirstId,
570 const sal_Char* Strings[],
571 sal_uInt32 Default)
573 sal_uInt32 i;
574 sal_Char Line[256];
575 Line[0] = '\0';
577 #ifdef TRACE_OSL_PROFILE
578 OSL_TRACE("In osl_readProfileIdent");
579 #endif
581 if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
583 i = 0;
584 while (Strings[i] != NULL)
586 if (strcasecmp(Line, Strings[i]) == 0)
588 Default = i + FirstId;
589 break;
591 i++;
595 #ifdef TRACE_OSL_PROFILE
596 OSL_TRACE("Out osl_readProfileIdent [ok]");
597 #endif
598 return (Default);
601 sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile,
602 const sal_Char* pszSection,
603 const sal_Char* pszEntry,
604 const sal_Char* pszString)
606 sal_uInt32 i;
607 sal_Bool bRet = sal_False;
608 sal_uInt32 NoEntry;
609 sal_Char* pStr;
610 sal_Char* Line = 0;
611 osl_TProfileSection* pSec;
612 osl_TProfileImpl* pProfile = 0;
613 osl_TProfileImpl* pTmpProfile = 0;
615 #ifdef TRACE_OSL_PROFILE
616 OSL_TRACE("In osl_writeProfileString");
617 #endif
619 pTmpProfile = (osl_TProfileImpl*) Profile;
621 if ( pTmpProfile == 0 )
623 #ifdef TRACE_OSL_PROFILE
624 OSL_TRACE("Out osl_writeProfileString [pTmpProfile==0]");
625 #endif
626 return sal_False;
629 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
631 if ( pTmpProfile->m_bIsValid == sal_False )
633 OSL_ASSERT(pTmpProfile->m_bIsValid);
634 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
635 #ifdef TRACE_OSL_PROFILE
636 OSL_TRACE("Out osl_writeProfileString [not valid]");
637 #endif
638 return sal_False;
641 pProfile=acquireProfile(Profile, sal_True);
643 if (pProfile == NULL)
645 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
646 #ifdef TRACE_OSL_PROFILE
647 OSL_TRACE("Out osl_writeProfileString [pProfile==0]");
648 #endif
649 return (sal_False);
652 Line = (sal_Char*) malloc(strlen(pszEntry)+strlen(pszString)+48);
654 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
656 if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == NULL)
658 Line[0] = '\0';
659 addLine(pProfile, Line);
661 Line[0] = '[';
662 strcpy(&Line[1], pszSection);
663 Line[1 + strlen(pszSection)] = ']';
664 Line[2 + strlen(pszSection)] = '\0';
666 if (((pStr = addLine(pProfile, Line)) == NULL) ||
667 (! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection))))
669 bRet=releaseProfile(pProfile);
670 OSL_ASSERT(bRet);
672 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
674 free(Line);
676 #ifdef TRACE_OSL_PROFILE
677 OSL_TRACE("Out osl_writeProfileString [not added]");
678 #endif
679 return (sal_False);
682 pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1];
683 NoEntry = pSec->m_NoEntries;
686 Line[0] = '\0';
687 strcpy(&Line[0], pszEntry);
688 Line[0 + strlen(pszEntry)] = '=';
689 strcpy(&Line[1 + strlen(pszEntry)], pszString);
691 if (NoEntry >= pSec->m_NoEntries)
693 if (pSec->m_NoEntries > 0)
694 i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1;
695 else
696 i = pSec->m_Line + 1;
698 if (((pStr = insertLine(pProfile, Line, i)) == NULL) ||
699 (! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry))))
701 bRet=releaseProfile(pProfile);
702 OSL_ASSERT(bRet);
704 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
705 free(Line);
707 #ifdef TRACE_OSL_PROFILE
708 OSL_TRACE("Out osl_writeProfileString [not inserted]");
709 #endif
710 return (sal_False);
713 pProfile->m_Flags |= FLG_MODIFIED;
715 else
717 i = pSec->m_Entries[NoEntry].m_Line;
718 free(pProfile->m_Lines[i]);
719 pProfile->m_Lines[i] = strdup(Line);
720 setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry));
722 pProfile->m_Flags |= FLG_MODIFIED;
725 else {
726 /* not implemented */
729 bRet = releaseProfile(pProfile);
730 OSL_ASSERT(bRet);
732 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
733 if ( Line!= 0 )
735 free(Line);
738 #ifdef TRACE_OSL_PROFILE
739 OSL_TRACE("Out osl_writeProfileString [ok]");
740 #endif
742 return bRet;
745 sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile,
746 const sal_Char* pszSection,
747 const sal_Char* pszEntry,
748 sal_Bool Value)
750 sal_Bool bRet=sal_False;
752 #ifdef TRACE_OSL_PROFILE
753 OSL_TRACE("In osl_writeProfileBool");
754 #endif
756 if (Value)
757 bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE);
758 else
759 bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO);
761 #ifdef TRACE_OSL_PROFILE
762 OSL_TRACE("Out osl_writeProfileBool [ok]");
763 #endif
765 return bRet;
768 sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile,
769 const sal_Char* pszSection,
770 const sal_Char* pszEntry,
771 sal_uInt32 FirstId,
772 const sal_Char* Strings[],
773 sal_uInt32 Value)
775 int i, n = 0;
776 sal_Bool bRet=sal_False;
778 #ifdef TRACE_OSL_PROFILE
779 OSL_TRACE("In osl_writeProfileIdent");
780 #endif
782 while (Strings[n] != NULL)
783 ++n;
785 if ((i = Value - FirstId) >= n)
786 bRet = sal_False;
787 else
788 bRet = osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]);
790 #ifdef TRACE_OSL_PROFILE
791 OSL_TRACE("Out osl_writeProfileIdent");
792 #endif
793 return bRet;
796 sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile,
797 const sal_Char *pszSection,
798 const sal_Char *pszEntry)
800 sal_uInt32 NoEntry;
801 osl_TProfileSection* pSec;
802 osl_TProfileImpl* pProfile = 0;
803 osl_TProfileImpl* pTmpProfile = 0;
804 sal_Bool bRet = sal_False;
806 #ifdef TRACE_OSL_PROFILE
807 OSL_TRACE("In osl_removeProfileEntry");
808 #endif
810 pTmpProfile = (osl_TProfileImpl*) Profile;
812 if ( pTmpProfile == 0 )
814 #ifdef TRACE_OSL_PROFILE
815 OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]");
816 #endif
817 return sal_False;
820 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
822 if ( pTmpProfile->m_bIsValid == sal_False )
824 OSL_ASSERT(pTmpProfile->m_bIsValid);
825 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
826 #ifdef TRACE_OSL_PROFILE
827 OSL_TRACE("Out osl_removeProfileEntry [not valid]");
828 #endif
829 return sal_False;
833 pProfile = acquireProfile(Profile, sal_True);
835 if (pProfile == NULL)
837 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
838 #ifdef TRACE_OSL_PROFILE
839 OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]");
840 #endif
841 return (sal_False);
845 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
847 if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
848 (NoEntry < pSec->m_NoEntries))
850 removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line);
851 removeEntry(pSec, NoEntry);
852 if (pSec->m_NoEntries == 0)
854 removeLine(pProfile, pSec->m_Line);
856 /* remove any empty separation line */
857 if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0'))
858 removeLine(pProfile, pSec->m_Line - 1);
860 removeSection(pProfile, pSec);
863 pProfile->m_Flags |= FLG_MODIFIED;
866 else
867 { /* not implemented */ }
870 bRet = releaseProfile(pProfile);
871 OSL_ASSERT(bRet);
873 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
875 #ifdef TRACE_OSL_PROFILE
876 OSL_TRACE("Out osl_removeProfileEntry [ok]");
877 #endif
878 return bRet;
881 sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile,
882 const sal_Char *pszSection,
883 sal_Char* pszBuffer,
884 sal_uInt32 MaxLen)
886 sal_uInt32 i, n = 0;
887 sal_uInt32 NoEntry;
888 osl_TProfileSection* pSec;
889 osl_TProfileImpl* pProfile = 0;
890 osl_TProfileImpl* pTmpProfile = 0;
891 sal_Bool bRet = sal_False;
893 #ifdef TRACE_OSL_PROFILE
894 OSL_TRACE("In osl_getProfileSectionEntries");
895 #endif
897 pTmpProfile = (osl_TProfileImpl*) Profile;
899 if ( pTmpProfile == 0 )
901 #ifdef TRACE_OSL_PROFILE
902 OSL_TRACE("Out osl_getProfileSectionEntries [pTmpProfile==0]");
903 #endif
904 return sal_False;
908 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
910 if ( pTmpProfile->m_bIsValid == sal_False )
912 OSL_ASSERT(pTmpProfile->m_bIsValid);
914 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
916 #ifdef TRACE_OSL_PROFILE
917 OSL_TRACE("Out osl_getProfileSectionEntries [not valid]");
918 #endif
920 return sal_False;
923 pProfile = acquireProfile(Profile, sal_False);
925 if (pProfile == NULL)
927 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
929 #ifdef TRACE_OSL_PROFILE
930 OSL_TRACE("Out osl_getProfileSectionEntries [pProfile=0]");
931 #endif
933 return (0);
937 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
939 if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != NULL)
941 if (MaxLen != 0)
943 for (i = 0; i < pSec->m_NoEntries; i++)
945 if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen)
947 strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
948 [pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len);
949 n += pSec->m_Entries[i].m_Len;
950 pszBuffer[n++] = '\0';
952 else
953 break;
957 pszBuffer[n++] = '\0';
959 else
961 for (i = 0; i < pSec->m_NoEntries; i++)
962 n += pSec->m_Entries[i].m_Len + 1;
964 n += 1;
967 else
968 n = 0;
970 else {
971 /* not implemented */
974 bRet=releaseProfile(pProfile);
975 OSL_ASSERT(bRet);
976 (void)bRet;
978 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
980 #ifdef TRACE_OSL_PROFILE
981 OSL_TRACE("Out osl_getProfileSectionEntries [ok]");
982 #endif
984 return (n);
987 sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile,
988 sal_Char* pszBuffer,
989 sal_uInt32 MaxLen)
991 sal_uInt32 i, n = 0;
992 osl_TProfileSection* pSec;
993 osl_TProfileImpl* pProfile = 0;
994 osl_TProfileImpl* pTmpProfile = 0;
995 sal_Bool bRet = sal_False;
997 #ifdef TRACE_OSL_PROFILE
998 OSL_TRACE("In osl_getProfileSections");
999 #endif
1001 pTmpProfile = (osl_TProfileImpl*) Profile;
1003 if ( pTmpProfile == 0 )
1005 #ifdef TRACE_OSL_PROFILE
1006 OSL_TRACE("Out osl_getProfileSections [pTmpProfile==0]");
1007 #endif
1008 return sal_False;
1011 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
1013 if ( pTmpProfile->m_bIsValid == sal_False )
1015 OSL_ASSERT(pTmpProfile->m_bIsValid);
1016 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
1017 #ifdef TRACE_OSL_PROFILE
1018 OSL_TRACE("Out osl_getProfileSections [not valid]");
1019 #endif
1020 return sal_False;
1023 pProfile = acquireProfile(Profile, sal_False);
1025 if (pProfile == NULL)
1027 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
1029 #ifdef TRACE_OSL_PROFILE
1030 OSL_TRACE("Out osl_getProfileSections [pProfile==0]");
1031 #endif
1032 return (0);
1035 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
1037 if (MaxLen != 0)
1039 for (i = 0; i < pProfile->m_NoSections; i++)
1041 pSec = &pProfile->m_Sections[i];
1043 if ((n + pSec->m_Len + 1) < MaxLen)
1045 strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset],
1046 pSec->m_Len);
1047 n += pSec->m_Len;
1048 pszBuffer[n++] = '\0';
1050 else
1051 break;
1054 pszBuffer[n++] = '\0';
1056 else
1058 for (i = 0; i < pProfile->m_NoSections; i++)
1059 n += pProfile->m_Sections[i].m_Len + 1;
1061 n += 1;
1064 else
1065 { /* not implemented */ }
1068 bRet=releaseProfile(pProfile);
1069 OSL_ASSERT(bRet);
1070 (void)bRet;
1072 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
1074 #ifdef TRACE_OSL_PROFILE
1075 OSL_TRACE("Out osl_getProfileSections [ok]");
1076 #endif
1078 return (n);
1081 static osl_TStamp OslProfile_getFileStamp(osl_TFile* pFile)
1083 struct stat status;
1085 if ( (pFile->m_Handle < 0) || (fstat(pFile->m_Handle, &status) < 0) )
1087 return (0);
1091 return (status.st_mtime);
1094 static sal_Bool OslProfile_lockFile(const osl_TFile* pFile, osl_TLockMode eMode)
1096 struct flock lock;
1097 /* boring hack, but initializers for static vars must be constant */
1098 static sal_Bool bIsInitialized = sal_False;
1099 static sal_Bool bLockingDisabled;
1101 #ifdef TRACE_OSL_PROFILE
1102 OSL_TRACE("In OslProfile_lockFile");
1103 #endif
1105 if ( !bIsInitialized )
1107 sal_Char* pEnvValue;
1108 pEnvValue = getenv( "STAR_PROFILE_LOCKING_DISABLED" );
1110 if ( pEnvValue == 0 )
1112 bLockingDisabled = sal_False;
1115 else
1117 bLockingDisabled = sal_True;
1120 bIsInitialized = sal_True;
1123 if (pFile->m_Handle < 0)
1125 #ifdef TRACE_OSL_PROFILE
1126 OSL_TRACE("Out OslProfile_lockFile [invalid file handle]");
1127 #endif
1128 return (sal_False);
1132 if ( bLockingDisabled )
1134 #ifdef TRACE_OSL_PROFILE
1135 OSL_TRACE("Out OslProfile_lockFile [locking disabled]");
1136 #endif
1137 return (sal_True);
1141 lock.l_start = 0;
1142 lock.l_whence = SEEK_SET;
1143 lock.l_len = 0;
1145 switch (eMode)
1147 case un_lock:
1148 lock.l_type = F_UNLCK;
1149 break;
1151 case read_lock:
1152 lock.l_type = F_RDLCK;
1153 break;
1155 case write_lock:
1156 lock.l_type = F_WRLCK;
1157 break;
1160 #ifndef MACOSX
1161 if ( fcntl(pFile->m_Handle, F_SETLKW, &lock) == -1 )
1162 #else
1163 /* Mac OSX will return ENOTSUP for webdav drives so we should ignore it */
1164 if ( fcntl(pFile->m_Handle, F_SETLKW, &lock) == -1 && errno != ENOTSUP )
1165 #endif
1167 OSL_TRACE("fcntl returned -1 (%s)",strerror(errno));
1168 #ifdef TRACE_OSL_PROFILE
1169 OSL_TRACE("Out OslProfile_lockFile [fcntl F_SETLKW]");
1170 #endif
1171 return sal_False;
1174 #ifdef TRACE_OSL_PROFILE
1175 OSL_TRACE("Out OslProfile_lockFile [ok]");
1176 #endif
1177 return sal_True;
1180 static osl_TFile* openFileImpl(const sal_Char* pszFilename, oslProfileOption ProfileFlags )
1182 int Flags;
1183 osl_TFile* pFile = (osl_TFile*) calloc(1, sizeof(osl_TFile));
1184 sal_Bool bWriteable = sal_False;
1186 if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
1188 #ifdef DEBUG_OSL_PROFILE
1189 OSL_TRACE("setting bWriteable to TRUE");
1190 #endif
1191 bWriteable=sal_True;
1194 if (! bWriteable)
1196 #ifdef DEBUG_OSL_PROFILE
1197 OSL_TRACE("opening '%s' read only",pszFilename);
1198 #endif
1200 pFile->m_Handle = open(pszFilename, O_RDONLY);
1201 /* mfe: argghh!!! do not check if the file could be openend */
1202 /* default mode expects it that way!!! */
1204 else
1206 #ifdef DEBUG_OSL_PROFILE
1207 OSL_TRACE("opening '%s' read/write",pszFilename);
1208 #endif
1209 if (((pFile->m_Handle = open(pszFilename, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PMODE)) < 0) &&
1210 ((pFile->m_Handle = open(pszFilename, O_RDWR)) < 0))
1212 free(pFile);
1213 #ifdef TRACE_OSL_PROFILE
1214 OSL_TRACE("Out openFileImpl [open read/write]");
1215 #endif
1216 return (NULL);
1220 /* set close-on-exec flag */
1221 if ((Flags = fcntl(pFile->m_Handle, F_GETFD, 0)) != -1)
1223 Flags |= FD_CLOEXEC;
1224 fcntl(pFile->m_Handle, F_SETFD, Flags);
1227 pFile->m_pWriteBuf=0;
1228 pFile->m_nWriteBufFree=0;
1229 pFile->m_nWriteBufLen=0;
1231 if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
1233 #ifdef DEBUG_OSL_PROFILE
1234 OSL_TRACE("locking '%s' file",pszFilename);
1235 #endif
1236 OslProfile_lockFile(pFile, bWriteable ? write_lock : read_lock);
1239 #ifdef TRACE_OSL_PROFILE
1240 OSL_TRACE("Out openFileImpl [ok]");
1241 #endif
1242 return (pFile);
1245 static osl_TStamp closeFileImpl(osl_TFile* pFile, oslProfileOption Flags)
1247 osl_TStamp stamp = 0;
1249 #ifdef TRACE_OSL_PROFILE
1250 OSL_TRACE("In closeFileImpl");
1251 #endif
1253 if ( pFile == 0 )
1255 #ifdef TRACE_OSL_PROFILE
1256 OSL_TRACE("Out closeFileImpl [pFile == 0]");
1257 #endif
1258 return stamp;
1261 if ( pFile->m_Handle >= 0 )
1263 stamp = OslProfile_getFileStamp(pFile);
1265 if ( Flags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
1267 OslProfile_lockFile(pFile, un_lock);
1270 close(pFile->m_Handle);
1271 pFile->m_Handle = -1;
1275 if ( pFile->m_pWriteBuf )
1277 free(pFile->m_pWriteBuf);
1280 free(pFile);
1282 #ifdef TRACE_OSL_PROFILE
1283 OSL_TRACE("Out closeFileImpl [ok]");
1284 #endif
1286 return(stamp);
1289 static sal_Bool OslProfile_rewindFile(osl_TFile* pFile, sal_Bool bTruncate)
1291 sal_Bool bRet = sal_True;
1292 #ifdef TRACE_OSL_PROFILE
1293 OSL_TRACE("In osl_OslProfile_rewindFile");
1294 #endif
1296 if (pFile->m_Handle >= 0)
1298 pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1300 #ifdef DEBUG_OSL_PROFILE
1301 OSL_TRACE("rewinding");
1302 #endif
1303 bRet = (lseek(pFile->m_Handle, SEEK_SET, 0L) == 0L);
1305 if (bTruncate)
1307 #ifdef DEBUG_OSL_PROFILE
1308 OSL_TRACE("truncating");
1309 #endif
1310 bRet &= (ftruncate(pFile->m_Handle, 0L) == 0);
1315 #ifdef TRACE_OSL_PROFILE
1316 OSL_TRACE("Out osl_OslProfile_rewindFile [ok]");
1317 #endif
1318 return bRet;
1322 static sal_Char* OslProfile_getLine(osl_TFile* pFile)
1324 int Max, Free, Bytes, nLineBytes = 0;
1325 sal_Char* pChr;
1326 sal_Char* pLine = NULL;
1327 sal_Char* pNewLine;
1329 if ( pFile == 0 )
1331 return 0;
1334 if (pFile->m_Handle < 0)
1335 return NULL;
1339 Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf);
1341 if (Bytes <= 1)
1343 /* refill buffer */
1344 memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes);
1345 pFile->m_pReadPtr = pFile->m_ReadBuf;
1347 Free = sizeof(pFile->m_ReadBuf) - Bytes;
1349 if ((Max = read(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free)) < 0)
1351 OSL_TRACE("read failed '%s'",strerror(errno));
1353 if( pLine )
1354 rtl_freeMemory( pLine );
1355 pLine = NULL;
1356 break;
1359 if (Max < Free)
1361 if ((Max == 0) && ! pLine)
1362 break;
1364 pFile->m_ReadBuf[Bytes + Max] = '\0';
1368 for (pChr = pFile->m_pReadPtr;
1369 (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') &&
1370 (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1));
1371 pChr++);
1373 Max = pChr - pFile->m_pReadPtr;
1374 pNewLine = (sal_Char*) rtl_allocateMemory( nLineBytes + Max + 1 );
1375 if( pLine )
1377 memcpy( pNewLine, pLine, nLineBytes );
1378 rtl_freeMemory( pLine );
1380 memcpy(pNewLine+nLineBytes, pFile->m_pReadPtr, Max);
1381 nLineBytes += Max;
1382 pNewLine[ nLineBytes ] = 0;
1383 pLine = pNewLine;
1385 if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1))
1387 if (*pChr != '\0')
1389 if ((pChr[0] == '\r') && (pChr[1] == '\n'))
1390 pChr += 2;
1391 else
1392 pChr += 1;
1395 if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) &&
1396 (*pChr == '\0'))
1397 pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1399 /* setting Max to -1 indicates terminating read loop */
1400 Max = -1;
1403 pFile->m_pReadPtr = pChr;
1405 while (Max > 0);
1407 return pLine;
1410 static sal_Bool OslProfile_putLine(osl_TFile* pFile, const sal_Char *pszLine)
1412 unsigned int Len = strlen(pszLine);
1414 #ifdef DEBUG_OSL_PROFILE
1415 int strLen=0;
1416 #endif
1418 if ( pFile == 0 || pFile->m_Handle < 0 )
1420 return (sal_False);
1423 if ( pFile->m_pWriteBuf == 0 )
1425 pFile->m_pWriteBuf = (sal_Char*) malloc(Len+3);
1426 pFile->m_nWriteBufLen = Len+3;
1427 pFile->m_nWriteBufFree = Len+3;
1429 else
1431 if ( pFile->m_nWriteBufFree <= Len + 3 )
1433 sal_Char* pTmp;
1435 pTmp=(sal_Char*) realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) );
1436 if ( pTmp == 0 )
1438 return sal_False;
1440 pFile->m_pWriteBuf = pTmp;
1441 pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len );
1442 pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2;
1443 memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree);
1449 memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1);
1450 #ifdef DEBUG_OSL_PROFILE
1451 strLen = strlen(pFile->m_pWriteBuf);
1452 #endif
1453 pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\n';
1454 pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\0';
1456 pFile->m_nWriteBufFree-=Len+1;
1458 return sal_True;
1461 static sal_Char* stripBlanks(sal_Char* String, sal_uInt32* pLen)
1463 if ( ( pLen != NULL ) && ( *pLen != 0 ) )
1465 while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t'))
1466 (*pLen)--;
1468 while ( (*String == ' ') || (*String == '\t') )
1470 String++;
1471 (*pLen)--;
1474 else
1475 while ( (*String == ' ') || (*String == '\t') )
1476 String++;
1478 return (String);
1481 static sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line)
1483 if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1485 if (pProfile->m_Lines == NULL)
1487 pProfile->m_MaxLines = LINES_INI;
1488 pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
1489 memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
1491 else
1493 unsigned int idx=0;
1494 unsigned int oldmax=pProfile->m_MaxLines;
1496 pProfile->m_MaxLines += LINES_ADD;
1497 pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
1498 pProfile->m_MaxLines * sizeof(sal_Char *));
1499 for ( idx = oldmax ; idx < pProfile->m_MaxLines ; ++idx )
1501 pProfile->m_Lines[idx]=0;
1505 if (pProfile->m_Lines == NULL)
1507 pProfile->m_NoLines = 0;
1508 pProfile->m_MaxLines = 0;
1509 return (NULL);
1514 if ( pProfile->m_Lines != 0 && pProfile->m_Lines[pProfile->m_NoLines] != 0 )
1516 free(pProfile->m_Lines[pProfile->m_NoLines]);
1518 pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line);
1520 return (pProfile->m_Lines[pProfile->m_NoLines - 1]);
1523 static sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo)
1525 if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1527 if (pProfile->m_Lines == NULL)
1529 pProfile->m_MaxLines = LINES_INI;
1530 pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
1531 memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
1533 else
1535 pProfile->m_MaxLines += LINES_ADD;
1536 pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
1537 pProfile->m_MaxLines * sizeof(sal_Char *));
1539 memset(&pProfile->m_Lines[pProfile->m_NoLines],
1541 (pProfile->m_MaxLines - pProfile->m_NoLines - 1) * sizeof(sal_Char*));
1544 if (pProfile->m_Lines == NULL)
1546 pProfile->m_NoLines = 0;
1547 pProfile->m_MaxLines = 0;
1548 return (NULL);
1552 LineNo = LineNo > pProfile->m_NoLines ? pProfile->m_NoLines : LineNo;
1554 if (LineNo < pProfile->m_NoLines)
1556 sal_uInt32 i, n;
1557 osl_TProfileSection* pSec;
1559 memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo],
1560 (pProfile->m_NoLines - LineNo) * sizeof(sal_Char *));
1563 /* adjust line references */
1564 for (i = 0; i < pProfile->m_NoSections; i++)
1566 pSec = &pProfile->m_Sections[i];
1568 if (pSec->m_Line >= LineNo)
1569 pSec->m_Line++;
1571 for (n = 0; n < pSec->m_NoEntries; n++)
1572 if (pSec->m_Entries[n].m_Line >= LineNo)
1573 pSec->m_Entries[n].m_Line++;
1577 pProfile->m_NoLines++;
1579 pProfile->m_Lines[LineNo] = strdup(Line);
1581 return (pProfile->m_Lines[LineNo]);
1584 static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo)
1586 if (LineNo < pProfile->m_NoLines)
1588 free(pProfile->m_Lines[LineNo]);
1589 pProfile->m_Lines[LineNo]=0;
1590 if (pProfile->m_NoLines - LineNo > 1)
1592 sal_uInt32 i, n;
1593 osl_TProfileSection* pSec;
1595 memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1],
1596 (pProfile->m_NoLines - LineNo - 1) * sizeof(sal_Char *));
1598 memset(&pProfile->m_Lines[pProfile->m_NoLines - 1],
1600 (pProfile->m_MaxLines - pProfile->m_NoLines) * sizeof(sal_Char*));
1602 /* adjust line references */
1603 for (i = 0; i < pProfile->m_NoSections; i++)
1605 pSec = &pProfile->m_Sections[i];
1607 if (pSec->m_Line > LineNo)
1608 pSec->m_Line--;
1610 for (n = 0; n < pSec->m_NoEntries; n++)
1611 if (pSec->m_Entries[n].m_Line > LineNo)
1612 pSec->m_Entries[n].m_Line--;
1615 else
1617 pProfile->m_Lines[LineNo] = 0;
1620 pProfile->m_NoLines--;
1623 return;
1626 static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
1627 sal_uInt32 NoEntry, sal_uInt32 Line,
1628 sal_Char* Entry, sal_uInt32 Len)
1630 Entry = stripBlanks(Entry, &Len);
1631 pSection->m_Entries[NoEntry].m_Line = Line;
1632 pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line];
1633 pSection->m_Entries[NoEntry].m_Len = Len;
1635 return;
1638 static sal_Bool addEntry(osl_TProfileImpl* pProfile,
1639 osl_TProfileSection *pSection,
1640 int Line, sal_Char* Entry,
1641 sal_uInt32 Len)
1643 if (pSection != NULL)
1645 if (pSection->m_NoEntries >= pSection->m_MaxEntries)
1647 if (pSection->m_Entries == NULL)
1649 pSection->m_MaxEntries = ENTRIES_INI;
1650 pSection->m_Entries = (osl_TProfileEntry *)malloc(
1651 pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
1653 else
1655 pSection->m_MaxEntries += ENTRIES_ADD;
1656 pSection->m_Entries = (osl_TProfileEntry *)realloc(pSection->m_Entries,
1657 pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
1660 if (pSection->m_Entries == NULL)
1662 pSection->m_NoEntries = 0;
1663 pSection->m_MaxEntries = 0;
1664 return (sal_False);
1668 pSection->m_NoEntries++;
1670 Entry = stripBlanks(Entry, &Len);
1671 setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line,
1672 Entry, Len);
1674 return (sal_True);
1677 return (sal_False);
1680 static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry)
1682 if (NoEntry < pSection->m_NoEntries)
1684 if (pSection->m_NoEntries - NoEntry > 1)
1686 memmove(&pSection->m_Entries[NoEntry],
1687 &pSection->m_Entries[NoEntry + 1],
1688 (pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry));
1689 pSection->m_Entries[pSection->m_NoEntries - 1].m_Line=0;
1690 pSection->m_Entries[pSection->m_NoEntries - 1].m_Offset=0;
1691 pSection->m_Entries[pSection->m_NoEntries - 1].m_Len=0;
1694 pSection->m_NoEntries--;
1697 return;
1700 static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len)
1702 if (pProfile->m_NoSections >= pProfile->m_MaxSections)
1704 if (pProfile->m_Sections == NULL)
1706 pProfile->m_MaxSections = SECTIONS_INI;
1707 pProfile->m_Sections = (osl_TProfileSection *)malloc(pProfile->m_MaxSections * sizeof(osl_TProfileSection));
1708 memset(pProfile->m_Sections,0,pProfile->m_MaxSections * sizeof(osl_TProfileSection));
1710 else
1712 unsigned int idx=0;
1713 unsigned int oldmax=pProfile->m_MaxSections;
1715 pProfile->m_MaxSections += SECTIONS_ADD;
1716 pProfile->m_Sections = (osl_TProfileSection *)realloc(pProfile->m_Sections,
1717 pProfile->m_MaxSections * sizeof(osl_TProfileSection));
1718 for ( idx = oldmax ; idx < pProfile->m_MaxSections ; ++idx )
1720 pProfile->m_Sections[idx].m_Entries=0;
1724 if (pProfile->m_Sections == NULL)
1726 pProfile->m_NoSections = 0;
1727 pProfile->m_MaxSections = 0;
1728 return (sal_False);
1732 pProfile->m_NoSections++;
1734 if ( pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries != 0 )
1736 free(pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries);
1738 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = NULL;
1739 pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries = 0;
1740 pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0;
1742 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line;
1743 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line];
1744 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len;
1746 return (sal_True);
1749 static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection)
1751 sal_uInt32 Section;
1753 if ((Section = pSection - pProfile->m_Sections) < pProfile->m_NoSections)
1755 free (pSection->m_Entries);
1756 pSection->m_Entries=0;
1757 if (pProfile->m_NoSections - Section > 1)
1759 memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1],
1760 (pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection));
1762 memset(&pProfile->m_Sections[pProfile->m_NoSections - 1],
1764 (pProfile->m_MaxSections - pProfile->m_NoSections) * sizeof(osl_TProfileSection));
1765 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = 0;
1767 else
1769 pSection->m_Entries = 0;
1772 pProfile->m_NoSections--;
1775 return;
1778 static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile,
1779 const sal_Char* Section,
1780 const sal_Char* Entry,
1781 sal_uInt32 *pNoEntry)
1783 static sal_uInt32 Sect = 0;
1784 sal_uInt32 i, n;
1785 sal_uInt32 Len;
1786 const sal_Char* pStr;
1787 osl_TProfileSection* pSec=0;
1789 Len = strlen(Section);
1791 n = Sect;
1793 for (i = 0; i < pProfile->m_NoSections; i++)
1795 n %= pProfile->m_NoSections;
1796 pSec = &pProfile->m_Sections[n];
1797 if ((Len == pSec->m_Len) &&
1798 (strncasecmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len)
1799 == 0))
1800 break;
1801 n++;
1804 Sect = n;
1806 if (i < pProfile->m_NoSections)
1808 Len = strlen(Entry);
1810 *pNoEntry = pSec->m_NoEntries;
1812 for (i = 0; i < pSec->m_NoEntries; i++)
1814 pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
1815 [pSec->m_Entries[i].m_Offset];
1816 if ((Len == pSec->m_Entries[i].m_Len) &&
1817 (strncasecmp(Entry, pStr, pSec->m_Entries[i].m_Len)
1818 == 0))
1820 *pNoEntry = i;
1821 break;
1825 else
1826 pSec = NULL;
1828 return (pSec);
1831 static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile)
1833 sal_uInt32 i;
1834 sal_Char* pStr;
1835 sal_Char* pChar;
1837 sal_Char* pLine;
1838 sal_Char* bWasAdded = NULL;
1841 if ( !pFile )
1843 return sal_False;
1846 if ( !pProfile )
1848 return sal_False;
1851 pProfile->m_NoLines = 0;
1852 pProfile->m_NoSections = 0;
1854 OSL_VERIFY(OslProfile_rewindFile(pFile, sal_False));
1856 while ( ( pLine=OslProfile_getLine(pFile) ) != 0 )
1858 bWasAdded = addLine( pProfile, pLine );
1859 rtl_freeMemory( pLine );
1860 OSL_ASSERT(bWasAdded);
1861 if ( ! bWasAdded )
1862 return (sal_False);
1865 for (i = 0; i < pProfile->m_NoLines; i++)
1867 pStr = (sal_Char *)stripBlanks(pProfile->m_Lines[i], NULL);
1869 if ((*pStr == '\0') || (*pStr == ';'))
1870 continue;
1872 if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == NULL) ||
1873 ((pChar - pStr) <= 2))
1875 /* insert entry */
1877 if (pProfile->m_NoSections < 1)
1878 continue;
1880 if ((pChar = strchr(pStr, '=')) == NULL)
1881 pChar = pStr + strlen(pStr);
1883 if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1],
1884 i, pStr, pChar - pStr))
1886 OSL_ASSERT(0);
1887 continue;
1891 else
1893 /* new section */
1895 if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1))
1897 OSL_ASSERT(0);
1898 continue;
1904 return (sal_True);
1907 static sal_Bool storeProfile(osl_TProfileImpl* pProfile, sal_Bool bCleanup)
1909 #ifdef TRACE_OSL_PROFILE
1910 OSL_TRACE("In storeProfile");
1911 #endif
1913 if (pProfile->m_Lines != NULL)
1915 if (pProfile->m_Flags & FLG_MODIFIED)
1917 sal_uInt32 i;
1919 osl_TFile* pTmpFile = osl_openTmpProfileImpl(pProfile);
1921 if ( pTmpFile == 0 )
1923 return sal_False;
1926 OSL_VERIFY(OslProfile_rewindFile(pTmpFile, sal_True));
1928 for ( i = 0 ; i < pProfile->m_NoLines ; i++ )
1930 OSL_VERIFY(OslProfile_putLine(pTmpFile, pProfile->m_Lines[i]));
1933 if ( ! writeProfileImpl(pTmpFile) )
1935 if ( pTmpFile->m_pWriteBuf != 0 )
1937 free(pTmpFile->m_pWriteBuf);
1940 pTmpFile->m_pWriteBuf=0;
1941 pTmpFile->m_nWriteBufLen=0;
1942 pTmpFile->m_nWriteBufFree=0;
1944 #ifdef TRACE_OSL_PROFILE
1945 OSL_TRACE("Out storeProfile [not flushed]");
1946 #endif
1947 closeFileImpl(pTmpFile,pProfile->m_Flags);
1949 return sal_False;
1952 pProfile->m_Flags &= ~FLG_MODIFIED;
1954 closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
1955 closeFileImpl(pTmpFile,pProfile->m_Flags);
1957 osl_ProfileSwapProfileNames(pProfile);
1959 pProfile->m_pFile = openFileImpl(pProfile->m_FileName,pProfile->m_Flags);
1963 if (bCleanup)
1965 while (pProfile->m_NoLines > 0)
1966 removeLine(pProfile, pProfile->m_NoLines - 1);
1968 free(pProfile->m_Lines);
1969 pProfile->m_Lines = NULL;
1970 pProfile->m_NoLines = 0;
1971 pProfile->m_MaxLines = 0;
1973 while (pProfile->m_NoSections > 0)
1974 removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]);
1976 free(pProfile->m_Sections);
1977 pProfile->m_Sections = NULL;
1978 pProfile->m_NoSections = 0;
1979 pProfile->m_MaxSections = 0;
1983 #ifdef TRACE_OSL_PROFILE
1984 OSL_TRACE("Out storeProfile [ok]");
1985 #endif
1986 return (sal_True);
1989 static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl* pProfile)
1991 osl_TFile* pFile=0;
1992 sal_Char* pszExtension = "tmp";
1993 sal_Char pszTmpName[PATH_MAX];
1994 oslProfileOption PFlags=0;
1996 pszTmpName[0] = '\0';
1998 /* generate tmp profilename */
1999 osl_ProfileGenerateExtension(pProfile->m_FileName, pszExtension, pszTmpName, PATH_MAX);
2001 if ( pszTmpName[0] == 0 )
2003 return 0;
2006 if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) )
2008 PFlags |= osl_Profile_WRITELOCK;
2011 /* open this file */
2012 pFile = openFileImpl(pszTmpName,pProfile->m_Flags | PFlags);
2015 /* return new pFile */
2016 return pFile;
2019 static sal_Bool osl_ProfileSwapProfileNames(osl_TProfileImpl* pProfile)
2021 sal_Bool bRet = sal_False;
2023 sal_Char pszBakFile[PATH_MAX];
2024 sal_Char pszTmpFile[PATH_MAX];
2025 sal_Char pszIniFile[PATH_MAX];
2027 pszBakFile[0] = '\0';
2028 pszTmpFile[0] = '\0';
2029 pszIniFile[0] = '\0';
2031 osl_ProfileGenerateExtension(pProfile->m_FileName, "bak", pszBakFile, PATH_MAX);
2033 strcpy(pszIniFile,pProfile->m_FileName);
2035 osl_ProfileGenerateExtension(pProfile->m_FileName, "tmp", pszTmpFile, PATH_MAX);
2037 /* unlink bak */
2038 unlink( pszBakFile );
2040 /* rename ini bak */
2041 rename( pszIniFile, pszBakFile );
2043 /* rename tmp ini */
2044 rename( pszTmpFile, pszIniFile );
2046 return bRet;
2049 static void osl_ProfileGenerateExtension(const sal_Char* pszFileName, const sal_Char* pszExtension, sal_Char* pszTmpName, int BufferMaxLen)
2051 sal_Char* cursor = pszTmpName;
2052 int len;
2054 /* concatenate filename + "." + extension, limited to the size of the
2055 * output buffer; in case of overrun, data is truncated at the end...
2056 * and the result is always 0-terminated.
2058 len = strlen(pszFileName);
2059 if(len < BufferMaxLen)
2061 memcpy(cursor, pszFileName, len);
2062 cursor += len;
2063 BufferMaxLen -= len;
2065 else
2067 memcpy(cursor, pszFileName, BufferMaxLen - 1);
2068 cursor += BufferMaxLen - 1;
2069 BufferMaxLen = 1;
2071 if(BufferMaxLen > 1)
2073 *cursor++ = '.';
2074 BufferMaxLen -= 1;
2076 len = strlen(pszExtension);
2077 if(len < BufferMaxLen)
2079 memcpy(cursor, pszExtension, len);
2080 cursor += len;
2082 else
2084 memcpy(cursor, pszExtension, BufferMaxLen - 1);
2085 cursor += BufferMaxLen - 1;
2086 BufferMaxLen = 1;
2088 *cursor = 0;
2090 return;
2094 static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable)
2096 osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
2097 oslProfileOption PFlags=0;
2099 if ( bWriteable )
2101 PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK;
2103 else
2105 PFlags = osl_Profile_DEFAULT;
2109 if (pProfile == NULL)
2111 #ifdef DEBUG_OSL_PROFILE
2112 OSL_TRACE("AUTOOPEN MODE");
2113 #endif
2115 if ( ( pProfile = (osl_TProfileImpl*) osl_openProfile(0, PFlags ) ) != NULL )
2117 pProfile->m_Flags |= FLG_AUTOOPEN;
2120 else
2122 #ifdef DEBUG_OSL_PROFILE
2123 OSL_TRACE("try to acquire");
2124 #endif
2126 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
2128 if (! (pProfile->m_Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE )))
2130 osl_TStamp Stamp;
2132 #ifdef DEBUG_OSL_PROFILE
2133 OSL_TRACE("Profile acquire DEFAULT MODE");
2134 #endif
2135 if (! (pProfile->m_pFile = openFileImpl(pProfile->m_FileName, pProfile->m_Flags | PFlags )))
2136 return NULL;
2138 Stamp = OslProfile_getFileStamp(pProfile->m_pFile);
2140 if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp)))
2142 sal_Bool bRet=sal_False;
2144 pProfile->m_Stamp = Stamp;
2146 bRet=loadProfile(pProfile->m_pFile, pProfile);
2147 OSL_ASSERT(bRet);
2148 (void)bRet;
2151 else
2153 #ifdef DEBUG_OSL_PROFILE
2154 OSL_TRACE("Profile acquire READ/WRITELOCK MODE");
2155 #endif
2156 /* A readlock file could not be written */
2157 if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable)
2159 return (NULL);
2165 return (pProfile);
2168 static sal_Bool releaseProfile(osl_TProfileImpl* pProfile)
2170 #ifdef TRACE_OSL_PROFILE
2171 OSL_TRACE("In releaseProfile");
2172 #endif
2174 if ( pProfile == 0 )
2176 #ifdef TRACE_OSL_PROFILE
2177 OSL_TRACE("Out releaseProfile [profile==0]");
2178 #endif
2179 return sal_False;
2182 if (pProfile->m_Flags & FLG_AUTOOPEN)
2184 #ifdef TRACE_OSL_PROFILE
2185 OSL_TRACE("Out releaseProfile [AUTOOPEN]");
2186 #endif
2187 return (osl_closeProfile((oslProfile)pProfile));
2189 else
2191 #ifdef DEBUG_OSL_PROFILE
2192 OSL_TRACE("DEFAULT MODE");
2193 #endif
2194 if (! (pProfile->m_Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE )))
2196 if (pProfile->m_Flags & FLG_MODIFIED)
2198 sal_Bool bRet=storeProfile(pProfile, sal_False);
2199 OSL_ASSERT(bRet);
2200 (void)bRet;
2203 closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
2204 pProfile->m_pFile = NULL;
2208 #ifdef TRACE_OSL_PROFILE
2209 OSL_TRACE("Out releaseProfile [ok]");
2210 #endif
2211 return (sal_True);
2214 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */