Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sal / osl / unx / profile.cxx
blob354fe626f390c19aa887d0c1f86ab77b30b6dc09
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.hxx"
21 #include "readwrite_helper.hxx"
22 #include "file_url.hxx"
23 #include "unixerrnostring.hxx"
25 #include <osl/diagnose.h>
26 #include <osl/profile.h>
27 #include <osl/process.h>
28 #include <osl/thread.h>
29 #include <rtl/alloc.h>
30 #include <sal/log.hxx>
32 #define LINES_INI 32
33 #define LINES_ADD 10
34 #define SECTIONS_INI 5
35 #define SECTIONS_ADD 3
36 #define ENTRIES_INI 5
37 #define ENTRIES_ADD 3
39 #define STR_INI_BOOLYES "yes"
40 #define STR_INI_BOOLON "on"
41 #define STR_INI_BOOLONE "1"
42 #define STR_INI_BOOLNO "no"
43 #define STR_INI_BOOLOFF "off"
44 #define STR_INI_BOOLZERO "0"
46 #define FLG_USER 0x00FF
47 #define FLG_AUTOOPEN 0x0100
48 #define FLG_MODIFIED 0x0200
50 #define DEFAULT_PMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
52 typedef time_t osl_TStamp;
54 namespace {
56 enum osl_TLockMode
58 un_lock, read_lock, write_lock
61 struct osl_TFile
63 int m_Handle;
64 char* m_pReadPtr;
65 char m_ReadBuf[512];
66 char* m_pWriteBuf;
67 sal_uInt32 m_nWriteBufLen;
68 sal_uInt32 m_nWriteBufFree;
71 struct osl_TProfileEntry
73 sal_uInt32 m_Line;
74 sal_uInt32 m_Offset;
75 sal_uInt32 m_Len;
78 struct osl_TProfileSection
80 sal_uInt32 m_Line;
81 sal_uInt32 m_Offset;
82 sal_uInt32 m_Len;
83 sal_uInt32 m_NoEntries;
84 sal_uInt32 m_MaxEntries;
85 osl_TProfileEntry* m_Entries;
88 /* Profile-data structure hidden behind oslProfile: */
89 struct osl_TProfileImpl
91 sal_uInt32 m_Flags;
92 osl_TFile* m_pFile;
93 osl_TStamp m_Stamp;
94 char m_FileName[PATH_MAX + 1];
95 sal_uInt32 m_NoLines;
96 sal_uInt32 m_MaxLines;
97 sal_uInt32 m_NoSections;
98 sal_uInt32 m_MaxSections;
99 char** m_Lines;
100 osl_TProfileSection* m_Sections;
101 pthread_mutex_t m_AccessLock;
102 bool m_bIsValid;
107 static osl_TFile* openFileImpl(const char* pszFilename, oslProfileOption ProfileFlags);
108 static osl_TStamp closeFileImpl(osl_TFile* pFile, oslProfileOption Flags);
109 static bool OslProfile_lockFile(const osl_TFile* pFile, osl_TLockMode eMode);
110 static bool OslProfile_rewindFile(osl_TFile* pFile, bool bTruncate);
111 static osl_TStamp OslProfile_getFileStamp(osl_TFile* pFile);
113 static char* OslProfile_getLine(osl_TFile* pFile);
114 static bool OslProfile_putLine(osl_TFile* pFile, const char *pszLine);
115 static char* stripBlanks(char* String, sal_uInt32* pLen);
116 static char* addLine(osl_TProfileImpl* pProfile, const char* Line);
117 static char* insertLine(osl_TProfileImpl* pProfile, const char* Line, sal_uInt32 LineNo);
118 static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo);
119 static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
120 sal_uInt32 NoEntry, sal_uInt32 Line,
121 char* Entry, sal_uInt32 Len);
122 static bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
123 int Line, char* Entry, sal_uInt32 Len);
124 static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry);
125 static bool addSection(osl_TProfileImpl* pProfile, int Line, const char* Section, sal_uInt32 Len);
126 static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection);
127 static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const char* Section,
128 const char* Entry, sal_uInt32 *pNoEntry);
129 static bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile);
130 static bool storeProfile(osl_TProfileImpl* pProfile, bool bCleanup);
131 static osl_TProfileImpl* acquireProfile(oslProfile Profile, bool bWriteable);
132 static bool releaseProfile(osl_TProfileImpl* pProfile);
134 static bool writeProfileImpl (osl_TFile* pFile);
135 static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl*);
136 static bool osl_ProfileSwapProfileNames(osl_TProfileImpl*);
137 static void osl_ProfileGenerateExtension(const char* pszFileName, const char* pszExtension, char* pszTmpName, int BufferMaxLen);
138 static oslProfile osl_psz_openProfile(const char *pszProfileName, oslProfileOption Flags);
140 oslProfile SAL_CALL osl_openProfile(rtl_uString *ustrProfileName, oslProfileOption Options)
142 char profilePath[PATH_MAX] = "";
143 return
144 (ustrProfileName == nullptr
145 || ustrProfileName->buffer[0] == 0
146 || (FileURLToPath(profilePath, PATH_MAX, ustrProfileName)
147 == osl_File_E_None))
148 ? osl_psz_openProfile(profilePath, Options)
149 : nullptr;
152 static oslProfile osl_psz_openProfile(const char *pszProfileName, oslProfileOption Flags)
154 osl_TFile* pFile;
155 osl_TProfileImpl* pProfile;
156 bool bRet = false;
158 if ( ( pFile = openFileImpl(pszProfileName, Flags ) ) == nullptr )
160 return nullptr;
163 pProfile = static_cast<osl_TProfileImpl*>(calloc(1, sizeof(osl_TProfileImpl)));
165 if ( pProfile == nullptr )
167 closeFileImpl(pFile, Flags);
168 return nullptr;
171 pProfile->m_Flags = Flags & FLG_USER;
173 if ( Flags & ( osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
175 pProfile->m_pFile = pFile;
178 pthread_mutex_init(&(pProfile->m_AccessLock),PTHREAD_MUTEXATTR_DEFAULT);
179 pProfile->m_bIsValid = true;
181 pProfile->m_Stamp = OslProfile_getFileStamp(pFile);
182 bRet=loadProfile(pFile, pProfile);
183 bRet &= realpath(pszProfileName, pProfile->m_FileName) != nullptr;
184 SAL_WARN_IF(!bRet, "sal.osl", "realpath(pszProfileName, pProfile->m_FileName) != NULL ==> false");
186 if (pProfile->m_pFile == nullptr)
187 closeFileImpl(pFile,pProfile->m_Flags);
189 // coverity[leaked_storage] - pFile is not leaked
190 return pProfile;
193 sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile)
195 osl_TProfileImpl* pProfile = static_cast<osl_TProfileImpl*>(Profile);
196 osl_TProfileImpl* pTmpProfile;
198 if ( Profile == nullptr )
200 return false;
203 pthread_mutex_lock(&(pProfile->m_AccessLock));
205 if ( !pProfile->m_bIsValid )
207 SAL_WARN("sal.osl", "!pProfile->m_bIsValid");
208 pthread_mutex_unlock(&(pProfile->m_AccessLock));
210 return false;
213 pProfile->m_bIsValid = false;
215 if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) && ( pProfile->m_Flags & FLG_MODIFIED ) )
217 pTmpProfile = acquireProfile(Profile, true);
219 if ( pTmpProfile != nullptr )
221 bool bRet = storeProfile(pTmpProfile, true);
222 SAL_WARN_IF(!bRet, "sal.osl", "storeProfile(pTmpProfile, true) ==> false");
225 else
227 pTmpProfile = acquireProfile(Profile, false);
230 if ( pTmpProfile == nullptr )
232 pthread_mutex_unlock(&(pProfile->m_AccessLock));
234 SAL_INFO("sal.osl", "Out osl_closeProfile [pProfile==0]");
235 return false;
238 pProfile = pTmpProfile;
240 if (pProfile->m_pFile != nullptr)
241 closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
243 pProfile->m_pFile = nullptr;
244 pProfile->m_FileName[0] = '\0';
246 /* release whole profile data types memory */
247 if ( pProfile->m_NoLines > 0)
249 unsigned int idx=0;
250 if ( pProfile->m_Lines != nullptr )
252 for ( idx = 0 ; idx < pProfile->m_NoLines ; ++idx)
254 if ( pProfile->m_Lines[idx] != nullptr )
256 free(pProfile->m_Lines[idx]);
257 pProfile->m_Lines[idx]=nullptr;
260 free(pProfile->m_Lines);
261 pProfile->m_Lines=nullptr;
263 if ( pProfile->m_Sections != nullptr )
265 /*osl_TProfileSection* pSections=pProfile->m_Sections;*/
266 for ( idx = 0 ; idx < pProfile->m_NoSections ; ++idx )
268 if ( pProfile->m_Sections[idx].m_Entries != nullptr )
270 free(pProfile->m_Sections[idx].m_Entries);
271 pProfile->m_Sections[idx].m_Entries=nullptr;
274 free(pProfile->m_Sections);
275 pProfile->m_Sections=nullptr;
279 pthread_mutex_unlock(&(pProfile->m_AccessLock));
281 pthread_mutex_destroy(&(pProfile->m_AccessLock));
283 free(pProfile);
285 return true;
288 sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile)
290 osl_TProfileImpl* pProfile = static_cast<osl_TProfileImpl*>(Profile);
291 osl_TFile* pFile;
292 bool bRet = false;
294 if ( pProfile == nullptr )
296 return false;
299 pthread_mutex_lock(&(pProfile->m_AccessLock));
301 if ( !pProfile->m_bIsValid )
303 SAL_WARN_IF(!pProfile->m_bIsValid, "sal.osl", "!pProfile->m_bIsValid");
304 pthread_mutex_unlock(&(pProfile->m_AccessLock));
305 return false;
308 pFile = pProfile->m_pFile;
309 if ( pFile == nullptr || pFile->m_Handle < 0 )
311 pthread_mutex_unlock(&(pProfile->m_AccessLock));
313 return false;
316 if ( pProfile->m_Flags & FLG_MODIFIED )
318 bRet = storeProfile(pProfile, false);
319 SAL_WARN_IF(!bRet, "sal.osl", "storeProfile(pProfile, false) ==> false");
322 pthread_mutex_unlock(&(pProfile->m_AccessLock));
323 return bRet;
326 static bool writeProfileImpl(osl_TFile* pFile)
328 if ( pFile == nullptr || pFile->m_Handle < 0 || pFile->m_pWriteBuf == nullptr )
330 return false;
333 SAL_WARN_IF(
334 (strlen(pFile->m_pWriteBuf)
335 != pFile->m_nWriteBufLen - pFile->m_nWriteBufFree),
336 "sal.osl",
337 strlen(pFile->m_pWriteBuf) << " != "
338 << (pFile->m_nWriteBufLen - pFile->m_nWriteBufFree));
340 if ( !safeWrite(pFile->m_Handle, pFile->m_pWriteBuf, pFile->m_nWriteBufLen - pFile->m_nWriteBufFree) )
342 SAL_INFO("sal.osl", "write failed: " << UnixErrnoString(errno));
343 return false;
346 free(pFile->m_pWriteBuf);
347 pFile->m_pWriteBuf=nullptr;
348 pFile->m_nWriteBufLen=0;
349 pFile->m_nWriteBufFree=0;
351 return true;
354 sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile,
355 const char* pszSection,
356 const char* pszEntry,
357 char* pszString,
358 sal_uInt32 MaxLen,
359 const char* pszDefault)
361 sal_uInt32 NoEntry;
362 char* pStr=nullptr;
363 osl_TProfileImpl* pProfile=nullptr;
364 osl_TProfileImpl* pTmpProfile=nullptr;
365 bool bRet = false;
367 pTmpProfile = static_cast<osl_TProfileImpl*>(Profile);
369 if ( pTmpProfile == nullptr )
371 return false;
374 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
376 if ( !pTmpProfile->m_bIsValid )
378 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
380 return false;
383 pProfile = acquireProfile(Profile, false);
385 if ( pProfile == nullptr )
387 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
389 return false;
392 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
394 osl_TProfileSection* pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry);
395 if ((pSec != nullptr) &&
396 (NoEntry < pSec->m_NoEntries) &&
397 ((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line],
398 '=')) != nullptr))
400 pStr++;
402 else
404 pStr=const_cast<char*>(pszDefault);
407 if ( pStr != nullptr )
409 pStr = stripBlanks(pStr, nullptr);
410 MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr);
411 pStr = stripBlanks(pStr, &MaxLen);
412 strncpy(pszString, pStr, MaxLen);
413 pszString[MaxLen] = '\0';
416 else
417 { /* not implemented */ }
419 bRet=releaseProfile(pProfile);
420 SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
422 if ( pStr == nullptr )
424 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
426 return false;
429 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
431 return true;
434 sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile,
435 const char* pszSection,
436 const char* pszEntry,
437 sal_Bool Default)
439 char Line[32];
440 Line[0] = '\0';
442 if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
444 if ((strcasecmp(Line, STR_INI_BOOLYES) == 0) ||
445 (strcasecmp(Line, STR_INI_BOOLON) == 0) ||
446 (strcasecmp(Line, STR_INI_BOOLONE) == 0))
447 Default = true;
448 else
449 if ((strcasecmp(Line, STR_INI_BOOLNO) == 0) ||
450 (strcasecmp(Line, STR_INI_BOOLOFF) == 0) ||
451 (strcasecmp(Line, STR_INI_BOOLZERO) == 0))
452 Default = false;
455 return Default;
458 sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile,
459 const char* pszSection,
460 const char* pszEntry,
461 sal_uInt32 FirstId,
462 const char* Strings[],
463 sal_uInt32 Default)
465 sal_uInt32 i;
466 char Line[256];
467 Line[0] = '\0';
469 if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
471 i = 0;
472 while (Strings[i] != nullptr)
474 if (strcasecmp(Line, Strings[i]) == 0)
476 Default = i + FirstId;
477 break;
479 i++;
483 return Default;
486 sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile,
487 const char* pszSection,
488 const char* pszEntry,
489 const char* pszString)
491 bool bRet = false;
492 sal_uInt32 NoEntry;
493 char* pStr;
494 char* Line = nullptr;
495 osl_TProfileImpl* pProfile = nullptr;
496 osl_TProfileImpl* pTmpProfile = static_cast<osl_TProfileImpl*>(Profile);
498 if ( pTmpProfile == nullptr )
500 return false;
503 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
505 if ( !pTmpProfile->m_bIsValid )
507 SAL_WARN_IF(!pTmpProfile->m_bIsValid, "sal.osl", "!pTmpProfile->m_bIsValid");
508 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
510 return false;
513 pProfile=acquireProfile(Profile, true);
515 if (pProfile == nullptr)
517 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
519 return false;
522 Line = static_cast<char*>(malloc(strlen(pszEntry)+strlen(pszString)+48));
524 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
526 osl_TProfileSection* pSec;
527 if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == nullptr)
529 Line[0] = '\0';
530 addLine(pProfile, Line);
532 Line[0] = '[';
533 strcpy(&Line[1], pszSection);
534 Line[1 + strlen(pszSection)] = ']';
535 Line[2 + strlen(pszSection)] = '\0';
537 pStr = addLine(pProfile, Line);
538 if ((pStr == nullptr) ||
539 (! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection))))
541 bRet=releaseProfile(pProfile);
542 SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
544 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
546 free(Line);
547 return false;
550 pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1];
551 NoEntry = pSec->m_NoEntries;
554 Line[0] = '\0';
555 strcpy(&Line[0], pszEntry);
556 Line[0 + strlen(pszEntry)] = '=';
557 strcpy(&Line[1 + strlen(pszEntry)], pszString);
559 if (NoEntry >= pSec->m_NoEntries)
561 sal_uInt32 i;
562 if (pSec->m_NoEntries > 0)
563 i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1;
564 else
565 i = pSec->m_Line + 1;
567 pStr = insertLine(pProfile, Line, i);
568 if ((pStr == nullptr) ||
569 (! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry))))
571 bRet=releaseProfile(pProfile);
572 SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
574 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
575 free(Line);
577 return false;
580 pProfile->m_Flags |= FLG_MODIFIED;
582 else
584 sal_uInt32 i = pSec->m_Entries[NoEntry].m_Line;
585 free(pProfile->m_Lines[i]);
586 pProfile->m_Lines[i] = strdup(Line);
587 setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry));
589 pProfile->m_Flags |= FLG_MODIFIED;
592 else {
593 /* not implemented */
596 bRet = releaseProfile(pProfile);
597 SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
599 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
600 if ( Line!= nullptr )
602 free(Line);
605 return bRet;
608 sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile,
609 const char* pszSection,
610 const char* pszEntry,
611 sal_Bool Value)
613 bool bRet = false;
615 if (Value)
616 bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE);
617 else
618 bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO);
620 return bRet;
623 sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile,
624 const char* pszSection,
625 const char* pszEntry,
626 sal_uInt32 FirstId,
627 const char* Strings[],
628 sal_uInt32 Value)
630 int i, n = 0;
631 bool bRet = false;
633 while (Strings[n] != nullptr)
634 ++n;
636 if ((i = Value - FirstId) >= n)
637 bRet = false;
638 else
639 bRet = osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]);
641 return bRet;
644 sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile,
645 const char *pszSection,
646 const char *pszEntry)
648 sal_uInt32 NoEntry;
649 osl_TProfileImpl* pProfile = nullptr;
650 osl_TProfileImpl* pTmpProfile = nullptr;
651 bool bRet = false;
653 pTmpProfile = static_cast<osl_TProfileImpl*>(Profile);
655 if ( pTmpProfile == nullptr )
657 return false;
660 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
662 if ( !pTmpProfile->m_bIsValid )
664 SAL_WARN_IF(!pTmpProfile->m_bIsValid, "sal.osl", "!pTmpProfile->m_bIsValid");
665 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
666 return false;
669 pProfile = acquireProfile(Profile, true);
671 if (pProfile == nullptr)
673 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
675 return false;
678 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
680 osl_TProfileSection* pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry);
681 if ((pSec != nullptr) &&
682 (NoEntry < pSec->m_NoEntries))
684 removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line);
685 removeEntry(pSec, NoEntry);
686 if (pSec->m_NoEntries == 0)
688 removeLine(pProfile, pSec->m_Line);
690 /* remove any empty separation line */
691 if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0'))
692 removeLine(pProfile, pSec->m_Line - 1);
694 removeSection(pProfile, pSec);
697 pProfile->m_Flags |= FLG_MODIFIED;
700 else
701 { /* not implemented */ }
703 bRet = releaseProfile(pProfile);
704 SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
706 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
708 return bRet;
711 sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile,
712 const char *pszSection,
713 char* pszBuffer,
714 sal_uInt32 MaxLen)
716 sal_uInt32 i, n = 0;
717 sal_uInt32 NoEntry;
718 osl_TProfileImpl* pProfile = nullptr;
719 osl_TProfileImpl* pTmpProfile = nullptr;
720 bool bRet = false;
722 pTmpProfile = static_cast<osl_TProfileImpl*>(Profile);
724 if ( pTmpProfile == nullptr )
726 return 0;
730 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
732 if ( !pTmpProfile->m_bIsValid )
734 SAL_WARN_IF(!pTmpProfile->m_bIsValid, "sal.osl", "!pTmpProfile->m_bIsValid");
736 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
738 return 0;
741 pProfile = acquireProfile(Profile, false);
743 if (pProfile == nullptr)
745 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
747 return 0;
750 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
752 osl_TProfileSection* pSec;
753 if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != nullptr)
755 if (MaxLen != 0)
757 for (i = 0; i < pSec->m_NoEntries; i++)
759 if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen)
761 strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
762 [pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len);
763 n += pSec->m_Entries[i].m_Len;
764 pszBuffer[n++] = '\0';
766 else
767 break;
771 pszBuffer[n++] = '\0';
773 else
775 for (i = 0; i < pSec->m_NoEntries; i++)
776 n += pSec->m_Entries[i].m_Len + 1;
778 n += 1;
781 else
782 n = 0;
784 else {
785 /* not implemented */
788 bRet=releaseProfile(pProfile);
789 SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
791 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
793 return n;
796 sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile,
797 char* pszBuffer,
798 sal_uInt32 MaxLen)
800 sal_uInt32 i, n = 0;
801 osl_TProfileImpl* pProfile = nullptr;
802 osl_TProfileImpl* pTmpProfile = nullptr;
803 bool bRet = false;
805 pTmpProfile = static_cast<osl_TProfileImpl*>(Profile);
807 if ( pTmpProfile == nullptr )
809 return 0;
812 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
814 if ( !pTmpProfile->m_bIsValid )
816 SAL_WARN_IF(!pTmpProfile->m_bIsValid, "sal.osl", "!pTmpProfile->m_bIsValid");
817 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
819 return 0;
822 pProfile = acquireProfile(Profile, false);
824 if (pProfile == nullptr)
826 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
828 return 0;
831 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
833 if (MaxLen != 0)
835 for (i = 0; i < pProfile->m_NoSections; i++)
837 osl_TProfileSection* pSec = &pProfile->m_Sections[i];
839 if ((n + pSec->m_Len + 1) < MaxLen)
841 strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset],
842 pSec->m_Len);
843 n += pSec->m_Len;
844 pszBuffer[n++] = '\0';
846 else
847 break;
850 pszBuffer[n++] = '\0';
852 else
854 for (i = 0; i < pProfile->m_NoSections; i++)
855 n += pProfile->m_Sections[i].m_Len + 1;
857 n += 1;
860 else
861 { /* not implemented */ }
863 bRet=releaseProfile(pProfile);
864 SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
866 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
868 return n;
871 static osl_TStamp OslProfile_getFileStamp(osl_TFile* pFile)
873 struct stat status;
875 if ( (pFile->m_Handle < 0) || (fstat(pFile->m_Handle, &status) < 0) )
877 return 0;
880 return status.st_mtime;
883 static bool OslProfile_lockFile(const osl_TFile* pFile, osl_TLockMode eMode)
885 struct flock lock;
886 static bool const bLockingDisabled = getenv( "STAR_PROFILE_LOCKING_DISABLED" ) != nullptr;
888 if (pFile->m_Handle < 0)
890 return false;
893 if ( bLockingDisabled )
895 return true;
898 lock.l_start = 0;
899 lock.l_whence = SEEK_SET;
900 lock.l_len = 0;
902 switch (eMode)
904 case un_lock:
905 lock.l_type = F_UNLCK;
906 break;
908 case read_lock:
909 lock.l_type = F_RDLCK;
910 break;
912 case write_lock:
913 lock.l_type = F_WRLCK;
914 break;
917 #ifndef MACOSX
918 if ( fcntl(pFile->m_Handle, F_SETLKW, &lock) == -1 )
919 #else
920 /* Mac OSX will return ENOTSUP for webdav drives so we should ignore it */
921 if ( fcntl(pFile->m_Handle, F_SETLKW, &lock) == -1 && errno != ENOTSUP )
922 #endif
924 SAL_INFO("sal.osl", "fcntl failed: " << UnixErrnoString(errno));
925 return false;
928 return true;
931 static osl_TFile* openFileImpl(const char* pszFilename, oslProfileOption ProfileFlags )
933 int Flags;
934 osl_TFile* pFile = static_cast<osl_TFile*>(calloc(1, sizeof(osl_TFile)));
935 bool bWriteable = false;
937 if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
939 bWriteable = true;
942 if (! bWriteable)
944 pFile->m_Handle = open(pszFilename, O_RDONLY);
946 if (pFile->m_Handle == -1)
948 int e = errno;
949 SAL_INFO("sal.file", "open(" << pszFilename << ",O_RDONLY): " << UnixErrnoString(e));
951 else
952 SAL_INFO("sal.file", "open(" << pszFilename << ",O_RDONLY) => " << pFile->m_Handle);
954 /* mfe: argghh!!! do not check if the file could be opened */
955 /* default mode expects it that way!!! */
957 else
959 if (((pFile->m_Handle = open(pszFilename, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PMODE)) < 0) &&
960 ((pFile->m_Handle = open(pszFilename, O_RDWR)) < 0))
962 int e = errno;
963 SAL_INFO("sal.file", "open(" << pszFilename << ",...): " << UnixErrnoString(e));
964 free(pFile);
965 return nullptr;
967 else
968 SAL_INFO("sal.file", "open(" << pszFilename << ",...) => " << pFile->m_Handle);
971 /* set close-on-exec flag */
972 if ((Flags = fcntl(pFile->m_Handle, F_GETFD, 0)) != -1)
974 Flags |= FD_CLOEXEC;
975 int e = fcntl(pFile->m_Handle, F_SETFD, Flags);
976 SAL_INFO_IF(
977 e != 0, "sal.osl",
978 "fcntl to set FD_CLOEXEC failed for " << pszFilename);
981 pFile->m_pWriteBuf=nullptr;
982 pFile->m_nWriteBufFree=0;
983 pFile->m_nWriteBufLen=0;
985 if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
987 OslProfile_lockFile(pFile, bWriteable ? write_lock : read_lock);
990 return pFile;
993 static osl_TStamp closeFileImpl(osl_TFile* pFile, oslProfileOption Flags)
995 osl_TStamp stamp = 0;
997 if ( pFile == nullptr )
999 return stamp;
1002 if ( pFile->m_Handle >= 0 )
1004 stamp = OslProfile_getFileStamp(pFile);
1006 if ( Flags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
1008 OslProfile_lockFile(pFile, un_lock);
1011 close(pFile->m_Handle);
1012 SAL_INFO("sal.file", "close(" << pFile->m_Handle << ")");
1013 pFile->m_Handle = -1;
1016 if ( pFile->m_pWriteBuf )
1018 free(pFile->m_pWriteBuf);
1021 free(pFile);
1023 return stamp;
1026 static bool OslProfile_rewindFile(osl_TFile* pFile, bool bTruncate)
1028 bool bRet = true;
1030 if (pFile->m_Handle >= 0)
1032 pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1034 bRet = (lseek(pFile->m_Handle, SEEK_SET, 0) == 0);
1036 if (bTruncate)
1038 bRet &= (ftruncate(pFile->m_Handle, 0) == 0);
1043 return bRet;
1046 static char* OslProfile_getLine(osl_TFile* pFile)
1048 int Max, Free, nLineBytes = 0;
1049 char* pChr;
1050 char* pLine = nullptr;
1051 char* pNewLine;
1053 if ( pFile == nullptr )
1055 return nullptr;
1058 if (pFile->m_Handle < 0)
1059 return nullptr;
1063 int Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf);
1065 if (Bytes <= 1)
1067 /* refill buffer */
1068 memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes);
1069 pFile->m_pReadPtr = pFile->m_ReadBuf;
1071 Free = sizeof(pFile->m_ReadBuf) - Bytes;
1073 if ((Max = read(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free)) < 0)
1075 SAL_INFO("sal.osl", "read failed: " << UnixErrnoString(errno));
1077 if( pLine )
1078 free( pLine );
1079 pLine = nullptr;
1080 break;
1083 if (Max < Free)
1085 if ((Max == 0) && ! pLine)
1086 break;
1088 pFile->m_ReadBuf[Bytes + Max] = '\0';
1092 for (pChr = pFile->m_pReadPtr;
1093 (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') &&
1094 (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1));
1095 pChr++);
1097 Max = pChr - pFile->m_pReadPtr;
1098 pNewLine = static_cast<char*>(malloc( nLineBytes + Max + 1 ));
1099 if( pLine )
1101 memcpy( pNewLine, pLine, nLineBytes );
1102 free( pLine );
1104 memcpy(pNewLine+nLineBytes, pFile->m_pReadPtr, Max);
1105 nLineBytes += Max;
1106 pNewLine[ nLineBytes ] = 0;
1107 pLine = pNewLine;
1109 if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1))
1111 if (*pChr != '\0')
1113 if ((pChr[0] == '\r') && (pChr[1] == '\n'))
1114 pChr += 2;
1115 else
1116 pChr += 1;
1119 if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) &&
1120 (*pChr == '\0'))
1121 pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1123 /* setting Max to -1 indicates terminating read loop */
1124 Max = -1;
1127 pFile->m_pReadPtr = pChr;
1129 while (Max > 0) ;
1131 return pLine;
1134 static bool OslProfile_putLine(osl_TFile* pFile, const char *pszLine)
1136 unsigned int Len = strlen(pszLine);
1138 if ( pFile == nullptr || pFile->m_Handle < 0 )
1140 return false;
1143 if ( pFile->m_pWriteBuf == nullptr )
1145 pFile->m_pWriteBuf = static_cast<char*>(malloc(Len+3));
1146 pFile->m_nWriteBufLen = Len+3;
1147 pFile->m_nWriteBufFree = Len+3;
1149 else
1151 if ( pFile->m_nWriteBufFree <= Len + 3 )
1153 char* pTmp;
1155 pTmp=static_cast<char*>(realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) ));
1156 if ( pTmp == nullptr )
1158 return false;
1160 pFile->m_pWriteBuf = pTmp;
1161 pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len );
1162 pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2;
1163 memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree);
1167 memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1);
1168 pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\n';
1169 pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\0';
1171 pFile->m_nWriteBufFree-=Len+1;
1173 return true;
1176 static char* stripBlanks(char* String, sal_uInt32* pLen)
1178 if ( ( pLen != nullptr ) && ( *pLen != 0 ) )
1180 while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t'))
1181 (*pLen)--;
1183 while ( (*String == ' ') || (*String == '\t') )
1185 String++;
1186 (*pLen)--;
1189 else
1190 while ( (*String == ' ') || (*String == '\t') )
1191 String++;
1193 return String;
1196 static char* addLine(osl_TProfileImpl* pProfile, const char* Line)
1198 if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1200 if (pProfile->m_Lines == nullptr)
1202 pProfile->m_MaxLines = LINES_INI;
1203 pProfile->m_Lines = static_cast<char **>(calloc(pProfile->m_MaxLines, sizeof(char *)));
1205 else
1207 unsigned int idx=0;
1208 unsigned int oldmax=pProfile->m_MaxLines;
1210 pProfile->m_MaxLines += LINES_ADD;
1211 pProfile->m_Lines = static_cast<char **>(realloc(pProfile->m_Lines,
1212 pProfile->m_MaxLines * sizeof(char *)));
1213 for ( idx = oldmax ; idx < pProfile->m_MaxLines ; ++idx )
1215 pProfile->m_Lines[idx]=nullptr;
1219 if (pProfile->m_Lines == nullptr)
1221 pProfile->m_NoLines = 0;
1222 pProfile->m_MaxLines = 0;
1223 return nullptr;
1226 if ( pProfile->m_Lines[pProfile->m_NoLines] != nullptr )
1228 free(pProfile->m_Lines[pProfile->m_NoLines]);
1230 pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line);
1232 return pProfile->m_Lines[pProfile->m_NoLines - 1];
1235 static char* insertLine(osl_TProfileImpl* pProfile, const char* Line, sal_uInt32 LineNo)
1237 if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1239 if (pProfile->m_Lines == nullptr)
1241 pProfile->m_MaxLines = LINES_INI;
1242 pProfile->m_Lines = static_cast<char **>(calloc(pProfile->m_MaxLines, sizeof(char *)));
1244 else
1246 pProfile->m_MaxLines += LINES_ADD;
1247 pProfile->m_Lines = static_cast<char **>(realloc(pProfile->m_Lines,
1248 pProfile->m_MaxLines * sizeof(char *)));
1250 memset(&pProfile->m_Lines[pProfile->m_NoLines],
1252 (pProfile->m_MaxLines - pProfile->m_NoLines - 1) * sizeof(char*));
1255 if (pProfile->m_Lines == nullptr)
1257 pProfile->m_NoLines = 0;
1258 pProfile->m_MaxLines = 0;
1259 return nullptr;
1263 LineNo = std::min(LineNo, pProfile->m_NoLines);
1265 if (LineNo < pProfile->m_NoLines)
1267 sal_uInt32 i, n;
1269 memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo],
1270 (pProfile->m_NoLines - LineNo) * sizeof(char *));
1272 /* adjust line references */
1273 for (i = 0; i < pProfile->m_NoSections; i++)
1275 osl_TProfileSection* pSec = &pProfile->m_Sections[i];
1277 if (pSec->m_Line >= LineNo)
1278 pSec->m_Line++;
1280 for (n = 0; n < pSec->m_NoEntries; n++)
1281 if (pSec->m_Entries[n].m_Line >= LineNo)
1282 pSec->m_Entries[n].m_Line++;
1286 pProfile->m_NoLines++;
1288 pProfile->m_Lines[LineNo] = strdup(Line);
1290 return pProfile->m_Lines[LineNo];
1293 static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo)
1295 if (LineNo >= pProfile->m_NoLines)
1296 return;
1298 free(pProfile->m_Lines[LineNo]);
1299 pProfile->m_Lines[LineNo]=nullptr;
1300 if (pProfile->m_NoLines - LineNo > 1)
1302 sal_uInt32 i, n;
1304 memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1],
1305 (pProfile->m_NoLines - LineNo - 1) * sizeof(char *));
1307 memset(&pProfile->m_Lines[pProfile->m_NoLines - 1],
1309 (pProfile->m_MaxLines - pProfile->m_NoLines) * sizeof(char*));
1311 /* adjust line references */
1312 for (i = 0; i < pProfile->m_NoSections; i++)
1314 osl_TProfileSection* pSec = &pProfile->m_Sections[i];
1316 if (pSec->m_Line > LineNo)
1317 pSec->m_Line--;
1319 for (n = 0; n < pSec->m_NoEntries; n++)
1320 if (pSec->m_Entries[n].m_Line > LineNo)
1321 pSec->m_Entries[n].m_Line--;
1324 else
1326 pProfile->m_Lines[LineNo] = nullptr;
1329 pProfile->m_NoLines--;
1332 static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
1333 sal_uInt32 NoEntry, sal_uInt32 Line,
1334 char* Entry, sal_uInt32 Len)
1336 Entry = stripBlanks(Entry, &Len);
1337 pSection->m_Entries[NoEntry].m_Line = Line;
1338 pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line];
1339 pSection->m_Entries[NoEntry].m_Len = Len;
1342 static bool addEntry(osl_TProfileImpl* pProfile,
1343 osl_TProfileSection *pSection,
1344 int Line, char* Entry,
1345 sal_uInt32 Len)
1347 if (pSection != nullptr)
1349 if (pSection->m_NoEntries >= pSection->m_MaxEntries)
1351 if (pSection->m_Entries == nullptr)
1353 pSection->m_MaxEntries = ENTRIES_INI;
1354 pSection->m_Entries = static_cast<osl_TProfileEntry *>(malloc(
1355 pSection->m_MaxEntries * sizeof(osl_TProfileEntry)));
1357 else
1359 pSection->m_MaxEntries += ENTRIES_ADD;
1360 pSection->m_Entries = static_cast<osl_TProfileEntry *>(realloc(pSection->m_Entries,
1361 pSection->m_MaxEntries * sizeof(osl_TProfileEntry)));
1364 if (pSection->m_Entries == nullptr)
1366 pSection->m_NoEntries = 0;
1367 pSection->m_MaxEntries = 0;
1368 return false;
1372 pSection->m_NoEntries++;
1374 Entry = stripBlanks(Entry, &Len);
1375 setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line,
1376 Entry, Len);
1378 return true;
1381 return false;
1384 static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry)
1386 if (NoEntry >= pSection->m_NoEntries)
1387 return;
1389 if (pSection->m_NoEntries - NoEntry > 1)
1391 memmove(&pSection->m_Entries[NoEntry],
1392 &pSection->m_Entries[NoEntry + 1],
1393 (pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry));
1394 pSection->m_Entries[pSection->m_NoEntries - 1].m_Line=0;
1395 pSection->m_Entries[pSection->m_NoEntries - 1].m_Offset=0;
1396 pSection->m_Entries[pSection->m_NoEntries - 1].m_Len=0;
1399 pSection->m_NoEntries--;
1403 static bool addSection(osl_TProfileImpl* pProfile, int Line, const char* Section, sal_uInt32 Len)
1405 if (pProfile->m_NoSections >= pProfile->m_MaxSections)
1407 if (pProfile->m_Sections == nullptr)
1409 pProfile->m_MaxSections = SECTIONS_INI;
1410 pProfile->m_Sections = static_cast<osl_TProfileSection *>(calloc(pProfile->m_MaxSections, sizeof(osl_TProfileSection)));
1412 else
1414 unsigned int idx=0;
1415 unsigned int oldmax=pProfile->m_MaxSections;
1417 pProfile->m_MaxSections += SECTIONS_ADD;
1418 pProfile->m_Sections = static_cast<osl_TProfileSection *>(realloc(pProfile->m_Sections,
1419 pProfile->m_MaxSections * sizeof(osl_TProfileSection)));
1420 for ( idx = oldmax ; idx < pProfile->m_MaxSections ; ++idx )
1422 pProfile->m_Sections[idx].m_Entries=nullptr;
1426 if (pProfile->m_Sections == nullptr)
1428 pProfile->m_NoSections = 0;
1429 pProfile->m_MaxSections = 0;
1430 return false;
1434 pProfile->m_NoSections++;
1436 if ( pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries != nullptr )
1438 free(pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries);
1440 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = nullptr;
1441 pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries = 0;
1442 pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0;
1444 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line;
1445 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line];
1446 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len;
1448 return true;
1451 static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection)
1453 sal_uInt32 Section;
1455 if ((Section = pSection - pProfile->m_Sections) >= pProfile->m_NoSections)
1456 return;
1458 free (pSection->m_Entries);
1459 pSection->m_Entries=nullptr;
1460 if (pProfile->m_NoSections - Section > 1)
1462 memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1],
1463 (pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection));
1465 memset(&pProfile->m_Sections[pProfile->m_NoSections - 1],
1467 (pProfile->m_MaxSections - pProfile->m_NoSections) * sizeof(osl_TProfileSection));
1468 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = nullptr;
1470 else
1472 pSection->m_Entries = nullptr;
1475 pProfile->m_NoSections--;
1478 static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile,
1479 const char* Section,
1480 const char* Entry,
1481 sal_uInt32 *pNoEntry)
1483 static sal_uInt32 Sect = 0;
1484 sal_uInt32 i, n;
1485 sal_uInt32 Len;
1486 osl_TProfileSection* pSec=nullptr;
1488 Len = strlen(Section);
1490 n = Sect;
1492 for (i = 0; i < pProfile->m_NoSections; i++)
1494 n %= pProfile->m_NoSections;
1495 pSec = &pProfile->m_Sections[n];
1496 if ((Len == pSec->m_Len) &&
1497 (strncasecmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len)
1498 == 0))
1499 break;
1500 n++;
1503 Sect = n;
1505 if (i < pProfile->m_NoSections)
1507 Len = strlen(Entry);
1509 *pNoEntry = pSec->m_NoEntries;
1511 for (i = 0; i < pSec->m_NoEntries; i++)
1513 const char* pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
1514 [pSec->m_Entries[i].m_Offset];
1515 if ((Len == pSec->m_Entries[i].m_Len) &&
1516 (strncasecmp(Entry, pStr, pSec->m_Entries[i].m_Len)
1517 == 0))
1519 *pNoEntry = i;
1520 break;
1524 else
1525 pSec = nullptr;
1527 return pSec;
1530 static bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile)
1532 sal_uInt32 i;
1533 char* pStr;
1534 char* pChar;
1536 char* pLine;
1538 if ( !pFile )
1540 return false;
1543 if ( !pProfile )
1545 return false;
1548 pProfile->m_NoLines = 0;
1549 pProfile->m_NoSections = 0;
1551 OSL_VERIFY(OslProfile_rewindFile(pFile, false));
1553 while ( ( pLine=OslProfile_getLine(pFile) ) != nullptr )
1555 char* bWasAdded = addLine( pProfile, pLine );
1556 free( pLine );
1557 SAL_WARN_IF(!bWasAdded, "sal.osl", "addLine( pProfile, pLine ) ==> false");
1558 if ( ! bWasAdded )
1559 return false;
1562 for (i = 0; i < pProfile->m_NoLines; i++)
1564 pStr = stripBlanks(pProfile->m_Lines[i], nullptr);
1566 if ((*pStr == '\0') || (*pStr == ';'))
1567 continue;
1569 if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == nullptr) ||
1570 ((pChar - pStr) <= 2))
1572 /* insert entry */
1574 if (pProfile->m_NoSections < 1)
1575 continue;
1577 if ((pChar = strchr(pStr, '=')) == nullptr)
1578 pChar = pStr + strlen(pStr);
1580 if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1],
1581 i, pStr, pChar - pStr))
1583 SAL_WARN("sal.osl", "Adding entry => false");
1584 continue;
1588 else
1590 /* new section */
1592 if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1))
1594 SAL_WARN("sal.osl", "Adding section => false");
1595 continue;
1601 return true;
1604 static bool storeProfile(osl_TProfileImpl* pProfile, bool bCleanup)
1606 if (pProfile->m_Lines != nullptr)
1608 if (pProfile->m_Flags & FLG_MODIFIED)
1610 sal_uInt32 i;
1612 osl_TFile* pTmpFile = osl_openTmpProfileImpl(pProfile);
1614 if ( pTmpFile == nullptr )
1616 return false;
1619 OSL_VERIFY(OslProfile_rewindFile(pTmpFile, true));
1621 for ( i = 0 ; i < pProfile->m_NoLines ; i++ )
1623 OSL_VERIFY(OslProfile_putLine(pTmpFile, pProfile->m_Lines[i]));
1626 if ( ! writeProfileImpl(pTmpFile) )
1628 if ( pTmpFile->m_pWriteBuf != nullptr )
1630 free(pTmpFile->m_pWriteBuf);
1633 pTmpFile->m_pWriteBuf=nullptr;
1634 pTmpFile->m_nWriteBufLen=0;
1635 pTmpFile->m_nWriteBufFree=0;
1637 closeFileImpl(pTmpFile,pProfile->m_Flags);
1639 return false;
1642 pProfile->m_Flags &= ~FLG_MODIFIED;
1644 closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
1645 closeFileImpl(pTmpFile,pProfile->m_Flags);
1647 osl_ProfileSwapProfileNames(pProfile);
1649 pProfile->m_pFile = openFileImpl(pProfile->m_FileName,pProfile->m_Flags);
1653 if (bCleanup)
1655 while (pProfile->m_NoLines > 0)
1656 removeLine(pProfile, pProfile->m_NoLines - 1);
1658 free(pProfile->m_Lines);
1659 pProfile->m_Lines = nullptr;
1660 pProfile->m_NoLines = 0;
1661 pProfile->m_MaxLines = 0;
1663 while (pProfile->m_NoSections > 0)
1664 removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]);
1666 free(pProfile->m_Sections);
1667 pProfile->m_Sections = nullptr;
1668 pProfile->m_NoSections = 0;
1669 pProfile->m_MaxSections = 0;
1673 return true;
1676 static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl* pProfile)
1678 osl_TFile* pFile=nullptr;
1679 char const * const pszExtension = "tmp";
1680 char pszTmpName[PATH_MAX];
1681 oslProfileOption PFlags=0;
1683 pszTmpName[0] = '\0';
1685 /* generate tmp profilename */
1686 osl_ProfileGenerateExtension(pProfile->m_FileName, pszExtension, pszTmpName, PATH_MAX);
1688 if ( pszTmpName[0] == 0 )
1690 return nullptr;
1693 if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) )
1695 PFlags |= osl_Profile_WRITELOCK;
1698 /* open this file */
1699 pFile = openFileImpl(pszTmpName,pProfile->m_Flags | PFlags);
1701 /* return new pFile */
1702 return pFile;
1705 static bool osl_ProfileSwapProfileNames(osl_TProfileImpl* pProfile)
1707 char pszBakFile[PATH_MAX];
1708 char pszTmpFile[PATH_MAX];
1710 pszBakFile[0] = '\0';
1711 pszTmpFile[0] = '\0';
1713 osl_ProfileGenerateExtension(pProfile->m_FileName, "bak", pszBakFile, PATH_MAX);
1714 osl_ProfileGenerateExtension(pProfile->m_FileName, "tmp", pszTmpFile, PATH_MAX);
1716 /* unlink bak */
1717 unlink( pszBakFile );
1719 // Rename ini -> bak, then tmp -> ini:
1720 bool result = rename( pProfile->m_FileName, pszBakFile ) == 0;
1721 if (!result)
1723 int e = errno;
1724 SAL_INFO("sal.file", "rename(" << pProfile->m_FileName << "," << pszBakFile << "): " << UnixErrnoString(e));
1726 else
1728 SAL_INFO("sal.file", "rename(" << pProfile->m_FileName << "," << pszBakFile << "): OK");
1729 result = rename( pszTmpFile, pProfile->m_FileName ) == 0;
1730 if (!result)
1732 int e = errno;
1733 SAL_INFO("sal.file", "rename(" << pszTmpFile << "," << pProfile->m_FileName << "): " << UnixErrnoString(e));
1735 else
1737 SAL_INFO("sal.file", "rename(" << pszTmpFile << "," << pProfile->m_FileName << "): OK");
1740 return result;
1743 static void osl_ProfileGenerateExtension(const char* pszFileName, const char* pszExtension, char* pszTmpName, int BufferMaxLen)
1745 char* cursor = pszTmpName;
1746 int len;
1748 /* concatenate filename + "." + extension, limited to the size of the
1749 * output buffer; in case of overrun, data is truncated at the end...
1750 * and the result is always 0-terminated.
1752 len = strlen(pszFileName);
1753 if(len < BufferMaxLen)
1755 memcpy(cursor, pszFileName, len);
1756 cursor += len;
1757 BufferMaxLen -= len;
1759 else
1761 memcpy(cursor, pszFileName, BufferMaxLen - 1);
1762 cursor += BufferMaxLen - 1;
1763 BufferMaxLen = 1;
1765 if(BufferMaxLen > 1)
1767 *cursor++ = '.';
1768 BufferMaxLen -= 1;
1770 len = strlen(pszExtension);
1771 if(len < BufferMaxLen)
1773 memcpy(cursor, pszExtension, len);
1774 cursor += len;
1776 else
1778 memcpy(cursor, pszExtension, BufferMaxLen - 1);
1779 cursor += BufferMaxLen - 1;
1781 *cursor = 0;
1784 static osl_TProfileImpl* acquireProfile(oslProfile Profile, bool bWriteable)
1786 osl_TProfileImpl* pProfile = static_cast<osl_TProfileImpl*>(Profile);
1787 oslProfileOption PFlags=0;
1789 if ( bWriteable )
1791 PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK;
1793 else
1795 PFlags = osl_Profile_DEFAULT;
1798 if (pProfile == nullptr)
1800 if ( ( pProfile = static_cast<osl_TProfileImpl*>(osl_openProfile(nullptr, PFlags )) ) != nullptr )
1802 pProfile->m_Flags |= FLG_AUTOOPEN;
1805 else
1807 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
1809 if (! (pProfile->m_Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE )))
1811 osl_TStamp Stamp;
1813 if (! (pProfile->m_pFile = openFileImpl(pProfile->m_FileName, pProfile->m_Flags | PFlags )))
1814 return nullptr;
1816 Stamp = OslProfile_getFileStamp(pProfile->m_pFile);
1818 if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp)))
1820 pProfile->m_Stamp = Stamp;
1821 bool bRet = loadProfile(pProfile->m_pFile, pProfile);
1822 SAL_WARN_IF(!bRet, "sal.osl", "loadProfile(pProfile->m_pFile, pProfile) ==> false");
1825 else
1827 /* A readlock file could not be written */
1828 if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable)
1830 return nullptr;
1836 return pProfile;
1839 static bool releaseProfile(osl_TProfileImpl* pProfile)
1841 if ( pProfile == nullptr )
1843 return false;
1846 if (pProfile->m_Flags & FLG_AUTOOPEN)
1848 return osl_closeProfile(static_cast<oslProfile>(pProfile));
1851 if (! (pProfile->m_Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE )))
1853 if (pProfile->m_Flags & FLG_MODIFIED)
1855 bool bRet = storeProfile(pProfile, false);
1856 SAL_WARN_IF(!bRet, "sal.osl", "storeProfile(pProfile, false) ==> false");
1859 closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
1860 pProfile->m_pFile = nullptr;
1863 return true;
1866 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */