~samba-team/talloc/ppa-maverick

« back to all changes in this revision

Viewing changes to libreplace/replace.c

  • Committer: Jelmer Vernooij
  • Date: 2010-05-06 13:36:58 UTC
  • mfrom: (36.1.12 unstable)
  • Revision ID: jelmer@samba.org-20100506133658-l9k1768b1ww3zh62
Merge unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
   replacement routines for broken systems
 
4
   Copyright (C) Andrew Tridgell 1992-1998
 
5
   Copyright (C) Jelmer Vernooij 2005-2008
 
6
 
 
7
     ** NOTE! The following LGPL license applies to the replace
 
8
     ** library. This does NOT imply that all of Samba is released
 
9
     ** under the LGPL
 
10
   
 
11
   This library is free software; you can redistribute it and/or
 
12
   modify it under the terms of the GNU Lesser General Public
 
13
   License as published by the Free Software Foundation; either
 
14
   version 3 of the License, or (at your option) any later version.
 
15
 
 
16
   This library is distributed in the hope that it will be useful,
 
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
19
   Lesser General Public License for more details.
 
20
 
 
21
   You should have received a copy of the GNU Lesser General Public
 
22
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
 
23
*/
 
24
 
 
25
#include "replace.h"
 
26
 
 
27
#include "system/filesys.h"
 
28
#include "system/time.h"
 
29
#include "system/passwd.h"
 
30
#include "system/syslog.h"
 
31
#include "system/locale.h"
 
32
#include "system/wait.h"
 
33
 
 
34
#ifdef _WIN32
 
35
#define mkdir(d,m) _mkdir(d)
 
36
#endif
 
37
 
 
38
void replace_dummy(void);
 
39
void replace_dummy(void) {}
 
40
 
 
41
#ifndef HAVE_FTRUNCATE
 
42
 /*******************************************************************
 
43
ftruncate for operating systems that don't have it
 
44
********************************************************************/
 
45
int rep_ftruncate(int f, off_t l)
 
46
{
 
47
#ifdef HAVE_CHSIZE
 
48
      return chsize(f,l);
 
49
#elif defined(F_FREESP)
 
50
      struct  flock   fl;
 
51
 
 
52
      fl.l_whence = 0;
 
53
      fl.l_len = 0;
 
54
      fl.l_start = l;
 
55
      fl.l_type = F_WRLCK;
 
56
      return fcntl(f, F_FREESP, &fl);
 
57
#else
 
58
#error "you must have a ftruncate function"
 
59
#endif
 
60
}
 
61
#endif /* HAVE_FTRUNCATE */
 
62
 
 
63
 
 
64
#ifndef HAVE_STRLCPY
 
65
/* like strncpy but does not 0 fill the buffer and always null 
 
66
   terminates. bufsize is the size of the destination buffer */
 
67
size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
 
68
{
 
69
        size_t len = strlen(s);
 
70
        size_t ret = len;
 
71
        if (bufsize <= 0) return 0;
 
72
        if (len >= bufsize) len = bufsize-1;
 
73
        memcpy(d, s, len);
 
74
        d[len] = 0;
 
75
        return ret;
 
76
}
 
77
#endif
 
78
 
 
79
#ifndef HAVE_STRLCAT
 
80
/* like strncat but does not 0 fill the buffer and always null 
 
81
   terminates. bufsize is the length of the buffer, which should
 
82
   be one more than the maximum resulting string length */
 
83
size_t rep_strlcat(char *d, const char *s, size_t bufsize)
 
84
{
 
85
        size_t len1 = strlen(d);
 
86
        size_t len2 = strlen(s);
 
87
        size_t ret = len1 + len2;
 
88
 
 
89
        if (len1+len2 >= bufsize) {
 
90
                if (bufsize < (len1+1)) {
 
91
                        return ret;
 
92
                }
 
93
                len2 = bufsize - (len1+1);
 
94
        }
 
95
        if (len2 > 0) {
 
96
                memcpy(d+len1, s, len2);
 
97
                d[len1+len2] = 0;
 
98
        }
 
99
        return ret;
 
100
}
 
