Switch to unified view

a/src/utils/pathut.cpp b/src/utils/pathut.cpp
...
...
17
17
18
#ifndef TEST_PATHUT
18
#ifndef TEST_PATHUT
19
#include "autoconfig.h"
19
#include "autoconfig.h"
20
20
21
#include <stdio.h>
21
#include <stdio.h>
22
#include "safefcntl.h"
22
#include <unistd.h>
23
#include "safeunistd.h"
23
#include <fcntl.h>
24
#include <dirent.h>
24
#include "dirent.h"
25
#include "cstr.h"
26
#ifdef _WIN32
27
#include "safewindows.h"
28
#else
25
#include <sys/param.h>
29
#include <sys/param.h>
26
#include <pwd.h>
30
#include <pwd.h>
31
#include <sys/file.h>
32
#endif
27
#include <math.h>
33
#include <math.h>
28
#include <errno.h>
34
#include <errno.h>
29
#include <sys/types.h>
35
#include <sys/types.h>
30
#include <sys/file.h>
31
#include "safesysstat.h"
36
#include "safesysstat.h"
32
#include <glob.h>
37
#include "ptmutex.h"
33
38
34
// Let's include all files where statfs can be defined and hope for no
39
// Let's include all files where statfs can be defined and hope for no
35
// conflict...
40
// conflict...
36
#ifdef HAVE_SYS_MOUNT_H 
41
#ifdef HAVE_SYS_MOUNT_H 
37
#include <sys/mount.h>
42
#include <sys/mount.h>
...
...
50
#include <cstring>
55
#include <cstring>
51
#include <iostream>
56
#include <iostream>
52
#include <sstream>
57
#include <sstream>
53
#include <stack>
58
#include <stack>
54
#include <set>
59
#include <set>
55
using namespace std;
60
#include <vector>
56
61
57
#include "pathut.h"
62
#include "pathut.h"
58
#include "transcode.h"
63
#include "transcode.h"
59
#include "wipedir.h"
64
#include "wipedir.h"
60
#include "md5ut.h"
65
#include "md5ut.h"
61
66
67
using namespace std;
68
69
#ifdef _WIN32
70
/// Convert \ separators to /
71
void path_slashize(string& s)
72
{
73
    for (string::size_type i = 0; i < s.size(); i++) {
74
        if (s[i] == '\\')
75
            s[i] = '/';
76
    }
77
}
78
static bool path_strlookslikedrive(const string& s)
79
{
80
    return s.size() == 2 && isalpha(s[0]) && s[1] == ':';
81
}
82
83
static bool path_hasdrive(const string& s)
84
{
85
    if (s.size() >= 2 && isalpha(s[0]) && s[1] == ':')
86
        return true;
87
    return false;
88
}
89
static bool path_isdriveabs(const string& s)
90
{
91
    if (s.size() >= 3 && isalpha(s[0]) && s[1] == ':' && s[2] == '/')
92
        return true;
93
    return false;
94
}
95
96
#include <Shlwapi.h>
97
#pragma comment(lib, "shlwapi.lib")
98
99
string path_tchartoutf8(TCHAR *text)
100
{
101
#ifdef UNICODE
102
    // Simple C
103
    // const size_t size = ( wcslen(text) + 1 ) * sizeof(wchar_t);
104
    // wcstombs(&buffer[0], text, size);
105
    // std::vector<char> buffer(size);
106
    // Or:
107
    // Windows API
108
    std::vector<char> buffer;
109
    int size = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, NULL, NULL);
110
    if (size > 0) {
111
        buffer.resize(size);
112
        WideCharToMultiByte(CP_UTF8, 0, text, -1, 
113
                            &buffer[0], int(buffer.size()), NULL, NULL);
114
    } else {
115
        return string();
116
    }
117
    return string(&buffer[0]);
118
#else
119
    return text;
