Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sal/osl/unx/profile.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#include "system.hxx"
21
#include "readwrite_helper.hxx"
22
#include "file_url.hxx"
23
#include "file_impl.hxx"
24
#include "unixerrnostring.hxx"
25
26
#include <osl/diagnose.h>
27
#include <osl/profile.h>
28
#include <sal/log.hxx>
29
30
#include <fcntl.h>
31
#include <limits.h>
32
#include <string.h>
33
#include <sys/stat.h>
34
#include <unistd.h>
35
36
0
#define LINES_INI       32
37
0
#define LINES_ADD       10
38
0
#define SECTIONS_INI    5
39
0
#define SECTIONS_ADD    3
40
0
#define ENTRIES_INI     5
41
0
#define ENTRIES_ADD     3
42
43
0
#define STR_INI_BOOLYES     "yes"
44
0
#define STR_INI_BOOLON      "on"
45
0
#define STR_INI_BOOLONE     "1"
46
0
#define STR_INI_BOOLNO      "no"
47
0
#define STR_INI_BOOLOFF     "off"
48
0
#define STR_INI_BOOLZERO    "0"
49
50
0
#define FLG_USER            0x00FF
51
0
#define FLG_AUTOOPEN        0x0100
52
0
#define FLG_MODIFIED        0x0200
53
54
0
#define DEFAULT_PMODE   (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
55
56
typedef time_t  osl_TStamp;
57
58
namespace {
59
60
enum osl_TLockMode
61
{
62
    un_lock, read_lock, write_lock
63
};
64
65
struct osl_TFile
66
{
67
    int     m_Handle;
68
    char*   m_pReadPtr;
69
    char    m_ReadBuf[512];
70
    char*   m_pWriteBuf;
71
    sal_uInt32  m_nWriteBufLen;
72
    sal_uInt32  m_nWriteBufFree;
73
};
74
75
struct osl_TProfileEntry
76
{
77
    sal_uInt32  m_Line;
78
    sal_uInt32  m_Offset;
79
    sal_uInt32  m_Len;
80
};
81
82
struct osl_TProfileSection
83
{
84
    sal_uInt32  m_Line;
85
    sal_uInt32  m_Offset;
86
    sal_uInt32  m_Len;
87
    sal_uInt32  m_NoEntries;
88
    sal_uInt32  m_MaxEntries;
89
    osl_TProfileEntry*  m_Entries;
90
};
91
92
/* Profile-data structure hidden behind oslProfile: */
93
struct osl_TProfileImpl
94
{
95
    sal_uInt32  m_Flags;
96
    osl_TFile*  m_pFile;
97
    osl_TStamp  m_Stamp;
98
    char    m_FileName[PATH_MAX + 1];
99
    sal_uInt32  m_NoLines;
100
    sal_uInt32  m_MaxLines;
101
    sal_uInt32  m_NoSections;
102
    sal_uInt32  m_MaxSections;
103
    char**  m_Lines;
104
    osl_TProfileSection* m_Sections;
105
    pthread_mutex_t m_AccessLock;
106
    bool        m_bIsValid;
107
};
108
109
}
110
111
static osl_TFile* openFileImpl(const char* pszFilename, oslProfileOption ProfileFlags);
112
static osl_TStamp closeFileImpl(osl_TFile* pFile, oslProfileOption Flags);
113
static bool   OslProfile_lockFile(const osl_TFile* pFile, osl_TLockMode eMode);
114
static bool   OslProfile_rewindFile(osl_TFile* pFile, bool bTruncate);
115
static osl_TStamp OslProfile_getFileStamp(osl_TFile* pFile);
116
117
static char*   OslProfile_getLine(osl_TFile* pFile);
118
static bool   OslProfile_putLine(osl_TFile* pFile, const char *pszLine);
119
static char* stripBlanks(char* String, sal_uInt32* pLen);
120
static char* addLine(osl_TProfileImpl* pProfile, const char* Line);
121
static char* insertLine(osl_TProfileImpl* pProfile, const char* Line, sal_uInt32 LineNo);
122
static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo);
123
static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
124
                     sal_uInt32 NoEntry, sal_uInt32 Line,
125
                     char* Entry, sal_uInt32 Len);
126
static bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
127
                     int Line, char* Entry, sal_uInt32 Len);
128
static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry);
129
static bool addSection(osl_TProfileImpl* pProfile, int Line, const char* Section, sal_uInt32 Len);
130
static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection);
131
static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const char* Section,
132
                                      const char* Entry, sal_uInt32 *pNoEntry);
133
static bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile);
134
static bool storeProfile(osl_TProfileImpl* pProfile, bool bCleanup);
135
static osl_TProfileImpl* acquireProfile(oslProfile Profile, bool bWriteable);
136
static bool releaseProfile(osl_TProfileImpl* pProfile);
137
138
static bool writeProfileImpl (osl_TFile* pFile);
139
static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl*);
140
static bool osl_ProfileSwapProfileNames(osl_TProfileImpl*);
141
static void osl_ProfileGenerateExtension(const char* pszFileName, const char* pszExtension, char* pszTmpName, int BufferMaxLen);
142
static oslProfile osl_psz_openProfile(const char *pszProfileName, oslProfileOption Flags);
143
144
oslProfile SAL_CALL osl_openProfile(rtl_uString *ustrProfileName, oslProfileOption Options)
145
0
{
146
0
    char profilePath[PATH_MAX] = "";
147
0
    return
148
0
        (ustrProfileName == nullptr
149
0
         || ustrProfileName->buffer[0] == 0
150
0
         || (FileURLToPath(profilePath, PATH_MAX, ustrProfileName)
151
0
             == osl_File_E_None))
152
0
        ? osl_psz_openProfile(profilePath, Options)
153
0
        : nullptr;
154
0
}
155
156
static oslProfile osl_psz_openProfile(const char *pszProfileName, oslProfileOption Flags)
157
0
{
158
0
    osl_TFile*        pFile;
159
0
    osl_TProfileImpl* pProfile;
160
0
    bool bRet = false;
161
162
0
    if ( ( pFile = openFileImpl(pszProfileName, Flags ) ) == nullptr )
163
0
    {
164
0
        return nullptr;
165
0
    }
166
167
0
    pProfile = static_cast<osl_TProfileImpl*>(calloc(1, sizeof(osl_TProfileImpl)));
168
169
0
    if ( pProfile == nullptr )
170
0
    {
171
0
        closeFileImpl(pFile, Flags);
172
0
        return nullptr;
173
0
    }
174
175
0
    pProfile->m_Flags = Flags & FLG_USER;
176
177
0
    if ( Flags & ( osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
178
0
    {
179
0
        pProfile->m_pFile = pFile;
180
0
    }
181
182
0
    pthread_mutex_init(&(pProfile->m_AccessLock),PTHREAD_MUTEXATTR_DEFAULT);
183
0
    pProfile->m_bIsValid = true;
184
185
0
    pProfile->m_Stamp = OslProfile_getFileStamp(pFile);
186
0
    bRet=loadProfile(pFile, pProfile);
187
0
    bRet &= realpath(pszProfileName, pProfile->m_FileName) != nullptr;
188
0
    SAL_WARN_IF(!bRet, "sal.osl", "realpath(pszProfileName, pProfile->m_FileName) != NULL ==> false");
189
190
0
    if (pProfile->m_pFile == nullptr)
191
0
        closeFileImpl(pFile,pProfile->m_Flags);
192
193
0
    return pProfile;
194
0
}
195
196
sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile)
197
0
{
198
0
    osl_TProfileImpl* pProfile = static_cast<osl_TProfileImpl*>(Profile);
199
0
    osl_TProfileImpl* pTmpProfile;
200
201
0
    if ( Profile == nullptr )
202
0
    {
203
0
        return false;
204
0
    }
205
206
0
    pthread_mutex_lock(&(pProfile->m_AccessLock));
207
208
0
    if ( !pProfile->m_bIsValid )
209
0
    {
210
0
        SAL_WARN("sal.osl", "!pProfile->m_bIsValid");
211
0
        pthread_mutex_unlock(&(pProfile->m_AccessLock));
212
213
0
        return false;
214
0
    }
215
216
0
    pProfile->m_bIsValid = false;
217
218
0
    if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) && ( pProfile->m_Flags & FLG_MODIFIED ) )