101
#endif
 
102
 
 
103
#ifndef HAVE_MKTIME
 
104
/*******************************************************************
 
105
a mktime() replacement for those who don't have it - contributed by 
 
106
C.A. Lademann <cal@zls.com>
 
107
Corrections by richard.kettlewell@kewill.com
 
108
********************************************************************/
 
109
 
 
110
#define  MINUTE  60
 
111
#define  HOUR    60*MINUTE
 
112
#define  DAY             24*HOUR
 
113
#define  YEAR    365*DAY
 
114
time_t rep_mktime(struct tm *t)
 
115
{
 
116
  struct tm       *u;
 
117
  time_t  epoch = 0;
 
118
  int n;
 
119
  int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
 
120
  y, m, i;
 
121
 
 
122
  if(t->tm_year < 70)
 
123
    return((time_t)-1);
 
124
 
 
125
  n = t->tm_year + 1900 - 1;
 
126
  epoch = (t->tm_year - 70) * YEAR + 
 
127
    ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
 
128
 
 
129
  y = t->tm_year + 1900;
 
130
  m = 0;
 
131
 
 
132
  for(i = 0; i < t->tm_mon; i++) {
 
133
    epoch += mon [m] * DAY;
 
134
    if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
 
135
      epoch += DAY;
 
136
    
 
137
    if(++m > 11) {
 
138
      m = 0;
 
139
      y++;
 
140
    }
 
141
  }
 
142
 
 
143
  epoch += (t->tm_mday - 1) * DAY;
 
144
  epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
 
145
  
 
146
  if((u = localtime(&epoch)) != NULL) {
 
147
    t->tm_sec = u->tm_sec;
 
148
    t->tm_min = u->tm_min;
 
149
    t->tm_hour = u->tm_hour;
 
150
    t->tm_mday = u->tm_mday;
 
151
    t->tm_mon = u->tm_mon;
 
152
    t->tm_year = u->tm_year;
 
153
    t->tm_wday = u->tm_wday;
 
154
    t->tm_yday = u->tm_yday;
 
155
    t->tm_isdst = u->tm_isdst;
 
156
  }
 
157
 
 
158
  return(epoch);
 
159
}
 
160
#endif /* !HAVE_MKTIME */
 
161
 
 
162
 
 
163
#ifndef HAVE_INITGROUPS
 
164
/****************************************************************************
 
165
 some systems don't have an initgroups call 
 
166
****************************************************************************/
 
167
int rep_initgroups(char *name, gid_t id)
 
168
{
 
169
#ifndef HAVE_SETGROUPS
 
170
        /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
 
171
        errno = ENOSYS;
 
172
        return -1;
 
173
#else /* HAVE_SETGROUPS */
 
174
 
 
175
#include <grp.h>
 
176
 
 
177
        gid_t *grouplst = NULL;
 
178
        int max_gr = NGROUPS_MAX;
 
179
        int ret;
 
180
        int    i,j;
 
181
        struct group *g;
 
182
        char   *gr;
 
183
        
 
184
        if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
 
185
                errno = ENOMEM;
 
186
                return -1;
 
187
        }
 
188
 
 
189
        grouplst[0] = id;
 
190
        i = 1;
 
191
        while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
 
192
                if (g->gr_gid == id)
 
193
                        continue;
 
194
                j = 0;
 
195
                gr = g->gr_mem[0];
 
196
                while (gr && (*gr != (char)NULL)) {
 
197
                        if (strcmp(name,gr) == 0) {
 
198
                                grouplst[i] = g->gr_gid;
 
199
                                i++;
 
200
                                gr = (char *)NULL;
 
201
                                break;
 
202
                        }
 
203
                        gr = g->gr_mem[++j];
 
204
                }
 
205
        }
 
206
        endgrent();
 
207
        ret = setgroups(i, grouplst);
 
208
        free(grouplst);
 
209
        return ret;
 
210
#endif /* HAVE_SETGROUPS */
 
211
}
 
