1 /*
2   Copyright 2021 Northern.tech AS
3 
4   This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5 
6   This program is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published by the
8   Free Software Foundation; version 3.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
18 
19   To the extent this program is licensed as part of the Enterprise
20   versions of CFEngine, the applicable Commercial Open Source License
21   (COSL) may apply to this file if you as a licensee so wish it. See
22   included file COSL.txt.
23 */
24 
25 #ifndef CFENGINE_PLATFORM_H
26 #define CFENGINE_PLATFORM_H
27 
28 /*
29  * Platform-specific definitions and declarations.
30  *
31  * INCLUDE THIS HEADER ALWAYS FIRST in order to define appropriate macros for
32  * including system headers (such as _FILE_OFFSET_BITS).
33  */
34 
35 #ifdef HAVE_CONFIG_H
36 # include <config.h>
37 #endif
38 
39 #define _GNU_SOURCE 1
40 
41 #ifdef _WIN32
42 # define MAX_FILENAME 227
43 # define WINVER 0x501
44 # if defined(__CYGWIN__)
45 #  undef FD_SETSIZE
46 # endif
47   /* Increase select(2) FD limit from 64. It's documented and valid to do it
48    * like that provided that we define it *before* including winsock2.h. */
49 # define FD_SETSIZE 4096
50 #else
51 # define MAX_FILENAME 254
52 #endif
53 
54 #ifdef __MINGW32__
55 # include <winsock2.h>
56 # include <windows.h>
57 # include <accctrl.h>
58 # include <aclapi.h>
59 # include <psapi.h>
60 # include <wchar.h>
61 # include <sddl.h>
62 # include <tlhelp32.h>
63 # include <iphlpapi.h>
64 # include <ws2tcpip.h>
65 # include <objbase.h>           // for disphelper
66 # ifndef SHUT_RDWR              // for shutdown()
67 #  define SHUT_RDWR SD_BOTH
68 # endif
69 #endif
70 
71 /* Standard C. */
72 #include <stdio.h>
73 #include <math.h>
74 #include <string.h>
75 #include <ctype.h>
76 #include <assert.h>
77 #include <stddef.h>                                     /* offsetof, size_t */
78 
79 /* POSIX but available in all platforms. */
80 #include <strings.h>
81 #include <limits.h>
82 
83 #ifdef HAVE_SYS_SYSMACROS_H
84 # include <sys/sysmacros.h>
85 #endif
86 
87 #include <sys/types.h>
88 #include <sys/stat.h>
89 
90 /* We now require a pthreads implementation. */
91 #include <pthread.h>
92 
93 #ifndef _GETOPT_H
94 # include <../libcompat/getopt.h>
95 #endif
96 
97 #ifdef HAVE_STDLIB_H
98 # include <stdlib.h>
99 #endif
100 
101 #ifdef HAVE_UNAME
102 # include <sys/utsname.h>
103 #else
104 # define _SYS_NMLN       257
105 
106 struct utsname
107 {
108     char sysname[_SYS_NMLN];
109     char nodename[_SYS_NMLN];
110     char release[_SYS_NMLN];
111     char version[_SYS_NMLN];
112     char machine[_SYS_NMLN];
113 };
114 
115 #endif
116 
117 #ifdef HAVE_STDINT_H
118 # include <stdint.h>
119 #endif
120 
121 #ifdef HAVE_INTTYPES_H
122 # include <inttypes.h>
123 #endif
124 
125 #ifdef HAVE_SYS_SYSTEMINFO_H
126 # include <sys/systeminfo.h>
127 #endif
128 
129 #ifdef HAVE_SYS_PARAM_H
130 # include <sys/param.h>
131 #endif
132 
133 #ifdef HAVE_SYS_MOUNT_H
134 # include <sys/mount.h>
135 #endif
136 
137 #ifdef HAVE_SYS_WAIT_H
138 # include <sys/wait.h>
139 #endif
140 #ifndef WEXITSTATUS
141 # define WEXITSTATUS(s) ((unsigned)(s) >> 8)
142 #endif
143 #ifndef WIFEXITED
144 # define WIFEXITED(s) (((s) & 255) == 0)
145 #endif
146 #ifndef WIFSIGNALED
147 # define WIFSIGNALED(s) ((s) & 0)       /* Can't use for BSD */
148 #endif
149 #ifndef WTERMSIG
150 # define WTERMSIG(s) ((s) & 0)
151 #endif
152 
153 #include <stdbool.h>
154 
155 #include <errno.h>
156 
157 #ifdef HAVE_DIRENT_H
158 # include <dirent.h>
159 #else
160 # define dirent direct
161 # if HAVE_SYS_NDIR_H
162 #  include <sys/ndir.h>
163 # endif
164 # if HAVE_SYS_DIR_H
165 #  include <sys/dir.h>
166 # endif
167 # if HAVE_NDIR_H
168 #  include <ndir.h>
169 # endif
170 #endif
171 
172 #ifndef PATH_MAX
173 # ifdef _MAX_PATH
174 #  define PATH_MAX _MAX_PATH
175 # else
176 #  define PATH_MAX 4096
177 # endif
178 #endif
179 
180 #include <signal.h>
181 
182 #ifdef __MINGW32__
183 # define LOG_LOCAL0      (16<<3)
184 # define LOG_LOCAL1      (17<<3)
185 # define LOG_LOCAL2      (18<<3)
186 # define LOG_LOCAL3      (19<<3)
187 # define LOG_LOCAL4      (20<<3)
188 # define LOG_LOCAL5      (21<<3)
189 # define LOG_LOCAL6      (22<<3)
190 # define LOG_LOCAL7      (23<<3)
191 # define LOG_USER        (1<<3)
192 # define LOG_DAEMON      (3<<3)
193 
194 /* MinGW added this flag only in latest version. */
195 # ifndef IPV6_V6ONLY
196 #  define IPV6_V6ONLY 27
197 # endif
198 
199 // Not available in MinGW headers unless you raise WINVER and _WIN32_WINNT, but
200 // that is very badly supported in MinGW ATM.
201 ULONGLONG WINAPI GetTickCount64(void);
202 
203 #else /* !__MINGW32__ */
204 # include <syslog.h>
205 #endif
206 
207 #ifdef _AIX
208 # ifndef ps2
209 #  include <sys/statfs.h>
210 # endif
211 
212 # include <sys/systemcfg.h>
213 #endif
214 
215 #ifdef __sun
216 # include <sys/statvfs.h>
217 # undef nfstype
218 
219 #include <sys/mkdev.h>
220 
221 #ifndef timersub
222 # define timersub(a, b, result)                             \
223     do                                                      \
224     {                                                       \
225            (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;    \
226            (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
227            if ((result)->tv_usec < 0)                       \
228            {                                                \
229                --(result)->tv_sec;                          \
230                (result)->tv_usec += 1000000;                \
231            }                                                \
232     } while (0)
233 #endif
234 
235 #endif
236 
237 #if !HAVE_DECL_DIRFD
238 int dirfd(DIR *dirp);
239 #endif
240 
241 /* strndup is defined as a macro on many systems */
242 #if !HAVE_DECL_STRNDUP
243 # ifndef strndup
244 char *strndup(const char *s, size_t n);
245 # endif
246 #endif
247 
248 #if !HAVE_DECL_STRNLEN
249 size_t strnlen(const char *str, size_t maxlen);
250 #endif
251 
252 #ifdef HAVE_UNISTD_H
253 # include <unistd.h>
254 #endif
255 
256 #if !HAVE_DECL_STRLCPY
257 size_t strlcpy(char *destination, const char *source, size_t size);
258 #endif
259 
260 #if !HAVE_DECL_STRLCAT
261 size_t strlcat(char *destination, const char *source, size_t size);
262 #endif
263 
264 #if !HAVE_DECL_STRSEP
265 char *strsep(char **stringp, const char *delim);
266 #endif
267 
268 #if !HAVE_DECL_SOCKETPAIR
269 int socketpair(int domain, int type, int protocol, int sv[2]);
270 #endif
271 
272 #if !HAVE_DECL_FSYNC
273 int fsync(int fd);
274 #endif
275 
276 #if !HAVE_DECL_GLOB
277 #define GLOB_NOSPACE 1
278 #define GLOB_ABORTED 2
279 #define GLOB_NOMATCH 3
280 typedef struct {
281     size_t   gl_pathc;    /* Count of paths matched so far  */
282     char   **gl_pathv;    /* List of matched pathnames.  */
283     size_t   gl_offs;
284 } glob_t;
285 int glob(const char *pattern,
286          int flags,
287          int (*errfunc) (const char *epath, int eerrno),
288          glob_t *pglob);
289 void globfree(glob_t *pglob);
290 #endif
291 
292 #ifdef __APPLE__
293 # include <sys/malloc.h>
294 # include <sys/paths.h>
295 #endif
296 
297 #ifdef HAVE_SYS_MALLOC_H
298 # ifdef __APPLE__
299 #  include <sys/malloc.h>
300 #  include <sys/paths.h>
301 # endif
302 #else
303 # ifdef HAVE_MALLOC_H
304 #  ifndef __OpenBSD__
305 #   ifdef __FreeBSD__
306 #    include <stdlib.h>
307 #   else
308 #    include <malloc.h>
309 #   endif
310 #  endif
311 # endif
312 #endif
313 
314 #include <fcntl.h>
315 
316 #ifdef HAVE_VFS_H
317 # include <sys/vfs.h>
318 #endif
319 
320 #ifdef __hpux
321 # include <sys/dirent.h>
322 #endif
323 
324 #ifdef HAVE_UTIME_H
325 # include <utime.h>             /* use utime not utimes for portability */
326 #elif TIME_WITH_SYS_TIME
327 # include <sys/time.h>
328 # include <time.h>
329 #elif HAVE_SYS_TIME_H
330 # include <sys/time.h>
331 #elif ! defined(AOS)
332 # include <time.h>
333 #endif
334 
335 #ifdef HAVE_TIME_H
336 # include <time.h>
337 #endif
338 
339 #ifdef HAVE_SYS_TIME_H
340 # include <sys/time.h>
341 #endif
342 
343 #ifdef HAVE_SYS_RESOURCE_H
344 # include <sys/resource.h>
345 #endif
346 
347 #ifndef __MINGW32__
348 # include <pwd.h>
349 # include <grp.h>
350 #endif
351 
352 #ifdef HAVE_SYS_SOCKIO_H
353 # include <sys/sockio.h>
354 #endif
355 
356 /*
357   Work around bug in HPUX system headers:
358   "/usr/include/machine/sys/getppdp.h:65: error: array type has incomplete element type"
359 */
360 #ifdef __hpux
361 union mpinfou
362 {
363     int dummy;
364 };
365 #endif
366 
367 #ifndef __MINGW32__
368 # include <sys/socket.h>
369 # include <sys/ioctl.h>
370 # include <net/if.h>
371 # include <netinet/in.h>
372 # include <netinet/in_systm.h>
373 # include <netinet/ip.h>
374 # include <netinet/tcp.h>
375 # include <arpa/inet.h>
376 # include <netdb.h>
377 # if !defined __linux__ && !defined _WIN32
378 #  include <sys/protosw.h>
379 #  undef sgi
380 #  include <net/route.h>
381 # endif
382 #endif
383 
384 #ifdef __linux__
385 # ifdef HAVE_NET_ROUTE_H
386 #  include <net/route.h>
387 # else
388 #  include <linux/route.h>
389 # endif
390 
391 # ifdef HAVE_NETINET_IN_H
392 #  include <netinet/in.h>
393 # else
394 #  include <linux/in.h>
395 # endif
396 
397 # ifdef HAVE_NETINET_IP_H
398 #  include <netinet/ip.h>
399 # else
400 #  include <linux/ip.h>
401 # endif
402 #endif
403 
404 #ifdef __linux__
405 #define ARG_LINUX_ONLY
406 #else
407 #define ARG_LINUX_ONLY ARG_UNUSED
408 #endif
409 
410 #ifndef CLOCK_REALTIME
411 # define CLOCK_REALTIME 1
412 #endif
413 
414 #ifndef HAVE_CLOCKID_T
415 typedef int clockid_t;
416 #endif
417 
418 #ifndef HAVE_SOCKLEN_T
419 typedef int socklen_t;
420 #endif
421 
422 # ifndef _SC_THREAD_STACK_MIN
423 #  define _SC_THREAD_STACK_MIN PTHREAD_STACK_MIN
424 #endif
425 
426 #ifndef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
427 #  define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_MUTEX_INITIALIZER
428 #endif
429 
430 #if !HAVE_DECL_GETLOADAVG
431 int getloadavg (double loadavg[], int nelem);
432 #endif
433 
434 #ifdef HAVE_ENDIAN_H
435 # include <endian.h>
436 #endif
437 
438 #if !HAVE_DECL_LE32TOH
ByteSwap32(uint32_t le32uint)439 static inline uint32_t ByteSwap32(uint32_t le32uint)
440 {
441     uint32_t be32uint;
442     unsigned char *le_ptr = (unsigned char *)&le32uint;
443     unsigned char *be_ptr = (unsigned char *)&be32uint;
444     be_ptr[0] = le_ptr[3];
445     be_ptr[1] = le_ptr[2];
446     be_ptr[2] = le_ptr[1];
447     be_ptr[3] = le_ptr[0];
448     return be32uint;
449 }
450 # ifdef WORDS_BIGENDIAN
451 #  ifndef le32toh
452 #   define le32toh(x) ByteSwap32(x)
453 #  endif
454 #  ifndef htole32
455 #   define htole32(x) ByteSwap32(x)
456 #  endif
457 # else
458 #  ifndef le32toh
459 #   define le32toh(x) (x)
460 #  endif
461 #  ifndef htole32
462 #   define htole32(x) (x)
463 #  endif
464 # endif
465 #endif // !HAVE_DECL_LE32TOH
466 
467 #if !HAVE_DECL_CLOSEFROM
468 int closefrom(int fd);
469 #endif
470 
471 #if !HAVE_DECL_PTHREAD_ATTR_SETSTACKSIZE
472 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
473 #endif
474 
475 #ifdef HAVE_SCHED_H
476 # include <sched.h>
477 #endif
478 
479 #if defined(HAVE_SYS_XATTR_H)
480 # include <sys/xattr.h>
481 #elif defined(HAVE_ATTR_XATTR_H)
482 # include <attr/xattr.h>
483 #endif
484 
485 #ifndef MIN
486 # define MIN(a, b) ((a) < (b) ? (a) : (b))
487 #endif
488 
489 #ifndef MAX
490 # define MAX(a, b) ((a) > (b) ? (a) : (b))
491 #endif
492 
493 #ifndef INADDR_NONE
494 # define INADDR_NONE ((unsigned long int) 0xffffffff)
495 #endif
496 #ifndef HAVE_SETEGID
497 int setegid(gid_t gid);
498 #endif
499 #if !HAVE_DECL_UNAME
500 int uname(struct utsname *buf);
501 #endif
502 #if !HAVE_DECL_GETUID
503 uid_t getuid(void);
504 #endif
505 #if !HAVE_DECL_GETGID
506 gid_t getgid(void);
507 #endif
508 #if !HAVE_DECL_FGETGRENT
509 struct group *fgetgrent(FILE *stream);
510 #endif
511 #if !HAVE_DECL_DRAND48
512 double drand48(void);
513 #endif
514 #if !HAVE_DECL_SRAND48
515 void srand48(long seed);
516 #endif
517 #if !HAVE_DECL_CLOCK_GETTIME
518 int clock_gettime(clockid_t clock_id, struct timespec *tp);
519 #endif
520 
521 #if !HAVE_DECL_REALPATH
522     /**
523      * WARNING realpath() has varying behaviour among platforms.
524      *  - Do not use it to convert relative paths to absolute
525      *    (Solaris under certain conditions will return relative path).
526      *  - Do not use it to check existence of file
527      *    (on *BSD the last component of the path may not exist).
528      * Use it only to resolve all symlinks and canonicalise filename,
529      * i.e. remove double '/' and "/./" and "/../".
530      *
531      * @TODO what we need is a resolvepath(2) cross-platform implementation.
532      */
533 #    if defined (__MINGW32__)
534 #        define realpath(N,R) _fullpath((R), (N), PATH_MAX)
535 #    endif
536 #endif
537 
538 #if !HAVE_DECL_LSTAT
539 int lstat(const char *file_name, struct stat *buf);
540 #endif
541 #if !HAVE_DECL_SLEEP
542 unsigned int sleep(unsigned int seconds);
543 #endif
544 #if !HAVE_DECL_ROUND
545 double round(double x);
546 #endif
547 #if !HAVE_DECL_NANOSLEEP
548 int nanosleep(const struct timespec *req, struct timespec *rem);
549 #endif
550 #if !HAVE_DECL_CHOWN
551 int chown(const char *path, uid_t owner, gid_t group);
552 #endif
553 #if !HAVE_DECL_FCHMOD
554 int fchmod(int fd, mode_t mode);
555 #endif
556 
557 #if !HAVE_DECL_GETNETGRENT
558 int getnetgrent(char **host, char **user, char **domain);
559 #endif
560 
561 #if !HAVE_DECL_SETNETGRENT
562 #if SETNETGRENT_RETURNS_INT
563 int setnetgrent(const char *netgroup);
564 #else
565 void setnetgrent(const char *netgroup);
566 #endif
567 #endif
568 
569 #if !HAVE_DECL_ENDNETGRENT
570 #if ENDNETGRENT_RETURNS_INT
571 int endnetgrent(void);
572 #else
573 void endnetgrent(void);
574 #endif
575 #endif
576 
577 #if !HAVE_DECL_STRSTR
578 char *strstr(const char *haystack, const char *needle);
579 #endif
580 #if !HAVE_DECL_STRCASESTR
581 char *strcasestr(const char *haystack, const char *needle);
582 #endif
583 #if !HAVE_DECL_STRCASECMP
584 int strcasecmp(const char *s1, const char *s2);
585 #endif
586 #if !HAVE_DECL_STRNCASECMP
587 int strncasecmp(const char *s1, const char *s2, size_t n);
588 #endif
589 #if !HAVE_DECL_STRSIGNAL
590 char *strsignal(int sig);
591 #endif
592 #if !HAVE_DECL_STRDUP
593 char *strdup(const char *str);
594 #endif
595 #if !HAVE_DECL_MEMRCHR
596 void *memrchr(const void *s, int c, size_t n);
597 #endif
598 #if !HAVE_DECL_MEMDUP
599 void *memdup(const void *mem, size_t size);
600 #endif
601 #if !HAVE_DECL_MEMMEM
602 void *memmem(const void *haystack, size_t haystacklen,
603              const void *needle, size_t needlelen);
604 #endif
605 #if !HAVE_DECL_STRERROR
606 char *strerror(int err);
607 #endif
608 #if !HAVE_DECL_UNSETENV
609 int unsetenv(const char *name);
610 #endif
611 #ifndef HAVE_SETEUID
612 int seteuid(uid_t euid);
613 #endif
614 #ifndef HAVE_SETEUID
615 int setegid(gid_t egid);
616 #endif
617 #if !HAVE_DECL_SETLINEBUF
618 void setlinebuf(FILE *stream);
619 #endif
620 
621 #if HAVE_STDARG_H
622 # include <stdarg.h>
623 # if !HAVE_VSNPRINTF
624 int rpl_vsnprintf(char *, size_t, const char *, va_list);
625 /* If [v]snprintf() does not exist or is not C99 compatible, then we assume
626  * that [v]printf() and [v]fprintf() need to be provided as well. */
627 int rpl_vprintf(const char *format, va_list ap);
628 int rpl_vfprintf(FILE *stream, const char *format, va_list ap);
629 # endif
630 # if !HAVE_SNPRINTF
631 int rpl_snprintf(char *, size_t, const char *, ...);
632 int rpl_printf(const char *format, ...);
633 int rpl_fprintf(FILE *stream, const char *format, ...);
634 # endif
635 # if !HAVE_VASPRINTF
636 int rpl_vasprintf(char **, const char *, va_list);
637 # endif
638 # if !HAVE_ASPRINTF
639 int rpl_asprintf(char **, const char *, ...);
640 # endif
641 #endif /* HAVE_STDARG_H */
642 
643 /* For example Solaris, does not have isfinite() in <math.h>. */
644 #if !HAVE_DECL_ISFINITE && defined(HAVE_IEEEFP_H)
645 # include <ieeefp.h>
646 # define isfinite(x) finite(x)
647 #endif
648 
649 #if !HAVE_DECL_GETLINE
650 ssize_t getline(char **lineptr, size_t *n, FILE *stream);
651 #endif
652 #if !HAVE_DECL_STRCHRNUL
653 char *strchrnul(const char *s, int c);
654 #endif
655 #if !HAVE_DECL_GMTIME_R
656 struct tm *gmtime_r(const time_t *timep, struct tm *result);
657 #endif
658 #if !HAVE_DECL_LOCALTIME_R
659 struct tm *localtime_r(const time_t *timep, struct tm *result);
660 #endif
661 #if !HAVE_DECL_CHMOD
662 int chmod(const char *path, mode_t mode);
663 #endif
664 #if !HAVE_DECL_ALARM
665 unsigned int alarm(unsigned int seconds);
666 #endif
667 #if !HAVE_DECL_MKDTEMP
668 char *mkdtemp(char *template);
669 #endif
670 #if !HAVE_DECL_STRRSTR
671 char *strrstr(const char *haystack, const char *needle);
672 #endif
673 #if !HAVE_DECL_STPNCPY
674 char *stpncpy(char *dst, const char *src, size_t len);
675 #endif
676 #if !HAVE_DECL_INET_NTOP
677 const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
678 #endif
679 #if !HAVE_DECL_INET_PTON
680 int inet_pton(int af, const char *src, void *dst);
681 #endif
682 #if !HAVE_DECL_GETADDRINFO
683 int getaddrinfo(const char *node, const char *service,
684                 const struct addrinfo *hints, struct addrinfo **res);
685 void freeaddrinfo(struct addrinfo *res);
686 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
687                 char *node, socklen_t nodelen,
688                 char *service, socklen_t servicelen, int flags);
689 const char *gai_strerror(int errcode);
690 #endif
691 #if !HAVE_STRUCT_SOCKADDR_STORAGE
692     #ifdef AF_INET6
693         #define sockaddr_storage sockaddr_in6
694     #else
695         #define sockaddr_storage sockaddr
696     #endif
697 #endif
698 #ifndef AF_INET6
699     /* if the platform doesn't have it, it's useless, but define it as -1
700      * since we need it in our code... */
701     #define AF_INET6 -1
702 #endif
703 #ifndef AI_NUMERICSERV
704     /* Not portable to MinGW so don't use it. */
705     #define AI_NUMERICSERV -1
706 #endif
707 
708 #if !defined(HAVE_MKDIR_PROPER)
709 int rpl_mkdir(const char *pathname, mode_t mode);
710 #endif
711 
712 #if !defined(HAVE_STAT_PROPER)
713 int rpl_stat(const char *path, struct stat *buf);
714 #define _stat64(name, st) rpl_stat(name, st)
715 #endif
716 
717 #if !defined(HAVE_RENAME_PROPER)
718 int rpl_rename(const char *oldpath, const char *newpath);
719 #endif
720 
721 #if !defined(HAVE_CTIME_PROPER)
722 char *rpl_ctime(const time_t *t);
723 #endif
724 
725 #ifndef NGROUPS
726 # define NGROUPS 20
727 #endif
728 
729 #if !HAVE_DECL_OPENAT
730 int openat(int dirfd, const char *pathname, int flags, ...);
731 #endif
732 #if !HAVE_DECL_FSTATAT
733 int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags);
734 #endif
735 #if !HAVE_DECL_FCHOWNAT
736 int fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, int flags);
737 #endif
738 #if !HAVE_DECL_FCHMODAT
739 int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);
740 #endif
741 #if !HAVE_DECL_READLINKAT
742 int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz);
743 #endif
744 #ifndef AT_SYMLINK_NOFOLLOW
745 #define AT_SYMLINK_NOFOLLOW 0x1000
746 #endif
747 #ifndef AT_FDCWD
748 #define AT_FDCWD (-2)
749 #endif
750 
751 #if !HAVE_DECL_LOG2
752 double log2(double x);
753 #endif
754 
755 /*******************************************************************/
756 /*  Windows                                                        */
757 /*******************************************************************/
758 
759 #ifdef __MINGW32__
760 # define MAXHOSTNAMELEN 256     // always adequate: http://msdn.microsoft.com/en-us/library/ms738527(VS.85).aspx
761 
762 // as seen in in_addr struct in winsock.h
763 typedef u_long in_addr_t;
764 
765 // shold be in winnt.h, but is not in current MinGW version
766 # ifndef VER_SUITE_WH_SERVER
767 #  define VER_SUITE_WH_SERVER 0x00008000
768 # endif
769 
770 /* Dummy signals, can be set to anything below 23 but
771  * 2, 4, 8, 11, 15, 21, 22 which are taken.
772  * Calling signal() with anything from below causes SIG_ERR
773  * to be returned.                                         */
774 
775 # define SIGALRM 1
776 # define SIGHUP 3
777 # define SIGTRAP 5
778 # define SIGKILL 6
779 # define SIGPIPE 7
780 # define SIGCONT 9
781 # define SIGSTOP 10
782 # define SIGQUIT 12
783 # define SIGCHLD 13
784 # define SIGUSR1 14
785 # define SIGUSR2 16
786 # define SIGBUS 17
787 
788 # if !defined( _TIMESPEC_DEFINED) && !defined(HAVE_STRUCT_TIMESPEC)
789 #  define HAVE_STRUCT_TIMESPEC 1
790 struct timespec
791 {
792     long tv_sec;
793     long tv_nsec;
794 };
795 # endif/* NOT _TIMESPEC_DEFINED */
796 
797 #endif /* __MINGW32__ */
798 
799 #ifndef ERESTARTSYS
800 # define ERESTARTSYS EINTR
801 #endif
802 
803 #ifndef EOPNOTSUPP
804 # define EOPNOTSUPP EINVAL
805 #endif
806 
807 #ifndef ENOTSUPP
808 # define ENOTSUPP EINVAL
809 #endif
810 
811 #ifndef ENOLINK
812 // Should be well outside the range of any errno value.
813 // Will never actually be returned by any function on a platform that doesn't support it.
814 # define ENOLINK 123456
815 #endif
816 
817 /*******************************************************************/
818 /* Copy file defines                                               */
819 /*******************************************************************/
820 
821 /**
822  * DEV_BSIZE is 512 for most common platforms
823  *           (Linux, AIX on Power, Solaris etc).
824  *
825  * Exceptions:
826  *             HP-UX:       1024
827  *             AIX on PS/2: 4096
828  *             Windows:     undefined
829  */
830 #ifndef DEV_BSIZE                       /* usually defined in <sys/param.h> */
831 # ifdef BSIZE
832 #  define DEV_BSIZE BSIZE
833 # else
834 #  define DEV_BSIZE 512
835 # endif
836 #endif
837 
838 /**
839    Extract or fake data from a `struct stat'.
840    ST_BLKSIZE: Optimal I/O blocksize for the file, in bytes.
841                This is tightly coupled to ST_NBLOCKS, i.e it must stand that
842                (s.st_size <= ST_NBLOCKS(s) * ST_BLKSIZE(s))
843    ST_NBLOCKS: Number of blocks in the file, **in ST_BLKSIZE units**
844                WARNING this is different than "stat.st_nblocks" on most systems
845    ST_NBYTES : "disk usage" of the file on the disk, **in bytes**.
846 
847    TODO on Windows here is how to get the "cluster size" i.e. the block size:
848    - send IOCTL_DISK_GET_DRIVE_GEOMETRY_EX and use Geometry.BytesPerSector
849      from DISK_GEOMETRY_EX structure
850    - To check if a file is sparse: File.GetAttributes().SparseFile
851 */
852 
853 /*
854  * Known platforms that don't have stat.st_blocks:
855  *   Windows (MinGW)
856  */
857 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
858 
859 
860 # define ST_BLKSIZE(statbuf)    DEV_BSIZE
861 # define ST_NBLOCKS(statbuf)    (((statbuf).st_size + DEV_BSIZE - 1) / DEV_BSIZE)
862 # define ST_NBYTES(statbuf)     (ST_NBLOCKS(statbuf) * DEV_BSIZE)
863 
864 
865 #else  /* HAVE_STRUCT_STAT_ST_BLOCKS */
866   /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
867 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
868                                ? (statbuf).st_blksize : DEV_BSIZE)
869 # define ST_NBLOCKS(statbuf) ((ST_NBYTES(statbuf) + ST_BLKSIZE(statbuf) - 1) \
870                               / ST_BLKSIZE(statbuf))
871 
872 # if defined(_CRAY)
873 #  define ST_NBYTES(statbuf) ((statbuf).st_blocks * ST_BLKSIZE(statbuf))
874 # else
875    /* ======= DEFAULT ============================== */
876    /* Most OS give stat.st_blocks in DEV_BSIZE units */
877 #  define ST_NBYTES(statbuf) ((statbuf).st_blocks * DEV_BSIZE)
878    /* ============================================== */
879 # endif /* CRAY */
880 
881 
882 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
883 
884 
885 #ifndef SEEK_CUR
886 # define SEEK_CUR 1
887 #endif
888 
889 /*******************************************************************/
890 /* Ultrix/BSD don't have all these from sys/stat.h                 */
891 /*******************************************************************/
892 
893 #ifndef S_IFBLK
894 # define S_IFBLK 0060000
895 #endif
896 #ifndef S_IFCHR
897 # define S_IFCHR 0020000
898 #endif
899 #ifndef S_IFDIR
900 # define S_IFDIR 0040000
901 #endif
902 #ifndef S_IFIFO
903 # define S_IFIFO 0010000
904 #endif
905 #ifndef S_IFREG
906 # define S_IFREG 0100000
907 #endif
908 #ifndef S_IFLNK
909 # define S_IFLNK 0120000
910 #endif
911 #ifndef S_IFSOCK
912 # define S_IFSOCK 0140000
913 #endif
914 #ifndef S_IFMT
915 # define S_IFMT  00170000
916 #endif
917 
918 #ifndef S_ISREG
919 # define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
920 #endif
921 #ifndef S_ISDIR
922 # define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
923 #endif
924 #ifndef S_ISLNK
925 # define S_ISLNK(m)      (((m) & S_IFMT) == S_IFLNK)
926 #endif
927 #ifndef S_ISFIFO
928 # define S_ISFIFO(m)     (((m) & S_IFMT) == S_IFIFO)
929 #endif
930 #ifndef S_ISCHR
931 # define S_ISCHR(m)      (((m) & S_IFMT) == S_IFCHR)
932 #endif
933 #ifndef S_ISBLK
934 # define S_ISBLK(m)      (((m) & S_IFMT) == S_IFBLK)
935 #endif
936 #ifndef S_ISSOCK
937 # define S_ISSOCK(m)     (((m) & S_IFMT) == S_IFSOCK)
938 #endif
939 
940 #ifndef S_IRUSR
941 # define S_IRWXU 00700
942 # define S_IRUSR 00400
943 # define S_IWUSR 00200
944 # define S_IXUSR 00100
945 #endif
946 
947 #ifndef S_IRGRP
948 # define S_IRWXG 00070
949 # define S_IRGRP 00040
950 # define S_IWGRP 00020
951 # define S_IXGRP 00010
952 #endif
953 
954 #ifndef S_IROTH
955 # define S_IRWXO 00007
956 # define S_IROTH 00004
957 # define S_IWOTH 00002
958 # define S_IXOTH 00001
959 #endif
960 
961 /* kill(2) on OS X returns ETIMEDOUT instead of ESRCH */
962 #ifndef ETIMEDOUT
963 # define ETIMEDOUT ESRCH
964 #endif
965 
966 /* For getnameinfo(). */
967 #ifndef  NI_MAXHOST
968 # define NI_MAXHOST 1025
969 #endif
970 
971 /********************************************************************/
972 /* *BSD chflags stuff -                                             */
973 /********************************************************************/
974 
975 #if !defined UF_NODUMP
976 # define UF_NODUMP 0
977 #endif
978 #if !defined UF_IMMUTABLE
979 # define UF_IMMUTABLE 0
980 #endif
981 #if !defined UF_APPEND
982 # define UF_APPEND 0
983 #endif
984 #if !defined UF_OPAQUE
985 # define UF_OPAQUE 0
986 #endif
987 #if !defined UF_NOUNLINK
988 # define UF_NOUNLINK 0
989 #endif
990 #if !defined SF_ARCHIVED
991 # define SF_ARCHIVED 0
992 #endif
993 #if !defined SF_IMMUTABLE
994 # define SF_IMMUTABLE 0
995 #endif
996 #if !defined SF_APPEND
997 # define SF_APPEND 0
998 #endif
999 #if !defined SF_NOUNLINK
1000 # define SF_NOUNLINK 0
1001 #endif
1002 #define CHFLAGS_MASK  ( UF_NODUMP | UF_IMMUTABLE | UF_APPEND | UF_OPAQUE | UF_NOUNLINK | SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND | SF_NOUNLINK )
1003 
1004 /* For cygwin32 */
1005 
1006 #if !defined O_BINARY
1007 # define O_BINARY 0
1008 #endif
1009 
1010 #if !defined O_TEXT
1011 # define O_TEXT 0
1012 #endif
1013 
1014 #if defined(__MINGW32__)
1015 /* _mkdir(3) */
1016 # include <direct.h>
1017 #endif
1018 
1019 
1020 /* Some shorthands. */
1021 
1022 # if defined(__sun) && !defined(sun)
1023 #  define sun
1024 # endif
1025 
1026 # if defined(__SVR4) && !defined(SVR4)
1027 #  define SVR4
1028 # endif
1029 
1030 # if (defined(sun) && defined(SVR4)) || defined (SOLARIS2)
1031 #  define SUNOS_5
1032 # endif
1033 
1034 #include <condition_macros.h>
1035 
1036 /* Must be always the last one! */
1037 #include <deprecated.h>
1038 #include <config.post.h>
1039 
1040 
1041 #endif  /* CFENGINE_PLATFORM_H */
1042