219
0
    {
220
0
        pTmpProfile = acquireProfile(Profile, true);
221
222
0
        if ( pTmpProfile != nullptr )
223
0
        {
224
0
            bool bRet = storeProfile(pTmpProfile, true);
225
0
            SAL_WARN_IF(!bRet, "sal.osl", "storeProfile(pTmpProfile, true) ==> false");
226
0
        }
227
0
    }
228
0
    else
229
0
    {
230
0
        pTmpProfile = acquireProfile(Profile, false);
231
0
    }
232
233
0
    if ( pTmpProfile == nullptr )
234
0
    {
235
0
        pthread_mutex_unlock(&(pProfile->m_AccessLock));
236
237
0
        SAL_INFO("sal.osl", "Out osl_closeProfile [pProfile==0]");
238
0
        return false;
239
0
    }
240
241
0
    pProfile = pTmpProfile;
242
243
0
    if (pProfile->m_pFile != nullptr)
244
0
        closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
245
246
0
    pProfile->m_pFile = nullptr;
247
0
    pProfile->m_FileName[0] = '\0';
248
249
    /* release whole profile data types memory */
250
0
    if ( pProfile->m_NoLines > 0)
251
0
    {
252
0
        unsigned int idx=0;
253
0
        if ( pProfile->m_Lines != nullptr )
254
0
        {
255
0
            for ( idx = 0 ; idx < pProfile->m_NoLines ; ++idx)
256
0
            {
257
0
                if ( pProfile->m_Lines[idx] != nullptr )
258
0
                {
259
0
                    free(pProfile->m_Lines[idx]);
260
0
                    pProfile->m_Lines[idx]=nullptr;
261
0
                }
262
0
            }
263
0
            free(pProfile->m_Lines);
264
0
            pProfile->m_Lines=nullptr;
265
0
        }
266
0
        if ( pProfile->m_Sections != nullptr )
267
0
        {
268
            /*osl_TProfileSection* pSections=pProfile->m_Sections;*/
269
0
            for ( idx = 0 ; idx < pProfile->m_NoSections ; ++idx )
270
0
            {
271
0
                if ( pProfile->m_Sections[idx].m_Entries != nullptr )
272
0
                {
273
0
                    free(pProfile->m_Sections[idx].m_Entries);
274
0
                    pProfile->m_Sections[idx].m_Entries=nullptr;
275
0
                }
276
0
            }
277
0
            free(pProfile->m_Sections);
278
0
            pProfile->m_Sections=nullptr;
279
0
        }
280
0
    }
281
282
0
    pthread_mutex_unlock(&(pProfile->m_AccessLock));
283
284
0
    pthread_mutex_destroy(&(pProfile->m_AccessLock));
285
286
0
    free(pProfile);
287
288
0
    return true;
289
0
}
290
291
sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile)
292
0
{
293
0
    osl_TProfileImpl* pProfile = static_cast<osl_TProfileImpl*>(Profile);
294
0
    osl_TFile* pFile;
295
0
    bool bRet = false;
296
297
0
    if ( pProfile == nullptr )
298
0
    {
299
0
        return false;
300
0
    }
301
302
0
    pthread_mutex_lock(&(pProfile->m_AccessLock));
303
304
0
    if ( !pProfile->m_bIsValid )
305
0
    {
306
0
        SAL_WARN_IF(!pProfile->m_bIsValid, "sal.osl", "!pProfile->m_bIsValid");
307
0
        pthread_mutex_unlock(&(pProfile->m_AccessLock));
308
0
        return false;
309
0
    }
310
311
0
    pFile = pProfile->m_pFile;
312
0
    if ( pFile == nullptr || pFile->m_Handle < 0 )
313
0
    {
314
0
        pthread_mutex_unlock(&(pProfile->m_AccessLock));
315
316
0
        return false;
317
0
    }
318
319
0
    if ( pProfile->m_Flags & FLG_MODIFIED )
320
0
    {
321
0
        bRet = storeProfile(pProfile, false);
322
0
        SAL_WARN_IF(!bRet, "sal.osl", "storeProfile(pProfile, false) ==> false");
323
0
    }
324
325
0
    pthread_mutex_unlock(&(pProfile->m_AccessLock));
326
0
    return bRet;
327
0
}
328
329
static bool writeProfileImpl(osl_TFile* pFile)
330
0
{
331
0
    if ( pFile == nullptr || pFile->m_Handle < 0 || pFile->m_pWriteBuf == nullptr )
332
0
    {
333
0
        return false;
334
0
    }
335
336
0
    SAL_WARN_IF(
337
0
        (strlen(pFile->m_pWriteBuf)
338
0
         != pFile->m_nWriteBufLen - pFile->m_nWriteBufFree),
339
0
        "sal.osl",
340
0
        strlen(pFile->m_pWriteBuf) << " != "
341
0
            << (pFile->m_nWriteBufLen - pFile->m_nWriteBufFree));
342
343
0
    if ( !safeWrite(pFile->m_Handle, pFile->m_pWriteBuf, pFile->m_nWriteBufLen - pFile->m_nWriteBufFree) )
344
0
    {
345
0
        SAL_INFO("sal.osl", "write failed: " << UnixErrnoString(errno));
346
0
        return false;
347
0
    }
348
349
0
    free(pFile->m_pWriteBuf);
350
0
    pFile->m_pWriteBuf=nullptr;
351
0
    pFile->m_nWriteBufLen=0;
352
0
    pFile->m_nWriteBufFree=0;
353
354
0
    return true;
355
0
}
356
357
sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile,
358
                                        const char* pszSection,
359
                                        const char* pszEntry,
360
                                        char* pszString,
361
                                        sal_uInt32 MaxLen,
362
                                        const char* pszDefault)
363
0
{
364
0
    sal_uInt32    NoEntry;
365
0
    char* pStr=nullptr;
366
0
    osl_TProfileImpl*    pProfile=nullptr;
367
0
    osl_TProfileImpl*    pTmpProfile=nullptr;
368
0
    bool bRet = false;
369
370
0
    pTmpProfile = static_cast<osl_TProfileImpl*>(Profile);
371
372
0
    if ( pTmpProfile == nullptr )
373
0
    {
374
0
        return false;
375
0
    }
376
377
0
    pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
378
379
0
    if ( !pTmpProfile->m_bIsValid )
380
0
    {
381
0
        pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
382
383
0
        return false;
384
0
    }
385
386
0
    pProfile = acquireProfile(Profile, false);
387
388
0
    if ( pProfile == nullptr )
389
0
    {
390
0
        pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
391
392
0
        return false;
393
0
    }
394
395
0
    if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
396
0
    {
397
0
        osl_TProfileSection* pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry);
398
0
        if ((pSec != nullptr) &&
399
0
            (NoEntry < pSec->m_NoEntries) &&
400
0
            ((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line],
401
0
                            '=')) != nullptr))
402
0
        {
403
0
            pStr++;
404
0
        }
405
0
        else
406
0
        {
407
0
            pStr=const_cast<char*>(pszDefault);
408
0
        }
409
410
0
        if ( pStr != nullptr )
411
0
        {
412
0
            pStr = stripBlanks(pStr, nullptr);
413
0
            MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr);
414
0
            pStr = stripBlanks(pStr, &MaxLen);
415
0
            strncpy(pszString, pStr, MaxLen);
416
0
            pszString[MaxLen] = '\0';
417
0
        }
418
0
    }
419
0
    else
420
0
    { /* not implemented */ }
421
422
0
    bRet=releaseProfile(pProfile);
423
0
    SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
424
425
0
    if ( pStr == nullptr )
426
0
    {
427
0
        pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
428
429
0
        return false;
430
0
    }
431
432
0
    pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
433
434
0
    return true;
435
0
}
436
437
sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile,
438
                                      const char* pszSection,
439
                                      const char* pszEntry,
440
                                      sal_Bool Default)
441
0
{
442
0
    char Line[32];
443
0
    Line[0] = '\0';
444
445
0
    if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
446
0
    {
447
0
        if ((strcasecmp(Line, STR_INI_BOOLYES) == 0) ||
448
0
            (strcasecmp(Line, STR_INI_BOOLON)  == 0) ||
449
0
            (strcasecmp(Line, STR_INI_BOOLONE) == 0))
450
0
            Default = true;
451
0
        else
452
0
            if ((strcasecmp(Line, STR_INI_BOOLNO)   == 0) ||
453
0
                (strcasecmp(Line, STR_INI_BOOLOFF)  == 0) ||
454
0
                (strcasecmp(Line, STR_INI_BOOLZERO) == 0))
455
0
                Default = false;
456
0
    }
457
458
0
    return Default;
459
0
}
460
461
sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile,
462
                                         const char* pszSection,