212
#endif /* HAVE_INITGROUPS */
 
213
 
 
214
 
 
215
#if (defined(SecureWare) && defined(SCO))
 
216
/* This is needed due to needing the nap() function but we don't want
 
217
   to include the Xenix libraries since that will break other things...
 
218
   BTW: system call # 0x0c28 is the same as calling nap() */
 
219
long nap(long milliseconds) {
 
220
         return syscall(0x0c28, milliseconds);
 
221
 }
 
222
#endif
 
223
 
 
224
 
 
225
#ifndef HAVE_MEMMOVE
 
226
/*******************************************************************
 
227
safely copies memory, ensuring no overlap problems.
 
228
this is only used if the machine does not have its own memmove().
 
229
this is not the fastest algorithm in town, but it will do for our
 
230
needs.
 
231
********************************************************************/
 
232
void *rep_memmove(void *dest,const void *src,int size)
 
233
{
 
234
        unsigned long d,s;
 
235
        int i;
 
236
        if (dest==src || !size) return(dest);
 
237
 
 
238
        d = (unsigned long)dest;
 
239
        s = (unsigned long)src;
 
240
 
 
241
        if ((d >= (s+size)) || (s >= (d+size))) {
 
242
                /* no overlap */
 
243
                memcpy(dest,src,size);
 
244
                return(dest);
 
245
        }
 
246
 
 
247
        if (d < s) {
 
248
                /* we can forward copy */
 
249
                if (s-d >= sizeof(int) && 
 
250
                    !(s%sizeof(int)) && 
 
251
                    !(d%sizeof(int)) && 
 
252
                    !(size%sizeof(int))) {
 
253
                        /* do it all as words */
 
254
                        int *idest = (int *)dest;
 
255
                        int *isrc = (int *)src;
 
256
                        size /= sizeof(int);
 
257
                        for (i=0;i<size;i++) idest[i] = isrc[i];
 
258
                } else {
 
259
                        /* simplest */
 
260
                        char *cdest = (char *)dest;
 
261
                        char *csrc = (char *)src;
 
262
                        for (i=0;i<size;i++) cdest[i] = csrc[i];
 
263
                }
 
264
        } else {
 
265
                /* must backward copy */
 
266
                if (d-s >= sizeof(int) && 
 
267
                    !(s%sizeof(int)) && 
 
268
                    !(d%sizeof(int)) && 
 
269
                    !(size%sizeof(int))) {
 
270
                        /* do it all as words */
 
271
                        int *idest = (int *)dest;
 
272
                        int *isrc = (int *)src;
 
273
                        size /= sizeof(int);
 
274
                        for (i=size-1;i>=0;i--) idest[i] = isrc[i];
 
275
                } else {
 
276
                        /* simplest */
 
277
                        char *cdest = (char *)dest;
 
278
                        char *csrc = (char *)src;
 
279
                        for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
 
280
                }      
 
281
        }
 
282
        return(dest);
 
283
}
 
284
#endif /* HAVE_MEMMOVE */
 
285
 
 
286
#ifndef HAVE_STRDUP
 
287
/****************************************************************************
 
288
duplicate a string
 
289
****************************************************************************/
 
290
char *rep_strdup(const char *s)
 
291
{
 
292
        size_t len;
 
293
        char *ret;
 
294
 
 
295
        if (!s) return(NULL);
 
296
 
 
297
        len = strlen(s)+1;
 
298
        ret = (char *)malloc(len);
 
299
        if (!ret) return(NULL);
 
300
        memcpy(ret,s,len);
 
301
        return(ret);
 
302
}
 
303
#endif /* HAVE_STRDUP */
 
304
 
 
305
#ifndef HAVE_SETLINEBUF
 
306
void rep_setlinebuf(FILE *stream)
 
307
{
 
308
        setvbuf(stream, (char *)NULL, _IOLBF, 0);
 
309
}
 
310
#endif /* HAVE_SETLINEBUF */
 
311
 
 
312
#ifndef HAVE_VSYSLOG
 
313
#ifdef HAVE_SYSLOG
 