120
#endif
121
}
122
123
string path_thisexecpath()
124
{
125
    TCHAR text[MAX_PATH];
126
    DWORD length = GetModuleFileName(NULL, text, MAX_PATH);
127
#ifdef NTDDI_WIN8_future
128
    PathCchRemoveFileSpec(text, MAX_PATH);
129
#else
130
    PathRemoveFileSpec(text);
131
#endif
132
    string path = path_tchartoutf8(text);
133
    if (path.empty())
134
        path = "c:/";
135
136
    return path;
137
}
138
139
string path_wingettempfilename(TCHAR *pref)
140
{
141
    TCHAR buf[(MAX_PATH +1)*sizeof(TCHAR)];
142
    TCHAR dbuf[(MAX_PATH +1)*sizeof(TCHAR)];
143
    GetTempPath(MAX_PATH+1, dbuf);
144
    GetTempFileName(dbuf, pref, 0, buf);
145
    // Windows will have created a temp file, we delete it.
146
    string filename = path_tchartoutf8(buf);
147
    unlink(filename.c_str());
148
    return filename;
149
}
150
#endif
151
152
62
bool fsocc(const string &path, int *pc, long long *blocks)
153
bool fsocc(const string &path, int *pc, long long *blocks)
63
{
154
{
155
#ifdef _WIN32
156
  return false;
157
#else
64
#ifdef sun
158
#ifdef sun
65
    struct statvfs buf;
159
    struct statvfs buf;
66
    if (statvfs(path.c_str(), &buf) != 0) {
160
    if (statvfs(path.c_str(), &buf) != 0) {
67
    return false;
161
    return false;
68
    }
162
    }
...
...
92
                ((long long)buf.f_bavail) * ratio :
186
                ((long long)buf.f_bavail) * ratio :
93
        ((long long)buf.f_bavail) / ratio;
187
        ((long long)buf.f_bavail) / ratio;
94
    }
188
    }
95
    }
189
    }
96
    return true;
190
    return true;
191
#endif
97
}
192
}
98
193
99
const string& tmplocation()
194
const string& tmplocation()
100
{
195
{
101
    static string stmpdir;
196
    static string stmpdir;
102
    if (stmpdir.empty()) {
197
    if (stmpdir.empty()) {
103
        const char *tmpdir = getenv("RECOLL_TMPDIR");
198
        const char *tmpdir = getenv("RECOLL_TMPDIR");
104
        if (tmpdir == 0) 
199
        if (tmpdir == 0) 
105
            tmpdir = getenv("TMPDIR");
200
            tmpdir = getenv("TMPDIR");
106
        if (tmpdir == 0)
201
        if (tmpdir == 0) 
202
            tmpdir = getenv("TMP");
203
        if (tmpdir == 0) 
204
            tmpdir = getenv("TEMP");
205
        if (tmpdir == 0) {
206
#ifdef _WIN32
207
            TCHAR bufw[(MAX_PATH+1)*sizeof(TCHAR)];
208
            GetTempPath(MAX_PATH+1, bufw);
209
            stmpdir = path_tchartoutf8(bufw);
210
#else
107
            tmpdir = "/tmp";
211
            stmpdir = "/tmp";
212
#endif
213
        } else {
108
        stmpdir = string(tmpdir);
214
            stmpdir = tmpdir;
109
    }
215
        }
216
        stmpdir = path_canon(stmpdir);
217
    }
218
110
    return stmpdir;
219
    return stmpdir;
111
}
220
}
112
221
222
// Location for sample config, filters, etc. (e.g. /usr/share/recoll/)
223
const string& path_sharedatadir()
224
{
225
    static string datadir;
226
    if (datadir.empty()) {
227
#ifdef _WIN32
228
        datadir = path_cat(path_thisexecpath(), "Share");
229
#else
230
        const char *cdatadir = getenv("RECOLL_DATADIR");
231
        if (cdatadir == 0) {
232
            // If not in environment, use the compiled-in constant. 
233
            datadir = RECOLL_DATADIR;
234
        } else {
235
            datadir = cdatadir;
236
        }
237
#endif
238
    }
239
    return datadir;
240
}
241
242
string path_PATHsep()
243
{
244
    static const string w(";");
245
    static const string u(":");
246
#ifdef _WIN32
247
    return w;
248
#else
249
    return u;
250
#endif
251
}
252
113
bool maketmpdir(string& tdir, string& reason)
253
bool maketmpdir(string& tdir, string& reason)
114
{
254
{
255
#ifndef _WIN32
115
    tdir = path_cat(tmplocation(), "rcltmpXXXXXX");
256
    tdir = path_cat(tmplocation(), "rcltmpXXXXXX");
116
257
117
    char *cp = strdup(tdir.c_str());
258
    char *cp = strdup(tdir.c_str());
118
    if (!cp) {
259
    if (!cp) {
119
    reason = "maketmpdir: out of memory (for file name !)\n";
260
    reason = "maketmpdir: out of memory (for file name !)\n";
120
    tdir.erase();
261
    tdir.erase();
121
    return false;
262
    return false;
122
    }
263
    }
264
265
    // There is a race condition between name computation and
266
    // mkdir. try to make sure that we at least don't shoot ourselves
267
    // in the foot
268
#if !defined(HAVE_MKDTEMP) || defined(_WIN32)
269
    static PTMutexInit mlock;
270
    PTMutexLocker lock(mlock);
271
#endif
123
272
124
    if (!
273
    if (!
125
#ifdef HAVE_MKDTEMP
274
#ifdef HAVE_MKDTEMP
126
    mkdtemp(cp)
275
    mkdtemp(cp)
127
#else
276
#else
...
...
134
    tdir.erase();
283
    tdir.erase();
135
    return false;
284
    return false;
136
    }   
285
    }   
137
    tdir = cp;
286
    tdir = cp;
138
    free(cp);
287
    free(cp);
288
#else // _WIN32
289
    // There is a race condition between name computation and
290
    // mkdir. try to make sure that we at least don't shoot ourselves
291
    // in the foot
292
    static PTMutexInit mlock;
293
    PTMutexLocker lock(mlock);
294
    tdir = path_wingettempfilename(TEXT("rcltmp"));
295
#endif
139
296
140
#ifndef HAVE_MKDTEMP
297
    // At this point the directory does not exist yet except if we used
298
    // mkdtemp
299
300
#if !defined(HAVE_MKDTEMP) || defined(_WIN32)
141
    if (mkdir(tdir.c_str(), 0700) < 0) {
301
    if (mkdir(tdir.c_str(), 0700) < 0) {
142
    reason = string("maketmpdir: mkdir ") + tdir + " failed";
302
    reason = string("maketmpdir: mkdir ") + tdir + " failed";
143
    tdir.erase();
303
    tdir.erase();
144
    return false;
304
    return false;
145
    }
305
    }
...
...
149
}
309
}
150
310
151
TempFileInternal::TempFileInternal(const string& suffix)
311
TempFileInternal::TempFileInternal(const string& suffix)
152
    : m_noremove(false)