463
                                         const char* pszEntry,
464
                                         sal_uInt32 FirstId,
465
                                         const char* Strings[],
466
                                         sal_uInt32 Default)
467
0
{
468
0
    sal_uInt32  i;
469
0
    char    Line[256];
470
0
    Line[0] = '\0';
471
472
0
    if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
473
0
    {
474
0
        i = 0;
475
0
        while (Strings[i] != nullptr)
476
0
        {
477
0
            if (strcasecmp(Line, Strings[i]) == 0)
478
0
            {
479
0
                Default = i + FirstId;
480
0
                break;
481
0
            }
482
0
            i++;
483
0
        }
484
0
    }
485
486
0
    return Default;
487
0
}
488
489
sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile,
490
                                         const char* pszSection,
491
                                         const char* pszEntry,
492
                                         const char* pszString)
493
0
{
494
0
    bool bRet = false;
495
0
    sal_uInt32    NoEntry;
496
0
    char* pStr;
497
0
    char*       Line = nullptr;
498
0
    osl_TProfileImpl*    pProfile = nullptr;
499
0
    osl_TProfileImpl*    pTmpProfile = static_cast<osl_TProfileImpl*>(Profile);
500
501
0
    if ( pTmpProfile == nullptr )
502
0
    {
503
0
        return false;
504
0
    }
505
506
0
    pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
507
508
0
    if ( !pTmpProfile->m_bIsValid )
509
0
    {
510
0
        SAL_WARN_IF(!pTmpProfile->m_bIsValid, "sal.osl", "!pTmpProfile->m_bIsValid");
511
0
        pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
512
513
0
        return false;
514
0
    }
515
516
0
    pProfile=acquireProfile(Profile, true);
517
518
0
    if (pProfile == nullptr)
519
0
    {
520
0
        pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
521
522
0
        return false;
523
0
    }
524
525
0
    Line = static_cast<char*>(malloc(strlen(pszEntry)+strlen(pszString)+48));
526
527
0
    if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
528
0
    {
529
0
        osl_TProfileSection* pSec;
530
0
        if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == nullptr)
531
0
        {
532
0
            Line[0] = '\0';
533
0
            addLine(pProfile, Line);
534
535
0
            Line[0] = '[';
536
0
            strcpy(&Line[1], pszSection);
537
0
            Line[1 + strlen(pszSection)] = ']';
538
0
            Line[2 + strlen(pszSection)] = '\0';
539
540
0
            pStr = addLine(pProfile, Line);
541
0
            if ((pStr == nullptr) ||
542
0
                (! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection))))
543
0
            {
544
0
                bRet=releaseProfile(pProfile);
545
0
                SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
546
547
0
                pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
548
549
0
                free(Line);
550
0
                return false;
551
0
            }
552
553
0
            pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1];
554
0
            NoEntry = pSec->m_NoEntries;
555
0
        }
556
557
0
        Line[0] = '\0';
558
0
        strcpy(&Line[0], pszEntry);
559
0
        Line[0 + strlen(pszEntry)] = '=';
560
0
        strcpy(&Line[1 + strlen(pszEntry)], pszString);
561
562
0
        if (NoEntry >= pSec->m_NoEntries)
563
0
        {
564
0
            sal_uInt32  i;
565
0
            if (pSec->m_NoEntries > 0)
566
0
                i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1;
567
0
            else
568
0
                i = pSec->m_Line + 1;
569
570
0
            pStr = insertLine(pProfile, Line, i);
571
0
            if ((pStr == nullptr) ||
572
0
                (! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry))))
573
0
            {
574
0
                bRet=releaseProfile(pProfile);
575
0
                SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
576
577
0
                pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
578
0
                free(Line);
579
580
0
                return false;
581
0
            }
582
583
0
            pProfile->m_Flags |= FLG_MODIFIED;
584
0
        }
585
0
        else
586
0
        {
587
0
            sal_uInt32  i = pSec->m_Entries[NoEntry].m_Line;
588
0
            free(pProfile->m_Lines[i]);
589
0
            pProfile->m_Lines[i] = strdup(Line);
590
0
            setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry));
591
592
0
            pProfile->m_Flags |= FLG_MODIFIED;
593
0
        }
594
0
    }
595
0
    else {
596
        /* not implemented */
597
0
    }
598
599
0
    bRet = releaseProfile(pProfile);
600
0
    SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
601
602
0
    pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
603
0
    if ( Line!= nullptr )
604
0
    {
605
0
        free(Line);
606
0
    }
607
608
0
    return bRet;
609
0
}
610
611
sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile,
612
                                       const char* pszSection,
613
                                       const char* pszEntry,
614
                                       sal_Bool Value)
615
0
{
616
0
    bool bRet = false;
617
618
0
    if (Value)
619
0
        bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE);
620
0
    else
621
0
        bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO);
622
623
0
    return bRet;
624
0
}
625
626
sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile,
627
                                        const char* pszSection,
628
                                        const char* pszEntry,
629
                                        sal_uInt32 FirstId,
630
                                        const char* Strings[],
631
                                        sal_uInt32 Value)
632
0
{
633
0
    int i, n = 0;
634
0
    bool bRet = false;
635
636
0
    while (Strings[n] != nullptr)
637
0
        ++n;
638
639
0
    if ((i = Value - FirstId) >= n)
640
0
        bRet = false;
641
0
    else
642
0
        bRet = osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]);
643
644
0
    return bRet;
645
0
}
646
647
sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile,
648
                                         const char *pszSection,
649
                                         const char *pszEntry)
650
0
{
651
0
    sal_uInt32    NoEntry;
652
0
    osl_TProfileImpl*    pProfile = nullptr;
653
0
    osl_TProfileImpl*    pTmpProfile = nullptr;
654
0
    bool bRet = false;
655
656
0
    pTmpProfile = static_cast<osl_TProfileImpl*>(Profile);
657
658
0
    if ( pTmpProfile == nullptr )
659
0
    {
660
0
        return false;
661
0
    }
662
663
0
    pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
664
665
0
    if ( !pTmpProfile->m_bIsValid )
666
0
    {
667
0
        SAL_WARN_IF(!pTmpProfile->m_bIsValid, "sal.osl", "!pTmpProfile->m_bIsValid");
668
0
        pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
669
0
        return false;
670
0
    }
671
672
0
    pProfile = acquireProfile(Profile, true);
673
674
0
    if (pProfile == nullptr)
675
0
    {
676
0
        pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
677
678
0
        return false;
679
0
    }
680
681
0
    if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
682
0
    {
683
0
        osl_TProfileSection* pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry);
684
0
        if ((pSec != nullptr) &&
685
0
            (NoEntry < pSec->m_NoEntries))
686
0
        {
687
0
            removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line);
688
0
            removeEntry(pSec, NoEntry);
689
0
            if (pSec->m_NoEntries == 0)
690
0
            {
691
0
                removeLine(pProfile, pSec->m_Line);
692
693
                /* remove any empty separation line */
694
0
                if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0'))
695
0
                    removeLine(pProfile, pSec->m_Line - 1);
696
697
0
                removeSection(pProfile, pSec);
698
0
            }
699
700
0
            pProfile->m_Flags |= FLG_MODIFIED;
701
0
        }
702
0
    }
703
0
    else
704
0
    { /* not implemented */ }
705
706
0
    bRet = releaseProfile(pProfile);
707
0
    SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
708
709
0
    pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
710
711
0
    return bRet;
712
0
}
713
714
sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile,
715
                                                 const char *pszSection,
716
                                                 char* pszBuffer,
717
                                                 sal_uInt32 MaxLen)