314
void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
 
315
{
 
316
        char *msg = NULL;
 
317
        vasprintf(&msg, format, arglist);
 
318
        if (!msg)
 
319
                return;
 
320
        syslog(facility_priority, "%s", msg);
 
321
        free(msg);
 
322
}
 
323
#endif /* HAVE_SYSLOG */
 
324
#endif /* HAVE_VSYSLOG */
 
325
 
 
326
#ifndef HAVE_STRNLEN
 
327
/**
 
328
 Some platforms don't have strnlen
 
329
**/
 
330
 size_t rep_strnlen(const char *s, size_t max)
 
331
{
 
332
        size_t len;
 
333
  
 
334
        for (len = 0; len < max; len++) {
 
335
                if (s[len] == '\0') {
 
336
                        break;
 
337
                }
 
338
        }
 
339
        return len;  
 
340
}
 
341
#endif
 
342
  
 
343
#ifndef HAVE_STRNDUP
 
344
/**
 
345
 Some platforms don't have strndup.
 
346
**/
 
347
char *rep_strndup(const char *s, size_t n)
 
348
{
 
349
        char *ret;
 
350
        
 
351
        n = strnlen(s, n);
 
352
        ret = malloc(n+1);
 
353
        if (!ret)
 
354
                return NULL;
 
355
        memcpy(ret, s, n);
 
356
        ret[n] = 0;
 
357
 
 
358
        return ret;
 
359
}
 
360
#endif
 
361
 
 
362
#if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
 
363
int rep_waitpid(pid_t pid,int *status,int options)
 
364
{
 
365
  return wait4(pid, status, options, NULL);
 
366
}
 
367
#endif
 
368
 
 
369
#ifndef HAVE_SETEUID
 
370
int rep_seteuid(uid_t euid)
 
371
{
 
372
#ifdef HAVE_SETRESUID
 
373
        return setresuid(-1, euid, -1);
 
374
#else
 
375
        errno = ENOSYS;
 
376
        return -1;
 
377
#endif
 
378
}
 
379
#endif
 
380
 
 
381
#ifndef HAVE_SETEGID
 
382
int rep_setegid(gid_t egid)
 
383
{
 
384
#ifdef HAVE_SETRESGID
 
385
        return setresgid(-1, egid, -1);
 
386
#else
 
387
        errno = ENOSYS;
 
388
        return -1;
 
389
#endif
 
390
}
 
391
#endif
 
392
 
 
393
/*******************************************************************
 
394
os/2 also doesn't have chroot
 
395
********************************************************************/
 
396
#ifndef HAVE_CHROOT
 
397
int rep_chroot(const char *dname)
 
398
{
 
399
        errno = ENOSYS;
 
400
        return -1;
 
401
}
 
402
#endif
 
403
 
 
404
/*****************************************************************
 
405
 Possibly replace mkstemp if it is broken.
 
406
*****************************************************************/  
 
407
 
 
408
#ifndef HAVE_SECURE_MKSTEMP
 
409
int rep_mkstemp(char *template)
 
410
{
 
411
        /* have a reasonable go at emulating it. Hope that
 
412
           the system mktemp() isn't completly hopeless */
 
413
        char *p = mktemp(template);
 
414
        if (!p)
 
415
                return -1;
 
416
        return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
 
417
}
 
418
#endif
 
419
 
 
420
#ifndef HAVE_MKDTEMP
 
421
char *rep_mkdtemp(char *template)
 
422
{
 
423
        char *dname;
 
424
        
 
425
        if ((dname = mktemp(template))) {
 
426
                if (mkdir(dname, 0700) >= 0) {
 
427
                        return dname;
 
428
                }
 
429
        }
 
430
 
 
431
        return NULL;
 
432
}
 
433
#endif
 
434
 
 
435
/*****************************************************************
 
436
 Watch out: this is not thread safe.
 
437
*****************************************************************/
 
438
 
 
439
#ifndef HAVE_PREAD
 
440
ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
 