312
    : m_noremove(false)
153
{
313
{
314
    // Because we need a specific suffix, can't use mkstemp
315
    // well. There is a race condition between name computation and
316
    // file creation. try to make sure that we at least don't shoot
317
    // our own selves in the foot. maybe we'll use mkstemps one day.
318
    static PTMutexInit mlock;
319
    PTMutexLocker lock(mlock);
320
321
#ifndef _WIN32
154
    string filename = path_cat(tmplocation(), "rcltmpfXXXXXX");
322
    string filename = path_cat(tmplocation(), "rcltmpfXXXXXX");
155
    char *cp = strdup(filename.c_str());
323
    char *cp = strdup(filename.c_str());
156
    if (!cp) {
324
    if (!cp) {
157
    m_reason = "Out of memory (for file name !)\n";
325
    m_reason = "Out of memory (for file name !)\n";
158
    return;
326
    return;
159
    }
327
    }
160
328
161
    // Yes using mkstemp this way is awful (bot the suffix adding and
329
    // Using mkstemp this way is awful (bot the suffix adding and
162
    // using mkstemp() just to avoid the warnings)
330
    // using mkstemp() instead of mktemp just to avoid the warnings)
163
    int fd;
331
    int fd;
164
    if ((fd = mkstemp(cp)) < 0) {
332
    if ((fd = mkstemp(cp)) < 0) {
165
    free(cp);
333
    free(cp);
166
    m_reason = "TempFileInternal: mkstemp failed\n";
334
    m_reason = "TempFileInternal: mkstemp failed\n";
167
    return;
335
    return;
168
    }
336
    }
169
    close(fd);
337
    close(fd);
170
    unlink(cp);
338
    unlink(cp);
171
    
172
    filename = cp;
339
    filename = cp;
173
    free(cp);
340
    free(cp);
341
#else
342
    string filename = path_wingettempfilename(TEXT("recoll"));
343
#endif
174
344
175
    m_filename = filename + suffix;
345
    m_filename = filename + suffix;
176
    if (close(open(m_filename.c_str(), O_CREAT|O_EXCL, 0600)) != 0) {
346
    if (close(open(m_filename.c_str(), O_CREAT|O_EXCL, 0600)) != 0) {
177
    m_reason = string("Could not open/create") + m_filename;
347
    m_reason = string("Could not open/create") + m_filename;
178
    m_filename.erase();
348
    m_filename.erase();
...
...
212
    return false;
382
    return false;
213
    }
383
    }
214
    return true;
384
    return true;
215
}
385
}
216
386
217
void path_catslash(string &s) {
387
void path_catslash(string &s)
388
{
389
#ifdef WIN32
390
    path_slashize(s);
391
#endif
218
    if (s.empty() || s[s.length() - 1] != '/')
392
    if (s.empty() || s[s.length() - 1] != '/')
219
    s += '/';
393
    s += '/';
220
}
394
}
221
395
222
string path_cat(const string &s1, const string &s2) {
396
string path_cat(const string &s1, const string &s2)
397
{
223
    string res = s1;
398
    string res = s1;
224
    path_catslash(res);
399
    path_catslash(res);
225
    res +=  s2;
400
    res +=  s2;
226
    return res;
401
    return res;
227
}
402
}
228
403
229
string path_getfather(const string &s) {
404
string path_getfather(const string &s)
405
{
230
    string father = s;
406
    string father = s;
407
#ifdef WIN32
408
    path_slashize(father);
409
#endif
231
410
232
    // ??
411
    // ??
233
    if (father.empty())
412
    if (father.empty())
234
    return "./";
413
    return "./";
235
414
415
    if (path_isroot(father))
416
        return father;
417
    
236
    if (father[father.length() - 1] == '/') {
418
    if (father[father.length() - 1] == '/') {
237
    // Input ends with /. Strip it, handle special case for root
419
    // Input ends with /. Strip it, root special case was tested above
238
  if (father.length() == 1)
239
      return father;
240
    father.erase(father.length()-1);
420
    father.erase(father.length()-1);
241
    }
421
    }
242
422
243
    string::size_type slp = father.rfind('/');
423
    string::size_type slp = father.rfind('/');
244
    if (slp == string::npos)
424
    if (slp == string::npos)
...
...
247
    father.erase(slp);
427
    father.erase(slp);
248
    path_catslash(father);
428
    path_catslash(father);
249
    return father;
429
    return father;
250
}
430
}
251
431
252
string path_getsimple(const string &s) {
432
string path_getsimple(const string &s)
433
{
253
    string simple = s;
434
    string simple = s;
435
#ifdef WIN32
436
    path_slashize(simple);
437
#endif
254
438
255
    if (simple.empty())
439
    if (simple.empty())
256
    return simple;
440
    return simple;
257
441
258
    string::size_type slp = simple.rfind('/');
442
    string::size_type slp = simple.rfind('/');
...
...
283
    return s.substr(dotp+1);
467
    return s.substr(dotp+1);
284
}
468
}
285
469
286
string path_home()
470
string path_home()
287
{
471
{
472
#ifdef _WIN32
473
    string dir;
474
    const char *cp = getenv("USERPROFILE");
475
    if (cp != 0) {
476
        dir = cp;
477
    }
478
    if (dir.empty()) {
479
        cp = getenv("HOMEDRIVE");
480
        if (cp != 0) {
481
            const char *cp1 = getenv("HOMEPATH");
482
            if (cp1 != 0) {
483
                dir = string(cp) + string(cp1);
484
            }
485
        }
486
    }
487
    if (dir.empty()) {
488
        dir = "C:\\";
489
    }
490
    dir = path_canon(dir);
491
    path_catslash(dir);
492
    return dir;
493
#else
288
    uid_t uid = getuid();
494
    uid_t uid = getuid();
289
495
290
    struct passwd *entry = getpwuid(uid);
496
    struct passwd *entry = getpwuid(uid);
291
    if (entry == 0) {
497
    if (entry == 0) {
292
    const char *cp = getenv("HOME");
498
    const char *cp = getenv("HOME");
...
...
297
    }
503
    }
298
504
299
    string homedir = entry->pw_dir;
505
    string homedir = entry->pw_dir;
300
    path_catslash(homedir);
506
    path_catslash(homedir);
301
    return homedir;
507
    return homedir;
508
#endif
509
}
510
511
// The default place to store the default config and other stuff (e.g webqueue)
512
string path_homedata()
513
{
514
#ifdef _WIN32
515
    const char *cp = getenv("LOCALAPPDATA");
516
    string dir;
517
    if (cp != 0) {
518
        dir = path_canon(cp);
519
    }
520
    if (dir.empty()) {
521
        dir = path_cat(path_home(), "AppData/Local/");
522
    }
523
    return dir;
524
#else
525
    // We should use an xdg-conforming location, but, history...
526
    return path_home();
527
#endif
302
}
528
}
303
529
304
string path_tildexpand(const string &s) 
530
string path_tildexpand(const string &s) 
305
{
531
{
306
    if (s.empty() || s[0] != '~')
532
    if (s.empty() || s[0] != '~')
307
    return s;
533
    return s;
308
    string o = s;
534
    string o = s;
535
#ifdef WIN32
536
    path_slashize(o);
537
#endif
538
    
309
    if (s.length() == 1) {
539
    if (s.length() == 1) {
310
    o.replace(0, 1, path_home());
540
    o.replace(0, 1, path_home());
311
    } else if  (s[1] == '/') {
541
    } else if  (s[1] == '/') {
312
    o.replace(0, 2, path_home());
542
    o.replace(0, 2, path_home());
313
    } else {
543
    } else {
314
    string::size_type pos = s.find('/');
544
    string::size_type pos = s.find('/');
315
  int l = (pos == string::npos) ? s.length() - 1 : pos - 1;
545
        string::size_type l = (pos == string::npos) ? s.length() - 1 : pos - 1;
546
#ifdef _WIN32
547
        // Dont know what this means. Just replace with HOME
548
        o.replace(0, l+1, path_home());
549
#else
316
    struct passwd *entry = getpwnam(s.substr(1, l).c_str());
550
    struct passwd *entry = getpwnam(s.substr(1, l).c_str());
317
    if (entry)
551
    if (entry)
318
        o.replace(0, l+1, entry->pw_dir);
552
        o.replace(0, l+1, entry->pw_dir);
553
#endif
319
    }
554
    }
320
    return o;
555
    return o;
321
}
556
}
322
557
558
bool path_isroot(const string& path)
559
{
560
    if (path.size() == 1 && path[0] == '/')
561
        return true;
562
#ifdef _WIN32
563
    if (path.size() == 3 && isalpha(path[0]) && path[1] == ':' &&
564
        (path[2] == '/' || path[2] == '\\'))
565
        return true;
566
#endif
567
    return false;
568
}
569
570
bool path_isabsolute(const string &path)
571
{
572
    if (!path.empty() && (path[0] == '/'
573
#ifdef _WIN32
574
                          || path_isdriveabs(path)
575
#endif
576
            )) {
577
        return true;
578
    } 
579
    return false;
580
}
581
    