718
0
{
719
0
    sal_uInt32    i, n = 0;
720
0
    sal_uInt32    NoEntry;
721
0
    osl_TProfileImpl*    pProfile = nullptr;
722
0
    osl_TProfileImpl*    pTmpProfile = nullptr;
723
0
    bool bRet = false;
724
725
0
    pTmpProfile = static_cast<osl_TProfileImpl*>(Profile);
726
727
0
    if ( pTmpProfile == nullptr )
728
0
    {
729
0
        return 0;
730
731
0
    }
732
733
0
    pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
734
735
0
    if ( !pTmpProfile->m_bIsValid )
736
0
    {
737
0
        SAL_WARN_IF(!pTmpProfile->m_bIsValid, "sal.osl", "!pTmpProfile->m_bIsValid"); 
738
739
0
        pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
740
741
0
        return 0;
742
0
    }
743
744
0
    pProfile = acquireProfile(Profile, false);
745
746
0
    if (pProfile == nullptr)
747
0
    {
748
0
        pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
749
750
0
        return 0;
751
0
    }
752
753
0
    if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
754
0
    {
755
0
        osl_TProfileSection* pSec;
756
0
        if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != nullptr)
757
0
        {
758
0
            if (MaxLen != 0)
759
0
            {
760
0
                for (i = 0; i < pSec->m_NoEntries; i++)
761
0
                {
762
0
                    if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen)
763
0
                    {
764
0
                        strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
765
0
                                [pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len);
766
0
                        n += pSec->m_Entries[i].m_Len;
767
0
                        pszBuffer[n++] = '\0';
768
0
                    }
769
0
                    else
770
0
                        break;
771
772
0
                }
773
774
0
                pszBuffer[n++] = '\0';
775
0
            }
776
0
            else
777
0
            {
778
0
                for (i = 0; i < pSec->m_NoEntries; i++)
779
0
                    n += pSec->m_Entries[i].m_Len + 1;
780
781
0
                n += 1;
782
0
            }
783
0
        }
784
0
        else
785
0
            n = 0;
786
0
    }
787
0
    else {
788
        /* not implemented */
789
0
    }
790
791
0
    bRet=releaseProfile(pProfile);
792
0
    SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
793
794
0
    pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
795
796
0
    return n;
797
0
}
798
799
sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile,
800
                                           char* pszBuffer,
801
                                           sal_uInt32 MaxLen)
802
0
{
803
0
    sal_uInt32    i, n = 0;
804
0
    osl_TProfileImpl*    pProfile = nullptr;
805
0
    osl_TProfileImpl*    pTmpProfile = nullptr;
806
0
    bool bRet = false;
807
808
0
    pTmpProfile = static_cast<osl_TProfileImpl*>(Profile);
809
810
0
    if ( pTmpProfile == nullptr )
811
0
    {
812
0
        return 0;
813
0
    }
814
815
0
    pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
816
817
0
    if ( !pTmpProfile->m_bIsValid )
818
0
    {
819
0
        SAL_WARN_IF(!pTmpProfile->m_bIsValid, "sal.osl", "!pTmpProfile->m_bIsValid"); 
820
0
        pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
821
822
0
        return 0;
823
0
    }
824
825
0
    pProfile = acquireProfile(Profile, false);
826
827
0
    if (pProfile == nullptr)
828
0
    {
829
0
        pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
830
831
0
        return 0;
832
0
    }
833
834
0
    if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
835
0
    {
836
0
        if (MaxLen != 0)
837
0
        {
838
0
            for (i = 0; i < pProfile->m_NoSections; i++)
839
0
            {
840
0
                osl_TProfileSection* pSec = &pProfile->m_Sections[i];
841
842
0
                if ((n + pSec->m_Len + 1) < MaxLen)
843
0
                {
844
0
                    strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset],
845
0
                            pSec->m_Len);
846
0
                    n += pSec->m_Len;
847
0
                    pszBuffer[n++] = '\0';
848
0
                }
849
0
                else
850
0
                    break;
851
0
            }
852
853
0
            pszBuffer[n++] = '\0';
854
0
        }
855
0
        else
856
0
        {
857
0
            for (i = 0; i < pProfile->m_NoSections; i++)
858
0
                n += pProfile->m_Sections[i].m_Len + 1;
859
860
0
            n += 1;
861
0
        }
862
0
    }
863
0
    else
864
0
    { /* not implemented */ }
865
866
0
    bRet=releaseProfile(pProfile);
867
0
    SAL_WARN_IF(!bRet, "sal.osl", "releaseProfile(pProfile) ==> false");
868
869
0
    pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
870
871
0
    return n;