441
{
 
442
        if (lseek(__fd, __offset, SEEK_SET) != __offset) {
 
443
                return -1;
 
444
        }
 
445
        return read(__fd, __buf, __nbytes);
 
446
}
 
447
#endif
 
448
 
 
449
/*****************************************************************
 
450
 Watch out: this is not thread safe.
 
451
*****************************************************************/
 
452
 
 
453
#ifndef HAVE_PWRITE
 
454
ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
 
455
{
 
456
        if (lseek(__fd, __offset, SEEK_SET) != __offset) {
 
457
                return -1;
 
458
        }
 
459
        return write(__fd, __buf, __nbytes);
 
460
}
 
461
#endif
 
462
 
 
463
#ifndef HAVE_STRCASESTR
 
464
char *rep_strcasestr(const char *haystack, const char *needle)
 
465
{
 
466
        const char *s;
 
467
        size_t nlen = strlen(needle);
 
468
        for (s=haystack;*s;s++) {
 
469
                if (toupper(*needle) == toupper(*s) &&
 
470
                    strncasecmp(s, needle, nlen) == 0) {
 
471
                        return (char *)((uintptr_t)s);
 
472
                }
 
473
        }
 
474
        return NULL;
 
475
}
 
476
#endif
 
477
 
 
478
#ifndef HAVE_STRTOK_R
 
479
/* based on GLIBC version, copyright Free Software Foundation */
 
480
char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
 
481
{
 
482
        char *token;
 
483
 
 
484
        if (s == NULL) s = *save_ptr;
 
485
 
 
486
        s += strspn(s, delim);
 
487
        if (*s == '\0') {
 
488
                *save_ptr = s;
 
489
                return NULL;
 
490
        }
 
491
 
 
492
        token = s;
 
493
        s = strpbrk(token, delim);
 
494
        if (s == NULL) {
 
495
                *save_ptr = token + strlen(token);
 
496
        } else {
 
497
                *s = '\0';
 
498
                *save_ptr = s + 1;
 
499
        }
 
500
 
 
501
        return token;
 
502
}
 
503
#endif
 
504
 
 
505
#ifndef HAVE_STRTOLL
 
506
long long int rep_strtoll(const char *str, char **endptr, int base)
 
507
{
 
508
#ifdef HAVE_STRTOQ
 
509
        return strtoq(str, endptr, base);
 
510
#elif defined(HAVE___STRTOLL) 
 
511
        return __strtoll(str, endptr, base);
 
512
#elif SIZEOF_LONG == SIZEOF_LONG_LONG
 
513
        return (long long int) strtol(str, endptr, base);
 
514
#else
 
515
# error "You need a strtoll function"
 
516
#endif
 
517
}
 
518
#endif
 
519
 
 
520
 
 
521
#ifndef HAVE_STRTOULL
 
522
unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
 
523
{
 
524
#ifdef HAVE_STRTOUQ
 
525
        return strtouq(str, endptr, base);
 
526
#elif defined(HAVE___STRTOULL) 
 
527
        return __strtoull(str, endptr, base);
 
528
#elif SIZEOF_LONG == SIZEOF_LONG_LONG
 
529
        return (unsigned long long int) strtoul(str, endptr, base);
 
530
#else
 
531
# error "You need a strtoull function"
 
532
#endif
 
533
}
 
534
#endif
 
535
 
 
536
#ifndef HAVE_SETENV
 
537
int rep_setenv(const char *name, const char *value, int overwrite) 
 
538
{
 
539
        char *p;
 
540
        size_t l1, l2;
 
541
        int ret;
 
542
 
 
543
        if (!overwrite && getenv(name)) {
 
544
                return 0;
 
545
        }
 
546
 
 
547
        l1 = strlen(name);
 
548
        l2 = strlen(value);
 
549
 
 
550
        p = malloc(l1+l2+2);
 
551
        if (p == NULL) {
 
552
                return -1;
 
553
        }
 
554
        memcpy(p, name, l1);
 
555
        p[l1] = '=';
 
556
        memcpy(p+l1+1, value, l2);
 
557
        p[l1+l2+1] = 0;
 
558
 
 
559
        ret = putenv(p);
 
560
        if (ret != 0) {
 
561
                free(p);
 
562
        }
 
563
 
 
564
        return ret;
 
565
}
 