323
string path_absolute(const string &is)
582
string path_absolute(const string &is)
324
{
583
{
325
    if (is.length() == 0)
584
    if (is.length() == 0)
326
    return is;
585
    return is;
327
    string s = is;
586
    string s = is;
328
    if (s[0] != '/') {
587
    if (!path_isabsolute(s)) {
329
    char buf[MAXPATHLEN];
588
    char buf[MAXPATHLEN];
330
    if (!getcwd(buf, MAXPATHLEN)) {
589
    if (!getcwd(buf, MAXPATHLEN)) {
331
        return string();
590
        return string();
332
    }
591
    }
333
    s = path_cat(string(buf), s); 
592
    s = path_cat(string(buf), s);
593
#ifdef _WIN32
594
        path_slashize(s);
595
#endif
334
    }
596
    }
335
    return s;
597
    return s;
336
}
598
}
337
599
338
#include <smallut.h>
600
#include <smallut.h>
339
string path_canon(const string &is, const string* cwd)
601
string path_canon(const string &is, const string* cwd)
340
{
602
{
341
    if (is.length() == 0)
603
    if (is.length() == 0)
342
    return is;
604
    return is;
343
    string s = is;
605
    string s = is;
344
    if (s[0] != '/') {
606
#ifdef _WIN32
607
    path_slashize(s);
608
    // fix possible path from file: absolute url
609
    if (s.size() && s[0] == '/' && path_hasdrive(s.substr(1))) {
610
        s = s.substr(1);
611
    }
612
#endif
613
614
    if (!path_isabsolute(s)) {
345
    char buf[MAXPATHLEN];
615
    char buf[MAXPATHLEN];
346
    const char *cwdp = buf;
616
    const char *cwdp = buf;
347
    if (cwd) {
617
    if (cwd) {
348
        cwdp = cwd->c_str();
618
        cwdp = cwd->c_str();
349
    } else {
619
    } else {
...
...
368
    }
638
    }
369
    string ret;
639
    string ret;
370
    if (!cleaned.empty()) {
640
    if (!cleaned.empty()) {
371
    for (vector<string>::const_iterator it = cleaned.begin(); 
641
    for (vector<string>::const_iterator it = cleaned.begin(); 
372
         it != cleaned.end(); it++) {
642
         it != cleaned.end(); it++) {
373
      ret += "/";
643
            ret += "/";
644
#ifdef _WIN32
645
            if (it == cleaned.begin() && path_strlookslikedrive(*it)) {
646
                // Get rid of just added initial "/"
647
                ret.clear();
648
            }
649
#endif
374
        ret += *it;
650
        ret += *it;
375
    }
651
    }
376
    } else {
652
    } else {
377
    ret = "/";
653
    ret = "/";
378
    }
654
    }
...
...
385
    vector<string> elems;
661
    vector<string> elems;
386
    stringToTokens(path, elems, "/");
662
    stringToTokens(path, elems, "/");
387
    path = "/";
663
    path = "/";
388
    for (vector<string>::const_iterator it = elems.begin(); 
664
    for (vector<string>::const_iterator it = elems.begin(); 
389
     it != elems.end(); it++){
665
     it != elems.end(); it++){
666
#ifdef _WIN32
667
        if (it == elems.begin() && path_strlookslikedrive(*it))
668
            path = "";
669
#endif
390
    path += *it;
670
    path += *it;
391
    // Not using path_isdir() here, because this cant grok symlinks
671
    // Not using path_isdir() here, because this cant grok symlinks
392
    // If we hit an existing file, no worry, mkdir will just fail.
672
    // If we hit an existing file, no worry, mkdir will just fail.
393
    if (access(path.c_str(), 0) != 0) {
673
    if (access(path.c_str(), 0) != 0) {
394
        if (mkdir(path.c_str(), 0700) != 0)  {
674
        if (mkdir(path.c_str(), 0700) != 0)  {
...
...
396
        }
676
        }
397
    }
677
    }
398
    path += "/";
678
    path += "/";
399
    }
679
    }
400
    return true;
680
    return true;
401
}
402
403
vector<string> path_dirglob(const string &dir, const string pattern)
404
{
405
    vector<string> res;
406
    glob_t mglob;
407
    string mypat=path_cat(dir, pattern);
408
    if (glob(mypat.c_str(), 0, 0, &mglob)) {
409
  return res;
410
    }
411
    for (int i = 0; i < int(mglob.gl_pathc); i++) {
412
  res.push_back(mglob.gl_pathv[i]);
413
    }
414
    globfree(&mglob);
415
    return res;
416
}
681
}
417
682
418
bool path_isdir(const string& path)
683
bool path_isdir(const string& path)
419
{
684
{
420
    struct stat st;
685
    struct stat st;
...
...
551
    }
816
    }
552
    return isfileurl ? string("file://") + parenturl :
817
    return isfileurl ? string("file://") + parenturl :
553
        string("http://") + parenturl;
818
        string("http://") + parenturl;
554
}
819
}
555
820
821
822
string path_defaultrecollconfsubdir()
823
{
824
#ifdef _WIN32
825
    return "Recoll";
826
#else
827
    return ".recoll";
828
#endif
829
}
830
556
// Convert to file path if url is like file:
831
// Convert to file path if url is like file:
557
// Note: this only works with our internal pseudo-urls which are not
832
// Note: this only works with our internal pseudo-urls which are not
558
// encoded/escaped
833
// encoded/escaped
559
string fileurltolocalpath(string url)
834
string fileurltolocalpath(string url)
560
{
835
{
561
    if (url.find("file://") == 0)
836
    if (url.find("file://") == 0)
562
        url = url.substr(7, string::npos);
837
        url = url.substr(7, string::npos);
563
    else
838
    else
564
        return string();
839
        return string();
840
841
#ifdef _WIN32
842
    // Absolute file urls are like: file:///c:/mydir/...
843
    // Get rid of the initial '/'
844
    if (url.size() >= 3 && url[0] == '/' && isalpha(url[1]) && url[2] == ':') {
845
        url = url.substr(1);
846
    }
847
#endif
565
848
566
    // Removing the fragment part. This is exclusively used when
849
    // Removing the fragment part. This is exclusively used when
567
    // executing a viewer for the recoll manual, and we only strip the
850
    // executing a viewer for the recoll manual, and we only strip the
568
    // part after # if it is preceded by .html
851
    // part after # if it is preceded by .html
569
    string::size_type pos;
852
    string::size_type pos;
...
...
572
    } else if ((pos = url.rfind(".htm#")) != string::npos) {
855
    } else if ((pos = url.rfind(".htm#")) != string::npos) {
573
        url.erase(pos+4);
856
        url.erase(pos+4);
574
    }
857
    }