872
0
}
873
874
static osl_TStamp OslProfile_getFileStamp(osl_TFile* pFile)
875
0
{
876
0
    struct stat status;
877
878
0
    if ( (pFile->m_Handle < 0) || (fstat(pFile->m_Handle, &status) < 0) )
879
0
    {
880
0
        return 0;
881
0
    }
882
883
0
    return status.st_mtime;
884
0
}
885
886
static bool OslProfile_lockFile(const osl_TFile* pFile, osl_TLockMode eMode)
887
0
{
888
0
    struct flock lock;
889
0
    static bool const bLockingDisabled = getenv( "STAR_PROFILE_LOCKING_DISABLED" ) != nullptr;
890
891
0
    if (pFile->m_Handle < 0)
892
0
    {
893
0
        return false;
894
0
    }
895
896
0
    if ( bLockingDisabled )
897
0
    {
898
0
        return true;
899
0
    }
900
901
0
    lock.l_start  = 0;
902
0
    lock.l_whence = SEEK_SET;
903
0
    lock.l_len    = 0;
904
905
0
    switch (eMode)
906
0
    {
907
0
        case un_lock:
908
0
            lock.l_type = F_UNLCK;
909
0
            break;
910
911
0
        case read_lock:
912
0
            lock.l_type = F_RDLCK;
913
0
            break;
914
915
0
        case write_lock:
916
0
            lock.l_type = F_WRLCK;
917
0
            break;
918
0
    }
919
920
0
#ifndef MACOSX
921
0
    if ( fcntl(pFile->m_Handle, F_SETLKW, &lock) == -1 )
922
#else
923
    /* Mac OSX will return ENOTSUP for webdav drives so we should ignore it */
924
    if ( fcntl(pFile->m_Handle, F_SETLKW, &lock) == -1 && errno != ENOTSUP )
925
#endif
926
0
    {
927
0
        SAL_INFO("sal.osl", "fcntl failed: " << UnixErrnoString(errno));
928
0
        return false;
929
0
    }
930
931
0
    return true;
932
0
}
933
934
static osl_TFile* openFileImpl(const char* pszFilename, oslProfileOption ProfileFlags )
935
0
{
936
0
    int        Flags;
937
0
    bool       bWriteable = false;
938
939
0
    if ( isForbidden( pszFilename, osl_File_OpenFlag_Write ) )
940
0
        return nullptr;
941
942
0
    osl_TFile* pFile = static_cast<osl_TFile*>(calloc(1, sizeof(osl_TFile)));
943
944
0
    if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
945
0
    {
946
0
        bWriteable = true;
947
0
    }
948
949
0
    if (! bWriteable)
950
0
    {
951
0
        pFile->m_Handle = open(pszFilename, O_RDONLY);
952
953
0
        if (pFile->m_Handle == -1)
954
0
        {
955
0
            int e = errno;
956
0
            SAL_INFO("sal.file", "open(" << pszFilename << ",O_RDONLY): " << UnixErrnoString(e));
957
0
        }
958
0
        else
959
0
            SAL_INFO("sal.file", "open(" << pszFilename << ",O_RDONLY) => " << pFile->m_Handle);
960
961
        /* mfe: argghh!!! do not check if the file could be opened */
962
        /*      default mode expects it that way!!!                 */
963
0
    }
964
0
    else
965
0
    {
966
0
        if (((pFile->m_Handle = open(pszFilename, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PMODE)) < 0) &&
967
0
            ((pFile->m_Handle = open(pszFilename, O_RDWR)) < 0))
968
0
        {
969
0
            int e = errno;
970
0
            SAL_INFO("sal.file", "open(" << pszFilename << ",...): " << UnixErrnoString(e));
971
0
            free(pFile);
972
0
            return nullptr;
973
0
        }
974
0
        else
975
0
            SAL_INFO("sal.file", "open(" << pszFilename << ",...) => " << pFile->m_Handle);
976
0
    }
977
978
    /* set close-on-exec flag */
979
0
    if ((Flags = fcntl(pFile->m_Handle, F_GETFD, 0)) != -1)
980
0
    {
981
0
        Flags |= FD_CLOEXEC;
982
0
        int e = fcntl(pFile->m_Handle, F_SETFD, Flags);
983
0
        SAL_INFO_IF(
984
0
            e != 0, "sal.osl",
985
0
            "fcntl to set FD_CLOEXEC failed for " << pszFilename);
986
0
    }
987
988
0
    pFile->m_pWriteBuf=nullptr;
989
0
    pFile->m_nWriteBufFree=0;
990
0
    pFile->m_nWriteBufLen=0;
991
992
0
    if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
993
0
    {
994
0
        OslProfile_lockFile(pFile, bWriteable ? write_lock : read_lock);
995
0
    }
996
997
0
    return pFile;
998
0
}
999
1000
static osl_TStamp closeFileImpl(osl_TFile* pFile, oslProfileOption Flags)
1001
0
{
1002
0
    osl_TStamp stamp = 0;
1003
1004
0
    if ( pFile == nullptr )
1005
0
    {
1006
0
        return stamp;
1007
0
    }
1008
1009
0
    if ( pFile->m_Handle >= 0 )
1010
0
    {
1011
0
        stamp = OslProfile_getFileStamp(pFile);
1012
1013
0
        if ( Flags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
1014
0
        {
1015
0
            OslProfile_lockFile(pFile, un_lock);
1016
0
        }
1017
1018
0
        close(pFile->m_Handle);
1019
0
        SAL_INFO("sal.file", "close(" << pFile->m_Handle << ")");
1020
0
        pFile->m_Handle = -1;
1021
0
    }
1022
1023
0
    if ( pFile->m_pWriteBuf )
1024
0
    {
1025
0
        free(pFile->m_pWriteBuf);
1026
0
    }
1027
1028
0
    free(pFile);
1029
1030
0
    return stamp;
1031
0
}
1032
1033
static bool OslProfile_rewindFile(osl_TFile* pFile, bool bTruncate)
1034
0
{
1035
0
    bool bRet = true;
1036
1037
0
    if (pFile->m_Handle >= 0)
1038
0
    {
1039
0
        pFile->m_pReadPtr  = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1040
1041
0
        bRet = (lseek(pFile->m_Handle, SEEK_SET, 0) == 0);
1042
1043
0
        if (bTruncate)
1044
0
        {
1045
0
            bRet &= (ftruncate(pFile->m_Handle, 0) == 0);
1046
0
        }
1047
1048
0
    }
1049
1050
0
    return bRet;
1051
0
}
1052
1053
static char* OslProfile_getLine(osl_TFile* pFile)
1054
0
{
1055
0
    ssize_t Max, nLineBytes = 0;
1056
0
    char* pChr;
1057
0
    char* pLine = nullptr;
1058
0
    char* pNewLine;
1059
1060
0
    if ( pFile == nullptr )
1061
0
    {
1062
0
        return nullptr;
1063
0
    }
1064
1065
0
    if (pFile->m_Handle < 0)
1066
0
        return nullptr;
1067
1068
0
    do
1069
0
    {
1070
0
        ssize_t Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf);
1071
1072
0
        if (Bytes <= 1)
1073
0
        {
1074
            /* refill buffer */
1075
0
            memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes);
1076
0
            pFile->m_pReadPtr = pFile->m_ReadBuf;
1077
1078
0
            ssize_t Free = sizeof(pFile->m_ReadBuf) - Bytes;
1079
1080
0
            Max = read(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free);
1081
0
            if (Max < 0)
1082
0
            {
1083
0
                SAL_INFO("sal.osl", "read failed: " << UnixErrnoString(errno));
1084
1085
0
                if( pLine )
1086
0
                    free( pLine );
1087
0
                pLine = nullptr;
1088
0
                break;
1089
0
            }
1090
1091
0
            if (Max < Free)
1092
0
            {
1093
0
                 if ((Max == 0) && ! pLine)
1094
0
                     break;
1095
1096
0
                 pFile->m_ReadBuf[Bytes + Max] = '\0';
1097
0
            }
1098
0
        }
1099
1100
0
        for (pChr = pFile->m_pReadPtr;
1101
0
             (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') &&
1102
0
             (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1));
1103
0
             pChr++);
1104
1105
0
        Max = pChr - pFile->m_pReadPtr;
1106
0
        pNewLine = static_cast<char*>(malloc( nLineBytes + Max + 1 ));
1107
0
        if( pLine )
1108
0
        {
1109
0
            memcpy( pNewLine, pLine, nLineBytes );
1110
0
            free( pLine );
1111
0
        }
1112
0
        memcpy(pNewLine+nLineBytes, pFile->m_pReadPtr, Max);
1113
0
        nLineBytes += Max;
1114
0
        pNewLine[ nLineBytes ] = 0;
1115
0
        pLine = pNewLine;
1116
1117
0
        if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1))
1118
0
        {
1119
0
            if (*pChr != '\0')
1120
0
            {
1121
0
                if ((pChr[0] == '\r') && (pChr[1] == '\n'))
1122
0
                    pChr += 2;
1123
0
                else
1124
0
                    pChr += 1;
1125
0
            }
1126
1127
0
            if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) &&
1128
0
                (*pChr == '\0'))
1129
0
                pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
1130
1131
            /* setting Max to -1 indicates terminating read loop */
1132
0
            Max = -1;
1133
0
        }
1134
1135
0
        pFile->m_pReadPtr = pChr;
1136
0
    }
1137
0
    while (Max > 0) ;
1138
1139
0
    return pLine;
1140
0
}
1141
1142
static bool OslProfile_putLine(osl_TFile* pFile, const char *pszLine)
1143
0
{
1144
0
    unsigned int Len = strlen(pszLine);
1145
1146
0
    if ( pFile == nullptr || pFile->m_Handle < 0 )
1147
0
    {
1148
0
        return false;
1149
0
    }
1150
1151
0
    if ( pFile->m_pWriteBuf == nullptr )
1152
0
    {
1153
0
        pFile->m_pWriteBuf = static_cast<char*>(malloc(Len+3));
1154
0
        pFile->m_nWriteBufLen = Len+3;
1155
0
        pFile->m_nWriteBufFree = Len+3;
1156
0
    }
1157
0
    else
1158
0
    {
1159
0
        if ( pFile->m_nWriteBufFree <= Len + 3 )
1160
0
        {
1161
0
            char* pTmp;
1162
1163
0
            pTmp=static_cast<char*>(realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) ));
1164
0
            if ( pTmp == nullptr )
1165
0
            {
1166
0
                return false;
1167
0
            }
1168
0
            pFile->m_pWriteBuf = pTmp;
1169
0
            pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len );
1170
0
            pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2;
1171
0
            memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree);
1172
0
        }
1173
0
    }
1174
1175
0
    memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1);
1176
0
    pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\n';
1177
0
    pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\0';
1178
1179
0
    pFile->m_nWriteBufFree-=Len+1;
1180
1181
0
    return true;
1182
0
}
1183
1184
static char* stripBlanks(char* String, sal_uInt32* pLen)
1185
0
{
1186
0
    if ( ( pLen != nullptr ) && ( *pLen != 0 ) )
1187
0
    {
1188
0
        while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t'))
1189
0
            (*pLen)--;
1190
1191
0
        while ( (*String == ' ') || (*String == '\t') )
1192
0
        {
1193
0
            String++;
1194
0
            (*pLen)--;
1195
0
        }
1196
0
    }
1197
0
    else
1198
0
        while ( (*String == ' ') || (*String == '\t') )
1199
0
            String++;
1200
1201
0
    return String;
1202
0
}
1203
1204
static char* addLine(osl_TProfileImpl* pProfile, const char* Line)
1205
0
{
1206
0
    if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1207
0
    {
1208
0
        if (pProfile->m_Lines == nullptr)
1209
0
        {
1210
0
            pProfile->m_MaxLines = LINES_INI;
1211
0
            pProfile->m_Lines = static_cast<char **>(calloc(pProfile->m_MaxLines, sizeof(char *)));
1212
0
        }
1213
0
        else
1214
0
        {
1215
0
            unsigned int idx=0;
1216
0
            unsigned int oldmax=pProfile->m_MaxLines;
1217
1218
0
            pProfile->m_MaxLines += LINES_ADD;
1219
0
            pProfile->m_Lines = static_cast<char **>(realloc(pProfile->m_Lines,
1220
0
                                                 pProfile->m_MaxLines * sizeof(char *)));
1221
0
            for ( idx = oldmax ; idx < pProfile->m_MaxLines ; ++idx )
1222
0
            {
1223
0
                pProfile->m_Lines[idx]=nullptr;
1224
0
            }
1225
0
        }
1226
0
    }
1227
0
    if (pProfile->m_Lines == nullptr)
1228
0
    {
1229
0
        pProfile->m_NoLines  = 0;
1230
0
        pProfile->m_MaxLines = 0;
1231
0
        return nullptr;
1232
0
    }
1233
1234
0
    if ( pProfile->m_Lines[pProfile->m_NoLines] != nullptr )
1235
0
    {
1236
0
        free(pProfile->m_Lines[pProfile->m_NoLines]);
1237
0
    }
1238
0
    pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line);
1239
1240
0
    return pProfile->m_Lines[pProfile->m_NoLines - 1];
1241
0
}
1242
1243
static char* insertLine(osl_TProfileImpl* pProfile, const char* Line, sal_uInt32 LineNo)
1244
0
{
1245
0
    if (pProfile->m_NoLines >= pProfile->m_MaxLines)
1246
0
    {
1247
0
        if (pProfile->m_Lines == nullptr)
1248
0
        {
1249
0
            pProfile->m_MaxLines = LINES_INI;
1250
0
            pProfile->m_Lines = static_cast<char **>(calloc(pProfile->m_MaxLines, sizeof(char *)));
1251
0
        }
1252
0
        else
1253
0
        {
1254
0
            pProfile->m_MaxLines += LINES_ADD;
1255
0
            pProfile->m_Lines = static_cast<char **>(realloc(pProfile->m_Lines,
1256
0
                                                 pProfile->m_MaxLines * sizeof(char *)));
1257
1258
0
            memset(&pProfile->m_Lines[pProfile->m_NoLines],
1259
0
                0,
1260
0
                (pProfile->m_MaxLines - pProfile->m_NoLines - 1) * sizeof(char*));
1261
0
        }
1262
1263
0
        if (pProfile->m_Lines == nullptr)
1264
0
        {
1265
0
            pProfile->m_NoLines  = 0;
1266
0
            pProfile->m_MaxLines = 0;
1267
0
            return nullptr;
1268
0
        }
1269
0
    }
1270
1271
0
    LineNo = std::min(LineNo, pProfile->m_NoLines);
1272
1273
0
    if (LineNo < pProfile->m_NoLines)
1274
0
    {
1275
0
        sal_uInt32 i, n;
1276
1277
0
        memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo],
1278
0
                (pProfile->m_NoLines - LineNo) * sizeof(char *));
1279
1280
        /* adjust line references */
1281
0
        for (i = 0; i < pProfile->m_NoSections; i++)
1282
0
        {
1283
0
            osl_TProfileSection* pSec = &pProfile->m_Sections[i];
1284
1285
0
            if (pSec->m_Line >= LineNo)
1286
0
                pSec->m_Line++;
1287
1288
0
            for (n = 0; n < pSec->m_NoEntries; n++)
1289
0
                if (pSec->m_Entries[n].m_Line >= LineNo)
1290
0
                    pSec->m_Entries[n].m_Line++;
1291
0
        }
1292
0
    }
1293
1294
0
    pProfile->m_NoLines++;
1295
1296
0
    pProfile->m_Lines[LineNo] = strdup(Line);
1297
1298
0
    return pProfile->m_Lines[LineNo];
1299
0
}
1300
1301
static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo)
1302
0
{
1303
0
    if (LineNo >= pProfile->m_NoLines)
1304
0
        return;
1305
1306
0
    free(pProfile->m_Lines[LineNo]);
1307
0
    pProfile->m_Lines[LineNo]=nullptr;
1308
0
    if (pProfile->m_NoLines - LineNo > 1)
1309
0
    {
1310
0
        sal_uInt32 i, n;
1311
1312
0
        memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1],
1313
0
                (pProfile->m_NoLines - LineNo - 1) * sizeof(char *));
1314
1315
0
        memset(&pProfile->m_Lines[pProfile->m_NoLines - 1],
1316
0
            0,
1317
0
            (pProfile->m_MaxLines - pProfile->m_NoLines) * sizeof(char*));
1318
1319
        /* adjust line references */
1320
0
        for (i = 0; i < pProfile->m_NoSections; i++)
1321
0
        {
1322
0
            osl_TProfileSection* pSec = &pProfile->m_Sections[i];
1323
1324
0
            if (pSec->m_Line > LineNo)
1325
0
                pSec->m_Line--;
1326
1327
0
            for (n = 0; n < pSec->m_NoEntries; n++)
1328
0
                if (pSec->m_Entries[n].m_Line > LineNo)
1329
0
                    pSec->m_Entries[n].m_Line--;
1330
0
        }
1331
0
    }
1332
0
    else
1333
0
    {
1334
0
        pProfile->m_Lines[LineNo] = nullptr;
1335
0
    }
1336
1337
0
    pProfile->m_NoLines--;
1338
0
}
1339
1340
static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
1341
                     sal_uInt32 NoEntry, sal_uInt32 Line,
1342
                     char* Entry, sal_uInt32 Len)
1343
0
{
1344
0
    Entry = stripBlanks(Entry, &Len);
1345
0
    pSection->m_Entries[NoEntry].m_Line   = Line;
1346
0
    pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line];
1347
0
    pSection->m_Entries[NoEntry].m_Len    = Len;
1348
0
}
1349
1350
static bool addEntry(osl_TProfileImpl* pProfile,
1351
                     osl_TProfileSection *pSection,
1352
                     int Line, char* Entry,
1353
                     sal_uInt32 Len)
1354
0
{
1355
0
    if (pSection != nullptr)
1356
0
    {
1357
0
        if (pSection->m_NoEntries >= pSection->m_MaxEntries)
1358
0
        {
1359
0
            if (pSection->m_Entries == nullptr)
1360
0
            {
1361
0
                pSection->m_MaxEntries = ENTRIES_INI;
1362
0
                pSection->m_Entries = static_cast<osl_TProfileEntry *>(malloc(
1363
0
                                pSection->m_MaxEntries * sizeof(osl_TProfileEntry)));
1364
0
            }
1365
0
            else
1366
0
            {
1367
0
                pSection->m_MaxEntries += ENTRIES_ADD;
1368
0
                pSection->m_Entries = static_cast<osl_TProfileEntry *>(realloc(pSection->m_Entries,
1369
0
                                pSection->m_MaxEntries * sizeof(osl_TProfileEntry)));
1370
0
            }
1371
1372
0
            if (pSection->m_Entries == nullptr)
1373
0
            {
1374
0
                pSection->m_NoEntries  = 0;
1375
0
                pSection->m_MaxEntries = 0;
1376
0
                return false;
1377
0
            }
1378
0
        }
1379
1380
0
        pSection->m_NoEntries++;
1381
1382
0
        Entry = stripBlanks(Entry, &Len);
1383
0
        setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line,
1384
0
                 Entry, Len);
1385
1386
0
        return true;
1387
0
    }
1388
1389
0
    return false;
1390
0
}
1391
1392
static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry)
1393
0
{
1394
0
    if (NoEntry >= pSection->m_NoEntries)
1395
0
        return;
1396
1397
0
    if (pSection->m_NoEntries - NoEntry > 1)
1398
0
    {
1399
0
        memmove(&pSection->m_Entries[NoEntry],
1400
0
                &pSection->m_Entries[NoEntry + 1],
1401
0
                (pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry));
1402
0
        pSection->m_Entries[pSection->m_NoEntries - 1].m_Line=0;
1403
0
        pSection->m_Entries[pSection->m_NoEntries - 1].m_Offset=0;
1404
0
        pSection->m_Entries[pSection->m_NoEntries - 1].m_Len=0;
1405
0
    }
1406
1407
0
    pSection->m_NoEntries--;
1408
1409
0
}
1410
1411
static bool addSection(osl_TProfileImpl* pProfile, int Line, const char* Section, sal_uInt32 Len)
1412
0
{
1413
0
    if (pProfile->m_NoSections >= pProfile->m_MaxSections)
1414
0
    {
1415
0
        if (pProfile->m_Sections == nullptr)
1416
0
        {
1417
0
            pProfile->m_MaxSections = SECTIONS_INI;
1418
0
            pProfile->m_Sections = static_cast<osl_TProfileSection *>(calloc(pProfile->m_MaxSections, sizeof(osl_TProfileSection)));
1419
0
        }
1420
0
        else
1421
0
        {
1422
0
            unsigned int idx=0;
1423
0
            unsigned int oldmax=pProfile->m_MaxSections;
1424
1425
0
            pProfile->m_MaxSections += SECTIONS_ADD;
1426
0
            pProfile->m_Sections = static_cast<osl_TProfileSection *>(realloc(pProfile->m_Sections,
1427
0
                                          pProfile->m_MaxSections * sizeof(osl_TProfileSection)));
1428
0
            for ( idx = oldmax ; idx < pProfile->m_MaxSections ; ++idx )
1429
0
            {
1430
0
                pProfile->m_Sections[idx].m_Entries=nullptr;
1431
0
            }
1432
0
        }
1433
1434
0
        if (pProfile->m_Sections == nullptr)
1435
0
        {
1436
0
            pProfile->m_NoSections = 0;
1437
0
            pProfile->m_MaxSections = 0;
1438
0
            return false;
1439
0
        }
1440
0
    }
1441
1442
0
    pProfile->m_NoSections++;
1443
1444
0
    if ( pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries != nullptr )
1445
0
    {
1446
0
         free(pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries);
1447
0
    }
1448
0
    pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries    = nullptr;
1449
0
    pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries  = 0;
1450
0
    pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0;
1451
1452
0
    pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line;
1453
0
    pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line];