566
#endif
 
567
 
 
568
#ifndef HAVE_UNSETENV
 
569
int rep_unsetenv(const char *name)
 
570
{
 
571
        extern char **environ;
 
572
        size_t len = strlen(name);
 
573
        size_t i, count;
 
574
 
 
575
        if (environ == NULL || getenv(name) == NULL) {
 
576
                return 0;
 
577
        }
 
578
 
 
579
        for (i=0;environ[i];i++) /* noop */ ;
 
580
 
 
581
        count=i;
 
582
        
 
583
        for (i=0;i<count;) {
 
584
                if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
 
585
                        /* note: we do _not_ free the old variable here. It is unsafe to 
 
586
                           do so, as the pointer may not have come from malloc */
 
587
                        memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));
 
588
                        count--;
 
589
                } else {
 
590
                        i++;
 
591
                }
 
592
        }
 
593
 
 
594
        return 0;
 
595
}
 
596
#endif
 
597
 
 
598
#ifndef HAVE_UTIME
 
599
int rep_utime(const char *filename, const struct utimbuf *buf)
 
600
{
 
601
        errno = ENOSYS;
 
602
        return -1;
 
603
}
 
604
#endif
 
605
 
 
606
#ifndef HAVE_UTIMES
 
607
int rep_utimes(const char *filename, const struct timeval tv[2])
 
608
{
 
609
        struct utimbuf u;
 
610
 
 
611
        u.actime = tv[0].tv_sec;
 
612
        if (tv[0].tv_usec > 500000) {
 
613
                u.actime += 1;
 
614
        }
 
615
 
 
616
        u.modtime = tv[1].tv_sec;
 
617
        if (tv[1].tv_usec > 500000) {
 
618
                u.modtime += 1;
 
619
        }
 
620
 
 
621
        return utime(filename, &u);
 
622
}
 
623
#endif
 
624
 
 
625
#ifndef HAVE_DUP2
 
626
int rep_dup2(int oldfd, int newfd) 
 
627
{
 
628
        errno = ENOSYS;
 
629
        return -1;
 
630
}
 
631
#endif
 
632
 
 
633
#ifndef HAVE_CHOWN
 
634
/**
 
635
chown isn't used much but OS/2 doesn't have it
 
636
**/
 
637
int rep_chown(const char *fname, uid_t uid, gid_t gid)
 
638
{
 
639
        errno = ENOSYS;
 
640
        return -1;
 
641
}
 
642
#endif
 
643
 
 
644
#ifndef HAVE_LINK
 
645
int rep_link(const char *oldpath, const char *newpath)
 
646
{
 
647
        errno = ENOSYS;
 
648
        return -1;
 
649
}
 
650
#endif
 
651
 
 
652
#ifndef HAVE_READLINK
 
653
int rep_readlink(const char *path, char *buf, size_t bufsiz)
 
654
{
 
655
        errno = ENOSYS;
 
656
        return -1;
 
657
}
 
658
#endif
 
659
 
 
660
#ifndef HAVE_SYMLINK
 
661
int rep_symlink(const char *oldpath, const char *newpath)
 
662
{
 
663
        errno = ENOSYS;
 
664
        return -1;
 
665
}
 
666
#endif
 
667
 
 
668
#ifndef HAVE_LCHOWN
 
669
int rep_lchown(const char *fname,uid_t uid,gid_t gid)
 
670
{
 
671
        errno = ENOSYS;
 
672
        return -1;
 
673
}
 
674
#endif
 
675
 
 
676
#ifndef HAVE_REALPATH
 
677
char *rep_realpath(const char *path, char *resolved_path)
 
678
{
 
679
        /* As realpath is not a system call we can't return ENOSYS. */
 
680
        errno = EINVAL;
 
681
        return NULL;
 
682
}
 
683
#endif