575
858
576
    return url;
859
    return url;
860
}
861
862
string path_pathtofileurl(const string& path)
863
{
864
  // We're supposed to receive a canonic absolute path, but on windows we
865
  // may need to add a '/' in front of the drive spec
866
  string url(cstr_fileu);
867
  if (path.empty() || path[0] != '/')
868
      url.push_back('/');
869
  url += path;
870
  return url;
577
}
871
}
578
872
579
bool urlisfileurl(const string& url)
873
bool urlisfileurl(const string& url)
580
{
874
{
581
    return url.find("file://") == 0;
875
    return url.find("file://") == 0;
...
...
685
    errno = serrno;
979
    errno = serrno;
686
    m_reason = "fcntl lock failed";
980
    m_reason = "fcntl lock failed";
687
    return -1;
981
    return -1;
688
    }
982
    }
689
#else
983
#else
984
#ifdef _WIN32
985
  return 0;
986
#else
690
    int operation = LOCK_EX | LOCK_NB;
987
    int operation = LOCK_EX | LOCK_NB;
691
    if (flock(m_fd, operation) == -1) {
988
    if (flock(m_fd, operation) == -1) {
692
    int serrno = errno;
989
    int serrno = errno;
693
    (void)::close(m_fd);
990
    (void)::close(m_fd);
694
    errno = serrno;
991
    errno = serrno;
695
    m_reason = "flock failed";
992
    m_reason = "flock failed";
696
    return -1;
993
    return -1;
697
    }
994
    }
