1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
34 #define SECTIONS_INI 5
35 #define SECTIONS_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
;
56 un_lock
, read_lock
, write_lock
63 sal_Char m_ReadBuf
[512];
64 sal_Char
* m_pWriteBuf
;
65 sal_uInt32 m_nWriteBufLen
;
66 sal_uInt32 m_nWriteBufFree
;
69 struct osl_TProfileEntry
76 struct osl_TProfileSection
81 sal_uInt32 m_NoEntries
;
82 sal_uInt32 m_MaxEntries
;
83 osl_TProfileEntry
* m_Entries
;
86 /* Profile-data structure hidden behind oslProfile: */
87 struct osl_TProfileImpl
92 sal_Char m_FileName
[PATH_MAX
+ 1];
94 sal_uInt32 m_MaxLines
;
95 sal_uInt32 m_NoSections
;
96 sal_uInt32 m_MaxSections
;
98 osl_TProfileSection
* m_Sections
;
99 pthread_mutex_t m_AccessLock
;
103 static osl_TFile
* openFileImpl(const sal_Char
* pszFilename
, oslProfileOption ProfileFlags
);
104 static osl_TStamp
closeFileImpl(osl_TFile
* pFile
, oslProfileOption Flags
);
105 static bool OslProfile_lockFile(const osl_TFile
* pFile
, osl_TLockMode eMode
);
106 static bool OslProfile_rewindFile(osl_TFile
* pFile
, bool bTruncate
);
107 static osl_TStamp
OslProfile_getFileStamp(osl_TFile
* pFile
);
109 static sal_Char
* OslProfile_getLine(osl_TFile
* pFile
);
110 static bool OslProfile_putLine(osl_TFile
* pFile
, const sal_Char
*pszLine
);
111 static sal_Char
* stripBlanks(sal_Char
* String
, sal_uInt32
* pLen
);
112 static sal_Char
* addLine(osl_TProfileImpl
* pProfile
, const sal_Char
* Line
);
113 static sal_Char
* insertLine(osl_TProfileImpl
* pProfile
, const sal_Char
* Line
, sal_uInt32 LineNo
);
114 static void removeLine(osl_TProfileImpl
* pProfile
, sal_uInt32 LineNo
);
115 static void setEntry(osl_TProfileImpl
* pProfile
, osl_TProfileSection
* pSection
,
116 sal_uInt32 NoEntry
, sal_uInt32 Line
,
117 sal_Char
* Entry
, sal_uInt32 Len
);
118 static bool addEntry(osl_TProfileImpl
* pProfile
, osl_TProfileSection
*pSection
,
119 int Line
, sal_Char
* Entry
, sal_uInt32 Len
);
120 static void removeEntry(osl_TProfileSection
*pSection
, sal_uInt32 NoEntry
);
121 static bool addSection(osl_TProfileImpl
* pProfile
, int Line
, const sal_Char
* Section
, sal_uInt32 Len
);
122 static void removeSection(osl_TProfileImpl
* pProfile
, osl_TProfileSection
*pSection
);
123 static osl_TProfileSection
* findEntry(osl_TProfileImpl
* pProfile
, const sal_Char
* Section
,
124 const sal_Char
* Entry
, sal_uInt32
*pNoEntry
);
125 static bool loadProfile(osl_TFile
* pFile
, osl_TProfileImpl
* pProfile
);
126 static bool storeProfile(osl_TProfileImpl
* pProfile
, bool bCleanup
);
127 static osl_TProfileImpl
* acquireProfile(oslProfile Profile
, bool bWriteable
);
128 static bool releaseProfile(osl_TProfileImpl
* pProfile
);
130 static bool writeProfileImpl (osl_TFile
* pFile
);
131 static osl_TFile
* osl_openTmpProfileImpl(osl_TProfileImpl
*);
132 static bool osl_ProfileSwapProfileNames(osl_TProfileImpl
*);
133 static void osl_ProfileGenerateExtension(const sal_Char
* pszFileName
, const sal_Char
* pszExtension
, sal_Char
* pszTmpName
, int BufferMaxLen
);
134 static oslProfile
osl_psz_openProfile(const sal_Char
*pszProfileName
, oslProfileOption Flags
);
136 oslProfile SAL_CALL
osl_openProfile(rtl_uString
*ustrProfileName
, oslProfileOption Options
)
138 char profilePath
[PATH_MAX
] = "";
140 (ustrProfileName
== nullptr
141 || ustrProfileName
->buffer
[0] == 0
142 || (FileURLToPath(profilePath
, PATH_MAX
, ustrProfileName
)
144 ? osl_psz_openProfile(profilePath
, Options
)
148 static oslProfile
osl_psz_openProfile(const sal_Char
*pszProfileName
, oslProfileOption Flags
)
151 osl_TProfileImpl
* pProfile
;
154 if ( ( pFile
= openFileImpl(pszProfileName
, Flags
) ) == nullptr )
159 pProfile
= static_cast<osl_TProfileImpl
*>(calloc(1, sizeof(osl_TProfileImpl
)));
161 if ( pProfile
== nullptr )
163 closeFileImpl(pFile
, Flags
);
167 pProfile
->m_Flags
= Flags
& FLG_USER
;
169 if ( Flags
& ( osl_Profile_READLOCK
| osl_Profile_WRITELOCK
| osl_Profile_FLUSHWRITE
) )
171 pProfile
->m_pFile
= pFile
;
174 pthread_mutex_init(&(pProfile
->m_AccessLock
),PTHREAD_MUTEXATTR_DEFAULT
);
175 pProfile
->m_bIsValid
= true;
177 pProfile
->m_Stamp
= OslProfile_getFileStamp(pFile
);
178 bRet
=loadProfile(pFile
, pProfile
);
179 bRet
&= realpath(pszProfileName
, pProfile
->m_FileName
) != nullptr;
180 SAL_WARN_IF(!bRet
, "sal.osl", "realpath(pszProfileName, pProfile->m_FileName) != NULL ==> false");
182 if (pProfile
->m_pFile
== nullptr)
183 closeFileImpl(pFile
,pProfile
->m_Flags
);
185 // coverity[leaked_storage] - pFile is not leaked
189 sal_Bool SAL_CALL
osl_closeProfile(oslProfile Profile
)
191 osl_TProfileImpl
* pProfile
= static_cast<osl_TProfileImpl
*>(Profile
);
192 osl_TProfileImpl
* pTmpProfile
;
194 if ( Profile
== nullptr )
199 pthread_mutex_lock(&(pProfile
->m_AccessLock
));
201 if ( !pProfile
->m_bIsValid
)
203 SAL_WARN("sal.osl", "!pProfile->m_bIsValid");
204 pthread_mutex_unlock(&(pProfile
->m_AccessLock
));
209 pProfile
->m_bIsValid
= false;
211 if ( ! ( pProfile
->m_Flags
& osl_Profile_READLOCK
) && ( pProfile
->m_Flags
& FLG_MODIFIED
) )
213 pTmpProfile
= acquireProfile(Profile
, true);
215 if ( pTmpProfile
!= nullptr )
217 bool bRet
= storeProfile(pTmpProfile
, true);
218 SAL_WARN_IF(!bRet
, "sal.osl", "storeProfile(pTmpProfile, true) ==> false");
223 pTmpProfile
= acquireProfile(Profile
, false);
226 if ( pTmpProfile
== nullptr )
228 pthread_mutex_unlock(&(pProfile
->m_AccessLock
));
230 SAL_INFO("sal.osl", "Out osl_closeProfile [pProfile==0]");
234 pProfile
= pTmpProfile
;
236 if (pProfile
->m_pFile
!= nullptr)
237 closeFileImpl(pProfile
->m_pFile
,pProfile
->m_Flags
);
239 pProfile
->m_pFile
= nullptr;
240 pProfile
->m_FileName
[0] = '\0';
242 /* release whole profile data types memory */
243 if ( pProfile
->m_NoLines
> 0)
246 if ( pProfile
->m_Lines
!= nullptr )
248 for ( idx
= 0 ; idx
< pProfile
->m_NoLines
; ++idx
)
250 if ( pProfile
->m_Lines
[idx
] != nullptr )
252 free(pProfile
->m_Lines
[idx
]);
253 pProfile
->m_Lines
[idx
]=nullptr;
256 free(pProfile
->m_Lines
);
257 pProfile
->m_Lines
=nullptr;
259 if ( pProfile
->m_Sections
!= nullptr )
261 /*osl_TProfileSection* pSections=pProfile->m_Sections;*/
262 for ( idx
= 0 ; idx
< pProfile
->m_NoSections
; ++idx
)
264 if ( pProfile
->m_Sections
[idx
].m_Entries
!= nullptr )
266 free(pProfile
->m_Sections
[idx
].m_Entries
);
267 pProfile
->m_Sections
[idx
].m_Entries
=nullptr;
270 free(pProfile
->m_Sections
);
271 pProfile
->m_Sections
=nullptr;
275 pthread_mutex_unlock(&(pProfile
->m_AccessLock
));
277 pthread_mutex_destroy(&(pProfile
->m_AccessLock
));
284 sal_Bool SAL_CALL
osl_flushProfile(oslProfile Profile
)
286 osl_TProfileImpl
* pProfile
= static_cast<osl_TProfileImpl
*>(Profile
);
290 if ( pProfile
== nullptr )
295 pthread_mutex_lock(&(pProfile
->m_AccessLock
));
297 if ( !pProfile
->m_bIsValid
)
299 SAL_WARN_IF(!pProfile
->m_bIsValid
, "sal.osl", "!pProfile->m_bIsValid");
300 pthread_mutex_unlock(&(pProfile
->m_AccessLock
));
304 pFile
= pProfile
->m_pFile
;
305 if ( !( pFile
!= nullptr && pFile
->m_Handle
>= 0 ) )
307 pthread_mutex_unlock(&(pProfile
->m_AccessLock
));
312 if ( pProfile
->m_Flags
& FLG_MODIFIED
)
314 bRet
= storeProfile(pProfile
, false);
315 SAL_WARN_IF(!bRet
, "sal.osl", "storeProfile(pProfile, false) ==> false");
318 pthread_mutex_unlock(&(pProfile
->m_AccessLock
));
322 static bool writeProfileImpl(osl_TFile
* pFile
)
324 if ( !( pFile
!= nullptr && pFile
->m_Handle
>= 0 ) || ( pFile
->m_pWriteBuf
== nullptr ) )
330 (strlen(pFile
->m_pWriteBuf
)
331 != pFile
->m_nWriteBufLen
- pFile
->m_nWriteBufFree
),
333 strlen(pFile
->m_pWriteBuf
) << " != "
334 << (pFile
->m_nWriteBufLen
- pFile
->m_nWriteBufFree
));
336 if ( !safeWrite(pFile
->m_Handle
, pFile
->m_pWriteBuf
, pFile
->m_nWriteBufLen
- pFile
->m_nWriteBufFree
) )
338 SAL_INFO("sal.osl", "write failed: " << UnixErrnoString(errno
));
342 free(pFile
->m_pWriteBuf
);
343 pFile
->m_pWriteBuf
=nullptr;
344 pFile
->m_nWriteBufLen
=0;
345 pFile
->m_nWriteBufFree
=0;
350 sal_Bool SAL_CALL
osl_readProfileString(oslProfile Profile
,
351 const sal_Char
* pszSection
,
352 const sal_Char
* pszEntry
,
355 const sal_Char
* pszDefault
)
358 sal_Char
* pStr
=nullptr;
359 osl_TProfileImpl
* pProfile
=nullptr;
360 osl_TProfileImpl
* pTmpProfile
=nullptr;
363 pTmpProfile
= static_cast<osl_TProfileImpl
*>(Profile
);
365 if ( pTmpProfile
== nullptr )
370 pthread_mutex_lock(&(pTmpProfile
->m_AccessLock
));
372 if ( !pTmpProfile
->m_bIsValid
)
374 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
379 pProfile
= acquireProfile(Profile
, false);
381 if ( pProfile
== nullptr )
383 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
388 if (! (pProfile
->m_Flags
& osl_Profile_SYSTEM
))
390 osl_TProfileSection
* pSec
;
391 if (((pSec
= findEntry(pProfile
, pszSection
, pszEntry
, &NoEntry
)) != nullptr) &&
392 (NoEntry
< pSec
->m_NoEntries
) &&
393 ((pStr
= strchr(pProfile
->m_Lines
[pSec
->m_Entries
[NoEntry
].m_Line
],
400 pStr
=const_cast<sal_Char
*>(pszDefault
);
403 if ( pStr
!= nullptr )
405 pStr
= stripBlanks(pStr
, nullptr);
406 MaxLen
= (MaxLen
- 1 < strlen(pStr
)) ? (MaxLen
- 1) : strlen(pStr
);
407 pStr
= stripBlanks(pStr
, &MaxLen
);
408 strncpy(pszString
, pStr
, MaxLen
);
409 pszString
[MaxLen
] = '\0';
413 { /* not implemented */ }
415 bRet
=releaseProfile(pProfile
);
416 SAL_WARN_IF(!bRet
, "sal.osl", "releaseProfile(pProfile) ==> false");
418 if ( pStr
== nullptr )
420 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
425 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
430 sal_Bool SAL_CALL
osl_readProfileBool(oslProfile Profile
,
431 const sal_Char
* pszSection
,
432 const sal_Char
* pszEntry
,
438 if (osl_readProfileString(Profile
, pszSection
, pszEntry
, Line
, sizeof(Line
), ""))
440 if ((strcasecmp(Line
, STR_INI_BOOLYES
) == 0) ||
441 (strcasecmp(Line
, STR_INI_BOOLON
) == 0) ||
442 (strcasecmp(Line
, STR_INI_BOOLONE
) == 0))
445 if ((strcasecmp(Line
, STR_INI_BOOLNO
) == 0) ||
446 (strcasecmp(Line
, STR_INI_BOOLOFF
) == 0) ||
447 (strcasecmp(Line
, STR_INI_BOOLZERO
) == 0))
454 sal_uInt32 SAL_CALL
osl_readProfileIdent(oslProfile Profile
,
455 const sal_Char
* pszSection
,
456 const sal_Char
* pszEntry
,
458 const sal_Char
* Strings
[],
465 if (osl_readProfileString(Profile
, pszSection
, pszEntry
, Line
, sizeof(Line
), ""))
468 while (Strings
[i
] != nullptr)
470 if (strcasecmp(Line
, Strings
[i
]) == 0)
472 Default
= i
+ FirstId
;
482 sal_Bool SAL_CALL
osl_writeProfileString(oslProfile Profile
,
483 const sal_Char
* pszSection
,
484 const sal_Char
* pszEntry
,
485 const sal_Char
* pszString
)
491 sal_Char
* Line
= nullptr;
492 osl_TProfileSection
* pSec
;
493 osl_TProfileImpl
* pProfile
= nullptr;
494 osl_TProfileImpl
* pTmpProfile
= nullptr;
496 pTmpProfile
= static_cast<osl_TProfileImpl
*>(Profile
);
498 if ( pTmpProfile
== nullptr )
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
));
513 pProfile
=acquireProfile(Profile
, true);
515 if (pProfile
== nullptr)
517 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
522 Line
= static_cast<sal_Char
*>(malloc(strlen(pszEntry
)+strlen(pszString
)+48));
524 if (! (pProfile
->m_Flags
& osl_Profile_SYSTEM
))
526 if ((pSec
= findEntry(pProfile
, pszSection
, pszEntry
, &NoEntry
)) == nullptr)
529 addLine(pProfile
, Line
);
532 strcpy(&Line
[1], pszSection
);
533 Line
[1 + strlen(pszSection
)] = ']';
534 Line
[2 + strlen(pszSection
)] = '\0';
536 if (((pStr
= addLine(pProfile
, Line
)) == nullptr) ||
537 (! addSection(pProfile
, pProfile
->m_NoLines
- 1, &pStr
[1], strlen(pszSection
))))
539 bRet
=releaseProfile(pProfile
);
540 SAL_WARN_IF(!bRet
, "sal.osl", "releaseProfile(pProfile) ==> false");
542 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
548 pSec
= &pProfile
->m_Sections
[pProfile
->m_NoSections
- 1];
549 NoEntry
= pSec
->m_NoEntries
;
553 strcpy(&Line
[0], pszEntry
);
554 Line
[0 + strlen(pszEntry
)] = '=';
555 strcpy(&Line
[1 + strlen(pszEntry
)], pszString
);
557 if (NoEntry
>= pSec
->m_NoEntries
)
559 if (pSec
->m_NoEntries
> 0)
560 i
= pSec
->m_Entries
[pSec
->m_NoEntries
- 1].m_Line
+ 1;
562 i
= pSec
->m_Line
+ 1;
564 if (((pStr
= insertLine(pProfile
, Line
, i
)) == nullptr) ||
565 (! addEntry(pProfile
, pSec
, i
, pStr
, strlen(pszEntry
))))
567 bRet
=releaseProfile(pProfile
);
568 SAL_WARN_IF(!bRet
, "sal.osl", "releaseProfile(pProfile) ==> false");
570 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
576 pProfile
->m_Flags
|= FLG_MODIFIED
;
580 i
= pSec
->m_Entries
[NoEntry
].m_Line
;
581 free(pProfile
->m_Lines
[i
]);
582 pProfile
->m_Lines
[i
] = strdup(Line
);
583 setEntry(pProfile
, pSec
, NoEntry
, i
, pProfile
->m_Lines
[i
], strlen(pszEntry
));
585 pProfile
->m_Flags
|= FLG_MODIFIED
;
589 /* not implemented */
592 bRet
= releaseProfile(pProfile
);
593 SAL_WARN_IF(!bRet
, "sal.osl", "releaseProfile(pProfile) ==> false");
595 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
596 if ( Line
!= nullptr )
604 sal_Bool SAL_CALL
osl_writeProfileBool(oslProfile Profile
,
605 const sal_Char
* pszSection
,
606 const sal_Char
* pszEntry
,
612 bRet
=osl_writeProfileString(Profile
, pszSection
, pszEntry
, STR_INI_BOOLONE
);
614 bRet
=osl_writeProfileString(Profile
, pszSection
, pszEntry
, STR_INI_BOOLZERO
);
619 sal_Bool SAL_CALL
osl_writeProfileIdent(oslProfile Profile
,
620 const sal_Char
* pszSection
,
621 const sal_Char
* pszEntry
,
623 const sal_Char
* Strings
[],
629 while (Strings
[n
] != nullptr)
632 if ((i
= Value
- FirstId
) >= n
)
635 bRet
= osl_writeProfileString(Profile
, pszSection
, pszEntry
, Strings
[i
]);
640 sal_Bool SAL_CALL
osl_removeProfileEntry(oslProfile Profile
,
641 const sal_Char
*pszSection
,
642 const sal_Char
*pszEntry
)
645 osl_TProfileImpl
* pProfile
= nullptr;
646 osl_TProfileImpl
* pTmpProfile
= nullptr;
649 pTmpProfile
= static_cast<osl_TProfileImpl
*>(Profile
);
651 if ( pTmpProfile
== nullptr )
656 pthread_mutex_lock(&(pTmpProfile
->m_AccessLock
));
658 if ( !pTmpProfile
->m_bIsValid
)
660 SAL_WARN_IF(!pTmpProfile
->m_bIsValid
, "sal.osl", "!pTmpProfile->m_bIsValid");
661 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
665 pProfile
= acquireProfile(Profile
, true);
667 if (pProfile
== nullptr)
669 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
674 if (! (pProfile
->m_Flags
& osl_Profile_SYSTEM
))
676 osl_TProfileSection
* pSec
;
677 if (((pSec
= findEntry(pProfile
, pszSection
, pszEntry
, &NoEntry
)) != nullptr) &&
678 (NoEntry
< pSec
->m_NoEntries
))
680 removeLine(pProfile
, pSec
->m_Entries
[NoEntry
].m_Line
);
681 removeEntry(pSec
, NoEntry
);
682 if (pSec
->m_NoEntries
== 0)
684 removeLine(pProfile
, pSec
->m_Line
);
686 /* remove any empty separation line */
687 if ((pSec
->m_Line
> 0) && (pProfile
->m_Lines
[pSec
->m_Line
- 1][0] == '\0'))
688 removeLine(pProfile
, pSec
->m_Line
- 1);
690 removeSection(pProfile
, pSec
);
693 pProfile
->m_Flags
|= FLG_MODIFIED
;
697 { /* not implemented */ }
699 bRet
= releaseProfile(pProfile
);
700 SAL_WARN_IF(!bRet
, "sal.osl", "releaseProfile(pProfile) ==> false");
702 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
707 sal_uInt32 SAL_CALL
osl_getProfileSectionEntries(oslProfile Profile
,
708 const sal_Char
*pszSection
,
714 osl_TProfileImpl
* pProfile
= nullptr;
715 osl_TProfileImpl
* pTmpProfile
= nullptr;
718 pTmpProfile
= static_cast<osl_TProfileImpl
*>(Profile
);
720 if ( pTmpProfile
== nullptr )
726 pthread_mutex_lock(&(pTmpProfile
->m_AccessLock
));
728 if ( !pTmpProfile
->m_bIsValid
)
730 SAL_WARN_IF(!pTmpProfile
->m_bIsValid
, "sal.osl", "!pTmpProfile->m_bIsValid");
732 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
737 pProfile
= acquireProfile(Profile
, false);
739 if (pProfile
== nullptr)
741 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
746 if (! (pProfile
->m_Flags
& osl_Profile_SYSTEM
))
748 osl_TProfileSection
* pSec
;
749 if ((pSec
= findEntry(pProfile
, pszSection
, "", &NoEntry
)) != nullptr)
753 for (i
= 0; i
< pSec
->m_NoEntries
; i
++)
755 if ((n
+ pSec
->m_Entries
[i
].m_Len
+ 1) < MaxLen
)
757 strncpy(&pszBuffer
[n
], &pProfile
->m_Lines
[pSec
->m_Entries
[i
].m_Line
]
758 [pSec
->m_Entries
[i
].m_Offset
], pSec
->m_Entries
[i
].m_Len
);
759 n
+= pSec
->m_Entries
[i
].m_Len
;
760 pszBuffer
[n
++] = '\0';
767 pszBuffer
[n
++] = '\0';
771 for (i
= 0; i
< pSec
->m_NoEntries
; i
++)
772 n
+= pSec
->m_Entries
[i
].m_Len
+ 1;
781 /* not implemented */
784 bRet
=releaseProfile(pProfile
);
785 SAL_WARN_IF(!bRet
, "sal.osl", "releaseProfile(pProfile) ==> false");
787 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
792 sal_uInt32 SAL_CALL
osl_getProfileSections(oslProfile Profile
,
797 osl_TProfileImpl
* pProfile
= nullptr;
798 osl_TProfileImpl
* pTmpProfile
= nullptr;
801 pTmpProfile
= static_cast<osl_TProfileImpl
*>(Profile
);
803 if ( pTmpProfile
== nullptr )
808 pthread_mutex_lock(&(pTmpProfile
->m_AccessLock
));
810 if ( !pTmpProfile
->m_bIsValid
)
812 SAL_WARN_IF(!pTmpProfile
->m_bIsValid
, "sal.osl", "!pTmpProfile->m_bIsValid");
813 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
818 pProfile
= acquireProfile(Profile
, false);
820 if (pProfile
== nullptr)
822 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
827 if (! (pProfile
->m_Flags
& osl_Profile_SYSTEM
))
831 for (i
= 0; i
< pProfile
->m_NoSections
; i
++)
833 osl_TProfileSection
* pSec
= &pProfile
->m_Sections
[i
];
835 if ((n
+ pSec
->m_Len
+ 1) < MaxLen
)
837 strncpy(&pszBuffer
[n
], &pProfile
->m_Lines
[pSec
->m_Line
][pSec
->m_Offset
],
840 pszBuffer
[n
++] = '\0';
846 pszBuffer
[n
++] = '\0';
850 for (i
= 0; i
< pProfile
->m_NoSections
; i
++)
851 n
+= pProfile
->m_Sections
[i
].m_Len
+ 1;
857 { /* not implemented */ }
859 bRet
=releaseProfile(pProfile
);
860 SAL_WARN_IF(!bRet
, "sal.osl", "releaseProfile(pProfile) ==> false");
862 pthread_mutex_unlock(&(pTmpProfile
->m_AccessLock
));
867 static osl_TStamp
OslProfile_getFileStamp(osl_TFile
* pFile
)
871 if ( (pFile
->m_Handle
< 0) || (fstat(pFile
->m_Handle
, &status
) < 0) )
876 return status
.st_mtime
;
879 static bool OslProfile_lockFile(const osl_TFile
* pFile
, osl_TLockMode eMode
)
882 /* boring hack, but initializers for static vars must be constant */
883 static bool bIsInitialized
= false;
884 static bool bLockingDisabled
;
886 if ( !bIsInitialized
)
889 pEnvValue
= getenv( "STAR_PROFILE_LOCKING_DISABLED" );
891 bLockingDisabled
= pEnvValue
!= nullptr;
893 bIsInitialized
= true;
896 if (pFile
->m_Handle
< 0)
901 if ( bLockingDisabled
)
907 lock
.l_whence
= SEEK_SET
;
913 lock
.l_type
= F_UNLCK
;
917 lock
.l_type
= F_RDLCK
;
921 lock
.l_type
= F_WRLCK
;
926 if ( fcntl(pFile
->m_Handle
, F_SETLKW
, &lock
) == -1 )
928 /* Mac OSX will return ENOTSUP for webdav drives so we should ignore it */
929 if ( fcntl(pFile
->m_Handle
, F_SETLKW
, &lock
) == -1 && errno
!= ENOTSUP
)
932 SAL_INFO("sal.osl", "fcntl failed: " << UnixErrnoString(errno
));
939 static osl_TFile
* openFileImpl(const sal_Char
* pszFilename
, oslProfileOption ProfileFlags
)
942 osl_TFile
* pFile
= static_cast<osl_TFile
*>(calloc(1, sizeof(osl_TFile
)));
943 bool bWriteable
= false;
945 if ( ProfileFlags
& ( osl_Profile_WRITELOCK
| osl_Profile_FLUSHWRITE
) )
952 pFile
->m_Handle
= open(pszFilename
, O_RDONLY
);
954 if (pFile
->m_Handle
== -1)
957 SAL_INFO("sal.file", "open(" << pszFilename
<< ",O_RDONLY): " << UnixErrnoString(e
));
960 SAL_INFO("sal.file", "open(" << pszFilename
<< ",O_RDONLY) => " << pFile
->m_Handle
);
962 /* mfe: argghh!!! do not check if the file could be opened */
963 /* default mode expects it that way!!! */
967 if (((pFile
->m_Handle
= open(pszFilename
, O_RDWR
| O_CREAT
| O_EXCL
, DEFAULT_PMODE
)) < 0) &&
968 ((pFile
->m_Handle
= open(pszFilename
, O_RDWR
)) < 0))
971 SAL_INFO("sal.file", "open(" << pszFilename
<< ",...): " << UnixErrnoString(e
));
976 SAL_INFO("sal.file", "open(" << pszFilename
<< ",...) => " << pFile
->m_Handle
);
979 /* set close-on-exec flag */
980 if ((Flags
= fcntl(pFile
->m_Handle
, F_GETFD
, 0)) != -1)
983 int e
= fcntl(pFile
->m_Handle
, F_SETFD
, Flags
);
986 "fcntl to set FD_CLOEXEC failed for " << pszFilename
);
989 pFile
->m_pWriteBuf
=nullptr;
990 pFile
->m_nWriteBufFree
=0;
991 pFile
->m_nWriteBufLen
=0;
993 if ( ProfileFlags
& (osl_Profile_WRITELOCK
| osl_Profile_READLOCK
) )
995 OslProfile_lockFile(pFile
, bWriteable
? write_lock
: read_lock
);
1001 static osl_TStamp
closeFileImpl(osl_TFile
* pFile
, oslProfileOption Flags
)
1003 osl_TStamp stamp
= 0;
1005 if ( pFile
== nullptr )
1010 if ( pFile
->m_Handle
>= 0 )
1012 stamp
= OslProfile_getFileStamp(pFile
);
1014 if ( Flags
& (osl_Profile_WRITELOCK
| osl_Profile_READLOCK
) )
1016 OslProfile_lockFile(pFile
, un_lock
);
1019 close(pFile
->m_Handle
);
1020 SAL_INFO("sal.file", "close(" << pFile
->m_Handle
<< ")");
1021 pFile
->m_Handle
= -1;
1024 if ( pFile
->m_pWriteBuf
)
1026 free(pFile
->m_pWriteBuf
);
1034 static bool OslProfile_rewindFile(osl_TFile
* pFile
, bool bTruncate
)
1038 if (pFile
->m_Handle
>= 0)
1040 pFile
->m_pReadPtr
= pFile
->m_ReadBuf
+ sizeof(pFile
->m_ReadBuf
);
1042 bRet
= (lseek(pFile
->m_Handle
, SEEK_SET
, 0L) == 0);
1046 bRet
&= (ftruncate(pFile
->m_Handle
, 0L) == 0);
1054 static sal_Char
* OslProfile_getLine(osl_TFile
* pFile
)
1056 int Max
, Free
, nLineBytes
= 0;
1058 sal_Char
* pLine
= nullptr;
1061 if ( pFile
== nullptr )
1066 if (pFile
->m_Handle
< 0)
1071 int Bytes
= sizeof(pFile
->m_ReadBuf
) - (pFile
->m_pReadPtr
- pFile
->m_ReadBuf
);
1076 memcpy(pFile
->m_ReadBuf
, pFile
->m_pReadPtr
, Bytes
);
1077 pFile
->m_pReadPtr
= pFile
->m_ReadBuf
;
1079 Free
= sizeof(pFile
->m_ReadBuf
) - Bytes
;
1081 if ((Max
= read(pFile
->m_Handle
, &pFile
->m_ReadBuf
[Bytes
], Free
)) < 0)
1083 SAL_INFO("sal.osl", "read failed: " << UnixErrnoString(errno
));
1093 if ((Max
== 0) && ! pLine
)
1096 pFile
->m_ReadBuf
[Bytes
+ Max
] = '\0';
1100 for (pChr
= pFile
->m_pReadPtr
;
1101 (*pChr
!= '\n') && (*pChr
!= '\r') && (*pChr
!= '\0') &&
1102 (pChr
< (pFile
->m_ReadBuf
+ sizeof(pFile
->m_ReadBuf
) - 1));
1105 Max
= pChr
- pFile
->m_pReadPtr
;
1106 pNewLine
= static_cast<sal_Char
*>(malloc( nLineBytes
+ Max
+ 1 ));
1109 memcpy( pNewLine
, pLine
, nLineBytes
);
1112 memcpy(pNewLine
+nLineBytes
, pFile
->m_pReadPtr
, Max
);
1114 pNewLine
[ nLineBytes
] = 0;
1117 if (pChr
< (pFile
->m_ReadBuf
+ sizeof(pFile
->m_ReadBuf
) - 1))
1121 if ((pChr
[0] == '\r') && (pChr
[1] == '\n'))
1127 if ((pChr
< (pFile
->m_ReadBuf
+ sizeof(pFile
->m_ReadBuf
))) &&
1129 pChr
= pFile
->m_ReadBuf
+ sizeof(pFile
->m_ReadBuf
);
1131 /* setting Max to -1 indicates terminating read loop */
1135 pFile
->m_pReadPtr
= pChr
;
1142 static bool OslProfile_putLine(osl_TFile
* pFile
, const sal_Char
*pszLine
)
1144 unsigned int Len
= strlen(pszLine
);
1146 if ( pFile
== nullptr || pFile
->m_Handle
< 0 )
1151 if ( pFile
->m_pWriteBuf
== nullptr )
1153 pFile
->m_pWriteBuf
= static_cast<sal_Char
*>(malloc(Len
+3));
1154 pFile
->m_nWriteBufLen
= Len
+3;
1155 pFile
->m_nWriteBufFree
= Len
+3;
1159 if ( pFile
->m_nWriteBufFree
<= Len
+ 3 )
1163 pTmp
=static_cast<sal_Char
*>(realloc(pFile
->m_pWriteBuf
,( ( pFile
->m_nWriteBufLen
+ Len
) * 2) ));
1164 if ( pTmp
== nullptr )
1168 pFile
->m_pWriteBuf
= pTmp
;
1169 pFile
->m_nWriteBufFree
= pFile
->m_nWriteBufFree
+ pFile
->m_nWriteBufLen
+ ( 2 * Len
);
1170 pFile
->m_nWriteBufLen
= ( pFile
->m_nWriteBufLen
+ Len
) * 2;
1171 memset( (pFile
->m_pWriteBuf
) + ( pFile
->m_nWriteBufLen
- pFile
->m_nWriteBufFree
), 0, pFile
->m_nWriteBufFree
);
1175 memcpy(pFile
->m_pWriteBuf
+ ( pFile
->m_nWriteBufLen
- pFile
->m_nWriteBufFree
),pszLine
,Len
+1);
1176 pFile
->m_pWriteBuf
[pFile
->m_nWriteBufLen
- pFile
->m_nWriteBufFree
+ Len
]='\n';
1177 pFile
->m_pWriteBuf
[pFile
->m_nWriteBufLen
- pFile
->m_nWriteBufFree
+ Len
+ 1]='\0';
1179 pFile
->m_nWriteBufFree
-=Len
+1;
1184 static sal_Char
* stripBlanks(sal_Char
* String
, sal_uInt32
* pLen
)
1186 if ( ( pLen
!= nullptr ) && ( *pLen
!= 0 ) )
1188 while ((String
[*pLen
- 1] == ' ') || (String
[*pLen
- 1] == '\t'))
1191 while ( (*String
== ' ') || (*String
== '\t') )
1198 while ( (*String
== ' ') || (*String
== '\t') )
1204 static sal_Char
* addLine(osl_TProfileImpl
* pProfile
, const sal_Char
* Line
)
1206 if (pProfile
->m_NoLines
>= pProfile
->m_MaxLines
)
1208 if (pProfile
->m_Lines
== nullptr)
1210 pProfile
->m_MaxLines
= LINES_INI
;
1211 pProfile
->m_Lines
= static_cast<sal_Char
**>(calloc(pProfile
->m_MaxLines
, sizeof(sal_Char
*)));
1216 unsigned int oldmax
=pProfile
->m_MaxLines
;
1218 pProfile
->m_MaxLines
+= LINES_ADD
;
1219 pProfile
->m_Lines
= static_cast<sal_Char
**>(realloc(pProfile
->m_Lines
,
1220 pProfile
->m_MaxLines
* sizeof(sal_Char
*)));
1221 for ( idx
= oldmax
; idx
< pProfile
->m_MaxLines
; ++idx
)
1223 pProfile
->m_Lines
[idx
]=nullptr;
1227 if (pProfile
->m_Lines
== nullptr)
1229 pProfile
->m_NoLines
= 0;
1230 pProfile
->m_MaxLines
= 0;
1234 if ( pProfile
->m_Lines
[pProfile
->m_NoLines
] != nullptr )
1236 free(pProfile
->m_Lines
[pProfile
->m_NoLines
]);
1238 pProfile
->m_Lines
[pProfile
->m_NoLines
++] = strdup(Line
);
1240 return pProfile
->m_Lines
[pProfile
->m_NoLines
- 1];
1243 static sal_Char
* insertLine(osl_TProfileImpl
* pProfile
, const sal_Char
* Line
, sal_uInt32 LineNo
)
1245 if (pProfile
->m_NoLines
>= pProfile
->m_MaxLines
)
1247 if (pProfile
->m_Lines
== nullptr)
1249 pProfile
->m_MaxLines
= LINES_INI
;
1250 pProfile
->m_Lines
= static_cast<sal_Char
**>(calloc(pProfile
->m_MaxLines
, sizeof(sal_Char
*)));
1254 pProfile
->m_MaxLines
+= LINES_ADD
;
1255 pProfile
->m_Lines
= static_cast<sal_Char
**>(realloc(pProfile
->m_Lines
,
1256 pProfile
->m_MaxLines
* sizeof(sal_Char
*)));
1258 memset(&pProfile
->m_Lines
[pProfile
->m_NoLines
],
1260 (pProfile
->m_MaxLines
- pProfile
->m_NoLines
- 1) * sizeof(sal_Char
*));
1263 if (pProfile
->m_Lines
== nullptr)
1265 pProfile
->m_NoLines
= 0;
1266 pProfile
->m_MaxLines
= 0;
1271 LineNo
= std::min(LineNo
, pProfile
->m_NoLines
);
1273 if (LineNo
< pProfile
->m_NoLines
)
1277 memmove(&pProfile
->m_Lines
[LineNo
+ 1], &pProfile
->m_Lines
[LineNo
],
1278 (pProfile
->m_NoLines
- LineNo
) * sizeof(sal_Char
*));
1280 /* adjust line references */
1281 for (i
= 0; i
< pProfile
->m_NoSections
; i
++)
1283 osl_TProfileSection
* pSec
= &pProfile
->m_Sections
[i
];
1285 if (pSec
->m_Line
>= LineNo
)
1288 for (n
= 0; n
< pSec
->m_NoEntries
; n
++)
1289 if (pSec
->m_Entries
[n
].m_Line
>= LineNo
)
1290 pSec
->m_Entries
[n
].m_Line
++;
1294 pProfile
->m_NoLines
++;
1296 pProfile
->m_Lines
[LineNo
] = strdup(Line
);
1298 return pProfile
->m_Lines
[LineNo
];
1301 static void removeLine(osl_TProfileImpl
* pProfile
, sal_uInt32 LineNo
)
1303 if (LineNo
< pProfile
->m_NoLines
)
1305 free(pProfile
->m_Lines
[LineNo
]);
1306 pProfile
->m_Lines
[LineNo
]=nullptr;
1307 if (pProfile
->m_NoLines
- LineNo
> 1)
1311 memmove(&pProfile
->m_Lines
[LineNo
], &pProfile
->m_Lines
[LineNo
+ 1],
1312 (pProfile
->m_NoLines
- LineNo
- 1) * sizeof(sal_Char
*));
1314 memset(&pProfile
->m_Lines
[pProfile
->m_NoLines
- 1],
1316 (pProfile
->m_MaxLines
- pProfile
->m_NoLines
) * sizeof(sal_Char
*));
1318 /* adjust line references */
1319 for (i
= 0; i
< pProfile
->m_NoSections
; i
++)
1321 osl_TProfileSection
* pSec
= &pProfile
->m_Sections
[i
];
1323 if (pSec
->m_Line
> LineNo
)
1326 for (n
= 0; n
< pSec
->m_NoEntries
; n
++)
1327 if (pSec
->m_Entries
[n
].m_Line
> LineNo
)
1328 pSec
->m_Entries
[n
].m_Line
--;
1333 pProfile
->m_Lines
[LineNo
] = nullptr;
1336 pProfile
->m_NoLines
--;
1340 static void setEntry(osl_TProfileImpl
* pProfile
, osl_TProfileSection
* pSection
,
1341 sal_uInt32 NoEntry
, sal_uInt32 Line
,
1342 sal_Char
* Entry
, sal_uInt32 Len
)
1344 Entry
= stripBlanks(Entry
, &Len
);
1345 pSection
->m_Entries
[NoEntry
].m_Line
= Line
;
1346 pSection
->m_Entries
[NoEntry
].m_Offset
= Entry
- pProfile
->m_Lines
[Line
];
1347 pSection
->m_Entries
[NoEntry
].m_Len
= Len
;
1350 static bool addEntry(osl_TProfileImpl
* pProfile
,
1351 osl_TProfileSection
*pSection
,
1352 int Line
, sal_Char
* Entry
,
1355 if (pSection
!= nullptr)
1357 if (pSection
->m_NoEntries
>= pSection
->m_MaxEntries
)
1359 if (pSection
->m_Entries
== nullptr)
1361 pSection
->m_MaxEntries
= ENTRIES_INI
;
1362 pSection
->m_Entries
= static_cast<osl_TProfileEntry
*>(malloc(
1363 pSection
->m_MaxEntries
* sizeof(osl_TProfileEntry
)));
1367 pSection
->m_MaxEntries
+= ENTRIES_ADD
;
1368 pSection
->m_Entries
= static_cast<osl_TProfileEntry
*>(realloc(pSection
->m_Entries
,
1369 pSection
->m_MaxEntries
* sizeof(osl_TProfileEntry
)));
1372 if (pSection
->m_Entries
== nullptr)
1374 pSection
->m_NoEntries
= 0;
1375 pSection
->m_MaxEntries
= 0;
1380 pSection
->m_NoEntries
++;
1382 Entry
= stripBlanks(Entry
, &Len
);
1383 setEntry(pProfile
, pSection
, pSection
->m_NoEntries
- 1, Line
,
1392 static void removeEntry(osl_TProfileSection
*pSection
, sal_uInt32 NoEntry
)
1394 if (NoEntry
< pSection
->m_NoEntries
)
1396 if (pSection
->m_NoEntries
- NoEntry
> 1)
1398 memmove(&pSection
->m_Entries
[NoEntry
],
1399 &pSection
->m_Entries
[NoEntry
+ 1],
1400 (pSection
->m_NoEntries
- NoEntry
- 1) * sizeof(osl_TProfileEntry
));
1401 pSection
->m_Entries
[pSection
->m_NoEntries
- 1].m_Line
=0;
1402 pSection
->m_Entries
[pSection
->m_NoEntries
- 1].m_Offset
=0;
1403 pSection
->m_Entries
[pSection
->m_NoEntries
- 1].m_Len
=0;
1406 pSection
->m_NoEntries
--;
1411 static bool addSection(osl_TProfileImpl
* pProfile
, int Line
, const sal_Char
* Section
, sal_uInt32 Len
)
1413 if (pProfile
->m_NoSections
>= pProfile
->m_MaxSections
)
1415 if (pProfile
->m_Sections
== nullptr)
1417 pProfile
->m_MaxSections
= SECTIONS_INI
;
1418 pProfile
->m_Sections
= static_cast<osl_TProfileSection
*>(calloc(pProfile
->m_MaxSections
, sizeof(osl_TProfileSection
)));
1423 unsigned int oldmax
=pProfile
->m_MaxSections
;
1425 pProfile
->m_MaxSections
+= SECTIONS_ADD
;
1426 pProfile
->m_Sections
= static_cast<osl_TProfileSection
*>(realloc(pProfile
->m_Sections
,
1427 pProfile
->m_MaxSections
* sizeof(osl_TProfileSection
)));
1428 for ( idx
= oldmax
; idx
< pProfile
->m_MaxSections
; ++idx
)
1430 pProfile
->m_Sections
[idx
].m_Entries
=nullptr;
1434 if (pProfile
->m_Sections
== nullptr)
1436 pProfile
->m_NoSections
= 0;
1437 pProfile
->m_MaxSections
= 0;
1442 pProfile
->m_NoSections
++;
1444 if ( pProfile
->m_Sections
[(pProfile
->m_NoSections
) - 1].m_Entries
!= nullptr )
1446 free(pProfile
->m_Sections
[(pProfile
->m_NoSections
) - 1].m_Entries
);
1448 pProfile
->m_Sections
[pProfile
->m_NoSections
- 1].m_Entries
= nullptr;
1449 pProfile
->m_Sections
[pProfile
->m_NoSections
- 1].m_NoEntries
= 0;
1450 pProfile
->m_Sections
[pProfile
->m_NoSections
- 1].m_MaxEntries
= 0;
1452 pProfile
->m_Sections
[pProfile
->m_NoSections
- 1].m_Line
= Line
;
1453 pProfile
->m_Sections
[pProfile
->m_NoSections
- 1].m_Offset
= Section
- pProfile
->m_Lines
[Line
];
1454 pProfile
->m_Sections
[pProfile
->m_NoSections
- 1].m_Len
= Len
;
1459 static void removeSection(osl_TProfileImpl
* pProfile
, osl_TProfileSection
*pSection
)
1463 if ((Section
= pSection
- pProfile
->m_Sections
) < pProfile
->m_NoSections
)
1465 free (pSection
->m_Entries
);
1466 pSection
->m_Entries
=nullptr;
1467 if (pProfile
->m_NoSections
- Section
> 1)
1469 memmove(&pProfile
->m_Sections
[Section
], &pProfile
->m_Sections
[Section
+ 1],
1470 (pProfile
->m_NoSections
- Section
- 1) * sizeof(osl_TProfileSection
));
1472 memset(&pProfile
->m_Sections
[pProfile
->m_NoSections
- 1],
1474 (pProfile
->m_MaxSections
- pProfile
->m_NoSections
) * sizeof(osl_TProfileSection
));
1475 pProfile
->m_Sections
[pProfile
->m_NoSections
- 1].m_Entries
= nullptr;
1479 pSection
->m_Entries
= nullptr;
1482 pProfile
->m_NoSections
--;
1486 static osl_TProfileSection
* findEntry(osl_TProfileImpl
* pProfile
,
1487 const sal_Char
* Section
,
1488 const sal_Char
* Entry
,
1489 sal_uInt32
*pNoEntry
)
1491 static sal_uInt32 Sect
= 0;
1494 osl_TProfileSection
* pSec
=nullptr;
1496 Len
= strlen(Section
);
1500 for (i
= 0; i
< pProfile
->m_NoSections
; i
++)
1502 n
%= pProfile
->m_NoSections
;
1503 pSec
= &pProfile
->m_Sections
[n
];
1504 if ((Len
== pSec
->m_Len
) &&
1505 (strncasecmp(Section
, &pProfile
->m_Lines
[pSec
->m_Line
][pSec
->m_Offset
], pSec
->m_Len
)
1513 if (i
< pProfile
->m_NoSections
)
1515 Len
= strlen(Entry
);
1517 *pNoEntry
= pSec
->m_NoEntries
;
1519 for (i
= 0; i
< pSec
->m_NoEntries
; i
++)
1521 const sal_Char
* pStr
= &pProfile
->m_Lines
[pSec
->m_Entries
[i
].m_Line
]
1522 [pSec
->m_Entries
[i
].m_Offset
];
1523 if ((Len
== pSec
->m_Entries
[i
].m_Len
) &&
1524 (strncasecmp(Entry
, pStr
, pSec
->m_Entries
[i
].m_Len
)
1538 static bool loadProfile(osl_TFile
* pFile
, osl_TProfileImpl
* pProfile
)
1556 pProfile
->m_NoLines
= 0;
1557 pProfile
->m_NoSections
= 0;
1559 OSL_VERIFY(OslProfile_rewindFile(pFile
, false));
1561 while ( ( pLine
=OslProfile_getLine(pFile
) ) != nullptr )
1563 sal_Char
* bWasAdded
= addLine( pProfile
, pLine
);
1565 SAL_WARN_IF(!bWasAdded
, "sal.osl", "addLine( pProfile, pLine ) ==> false");
1570 for (i
= 0; i
< pProfile
->m_NoLines
; i
++)
1572 pStr
= stripBlanks(pProfile
->m_Lines
[i
], nullptr);
1574 if ((*pStr
== '\0') || (*pStr
== ';'))
1577 if ((*pStr
!= '[') || ((pChar
= strrchr(pStr
, ']')) == nullptr) ||
1578 ((pChar
- pStr
) <= 2))
1582 if (pProfile
->m_NoSections
< 1)
1585 if ((pChar
= strchr(pStr
, '=')) == nullptr)
1586 pChar
= pStr
+ strlen(pStr
);
1588 if (! addEntry(pProfile
, &pProfile
->m_Sections
[pProfile
->m_NoSections
- 1],
1589 i
, pStr
, pChar
- pStr
))
1591 SAL_WARN("sal.osl", "Adding entry => false");
1600 if (! addSection(pProfile
, i
, pStr
+ 1, pChar
- pStr
- 1))
1602 SAL_WARN("sal.osl", "Adding section => false");
1612 static bool storeProfile(osl_TProfileImpl
* pProfile
, bool bCleanup
)
1614 if (pProfile
->m_Lines
!= nullptr)
1616 if (pProfile
->m_Flags
& FLG_MODIFIED
)
1620 osl_TFile
* pTmpFile
= osl_openTmpProfileImpl(pProfile
);
1622 if ( pTmpFile
== nullptr )
1627 OSL_VERIFY(OslProfile_rewindFile(pTmpFile
, true));
1629 for ( i
= 0 ; i
< pProfile
->m_NoLines
; i
++ )
1631 OSL_VERIFY(OslProfile_putLine(pTmpFile
, pProfile
->m_Lines
[i
]));
1634 if ( ! writeProfileImpl(pTmpFile
) )
1636 if ( pTmpFile
->m_pWriteBuf
!= nullptr )
1638 free(pTmpFile
->m_pWriteBuf
);
1641 pTmpFile
->m_pWriteBuf
=nullptr;
1642 pTmpFile
->m_nWriteBufLen
=0;
1643 pTmpFile
->m_nWriteBufFree
=0;
1645 closeFileImpl(pTmpFile
,pProfile
->m_Flags
);
1650 pProfile
->m_Flags
&= ~FLG_MODIFIED
;
1652 closeFileImpl(pProfile
->m_pFile
,pProfile
->m_Flags
);
1653 closeFileImpl(pTmpFile
,pProfile
->m_Flags
);
1655 osl_ProfileSwapProfileNames(pProfile
);
1657 pProfile
->m_pFile
= openFileImpl(pProfile
->m_FileName
,pProfile
->m_Flags
);
1663 while (pProfile
->m_NoLines
> 0)
1664 removeLine(pProfile
, pProfile
->m_NoLines
- 1);
1666 free(pProfile
->m_Lines
);
1667 pProfile
->m_Lines
= nullptr;
1668 pProfile
->m_NoLines
= 0;
1669 pProfile
->m_MaxLines
= 0;
1671 while (pProfile
->m_NoSections
> 0)
1672 removeSection(pProfile
, &pProfile
->m_Sections
[pProfile
->m_NoSections
- 1]);
1674 free(pProfile
->m_Sections
);
1675 pProfile
->m_Sections
= nullptr;
1676 pProfile
->m_NoSections
= 0;
1677 pProfile
->m_MaxSections
= 0;
1684 static osl_TFile
* osl_openTmpProfileImpl(osl_TProfileImpl
* pProfile
)
1686 osl_TFile
* pFile
=nullptr;
1687 sal_Char
const * const pszExtension
= "tmp";
1688 sal_Char pszTmpName
[PATH_MAX
];
1689 oslProfileOption PFlags
=0;
1691 pszTmpName
[0] = '\0';
1693 /* generate tmp profilename */
1694 osl_ProfileGenerateExtension(pProfile
->m_FileName
, pszExtension
, pszTmpName
, PATH_MAX
);
1696 if ( pszTmpName
[0] == 0 )
1701 if ( ! ( pProfile
->m_Flags
& osl_Profile_READLOCK
) )
1703 PFlags
|= osl_Profile_WRITELOCK
;
1706 /* open this file */
1707 pFile
= openFileImpl(pszTmpName
,pProfile
->m_Flags
| PFlags
);
1709 /* return new pFile */
1713 static bool osl_ProfileSwapProfileNames(osl_TProfileImpl
* pProfile
)
1715 sal_Char pszBakFile
[PATH_MAX
];
1716 sal_Char pszTmpFile
[PATH_MAX
];
1718 pszBakFile
[0] = '\0';
1719 pszTmpFile
[0] = '\0';
1721 osl_ProfileGenerateExtension(pProfile
->m_FileName
, "bak", pszBakFile
, PATH_MAX
);
1722 osl_ProfileGenerateExtension(pProfile
->m_FileName
, "tmp", pszTmpFile
, PATH_MAX
);
1725 unlink( pszBakFile
);
1727 // Rename ini -> bak, then tmp -> ini:
1728 bool result
= rename( pProfile
->m_FileName
, pszBakFile
) == 0;
1732 SAL_INFO("sal.file", "rename(" << pProfile
->m_FileName
<< "," << pszBakFile
<< "): " << UnixErrnoString(e
));
1736 SAL_INFO("sal.file", "rename(" << pProfile
->m_FileName
<< "," << pszBakFile
<< "): OK");
1737 result
= rename( pszTmpFile
, pProfile
->m_FileName
) == 0;
1741 SAL_INFO("sal.file", "rename(" << pszTmpFile
<< "," << pProfile
->m_FileName
<< "): " << UnixErrnoString(e
));
1745 SAL_INFO("sal.file", "rename(" << pszTmpFile
<< "," << pProfile
->m_FileName
<< "): OK");
1751 static void osl_ProfileGenerateExtension(const sal_Char
* pszFileName
, const sal_Char
* pszExtension
, sal_Char
* pszTmpName
, int BufferMaxLen
)
1753 sal_Char
* cursor
= pszTmpName
;
1756 /* concatenate filename + "." + extension, limited to the size of the
1757 * output buffer; in case of overrun, data is truncated at the end...
1758 * and the result is always 0-terminated.
1760 len
= strlen(pszFileName
);
1761 if(len
< BufferMaxLen
)
1763 memcpy(cursor
, pszFileName
, len
);
1765 BufferMaxLen
-= len
;
1769 memcpy(cursor
, pszFileName
, BufferMaxLen
- 1);
1770 cursor
+= BufferMaxLen
- 1;
1773 if(BufferMaxLen
> 1)
1778 len
= strlen(pszExtension
);
1779 if(len
< BufferMaxLen
)
1781 memcpy(cursor
, pszExtension
, len
);
1786 memcpy(cursor
, pszExtension
, BufferMaxLen
- 1);
1787 cursor
+= BufferMaxLen
- 1;
1792 static osl_TProfileImpl
* acquireProfile(oslProfile Profile
, bool bWriteable
)
1794 osl_TProfileImpl
* pProfile
= static_cast<osl_TProfileImpl
*>(Profile
);
1795 oslProfileOption PFlags
=0;
1799 PFlags
= osl_Profile_DEFAULT
| osl_Profile_WRITELOCK
;
1803 PFlags
= osl_Profile_DEFAULT
;
1806 if (pProfile
== nullptr)
1808 if ( ( pProfile
= static_cast<osl_TProfileImpl
*>(osl_openProfile(nullptr, PFlags
)) ) != nullptr )
1810 pProfile
->m_Flags
|= FLG_AUTOOPEN
;
1815 if (! (pProfile
->m_Flags
& osl_Profile_SYSTEM
))
1817 if (! (pProfile
->m_Flags
& (osl_Profile_READLOCK
| osl_Profile_WRITELOCK
| osl_Profile_FLUSHWRITE
)))
1821 if (! (pProfile
->m_pFile
= openFileImpl(pProfile
->m_FileName
, pProfile
->m_Flags
| PFlags
)))
1824 Stamp
= OslProfile_getFileStamp(pProfile
->m_pFile
);
1826 if (memcmp(&Stamp
, &(pProfile
->m_Stamp
), sizeof(osl_TStamp
)))
1828 pProfile
->m_Stamp
= Stamp
;
1829 bool bRet
= loadProfile(pProfile
->m_pFile
, pProfile
);
1830 SAL_WARN_IF(!bRet
, "sal.osl", "loadProfile(pProfile->m_pFile, pProfile) ==> false");
1835 /* A readlock file could not be written */
1836 if ((pProfile
->m_Flags
& osl_Profile_READLOCK
) && bWriteable
)
1847 static bool releaseProfile(osl_TProfileImpl
* pProfile
)
1849 if ( pProfile
== nullptr )
1854 if (pProfile
->m_Flags
& FLG_AUTOOPEN
)
1856 return osl_closeProfile(static_cast<oslProfile
>(pProfile
));
1859 if (! (pProfile
->m_Flags
& (osl_Profile_READLOCK
| osl_Profile_WRITELOCK
| osl_Profile_FLUSHWRITE
)))
1861 if (pProfile
->m_Flags
& FLG_MODIFIED
)
1863 bool bRet
= storeProfile(pProfile
, false);
1864 SAL_WARN_IF(!bRet
, "sal.osl", "storeProfile(pProfile, false) ==> false");
1867 closeFileImpl(pProfile
->m_pFile
,pProfile
->m_Flags
);
1868 pProfile
->m_pFile
= nullptr;
1874 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */