update dev300-m58
[ooovba.git] / sal / osl / unx / profile.c
blob8f89a226f6bb097113d42f1d1d21e98b4d60f50d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: profile.c,v $
10 * $Revision: 1.19 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 #include "system.h"
34 #include <osl/diagnose.h>
35 #include <osl/profile.h>
36 #include <osl/process.h>
37 #include <osl/thread.h>
38 #include <rtl/alloc.h>
39 #include <osl/util.h>
41 #define LINES_INI 32
42 #define LINES_ADD 10
43 #define SECTIONS_INI 5
44 #define SECTIONS_ADD 3
45 #define ENTRIES_INI 5
46 #define ENTRIES_ADD 3
49 #define STR_INI_EXTENSION "rc"
50 #define STR_INI_METAHOME "?~"
51 #define STR_INI_METASYS "?$"
52 #define STR_INI_METACFG "?^"
53 #define STR_INI_METAINS "?#"
55 #define STR_INI_BOOLYES "yes"
56 #define STR_INI_BOOLON "on"
57 #define STR_INI_BOOLONE "1"
58 #define STR_INI_BOOLNO "no"
59 #define STR_INI_BOOLOFF "off"
60 #define STR_INI_BOOLZERO "0"
62 #define FLG_USER 0x00FF
63 #define FLG_AUTOOPEN 0x0100
64 #define FLG_MODIFIED 0x0200
66 #define SVERSION_LOCATION STR_INI_METACFG
67 #define SVERSION_FALLBACK STR_INI_METASYS
68 #define SVERSION_NAME "sversion"
69 #define SVERSION_SECTION "Versions"
70 #define SVERSION_SOFFICE "StarOffice"
71 #define SVERSION_PROFILE "sofficerc"
72 #define SVERSION_OPTION "userid:"
73 #define SVERSION_DIRS { "bin", "program" }
74 #define SVERSION_USER "user"
76 #define DEFAULT_PMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
78 #define _BUILD_STR_(n) # n
79 #define BUILD_STR(n) _BUILD_STR_(n)
82 /*#define DEBUG_OSL_PROFILE*/
83 /*#define TRACE_OSL_PROFILE*/
85 /*****************************************************************************/
86 /* Data Type Definition */
87 /*****************************************************************************/
89 typedef time_t osl_TStamp;
91 typedef enum _osl_TLockMode
93 un_lock, read_lock, write_lock
94 } osl_TLockMode;
96 typedef struct _osl_TFile
98 int m_Handle;
99 sal_Char* m_pReadPtr;
100 sal_Char m_ReadBuf[512];
101 sal_Char* m_pWriteBuf;
102 sal_uInt32 m_nWriteBufLen;
103 sal_uInt32 m_nWriteBufFree;
104 } osl_TFile;
106 typedef struct _osl_TProfileEntry
108 sal_uInt32 m_Line;
109 sal_uInt32 m_Offset;
110 sal_uInt32 m_Len;
111 } osl_TProfileEntry;
113 typedef struct _osl_TProfileSection
115 sal_uInt32 m_Line;
116 sal_uInt32 m_Offset;
117 sal_uInt32 m_Len;
118 sal_uInt32 m_NoEntries;
119 sal_uInt32 m_MaxEntries;
120 osl_TProfileEntry* m_Entries;
121 } osl_TProfileSection;
125 Profile-data structure hidden behind oslProfile:
127 typedef struct _osl_TProfileImpl
129 sal_uInt32 m_Flags;
130 osl_TFile* m_pFile;
131 osl_TStamp m_Stamp;
132 sal_Char m_FileName[PATH_MAX + 1];
133 sal_uInt32 m_NoLines;
134 sal_uInt32 m_MaxLines;
135 sal_uInt32 m_NoSections;
136 sal_uInt32 m_MaxSections;
137 sal_Char** m_Lines;
138 osl_TProfileSection* m_Sections;
139 pthread_mutex_t m_AccessLock;
140 sal_Bool m_bIsValid;
141 } osl_TProfileImpl;
144 /*****************************************************************************/
145 /* Static Module Function Declarations */
146 /*****************************************************************************/
148 static osl_TFile* openFileImpl(const sal_Char* pszFilename, oslProfileOption ProfileFlags);
149 static osl_TStamp closeFileImpl(osl_TFile* pFile, oslProfileOption Flags);
150 static sal_Bool OslProfile_lockFile(const osl_TFile* pFile, osl_TLockMode eMode);
151 static sal_Bool OslProfile_rewindFile(osl_TFile* pFile, sal_Bool bTruncate);
152 static osl_TStamp OslProfile_getFileStamp(osl_TFile* pFile);
154 static sal_Char* OslProfile_getLine(osl_TFile* pFile);
155 static sal_Bool OslProfile_putLine(osl_TFile* pFile, const sal_Char *pszLine);
156 static sal_Char* stripBlanks(sal_Char* String, sal_uInt32* pLen);
157 static sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line);
158 static sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo);
159 static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo);
160 static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
161 sal_uInt32 NoEntry, sal_uInt32 Line,
162 sal_Char* Entry, sal_uInt32 Len);
163 static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
164 int Line, sal_Char* Entry, sal_uInt32 Len);
165 static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry);
166 static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len);
167 static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection);
168 static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
169 const sal_Char* Entry, sal_uInt32 *pNoEntry);
170 static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile);
171 static sal_Bool storeProfile(osl_TProfileImpl* pProfile, sal_Bool bCleanup);
172 static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable);
173 static sal_Bool releaseProfile(osl_TProfileImpl* pProfile);
175 static sal_Bool writeProfileImpl (osl_TFile* pFile);
176 static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl*);
177 static sal_Bool osl_ProfileSwapProfileNames(osl_TProfileImpl*);
178 static void osl_ProfileGenerateExtension(sal_Char* pszFileName, sal_Char* pszExtension, sal_Char* pszTmpName);
179 static oslProfile SAL_CALL osl_psz_openProfile(const sal_Char *pszProfileName, oslProfileOption Flags);
181 /* implemented in file.c */
182 extern oslFileError FileURLToPath( char *, size_t, rtl_uString* );
184 /*****************************************************************************/
185 /* Exported Module Functions */
186 /*****************************************************************************/
187 oslProfile SAL_CALL osl_openProfile(rtl_uString *ustrProfileName, oslProfileOption Options)
189 char profilePath[PATH_MAX] = "";
191 if ( ustrProfileName != 0 && ustrProfileName->buffer[0] != 0 )
192 FileURLToPath( profilePath, PATH_MAX, ustrProfileName );
194 return osl_psz_openProfile( profilePath,Options );
198 static oslProfile SAL_CALL osl_psz_openProfile(const sal_Char *pszProfileName, oslProfileOption Flags)
200 osl_TFile* pFile;
201 osl_TProfileImpl* pProfile;
202 sal_Char Filename[PATH_MAX];
203 sal_Bool bRet = sal_False;
205 Filename[0] = '\0';
207 #ifdef TRACE_OSL_PROFILE
208 OSL_TRACE("In osl_openProfile\n");
209 #endif
211 #ifdef DEBUG_OSL_PROFILE
212 Flags=osl_Profile_FLUSHWRITE;
214 OSL_TRACE("opening '%s'\n",pszProfileName);
215 if ( Flags == osl_Profile_DEFAULT )
217 OSL_TRACE("with osl_Profile_DEFAULT\n");
219 if ( Flags & osl_Profile_SYSTEM )
221 OSL_TRACE("with osl_Profile_SYSTEM\n");
223 if ( Flags & osl_Profile_READLOCK )
225 OSL_TRACE("with osl_Profile_READLOCK\n");
227 if ( Flags & osl_Profile_WRITELOCK )
229 OSL_TRACE("with osl_Profile_WRITELOCK\n");
231 if ( Flags & osl_Profile_FLUSHWRITE )
233 OSL_TRACE("with osl_Profile_FLUSHWRITE\n");
235 #endif
238 if ( ( pFile = openFileImpl(pszProfileName, Flags ) ) == NULL )
240 #ifdef TRACE_OSL_PROFILE
241 OSL_TRACE("Out osl_openProfile [not opened]\n");
242 #endif
243 return (NULL);
247 pProfile = (osl_TProfileImpl*)calloc(1, sizeof(osl_TProfileImpl));
249 if ( pProfile == 0 )
251 return 0;
254 pProfile->m_Flags = Flags & FLG_USER;
256 if ( Flags & ( osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
258 pProfile->m_pFile = pFile;
261 pthread_mutex_init(&(pProfile->m_AccessLock),PTHREAD_MUTEXATTR_DEFAULT);
262 pProfile->m_bIsValid=sal_True;
264 pProfile->m_Stamp = OslProfile_getFileStamp(pFile);
265 bRet=loadProfile(pFile, pProfile);
266 OSL_ASSERT(bRet);
268 /* #109261# using osl profiles is deprecated */
269 /* OSL_VERIFY(NULL != realpath(pszProfileName, pProfile->m_FileName)); */
270 realpath(pszProfileName, pProfile->m_FileName);
272 if (pProfile->m_pFile == NULL)
273 closeFileImpl(pFile,pProfile->m_Flags);
275 #ifdef TRACE_OSL_PROFILE
276 OSL_TRACE("Out osl_openProfile [ok]\n");
277 #endif
278 return (pProfile);
281 sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile)
283 osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
284 sal_Bool bRet = sal_False;
286 #ifdef TRACE_OSL_PROFILE
287 OSL_TRACE("In osl_closeProfile\n");
288 #endif
290 if ( Profile == 0 )
292 #ifdef TRACE_OSL_PROFILE
293 OSL_TRACE("Out osl_closeProfile [profile==0]\n");
294 #endif
295 return sal_False;
298 pthread_mutex_lock(&(pProfile->m_AccessLock));
300 if ( pProfile->m_bIsValid == sal_False )
302 OSL_ASSERT(pProfile->m_bIsValid);
303 pthread_mutex_unlock(&(pProfile->m_AccessLock));
304 #ifdef TRACE_OSL_PROFILE
305 OSL_TRACE("Out osl_closeProfile [not valid]\n");
306 #endif
307 return sal_False;
310 pProfile->m_bIsValid=sal_False;
312 if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) && ( pProfile->m_Flags & FLG_MODIFIED ) )
314 pProfile = acquireProfile(Profile,sal_True);
316 if ( pProfile != 0 )
318 bRet=storeProfile(pProfile, sal_True);
319 OSL_ASSERT(bRet);
322 else
324 pProfile = acquireProfile(Profile,sal_False);
328 if ( pProfile == 0 )
330 pthread_mutex_unlock(&(pProfile->m_AccessLock));
331 #ifdef TRACE_OSL_PROFILE
332 OSL_TRACE("Out osl_closeProfile [pProfile==0]\n");
333 #endif
334 return sal_False;
337 if (pProfile->m_pFile != NULL)
338 closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
340 pProfile->m_pFile = NULL;
341 pProfile->m_FileName[0] = '\0';
343 /* release whole profile data types memory */
344 if ( pProfile->m_NoLines > 0)
346 unsigned int idx=0;
347 if ( pProfile->m_Lines != 0 )
349 for ( idx = 0 ; idx < pProfile->m_NoLines ; ++idx)
351 if ( pProfile->m_Lines[idx] != 0 )
353 free(pProfile->m_Lines[idx]);
354 pProfile->m_Lines[idx]=0;
357 free(pProfile->m_Lines);
358 pProfile->m_Lines=0;
360 if ( pProfile->m_Sections != 0 )
362 /*osl_TProfileSection* pSections=pProfile->m_Sections;*/
363 for ( idx = 0 ; idx < pProfile->m_NoSections ; ++idx )
365 if ( pProfile->m_Sections[idx].m_Entries != 0 )
367 free(pProfile->m_Sections[idx].m_Entries);
368 pProfile->m_Sections[idx].m_Entries=0;
371 free(pProfile->m_Sections);
372 pProfile->m_Sections=0;
376 pthread_mutex_unlock(&(pProfile->m_AccessLock));
378 pthread_mutex_destroy(&(pProfile->m_AccessLock));
380 free(pProfile);
382 #ifdef TRACE_OSL_PROFILE
383 OSL_TRACE("Out osl_closeProfile [ok]\n");
384 #endif
385 return (sal_True);
389 sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile)
391 osl_TProfileImpl* pProfile = (osl_TProfileImpl*) Profile;
392 osl_TFile* pFile;
393 sal_Bool bRet = sal_False;
395 #ifdef TRACE_OSL_PROFILE
396 OSL_TRACE("In osl_flushProfile()\n");
397 #endif
399 if ( pProfile == 0 )
401 #ifdef TRACE_OSL_PROFILE
402 OSL_TRACE("Out osl_flushProfile() [pProfile == 0]\n");
403 #endif
404 return sal_False;
407 pthread_mutex_lock(&(pProfile->m_AccessLock));
409 if ( pProfile->m_bIsValid == sal_False )
411 OSL_ASSERT(pProfile->m_bIsValid);
412 pthread_mutex_unlock(&(pProfile->m_AccessLock));
413 #ifdef TRACE_OSL_PROFILE
414 OSL_TRACE("Out osl_flushProfile [not valid]\n");
415 #endif
416 return sal_False;
419 pFile = pProfile->m_pFile;
420 if ( !( pFile != 0 && pFile->m_Handle >= 0 ) )
422 pthread_mutex_unlock(&(pProfile->m_AccessLock));
423 #ifdef TRACE_OSL_PROFILE
424 OSL_TRACE("Out osl_flushProfile() [invalid file]\n");
425 #endif
426 return sal_False;
429 if ( pProfile->m_Flags & FLG_MODIFIED )
431 #ifdef DEBUG_OSL_PROFILE
432 OSL_TRACE("swapping to storeprofile\n");
433 #endif
434 bRet = storeProfile(pProfile,sal_False);
435 OSL_ASSERT(bRet);
438 #ifdef TRACE_OSL_PROFILE
439 OSL_TRACE("Out osl_flushProfile() [ok]\n");
440 #endif
441 pthread_mutex_unlock(&(pProfile->m_AccessLock));
442 return bRet;
445 static sal_Bool writeProfileImpl(osl_TFile* pFile)
447 int BytesWritten=0;
448 #if OSL_DEBUG_LEVEL > 1
449 unsigned int nLen=0;
450 #endif
452 #ifdef TRACE_OSL_PROFILE
453 OSL_TRACE("In osl_writeProfileImpl()\n");
454 #endif
456 if ( !( pFile != 0 && pFile->m_Handle >= 0 ) || ( pFile->m_pWriteBuf == 0 ) )
458 #ifdef TRACE_OSL_PROFILE
459 OSL_TRACE("Out osl_writeProfileImpl() [invalid args]\n");
460 #endif
461 return sal_False;
464 #if OSL_DEBUG_LEVEL > 1
465 nLen=strlen(pFile->m_pWriteBuf);
466 OSL_ASSERT(nLen == (pFile->m_nWriteBufLen - pFile->m_nWriteBufFree));
467 #endif
469 BytesWritten = write(pFile->m_Handle, pFile->m_pWriteBuf, pFile->m_nWriteBufLen - pFile->m_nWriteBufFree);
471 if ( BytesWritten <= 0 )
473 OSL_TRACE("write failed '%s'\n",strerror(errno));
474 return (sal_False);
477 #if OSL_DEBUG_LEVEL > 1
478 OSL_ASSERT(
479 BytesWritten >= 0 && SAL_INT_CAST(unsigned int, BytesWritten) == nLen);
480 #endif
482 free(pFile->m_pWriteBuf);
483 pFile->m_pWriteBuf=0;
484 pFile->m_nWriteBufLen=0;
485 pFile->m_nWriteBufFree=0;
486 #ifdef TRACE_OSL_PROFILE
487 OSL_TRACE("Out osl_writeProfileImpl() [ok]\n");
488 #endif
489 return sal_True;
493 sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile,
494 const sal_Char* pszSection, const sal_Char* pszEntry,
495 sal_Char* pszString, sal_uInt32 MaxLen,
496 const sal_Char* pszDefault)
498 sal_uInt32 NoEntry;
499 sal_Char* pStr=0;
500 osl_TProfileSection* pSec;
501 osl_TProfileImpl* pProfile=0;
502 osl_TProfileImpl* pTmpProfile=0;
503 sal_Bool bRet = sal_False;
505 #ifdef TRACE_OSL_PROFILE
506 OSL_TRACE("In osl_readProfileString\n");
507 #endif
509 pTmpProfile = (osl_TProfileImpl*) Profile;
511 if ( pTmpProfile == 0 )
513 #ifdef TRACE_OSL_PROFILE
514 OSL_TRACE("Out osl_readProfileString [pTmpProfile==0]\n");
515 #endif
516 return sal_False;
519 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
521 if ( pTmpProfile->m_bIsValid == sal_False )
523 OSL_ASSERT(pProfile->m_bIsValid);
524 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
525 #ifdef TRACE_OSL_PROFILE
526 OSL_TRACE("Out osl_readProfileString [not valid]\n");
527 #endif
528 return sal_False;
531 pProfile = acquireProfile(Profile, sal_False);
533 if ( pProfile == NULL )
535 #ifdef TRACE_OSL_PROFILE
536 OSL_TRACE("Out osl_readProfileString [pProfile==0]\n");
537 #endif
538 return (sal_False);
541 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
543 if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
544 (NoEntry < pSec->m_NoEntries) &&
545 ((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line],
546 '=')) != NULL))
548 pStr++;
550 else
552 pStr=(sal_Char*)pszDefault;
555 if ( pStr != 0 )
557 pStr = stripBlanks(pStr, NULL);
558 MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr);
559 pStr = stripBlanks(pStr, &MaxLen);
560 strncpy(pszString, pStr, MaxLen);
561 pszString[MaxLen] = '\0';
564 else
565 { /* not implemented */ }
568 bRet=releaseProfile(pProfile);
569 OSL_ASSERT(bRet);
571 if ( pStr == 0 )
573 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
574 #ifdef TRACE_OSL_PROFILE
575 OSL_TRACE("Out osl_readProfileString [pStr==0]\n");
576 #endif
577 return sal_False;
580 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
582 #ifdef TRACE_OSL_PROFILE
583 OSL_TRACE("Out osl_readProfileString [ok]\n");
584 #endif
586 return (sal_True);
590 sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile,
591 const sal_Char* pszSection, const sal_Char* pszEntry,
592 sal_Bool Default)
594 sal_Char Line[32];
595 Line[0] = '\0';
597 #ifdef TRACE_OSL_PROFILE
598 OSL_TRACE("In osl_readProfileBool\n");
599 #endif
601 if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
603 if ((strcasecmp(Line, STR_INI_BOOLYES) == 0) ||
604 (strcasecmp(Line, STR_INI_BOOLON) == 0) ||
605 (strcasecmp(Line, STR_INI_BOOLONE) == 0))
606 Default = sal_True;
607 else
608 if ((strcasecmp(Line, STR_INI_BOOLNO) == 0) ||
609 (strcasecmp(Line, STR_INI_BOOLOFF) == 0) ||
610 (strcasecmp(Line, STR_INI_BOOLZERO) == 0))
611 Default = sal_False;
614 #ifdef TRACE_OSL_PROFILE
615 OSL_TRACE("Out osl_readProfileBool [ok]\n");
616 #endif
618 return (Default);
622 sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile,
623 const sal_Char* pszSection, const sal_Char* pszEntry,
624 sal_uInt32 FirstId, const sal_Char* Strings[],
625 sal_uInt32 Default)
627 sal_uInt32 i;
628 sal_Char Line[256];
629 Line[0] = '\0';
631 #ifdef TRACE_OSL_PROFILE
632 OSL_TRACE("In osl_readProfileIdent\n");
633 #endif
635 if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
637 i = 0;
638 while (Strings[i] != NULL)
640 if (strcasecmp(Line, Strings[i]) == 0)
642 Default = i + FirstId;
643 break;
645 i++;
649 #ifdef TRACE_OSL_PROFILE
650 OSL_TRACE("Out osl_readProfileIdent [ok]\n");
651 #endif
652 return (Default);
655 sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile,
656 const sal_Char* pszSection, const sal_Char* pszEntry,
657 const sal_Char* pszString)
659 sal_uInt32 i;
660 sal_Bool bRet = sal_False;
661 sal_uInt32 NoEntry;
662 sal_Char* pStr;
663 sal_Char* Line = 0;
664 osl_TProfileSection* pSec;
665 osl_TProfileImpl* pProfile = 0;
666 osl_TProfileImpl* pTmpProfile = 0;
668 #ifdef TRACE_OSL_PROFILE
669 OSL_TRACE("In osl_writeProfileString\n");
670 #endif
672 pTmpProfile = (osl_TProfileImpl*) Profile;
674 if ( pTmpProfile == 0 )
676 #ifdef TRACE_OSL_PROFILE
677 OSL_TRACE("Out osl_writeProfileString [pTmpProfile==0]\n");
678 #endif
679 return sal_False;
682 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
684 if ( pTmpProfile->m_bIsValid == sal_False )
686 OSL_ASSERT(pTmpProfile->m_bIsValid);
687 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
688 #ifdef TRACE_OSL_PROFILE
689 OSL_TRACE("Out osl_writeProfileString [not valid]\n");
690 #endif
691 return sal_False;
694 pProfile=acquireProfile(Profile, sal_True);
696 if (pProfile == NULL)
698 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
699 #ifdef TRACE_OSL_PROFILE
700 OSL_TRACE("Out osl_writeProfileString [pProfile==0]\n");
701 #endif
702 return (sal_False);
705 Line = (sal_Char*) malloc(strlen(pszEntry)+strlen(pszString)+48);
707 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
709 if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == NULL)
711 Line[0] = '\0';
712 addLine(pProfile, Line);
714 Line[0] = '[';
715 strcpy(&Line[1], pszSection);
716 Line[1 + strlen(pszSection)] = ']';
717 Line[2 + strlen(pszSection)] = '\0';
719 if (((pStr = addLine(pProfile, Line)) == NULL) ||
720 (! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection))))
722 bRet=releaseProfile(pProfile);
723 OSL_ASSERT(bRet);
725 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
727 free(Line);
729 #ifdef TRACE_OSL_PROFILE
730 OSL_TRACE("Out osl_writeProfileString [not added]\n");
731 #endif
732 return (sal_False);
735 pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1];
736 NoEntry = pSec->m_NoEntries;
739 Line[0] = '\0';
740 strcpy(&Line[0], pszEntry);
741 Line[0 + strlen(pszEntry)] = '=';
742 strcpy(&Line[1 + strlen(pszEntry)], pszString);
744 if (NoEntry >= pSec->m_NoEntries)
746 if (pSec->m_NoEntries > 0)
747 i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1;
748 else
749 i = pSec->m_Line + 1;
751 if (((pStr = insertLine(pProfile, Line, i)) == NULL) ||
752 (! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry))))
754 bRet=releaseProfile(pProfile);
755 OSL_ASSERT(bRet);
757 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
758 free(Line);
760 #ifdef TRACE_OSL_PROFILE
761 OSL_TRACE("Out osl_writeProfileString [not inserted]\n");
762 #endif
763 return (sal_False);
766 pProfile->m_Flags |= FLG_MODIFIED;
768 else
770 i = pSec->m_Entries[NoEntry].m_Line;
771 free(pProfile->m_Lines[i]);
772 pProfile->m_Lines[i] = strdup(Line);
773 setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry));
775 pProfile->m_Flags |= FLG_MODIFIED;
778 else {
779 /* not implemented */
782 bRet = releaseProfile(pProfile);
783 OSL_ASSERT(bRet);
785 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
786 if ( Line!= 0 )
788 free(Line);
791 #ifdef TRACE_OSL_PROFILE
792 OSL_TRACE("Out osl_writeProfileString [ok]\n");
793 #endif
795 return bRet;
799 sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile,
800 const sal_Char* pszSection, const sal_Char* pszEntry,
801 sal_Bool Value)
803 sal_Bool bRet=sal_False;
805 #ifdef TRACE_OSL_PROFILE
806 OSL_TRACE("In osl_writeProfileBool\n");
807 #endif
809 if (Value)
810 bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE);
811 else
812 bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO);
814 #ifdef TRACE_OSL_PROFILE
815 OSL_TRACE("Out osl_writeProfileBool [ok]\n");
816 #endif
818 return bRet;
822 sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile,
823 const sal_Char* pszSection, const sal_Char* pszEntry,
824 sal_uInt32 FirstId, const sal_Char* Strings[],
825 sal_uInt32 Value)
827 int i, n;
828 sal_Bool bRet=sal_False;
830 #ifdef TRACE_OSL_PROFILE
831 OSL_TRACE("In osl_writeProfileIdent\n");
832 #endif
834 for (n = 0; Strings[n] != NULL; n++);
836 if ((i = Value - FirstId) >= n)
837 bRet=sal_False;
838 else
839 bRet = osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]);
841 #ifdef TRACE_OSL_PROFILE
842 OSL_TRACE("Out osl_writeProfileIdent\n");
843 #endif
844 return bRet;
848 sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile,
849 const sal_Char *pszSection, const sal_Char *pszEntry)
851 sal_uInt32 NoEntry;
852 osl_TProfileSection* pSec;
853 osl_TProfileImpl* pProfile = 0;
854 osl_TProfileImpl* pTmpProfile = 0;
855 sal_Bool bRet = sal_False;
857 #ifdef TRACE_OSL_PROFILE
858 OSL_TRACE("In osl_removeProfileEntry\n");
859 #endif
861 pTmpProfile = (osl_TProfileImpl*) Profile;
863 if ( pTmpProfile == 0 )
865 #ifdef TRACE_OSL_PROFILE
866 OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]\n");
867 #endif
868 return sal_False;
871 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
873 if ( pTmpProfile->m_bIsValid == sal_False )
875 OSL_ASSERT(pTmpProfile->m_bIsValid);
876 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
877 #ifdef TRACE_OSL_PROFILE
878 OSL_TRACE("Out osl_removeProfileEntry [not valid]\n");
879 #endif
880 return sal_False;
884 pProfile = acquireProfile(Profile, sal_True);
886 if (pProfile == NULL)
888 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
889 #ifdef TRACE_OSL_PROFILE
890 OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]\n");
891 #endif
892 return (sal_False);
896 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
898 if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
899 (NoEntry < pSec->m_NoEntries))
901 removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line);
902 removeEntry(pSec, NoEntry);
903 if (pSec->m_NoEntries == 0)
905 removeLine(pProfile, pSec->m_Line);
907 /* remove any empty separation line */
908 if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0'))
909 removeLine(pProfile, pSec->m_Line - 1);
911 removeSection(pProfile, pSec);
914 pProfile->m_Flags |= FLG_MODIFIED;
917 else
918 { /* not implemented */ }
921 bRet = releaseProfile(pProfile);
922 OSL_ASSERT(bRet);
924 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
926 #ifdef TRACE_OSL_PROFILE
927 OSL_TRACE("Out osl_removeProfileEntry [ok]\n");
928 #endif
929 return bRet;
933 sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile, const sal_Char *pszSection,
934 sal_Char* pszBuffer, sal_uInt32 MaxLen)
936 sal_uInt32 i, n = 0;
937 sal_uInt32 NoEntry;
938 osl_TProfileSection* pSec;
939 osl_TProfileImpl* pProfile = 0;
940 osl_TProfileImpl* pTmpProfile = 0;
941 sal_Bool bRet = sal_False;
943 #ifdef TRACE_OSL_PROFILE
944 OSL_TRACE("In osl_getProfileSectionEntries\n");
945 #endif
947 pTmpProfile = (osl_TProfileImpl*) Profile;
949 if ( pTmpProfile == 0 )
951 #ifdef TRACE_OSL_PROFILE
952 OSL_TRACE("Out osl_getProfileSectionEntries [pTmpProfile==0]\n");
953 #endif
954 return sal_False;
958 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
960 if ( pTmpProfile->m_bIsValid == sal_False )
962 OSL_ASSERT(pTmpProfile->m_bIsValid);
964 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
966 #ifdef TRACE_OSL_PROFILE
967 OSL_TRACE("Out osl_getProfileSectionEntries [not valid]\n");
968 #endif
970 return sal_False;
973 pProfile = acquireProfile(Profile, sal_False);
975 if (pProfile == NULL)
977 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
979 #ifdef TRACE_OSL_PROFILE
980 OSL_TRACE("Out osl_getProfileSectionEntries [pProfile=0]\n");
981 #endif
983 return (0);
987 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
989 if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != NULL)
991 if (MaxLen != 0)
993 for (i = 0; i < pSec->m_NoEntries; i++)
995 if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen)
997 strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
998 [pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len);
999 n += pSec->m_Entries[i].m_Len;
1000 pszBuffer[n++] = '\0';
1002 else
1003 break;
1007 pszBuffer[n++] = '\0';
1009 else
1011 for (i = 0; i < pSec->m_NoEntries; i++)
1012 n += pSec->m_Entries[i].m_Len + 1;
1014 n += 1;
1017 else
1018 n = 0;
1020 else {
1021 /* not implemented */
1024 bRet=releaseProfile(pProfile);
1025 OSL_ASSERT(bRet);
1027 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
1029 #ifdef TRACE_OSL_PROFILE
1030 OSL_TRACE("Out osl_getProfileSectionEntries [ok]\n");
1031 #endif
1033 return (n);
1036 sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile, sal_Char* pszBuffer, sal_uInt32 MaxLen)
1038 sal_uInt32 i, n = 0;
1039 osl_TProfileSection* pSec;
1040 osl_TProfileImpl* pProfile = 0;
1041 osl_TProfileImpl* pTmpProfile = 0;
1042 sal_Bool bRet = sal_False;
1044 #ifdef TRACE_OSL_PROFILE
1045 OSL_TRACE("In osl_getProfileSections\n");
1046 #endif
1048 pTmpProfile = (osl_TProfileImpl*) Profile;
1050 if ( pTmpProfile == 0 )
1052 #ifdef TRACE_OSL_PROFILE
1053 OSL_TRACE("Out osl_getProfileSections [pTmpProfile==0]\n");
1054 #endif
1055 return sal_False;
1058 pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
1060 if ( pTmpProfile->m_bIsValid == sal_False )
1062 OSL_ASSERT(pTmpProfile->m_bIsValid);
1063 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
1064 #ifdef TRACE_OSL_PROFILE
1065 OSL_TRACE("Out osl_getProfileSections [not valid]\n");
1066 #endif
1067 return sal_False;
1070 pProfile = acquireProfile(Profile, sal_False);
1072 if (pProfile == NULL)
1074 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
1076 #ifdef TRACE_OSL_PROFILE
1077 OSL_TRACE("Out osl_getProfileSections [pProfile==0]\n");
1078 #endif
1079 return (0);
1082 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
1084 if (MaxLen != 0)
1086 for (i = 0; i < pProfile->m_NoSections; i++)
1088 pSec = &pProfile->m_Sections[i];
1090 if ((n + pSec->m_Len + 1) < MaxLen)
1092 strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset],
1093 pSec->m_Len);
1094 n += pSec->m_Len;
1095 pszBuffer[n++] = '\0';
1097 else
1098 break;
1101 pszBuffer[n++] = '\0';
1103 else
1105 for (i = 0; i < pProfile->m_NoSections; i++)
1106 n += pProfile->m_Sections[i].m_Len + 1;
1108 n += 1;
1111 else
1112 { /* not implemented */ }
1115 bRet=releaseProfile(pProfile);
1116 OSL_ASSERT(bRet);
1118 pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
1120 #ifdef TRACE_OSL_PROFILE
1121 OSL_TRACE("Out osl_getProfileSections [ok]\n");
1122 #endif
1124 return (n);
1127 /*****************************************************************************/
1128 /* Static Module Functions */
1129 /*****************************************************************************/
1131 static osl_TStamp OslProfile_getFileStamp(osl_TFile* pFile)
1133 struct stat status;
1135 if ( (pFile->m_Handle < 0) || (fstat(pFile->m_Handle, &status) < 0) )
1137 return (0);
1141 return (status.st_mtime);
1144 static sal_Bool OslProfile_lockFile(const osl_TFile* pFile, osl_TLockMode eMode)
1146 struct flock lock;
1147 /* boring hack, but initializers for static vars must be constant */
1148 static sal_Bool bIsInitialized = sal_False;
1149 static sal_Bool bLockingDisabled;
1151 #ifdef TRACE_OSL_PROFILE
1152 OSL_TRACE("In OslProfile_lockFile\n");
1153 #endif
1155 if ( !bIsInitialized )
1157 sal_Char* pEnvValue;
1158 pEnvValue = getenv( "STAR_PROFILE_LOCKING_DISABLED" );
1160 if ( pEnvValue == 0 )
1162 bLockingDisabled = sal_False;
1165 else
1167 bLockingDisabled = sal_True;
1170 bIsInitialized = sal_True;
1173 if (pFile->m_Handle < 0)
1175 #ifdef TRACE_OSL_PROFILE
1176 OSL_TRACE("Out OslProfile_lockFile [invalid file handle]\n");
1177 #endif
1178 return (sal_False);
1182 if ( bLockingDisabled )
1184 #ifdef TRACE_OSL_PROFILE
1185 OSL_TRACE("Out OslProfile_lockFile [locking disabled]\n");
1186 #endif
1187 return (sal_True);
1191 lock.l_start = 0;
1192 lock.l_whence = SEEK_SET;
1193 lock.l_len = 0;
1195 switch (eMode)
1197 case un_lock:
1198 lock.l_type = F_UNLCK;
1199 break;
1201 case read_lock:
1202 lock.l_type = F_RDLCK;
1203 break;
1205 case write_lock:
1206 lock.l_type = F_WRLCK;
1207 break;
1210 #ifndef MACOSX // not MAC OSX
1211 if ( fcntl(pFile->m_Handle, F_SETLKW, &lock) == -1 )
1212 #else
1213 /* Mac OSX will return ENOTSUP for webdav drives so we should ignore it */
1214 if ( fcntl(pFile->m_Handle, F_SETLKW, &lock) == -1 && errno != ENOTSUP )
1215 #endif /* MACOSX */
1217 OSL_TRACE("fcntl returned -1 (%s)\n",strerror(errno));
1218 #ifdef TRACE_OSL_PROFILE
1219 OSL_TRACE("Out OslProfile_lockFile [fcntl F_SETLKW]\n");
1220 #endif
1221 return sal_False;
1224 #ifdef TRACE_OSL_PROFILE
1225 OSL_TRACE("Out OslProfile_lockFile [ok]\n");
1226 #endif
1227 return sal_True;
1230 static osl_TFile* openFileImpl(const sal_Char* pszFilename, oslProfileOption ProfileFlags )
1232 int Flags;
1233 osl_TFile* pFile = (osl_TFile*) calloc(1, sizeof(osl_TFile));
1234 sal_Bool bWriteable = sal_False;
1236 if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
1238 #ifdef DEBUG_OSL_PROFILE
1239 OSL_TRACE("setting bWriteable to TRUE\n");
1240 #endif
1241 bWriteable=sal_True;
1244 if (! bWriteable)
1246 #ifdef DEBUG_OSL_PROFILE
1247 OSL_TRACE("opening '%s' read only\n",pszFilename);
1248 #endif
1250 pFile->m_Handle = open(pszFilename, O_RDONLY);
1251 /* mfe: argghh!!! do not check if the file could be openend */
1252 /* default mode expects it that way!!! */
1254 else
1256 #ifdef DEBUG_OSL_PROFILE
1257 OSL_TRACE("opening '%s' read/write\n",pszFilename);
1258 #endif
1259 if (((pFile->m_Handle = open(pszFilename, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PMODE)) < 0) &&
1260 ((pFile->m_Handle = open(pszFilename, O_RDWR)) < 0))
1262 free(pFile);
1263 #ifdef TRACE_OSL_PROFILE
1264 OSL_TRACE("Out openFileImpl [open read/write]\n");
1265 #endif
1266 return (NULL);
1270 /* set close-on-exec flag */
1271 if ((Flags = fcntl(pFile->m_Handle, F_GETFD, 0)) != -1)
1273 Flags |= FD_CLOEXEC;
1274 fcntl(pFile->m_Handle, F_SETFD, Flags);
1277 pFile->m_pWriteBuf=0;
1278 pFile->m_nWriteBufFree=0;
1279 pFile->m_nWriteBufLen=0;
1281 if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
1283 #ifdef DEBUG_OSL_PROFILE
1284 OSL_TRACE("locking '%s' file\n",pszFilename);
1285 #endif
1286 OslProfile_lockFile(pFile, bWriteable ? write_lock : read_lock);
1289 #ifdef TRACE_OSL_PROFILE
1290 OSL_TRACE("Out openFileImpl [ok]\n");
1291 #endif
1292 return (pFile);
1295 static osl_TStamp closeFileImpl(osl_TFile* pFile, oslProfileOption Flags)
1297 osl_TStamp stamp = 0;
1299 #ifdef TRACE_OSL_PROFILE
1300 OSL_TRACE("In closeFileImpl\n");
1301 #endif
1303 if ( pFile == 0 )
1305 #ifdef TRACE_OSL_PROFILE
1306 OSL_TRACE("Out closeFileImpl [pFile == 0]\n");
1307 #endif
1308 return stamp;
1311 if ( pFile->m_Handle >= 0 )
1313 stamp = OslProfile_getFileStamp(pFile);
1315 if ( Flags & (osl_Profile_WRITELOCK | osl_Profile_WRITELOCK ) )
1317 OslProfile_lockFile(pFile, un_lock);
1320 close(pFile->m_Handle);
1321 pFile->m_Handle = -1;
1325 if ( pFile->m_pWriteBuf )
1327 free(pFile->m_pWriteBuf);
1330 free(pFile);
1332 #ifdef TRACE_OSL_PROFILE
1333 OSL_TRACE("Out closeFileImpl [ok]\n");
1334 #endif
1336 return(stamp);
1339 static sal_Bool OslProfile_rewindFile(osl_TFile* pFile, sal_Bool bTruncate)
1341 #ifdef TRACE_OSL_PROFILE
1342 OSL_TRACE("In osl_OslProfile_rewindFile\n");
1343 #endif
1345 if (pFile->m_Handle >= 0)
1347 pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1349 #ifdef DEBUG_OSL_PROFILE
1350 OSL_TRACE("rewinding\n");
1351 #endif
1352 lseek(pFile->m_Handle, SEEK_SET, 0L);
1354 if (bTruncate)
1356 #ifdef DEBUG_OSL_PROFILE
1357 OSL_TRACE("truncating\n");
1358 #endif
1359 ftruncate(pFile->m_Handle, 0L);
1364 #ifdef TRACE_OSL_PROFILE
1365 OSL_TRACE("Out osl_OslProfile_rewindFile [ok]\n");
1366 #endif
1367 return (sal_True);
1371 static sal_Char* OslProfile_getLine(osl_TFile* pFile)
1373 int Max, Free, Bytes, nLineBytes = 0;
1374 sal_Char* pChr;
1375 sal_Char* pLine = NULL;
1376 sal_Char* pNewLine;
1378 if ( pFile == 0 )
1380 return 0;
1383 if (pFile->m_Handle < 0)
1384 return NULL;
1388 Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf);
1390 if (Bytes <= 1)
1392 /* refill buffer */
1393 memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes);
1394 pFile->m_pReadPtr = pFile->m_ReadBuf;
1396 Free = sizeof(pFile->m_ReadBuf) - Bytes;
1398 if ((Max = read(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free)) < 0)
1400 OSL_TRACE("read failed '%s'\n",strerror(errno));
1402 if( pLine )
1403 rtl_freeMemory( pLine );
1404 pLine = NULL;
1405 break;
1408 if (Max < Free)
1410 if ((Max == 0) && ! pLine)
1411 break;
1413 pFile->m_ReadBuf[Bytes + Max] = '\0';
1417 for (pChr = pFile->m_pReadPtr;
1418 (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') &&
1419 (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1));
1420 pChr++);
1422 Max = pChr - pFile->m_pReadPtr;
1423 pNewLine = (sal_Char*) rtl_allocateMemory( nLineBytes + Max + 1 );
1424 if( pLine )
1426 memcpy( pNewLine, pLine, nLineBytes );
1427 rtl_freeMemory( pLine );
1429 memcpy(pNewLine+nLineBytes, pFile->m_pReadPtr, Max);
1430 nLineBytes += Max;
1431 pNewLine[ nLineBytes ] = 0;
1432 pLine = pNewLine;
1434 if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1))
1436 if (*pChr != '\0')
1438 if ((pChr[0] == '\r') && (pChr[1] == '\n'))
1439 pChr += 2;
1440 else
1441 pChr += 1;
1444 if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) &&
1445 (*pChr == '\0'))
1446 pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1448 /* setting Max to -1 indicates terminating read loop */
1449 Max = -1;
1452 pFile->m_pReadPtr = pChr;
1454 while (Max > 0);
1456 return pLine;
1459 static sal_Bool OslProfile_putLine(osl_TFile* pFile, const sal_Char *pszLine)
1461 unsigned int Len = strlen(pszLine);
1463 #ifdef DEBUG_OSL_PROFILE
1464 int strLen=0;
1465 #endif
1467 if ( pFile == 0 || pFile->m_Handle < 0 )
1469 return (sal_False);
1472 if ( pFile->m_pWriteBuf == 0 )
1474 pFile->m_pWriteBuf = (sal_Char*) malloc(Len+3);
1475 pFile->m_nWriteBufLen = Len+3;
1476 pFile->m_nWriteBufFree = Len+3;
1478 else
1480 if ( pFile->m_nWriteBufFree <= Len + 3 )
1482 sal_Char* pTmp;
1484 pTmp=(sal_Char*) realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) );
1485 if ( pTmp == 0 )
1487 return sal_False;
1489 pFile->m_pWriteBuf = pTmp;
1490 pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len );
1491 pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2;
1492 memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree);
1498 memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1);
1499 #ifdef DEBUG_OSL_PROFILE
1500 strLen = strlen(pFile->m_pWriteBuf);
1501 #endif
1502 pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\n';
1503 pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\0';
1505 pFile->m_nWriteBufFree-=Len+1;
1507 return sal_True;
1510 /* platform specific end */
1512 static sal_Char* stripBlanks(sal_Char* String, sal_uInt32* pLen)
1514 if ( ( pLen != NULL ) && ( *pLen != 0 ) )
1516 while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t'))
1517 (*pLen)--;
1519 while ( (*String == ' ') || (*String == '\t') )
1521 String++;
1522 (*pLen)--;
1525 else
1526 while ( (*String == ' ') || (*String == '\t') )
1527 String++;
1529 return (String);
1532 static sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line)
1534 if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1536 if (pProfile->m_Lines == NULL)
1538 pProfile->m_MaxLines = LINES_INI;
1539 pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
1540 memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
1542 else
1544 unsigned int idx=0;
1545 unsigned int oldmax=pProfile->m_MaxLines;
1547 pProfile->m_MaxLines += LINES_ADD;
1548 pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
1549 pProfile->m_MaxLines * sizeof(sal_Char *));
1550 for ( idx = oldmax ; idx < pProfile->m_MaxLines ; ++idx )
1552 pProfile->m_Lines[idx]=0;
1556 if (pProfile->m_Lines == NULL)
1558 pProfile->m_NoLines = 0;
1559 pProfile->m_MaxLines = 0;
1560 return (NULL);
1565 if ( pProfile->m_Lines != 0 && pProfile->m_Lines[pProfile->m_NoLines] != 0 )
1567 free(pProfile->m_Lines[pProfile->m_NoLines]);
1569 pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line);
1571 return (pProfile->m_Lines[pProfile->m_NoLines - 1]);
1574 static sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo)
1576 if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1578 if (pProfile->m_Lines == NULL)
1580 pProfile->m_MaxLines = LINES_INI;
1581 pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
1582 memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
1584 else
1586 pProfile->m_MaxLines += LINES_ADD;
1587 pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
1588 pProfile->m_MaxLines * sizeof(sal_Char *));
1590 memset(&pProfile->m_Lines[pProfile->m_NoLines],
1592 (pProfile->m_MaxLines - pProfile->m_NoLines - 1) * sizeof(sal_Char*));
1595 if (pProfile->m_Lines == NULL)
1597 pProfile->m_NoLines = 0;
1598 pProfile->m_MaxLines = 0;
1599 return (NULL);
1603 LineNo = LineNo > pProfile->m_NoLines ? pProfile->m_NoLines : LineNo;
1605 if (LineNo < pProfile->m_NoLines)
1607 sal_uInt32 i, n;
1608 osl_TProfileSection* pSec;
1610 memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo],
1611 (pProfile->m_NoLines - LineNo) * sizeof(sal_Char *));
1614 /* adjust line references */
1615 for (i = 0; i < pProfile->m_NoSections; i++)
1617 pSec = &pProfile->m_Sections[i];
1619 if (pSec->m_Line >= LineNo)
1620 pSec->m_Line++;
1622 for (n = 0; n < pSec->m_NoEntries; n++)
1623 if (pSec->m_Entries[n].m_Line >= LineNo)
1624 pSec->m_Entries[n].m_Line++;
1628 pProfile->m_NoLines++;
1630 pProfile->m_Lines[LineNo] = strdup(Line);
1632 return (pProfile->m_Lines[LineNo]);
1635 static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo)
1637 if (LineNo < pProfile->m_NoLines)
1639 free(pProfile->m_Lines[LineNo]);
1640 pProfile->m_Lines[LineNo]=0;
1641 if (pProfile->m_NoLines - LineNo > 1)
1643 sal_uInt32 i, n;
1644 osl_TProfileSection* pSec;
1646 memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1],
1647 (pProfile->m_NoLines - LineNo - 1) * sizeof(sal_Char *));
1649 memset(&pProfile->m_Lines[pProfile->m_NoLines - 1],
1651 (pProfile->m_MaxLines - pProfile->m_NoLines) * sizeof(sal_Char*));
1653 /* adjust line references */
1654 for (i = 0; i < pProfile->m_NoSections; i++)
1656 pSec = &pProfile->m_Sections[i];
1658 if (pSec->m_Line > LineNo)
1659 pSec->m_Line--;
1661 for (n = 0; n < pSec->m_NoEntries; n++)
1662 if (pSec->m_Entries[n].m_Line > LineNo)
1663 pSec->m_Entries[n].m_Line--;
1666 else
1668 pProfile->m_Lines[LineNo] = 0;
1671 pProfile->m_NoLines--;
1674 return;
1677 static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
1678 sal_uInt32 NoEntry, sal_uInt32 Line,
1679 sal_Char* Entry, sal_uInt32 Len)
1681 Entry = stripBlanks(Entry, &Len);
1682 pSection->m_Entries[NoEntry].m_Line = Line;
1683 pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line];
1684 pSection->m_Entries[NoEntry].m_Len = Len;
1686 return;
1689 static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
1690 int Line, sal_Char* Entry, sal_uInt32 Len)
1692 if (pSection != NULL)
1694 if (pSection->m_NoEntries >= pSection->m_MaxEntries)
1696 if (pSection->m_Entries == NULL)
1698 pSection->m_MaxEntries = ENTRIES_INI;
1699 pSection->m_Entries = (osl_TProfileEntry *)malloc(
1700 pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
1702 else
1704 pSection->m_MaxEntries += ENTRIES_ADD;
1705 pSection->m_Entries = (osl_TProfileEntry *)realloc(pSection->m_Entries,
1706 pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
1709 if (pSection->m_Entries == NULL)
1711 pSection->m_NoEntries = 0;
1712 pSection->m_MaxEntries = 0;
1713 return (sal_False);
1717 pSection->m_NoEntries++;
1719 Entry = stripBlanks(Entry, &Len);
1720 setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line,
1721 Entry, Len);
1723 return (sal_True);
1726 return (sal_False);
1729 static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry)
1731 if (NoEntry < pSection->m_NoEntries)
1733 if (pSection->m_NoEntries - NoEntry > 1)
1735 memmove(&pSection->m_Entries[NoEntry],
1736 &pSection->m_Entries[NoEntry + 1],
1737 (pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry));
1738 pSection->m_Entries[pSection->m_NoEntries - 1].m_Line=0;
1739 pSection->m_Entries[pSection->m_NoEntries - 1].m_Offset=0;
1740 pSection->m_Entries[pSection->m_NoEntries - 1].m_Len=0;
1743 pSection->m_NoEntries--;
1746 return;
1749 static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len)
1751 if (pProfile->m_NoSections >= pProfile->m_MaxSections)
1753 if (pProfile->m_Sections == NULL)
1755 pProfile->m_MaxSections = SECTIONS_INI;
1756 pProfile->m_Sections = (osl_TProfileSection *)malloc(pProfile->m_MaxSections * sizeof(osl_TProfileSection));
1757 memset(pProfile->m_Sections,0,pProfile->m_MaxSections * sizeof(osl_TProfileSection));
1759 else
1761 unsigned int idx=0;
1762 unsigned int oldmax=pProfile->m_MaxSections;
1764 pProfile->m_MaxSections += SECTIONS_ADD;
1765 pProfile->m_Sections = (osl_TProfileSection *)realloc(pProfile->m_Sections,
1766 pProfile->m_MaxSections * sizeof(osl_TProfileSection));
1767 for ( idx = oldmax ; idx < pProfile->m_MaxSections ; ++idx )
1769 pProfile->m_Sections[idx].m_Entries=0;
1773 if (pProfile->m_Sections == NULL)
1775 pProfile->m_NoSections = 0;
1776 pProfile->m_MaxSections = 0;
1777 return (sal_False);
1781 pProfile->m_NoSections++;
1783 if ( pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries != 0 )
1785 free(pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries);
1787 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = NULL;
1788 pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries = 0;
1789 pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0;
1791 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line;
1792 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line];
1793 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len;
1795 return (sal_True);
1798 static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection)
1800 sal_uInt32 Section;
1802 if ((Section = pSection - pProfile->m_Sections) < pProfile->m_NoSections)
1804 free (pSection->m_Entries);
1805 pSection->m_Entries=0;
1806 if (pProfile->m_NoSections - Section > 1)
1808 memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1],
1809 (pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection));
1811 memset(&pProfile->m_Sections[pProfile->m_NoSections - 1],
1813 (pProfile->m_MaxSections - pProfile->m_NoSections) * sizeof(osl_TProfileSection));
1814 pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = 0;
1816 else
1818 pSection->m_Entries = 0;
1821 pProfile->m_NoSections--;
1824 return;
1827 static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
1828 const sal_Char* Entry, sal_uInt32 *pNoEntry)
1830 static sal_uInt32 Sect = 0;
1831 sal_uInt32 i, n;
1832 sal_uInt32 Len;
1833 const sal_Char* pStr;
1834 osl_TProfileSection* pSec=0;
1836 Len = strlen(Section);
1838 n = Sect;
1840 for (i = 0; i < pProfile->m_NoSections; i++)
1842 n %= pProfile->m_NoSections;
1843 pSec = &pProfile->m_Sections[n];
1844 if ((Len == pSec->m_Len) &&
1845 (strncasecmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len)
1846 == 0))
1847 break;
1848 n++;
1851 Sect = n;
1853 if (i < pProfile->m_NoSections)
1855 Len = strlen(Entry);
1857 *pNoEntry = pSec->m_NoEntries;
1859 for (i = 0; i < pSec->m_NoEntries; i++)
1861 pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
1862 [pSec->m_Entries[i].m_Offset];
1863 if ((Len == pSec->m_Entries[i].m_Len) &&
1864 (strncasecmp(Entry, pStr, pSec->m_Entries[i].m_Len)
1865 == 0))
1867 *pNoEntry = i;
1868 break;
1872 else
1873 pSec = NULL;
1875 return (pSec);
1878 static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile)
1880 sal_uInt32 i;
1881 sal_Char* pStr;
1882 sal_Char* pChar;
1884 sal_Char* pLine;
1885 sal_Char* bWasAdded = NULL;
1887 pProfile->m_NoLines = 0;
1888 pProfile->m_NoSections = 0;
1890 if ( pFile == 0 )
1892 return sal_False;
1895 if ( pProfile == 0 )
1897 return sal_False;
1900 OSL_VERIFY(OslProfile_rewindFile(pFile, sal_False));
1902 while ( ( pLine=OslProfile_getLine(pFile) ) != 0 )
1904 bWasAdded = addLine( pProfile, pLine );
1905 rtl_freeMemory( pLine );
1906 OSL_ASSERT(bWasAdded);
1907 if ( ! bWasAdded )
1908 return (sal_False);
1911 for (i = 0; i < pProfile->m_NoLines; i++)
1913 pStr = (sal_Char *)stripBlanks(pProfile->m_Lines[i], NULL);
1915 if ((*pStr == '\0') || (*pStr == ';'))
1916 continue;
1918 if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == NULL) ||
1919 ((pChar - pStr) <= 2))
1921 /* insert entry */
1923 if (pProfile->m_NoSections < 1)
1924 continue;
1926 if ((pChar = strchr(pStr, '=')) == NULL)
1927 pChar = pStr + strlen(pStr);
1929 if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1],
1930 i, pStr, pChar - pStr))
1932 OSL_ASSERT(0);
1933 continue;
1937 else
1939 /* new section */
1941 if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1))
1943 OSL_ASSERT(0);
1944 continue;
1950 return (sal_True);
1953 static sal_Bool storeProfile(osl_TProfileImpl* pProfile, sal_Bool bCleanup)
1955 #ifdef TRACE_OSL_PROFILE
1956 OSL_TRACE("In storeProfile\n");
1957 #endif
1959 if (pProfile->m_Lines != NULL)
1961 if (pProfile->m_Flags & FLG_MODIFIED)
1963 sal_uInt32 i;
1965 osl_TFile* pTmpFile = osl_openTmpProfileImpl(pProfile);
1967 if ( pTmpFile == 0 )
1969 return sal_False;
1972 OSL_VERIFY(OslProfile_rewindFile(pTmpFile, sal_True));
1974 for ( i = 0 ; i < pProfile->m_NoLines ; i++ )
1976 OSL_VERIFY(OslProfile_putLine(pTmpFile, pProfile->m_Lines[i]));
1979 if ( ! writeProfileImpl(pTmpFile) )
1981 if ( pTmpFile->m_pWriteBuf != 0 )
1983 free(pTmpFile->m_pWriteBuf);
1986 pTmpFile->m_pWriteBuf=0;
1987 pTmpFile->m_nWriteBufLen=0;
1988 pTmpFile->m_nWriteBufFree=0;
1990 #ifdef TRACE_OSL_PROFILE
1991 OSL_TRACE("Out storeProfile [not flushed]\n");
1992 #endif
1993 closeFileImpl(pTmpFile,pProfile->m_Flags);
1995 return sal_False;
1998 pProfile->m_Flags &= ~FLG_MODIFIED;
2000 closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
2001 closeFileImpl(pTmpFile,pProfile->m_Flags);
2003 osl_ProfileSwapProfileNames(pProfile);
2005 pProfile->m_pFile = openFileImpl(pProfile->m_FileName,pProfile->m_Flags);
2009 if (bCleanup)
2011 while (pProfile->m_NoLines > 0)
2012 removeLine(pProfile, pProfile->m_NoLines - 1);
2014 free(pProfile->m_Lines);
2015 pProfile->m_Lines = NULL;
2016 pProfile->m_NoLines = 0;
2017 pProfile->m_MaxLines = 0;
2019 while (pProfile->m_NoSections > 0)
2020 removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]);
2022 free(pProfile->m_Sections);
2023 pProfile->m_Sections = NULL;
2024 pProfile->m_NoSections = 0;
2025 pProfile->m_MaxSections = 0;
2029 #ifdef TRACE_OSL_PROFILE
2030 OSL_TRACE("Out storeProfile [ok]\n");
2031 #endif
2032 return (sal_True);
2036 static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl* pProfile)
2038 osl_TFile* pFile=0;
2039 sal_Char* pszExtension = "tmp";
2040 sal_Char pszTmpName[PATH_MAX];
2041 oslProfileOption PFlags=0;
2043 pszTmpName[0] = '\0';
2045 /* generate tmp profilename */
2046 osl_ProfileGenerateExtension(pProfile->m_FileName,pszExtension,pszTmpName);
2048 if ( pszTmpName[0] == 0 )
2050 return 0;
2053 if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) )
2055 PFlags |= osl_Profile_WRITELOCK;
2058 /* open this file */
2059 pFile = openFileImpl(pszTmpName,pProfile->m_Flags | PFlags);
2062 /* return new pFile */
2063 return pFile;
2066 static sal_Bool osl_ProfileSwapProfileNames(osl_TProfileImpl* pProfile)
2068 sal_Bool bRet = sal_False;
2070 sal_Char pszBakFile[PATH_MAX];
2071 sal_Char pszTmpFile[PATH_MAX];
2072 sal_Char pszIniFile[PATH_MAX];
2074 pszBakFile[0] = '\0';
2075 pszTmpFile[0] = '\0';
2076 pszIniFile[0] = '\0';
2078 osl_ProfileGenerateExtension(pProfile->m_FileName,"bak",pszBakFile);
2080 strcpy(pszIniFile,pProfile->m_FileName);
2082 osl_ProfileGenerateExtension(pProfile->m_FileName,"tmp",pszTmpFile);
2084 /* unlink bak */
2085 unlink( pszBakFile );
2087 /* rename ini bak */
2088 rename( pszIniFile, pszBakFile );
2090 /* rename tmp ini */
2091 rename( pszTmpFile, pszIniFile );
2093 return bRet;
2097 static void osl_ProfileGenerateExtension(sal_Char* pszFileName, sal_Char* pszExtension, sal_Char* pszTmpName)
2100 strcpy(pszTmpName,pszFileName);
2101 strcat(pszTmpName,".");
2102 strcat(pszTmpName,pszExtension);
2104 return;
2108 static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable)
2110 osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
2111 oslProfileOption PFlags=0;
2112 sal_Bool bRet=sal_False;
2114 if ( bWriteable )
2116 PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK;
2118 else
2120 PFlags = osl_Profile_DEFAULT;
2124 if (pProfile == NULL)
2126 #ifdef DEBUG_OSL_PROFILE
2127 OSL_TRACE("AUTOOPEN MODE\n");
2128 #endif
2130 if ( ( pProfile = (osl_TProfileImpl*) osl_openProfile(0, PFlags ) ) != NULL )
2132 pProfile->m_Flags |= FLG_AUTOOPEN;
2135 else
2137 #ifdef DEBUG_OSL_PROFILE
2138 OSL_TRACE("try to acquire\n");
2139 #endif
2141 if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
2143 if (! (pProfile->m_Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE )))
2145 osl_TStamp Stamp;
2147 #ifdef DEBUG_OSL_PROFILE
2148 OSL_TRACE("Profile acquire DEFAULT MODE\n");
2149 #endif
2150 if (! (pProfile->m_pFile = openFileImpl(pProfile->m_FileName, pProfile->m_Flags | PFlags )))
2151 return NULL;
2153 Stamp = OslProfile_getFileStamp(pProfile->m_pFile);
2155 if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp)))
2157 pProfile->m_Stamp = Stamp;
2159 bRet=loadProfile(pProfile->m_pFile, pProfile);
2160 OSL_ASSERT(bRet);
2163 else
2165 #ifdef DEBUG_OSL_PROFILE
2166 OSL_TRACE("Profile acquire READ/WRITELOCK MODE\n");
2167 #endif
2168 /* A readlock file could not be written */
2169 if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable)
2171 return (NULL);
2177 return (pProfile);
2180 static sal_Bool releaseProfile(osl_TProfileImpl* pProfile)
2182 sal_Bool bRet=sal_False;
2184 #ifdef TRACE_OSL_PROFILE
2185 OSL_TRACE("In releaseProfile\n");
2186 #endif
2188 if ( pProfile == 0 )
2190 #ifdef TRACE_OSL_PROFILE
2191 OSL_TRACE("Out releaseProfile [profile==0]\n");
2192 #endif
2193 return sal_False;
2196 if (pProfile->m_Flags & FLG_AUTOOPEN)
2198 #ifdef TRACE_OSL_PROFILE
2199 OSL_TRACE("Out releaseProfile [AUTOOPEN]\n");
2200 #endif
2201 return (osl_closeProfile((oslProfile)pProfile));
2203 else
2205 #ifdef DEBUG_OSL_PROFILE
2206 OSL_TRACE("DEFAULT MODE\n");
2207 #endif
2208 if (! (pProfile->m_Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE )))
2210 if (pProfile->m_Flags & FLG_MODIFIED)
2212 bRet=storeProfile(pProfile, sal_False);
2213 OSL_ASSERT(bRet);
2217 closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
2218 pProfile->m_pFile = NULL;
2222 #ifdef TRACE_OSL_PROFILE
2223 OSL_TRACE("Out releaseProfile [ok]\n");
2224 #endif
2225 return (sal_True);