1454
0
    pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len;
1455
1456
0
    return true;
1457
0
}
1458
1459
static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection)
1460
0
{
1461
0
    sal_uInt32 Section;
1462
1463
0
    if ((Section = pSection - pProfile->m_Sections) >= pProfile->m_NoSections)
1464
0
        return;
1465
1466
0
    free (pSection->m_Entries);
1467
0
    pSection->m_Entries=nullptr;
1468
0
    if (pProfile->m_NoSections - Section > 1)
1469
0
    {
1470
0
        memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1],
1471
0
                (pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection));
1472
1473
0
        memset(&pProfile->m_Sections[pProfile->m_NoSections - 1],
1474
0
               0,
1475
0
               (pProfile->m_MaxSections - pProfile->m_NoSections) * sizeof(osl_TProfileSection));
1476
0
        pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = nullptr;
1477
0
    }
1478
0
    else
1479
0
    {
1480
0
        pSection->m_Entries = nullptr;
1481
0
    }
1482
1483
0
    pProfile->m_NoSections--;
1484
0
}
1485
1486
static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile,
1487
                                      const char* Section,
1488
                                      const char* Entry,
1489
                                      sal_uInt32 *pNoEntry)
1490
0
{
1491
0
    static  sal_uInt32    Sect = 0;
1492
0
    sal_uInt32    i, n;
1493
0
    sal_uInt32  Len;
1494
0
    osl_TProfileSection* pSec=nullptr;
1495
1496
0
    Len = strlen(Section);
1497
1498
0
    n = Sect;
1499
1500
0
    for (i = 0; i < pProfile->m_NoSections; i++)
1501
0
    {
1502
0
        n %= pProfile->m_NoSections;
1503
0
        pSec = &pProfile->m_Sections[n];
1504
0
        if ((Len == pSec->m_Len) &&
1505
0
            (strncasecmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len)
1506
0
             == 0))
1507
0
            break;
1508
0
        n++;
1509
0
    }
1510
1511
0
    Sect = n;
1512
1513
0
    if (i < pProfile->m_NoSections)
1514
0
    {
1515
0
        Len = strlen(Entry);
1516
1517
0
        *pNoEntry = pSec->m_NoEntries;
1518
1519
0
        for (i = 0; i < pSec->m_NoEntries; i++)
1520
0
        {
1521
0
            const char* pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
1522
0
                                     [pSec->m_Entries[i].m_Offset];
1523
0
            if ((Len == pSec->m_Entries[i].m_Len) &&
1524
0
                (strncasecmp(Entry, pStr, pSec->m_Entries[i].m_Len)
1525
0
                 == 0))
1526
0
            {
1527
0
                *pNoEntry = i;
1528
0
                break;
1529
0
            }
1530
0
        }
1531
0
    }
1532
0
    else
1533
0
        pSec = nullptr;
1534
1535
0
    return pSec;
1536
0
}
1537
1538
static bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile)
1539
0
{
1540
0
    sal_uInt32  i;
1541
0
    char*   pStr;
1542
0
    char*   pChar;
1543
1544
0
    char* pLine;
1545
1546
0
    if ( !pFile )
1547
0
    {
1548
0
        return false;
1549
0
    }
1550
1551
0
    if ( !pProfile )
1552
0
    {
1553
0
        return false;
1554
0
    }
1555
1556
0
    pProfile->m_NoLines    = 0;
1557
0
    pProfile->m_NoSections = 0;
1558
1559
0
    OSL_VERIFY(OslProfile_rewindFile(pFile, false));
1560
1561
0
    while ( ( pLine=OslProfile_getLine(pFile) ) != nullptr )
1562
0
    {
1563
0
        char* bWasAdded = addLine( pProfile, pLine );
1564
0
        free( pLine );
1565
0
        SAL_WARN_IF(!bWasAdded, "sal.osl", "addLine( pProfile, pLine ) ==> false");
1566
0
        if ( ! bWasAdded )
1567
0
            return false;
1568
0
    }
1569
1570
0
    for (i = 0; i < pProfile->m_NoLines; i++)
1571
0
    {
1572
0
        pStr = stripBlanks(pProfile->m_Lines[i], nullptr);
1573
1574
0
        if ((*pStr == '\0') || (*pStr == ';'))
1575
0
            continue;
1576
1577
0
        if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == nullptr) ||
1578
0
            ((pChar - pStr) <= 2))
1579
0
        {
1580
            /* insert entry */
1581
1582
0
            if (pProfile->m_NoSections < 1)
1583
0
                continue;
1584
1585
0
            if ((pChar = strchr(pStr, '=')) == nullptr)
1586
0
                pChar = pStr + strlen(pStr);
1587
1588
0
            if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1],
1589
0
                           i, pStr, pChar - pStr))
1590
0
            {
1591
0
                SAL_WARN("sal.osl", "Adding entry => false");
1592
0
                continue;
1593
0
            }
1594
1595
0
        }
1596
0
        else
1597
0
        {
1598
            /* new section */
1599
1600
0
            if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1))
1601
0
            {
1602
0
                SAL_WARN("sal.osl", "Adding section => false");
1603
0
                continue;
1604
0
            }
1605
1606
0
        }
1607
0
    }
1608
1609
0
    return true;
1610
0
}
1611
1612
static bool storeProfile(osl_TProfileImpl* pProfile, bool bCleanup)
1613
0
{
1614
0
    if (pProfile->m_Lines != nullptr)
1615
0
    {
1616
0
        if (pProfile->m_Flags & FLG_MODIFIED)
1617
0
        {
1618
0
            sal_uInt32 i;
1619
1620
0
            osl_TFile* pTmpFile = osl_openTmpProfileImpl(pProfile);
1621
1622
0
            if ( pTmpFile == nullptr )
1623
0
            {
1624
0
                return false;
1625
0
            }
1626
1627
0
            OSL_VERIFY(OslProfile_rewindFile(pTmpFile, true));
1628
1629
0
            for ( i = 0 ; i < pProfile->m_NoLines ; i++ )
1630
0
            {
1631
0
                OSL_VERIFY(OslProfile_putLine(pTmpFile, pProfile->m_Lines[i]));
1632
0
            }
1633
1634
0
            if ( ! writeProfileImpl(pTmpFile) )
1635
0
            {
1636
0
                if ( pTmpFile->m_pWriteBuf != nullptr )
1637
0
                {
1638
0
                    free(pTmpFile->m_pWriteBuf);
1639
0
                }
1640
1641
0
                pTmpFile->m_pWriteBuf=nullptr;
1642
0
                pTmpFile->m_nWriteBufLen=0;
1643
0
                pTmpFile->m_nWriteBufFree=0;
1644
1645
0
                closeFileImpl(pTmpFile,pProfile->m_Flags);
1646
1647
0
                return false;
1648
0
            }
1649
1650
0
            pProfile->m_Flags &= ~FLG_MODIFIED;
1651
1652
0
            closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
1653
0
            closeFileImpl(pTmpFile,pProfile->m_Flags);
1654
1655
0
            osl_ProfileSwapProfileNames(pProfile);
1656
1657
0
            pProfile->m_pFile = openFileImpl(pProfile->m_FileName,pProfile->m_Flags);
1658
1659
0
        }
1660
1661
0
        if (bCleanup)
1662
0
        {
1663
0
            while (pProfile->m_NoLines > 0)
1664
0
                removeLine(pProfile, pProfile->m_NoLines - 1);
1665
1666
0
            free(pProfile->m_Lines);
1667
0
            pProfile->m_Lines = nullptr;
1668
0
            pProfile->m_NoLines = 0;
1669
0
            pProfile->m_MaxLines = 0;
1670
1671
0
            while (pProfile->m_NoSections > 0)
1672
0
                removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]);
1673
1674
0
            free(pProfile->m_Sections);
1675
0
            pProfile->m_Sections = nullptr;
1676
0
            pProfile->m_NoSections = 0;
1677
0
            pProfile->m_MaxSections = 0;
1678
0
        }