995
#endif // ! win32
698
#endif // ! sun
996
#endif // ! sun
699
997
700
    if (ftruncate(m_fd, 0) != 0) {
998
    if (ftruncate(m_fd, 0) != 0) {
701
    /* can't happen [tm] */
999
    /* can't happen [tm] */
702
    int serrno = errno;
1000
    int serrno = errno;
...
...
813
void pathut_init_mt()
1111
void pathut_init_mt()
814
{
1112
{
815
    path_home();
1113
    path_home();
816
    tmplocation();
1114
    tmplocation();
817
    thumbnailsdir();
1115
    thumbnailsdir();
1116
    path_sharedatadir();
818
}
1117
}
819
1118
820
1119
821
#else // TEST_PATHUT
1120
#else // TEST_PATHUT
822
#include <stdlib.h>
1121
#include <stdlib.h>
...
...
931
  sleep(10);
1230
  sleep(10);
932
  pidfile.close();
1231
  pidfile.close();
933
  pidfile.remove();
1232
  pidfile.remove();
934
#endif
1233
#endif
935
1234
936
#if 1
1235
#if 0
937
  if (argc > 1) {
1236
  if (argc > 1) {
938
      cerr <<  "Usage: thumbpath <filepath>" << endl;
1237
      cerr <<  "Usage: thumbpath <filepath>" << endl;
939
      exit(1);
1238
      exit(1);
940
  }
1239
  }
941
  string input;
1240
  string input;
...
...
963
    string fn = *argv++;argc--;
1262
    string fn = *argv++;argc--;
964
    string ext = path_suffix(fn);
1263
    string ext = path_suffix(fn);
965
    cout << "Suffix: [" << ext << "]" << endl;
1264
    cout << "Suffix: [" << ext << "]" << endl;
966
    return 0;
1265
    return 0;
967
#endif
1266
#endif
1267
1268
#if 1
1269
    if (argc != 1) {
1270
  cerr << "Usage: trpathut url" << endl;
1271
  exit(1);
1272
    }
1273
    string url = *argv++;argc--;
1274
1275
    cout << "File: [" << fileurltolocalpath(url) << "]\n";
1276
    return 0;
1277
#endif
1278
1279
968
}
1280
}
969
1281
970
#endif // TEST_PATHUT
1282
#endif // TEST_PATHUT
971
1283