1679
0
    }
1680
1681
0
    return true;
1682
0
}
1683
1684
static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl* pProfile)
1685
0
{
1686
0
    osl_TFile* pFile=nullptr;
1687
0
    char const * const pszExtension = "tmp";
1688
0
    char pszTmpName[PATH_MAX];
1689
0
    oslProfileOption PFlags=0;
1690
1691
0
    pszTmpName[0] = '\0';
1692
1693
    /* generate tmp profilename */
1694
0
    osl_ProfileGenerateExtension(pProfile->m_FileName, pszExtension, pszTmpName, PATH_MAX);
1695
1696
0
    if ( pszTmpName[0] == 0 )
1697
0
    {
1698
0
        return nullptr;
1699
0
    }
1700
1701
0
    if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) )
1702
0
    {
1703
0
        PFlags |= osl_Profile_WRITELOCK;
1704
0
    }
1705
1706
    /* open this file */
1707
0
    pFile = openFileImpl(pszTmpName,pProfile->m_Flags | PFlags);
1708
1709
    /* return new pFile */
1710
0
    return pFile;
1711
0
}
1712
1713
static bool osl_ProfileSwapProfileNames(osl_TProfileImpl* pProfile)
1714
0
{
1715
0
    char pszBakFile[PATH_MAX];
1716
0
    char pszTmpFile[PATH_MAX];
1717
1718
0
    pszBakFile[0] = '\0';
1719
0
    pszTmpFile[0] = '\0';
1720
1721
0
    osl_ProfileGenerateExtension(pProfile->m_FileName, "bak", pszBakFile, PATH_MAX);
1722
0
    osl_ProfileGenerateExtension(pProfile->m_FileName, "tmp", pszTmpFile, PATH_MAX);
1723
1724
    /* unlink bak */
1725
0
    unlink( pszBakFile );
1726
1727
    // Rename ini -> bak, then tmp -> ini:
1728
0
    bool result = rename( pProfile->m_FileName, pszBakFile ) == 0;
1729
0
    if (!result)
1730
0
    {
1731
0
        int e = errno;
1732
0
        SAL_INFO("sal.file", "rename(" << pProfile->m_FileName << "," << pszBakFile << "): " << UnixErrnoString(e));
1733
0
    }
1734
0
    else
1735
0
    {
1736
0
        SAL_INFO("sal.file", "rename(" << pProfile->m_FileName << "," << pszBakFile << "): OK");
1737
0
        result = rename( pszTmpFile, pProfile->m_FileName ) == 0;
1738
0
        if (!result)
1739
0
        {
1740
0
            int e = errno;
1741
0
            SAL_INFO("sal.file", "rename(" << pszTmpFile << "," << pProfile->m_FileName << "): " << UnixErrnoString(e));
1742
0
        }
1743
0
        else
1744
0
        {
1745
0
            SAL_INFO("sal.file", "rename(" << pszTmpFile << "," << pProfile->m_FileName << "): OK");
1746
0
        }
1747
0
    }
1748
0
    return result;
1749
0
}
1750
1751
static void osl_ProfileGenerateExtension(const char* pszFileName, const char* pszExtension, char* pszTmpName, int BufferMaxLen)
1752
0
{
1753
0
    char* cursor = pszTmpName;
1754
0
    int len;
1755
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.
1759
     */
1760
0
    len = strlen(pszFileName);
1761
0
    if(len < BufferMaxLen)
1762
0
    {
1763
0
        memcpy(cursor, pszFileName, len);
1764
0
        cursor += len;
1765
0
        BufferMaxLen -= len;
1766
0
    }
1767
0
    else
1768
0
    {
1769
0
        memcpy(cursor, pszFileName, BufferMaxLen - 1);
1770
0
        cursor += BufferMaxLen - 1;
1771
0
        BufferMaxLen = 1;
1772
0
    }
1773
0
    if(BufferMaxLen > 1)
1774
0
    {
1775
0
        *cursor++ = '.';
1776
0
        BufferMaxLen -= 1;
1777
0
    }
1778
0
    len = strlen(pszExtension);
1779
0
    if(len < BufferMaxLen)
1780
0
    {
1781
0
        memcpy(cursor, pszExtension, len);
1782
0
        cursor += len;
1783
0
    }
1784
0
    else
1785
0
    {
1786
0
        memcpy(cursor, pszExtension, BufferMaxLen - 1);
1787
0
        cursor += BufferMaxLen - 1;
1788
0
    }
1789
0
    *cursor = 0;
1790
0
}
1791
1792
static osl_TProfileImpl* acquireProfile(oslProfile Profile, bool bWriteable)
1793
0
{
1794
0
    osl_TProfileImpl* pProfile = static_cast<osl_TProfileImpl*>(Profile);
1795
0
    oslProfileOption PFlags=0;
1796
1797
0
    if ( bWriteable )
1798
0
    {
1799
0
        PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK;
1800
0
    }
1801
0
    else
1802
0
    {
1803
0
        PFlags = osl_Profile_DEFAULT;
1804
0
    }
1805
1806
0
    if (pProfile == nullptr)
1807
0
    {
1808
0
        if ( ( pProfile = static_cast<osl_TProfileImpl*>(osl_openProfile(nullptr, PFlags )) ) != nullptr )
1809
0
        {
1810
0
            pProfile->m_Flags |= FLG_AUTOOPEN;
1811
0
        }
1812
0
    }
1813
0
    else
1814
0
    {
1815
0
        if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
1816
0
        {
1817
0
            if (! (pProfile->m_Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE )))
1818
0
            {
1819
0
                osl_TStamp Stamp;
1820
1821
0
                if (! (pProfile->m_pFile = openFileImpl(pProfile->m_FileName, pProfile->m_Flags | PFlags )))
1822
0
                    return nullptr;
1823
1824
0
                Stamp = OslProfile_getFileStamp(pProfile->m_pFile);
1825
1826
0
                if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp)))
1827
0
                {
1828
0
                    pProfile->m_Stamp = Stamp;
1829
0
                    bool bRet = loadProfile(pProfile->m_pFile, pProfile);
1830
0
                    SAL_WARN_IF(!bRet, "sal.osl", "loadProfile(pProfile->m_pFile, pProfile) ==> false");
1831
0
                }
1832
0
            }
1833
0
            else
1834
0
            {
1835
                /* A readlock file could not be written */
1836
0
                if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable)
1837
0
                {
1838
0
                    return nullptr;
1839
0
                }
1840
0
            }
1841
0
        }
1842
0
    }
1843
1844
0
    return pProfile;
1845
0
}
1846
1847
static bool releaseProfile(osl_TProfileImpl* pProfile)
1848
0
{
1849
0
    if ( pProfile == nullptr )
1850
0
    {
1851
0
        return false;
1852
0
    }
1853
1854
0
    if (pProfile->m_Flags & FLG_AUTOOPEN)
1855
0
    {
1856
0
        return osl_closeProfile(static_cast<oslProfile>(pProfile));
1857
0
    }
1858
1859
0
    if (! (pProfile->m_Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE )))
1860
0
    {
1861
0
        if (pProfile->m_Flags & FLG_MODIFIED)
1862
0
        {
1863
0
            bool bRet = storeProfile(pProfile, false);
1864
0
            SAL_WARN_IF(!bRet, "sal.osl", "storeProfile(pProfile, false) ==> false");
1865
0
        }
1866
1867
0
        closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
1868
0
        pProfile->m_pFile = nullptr;
1869
0
    }
1870
1871
0
    return true;
1872
0
}
1873
1874
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */