1 /* System dependent declarations.
2
3 Copyright (C) 1988-1989, 1992-1995, 1998, 2001-2002, 2004, 2006, 2009-2013,
4 2015-2023 Free Software Foundation, Inc.
5
6 This file is part of GNU DIFF.
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include <config.h>
22
23 /* Use this to suppress gcc's "...may be used before initialized" warnings. */
24 #ifdef GCC_LINT
25 # define IF_LINT(Code) Code
26 #else
27 # define IF_LINT(Code) /* empty */
28 #endif
29
30 #include <verify.h>
31
32 #include <sys/types.h>
33
34 #include <sys/stat.h>
35 #include <stat-macros.h>
36
37 #ifndef STAT_BLOCKSIZE
38 # if HAVE_STRUCT_STAT_ST_BLKSIZE
39 # define STAT_BLOCKSIZE(s) ((s).st_blksize)
40 # else
41 # define STAT_BLOCKSIZE(s) (8 * 1024)
42 # endif
43 #endif
44
45 #include <unistd.h>
46
47 #include <fcntl.h>
48 #include <time.h>
49
50 #include <sys/wait.h>
51
52 #include <dirent.h>
53 #ifndef _D_EXACT_NAMLEN
54 # define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name)
55 #endif
56
57 #include <stdlib.h>
58 #define EXIT_TROUBLE 2
59
60 #include <limits.h>
61 #include <locale.h>
62 #include <stddef.h>
63 #include <inttypes.h>
64
65 #include <string.h>
66 #if ! HAVE_STRCASECOLL
67 # if HAVE_STRICOLL || defined stricoll
68 # define strcasecoll(a, b) stricoll (a, b)
69 # else
70 # define strcasecoll(a, b) strcasecmp (a, b) /* best we can do */
71 # endif
72 #endif
73 #if ! (HAVE_STRCASECMP || defined strcasecmp)
74 int strcasecmp (char const *, char const *);
75 #endif
76
77 #include <gettext.h>
78 #if ! ENABLE_NLS
79 # undef textdomain
80 # define textdomain(Domainname) /* empty */
81 # undef bindtextdomain
82 # define bindtextdomain(Domainname, Dirname) /* empty */
83 #endif
84
85 #define _(msgid) gettext (msgid)
86 #define N_(msgid) msgid
87
88 #include <ctype.h>
89
90 /* ISDIGIT differs from isdigit, as follows:
91 - Its arg may be any int or unsigned int; it need not be an unsigned char.
92 - It's guaranteed to evaluate its argument exactly once.
93 - It's typically faster.
94 POSIX 1003.1-2001 says that only '0' through '9' are digits.
95 Prefer ISDIGIT to isdigit unless it's important to use the locale's
96 definition of 'digit' even when the host does not conform to POSIX. */
97 #define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
98
99 #include <errno.h>
100
101 #include <signal.h>
102 #if !defined SIGCHLD && defined SIGCLD
103 # define SIGCHLD SIGCLD
104 #endif
105
106 #undef MIN
107 #undef MAX
108 #define MIN(a, b) ((a) <= (b) ? (a) : (b))
109 #define MAX(a, b) ((a) >= (b) ? (a) : (b))
110
111 #include <attribute.h>
112 #include <intprops.h>
113 #include <propername.h>
114
115 #include "version.h"
116
117 /* Type used for fast comparison of several bytes at a time.
118 This used to be uintmax_t, but changing it to size_t
119 made plain 'cmp' 90% faster (GCC 4.8.1, x86). */
120
121 #ifndef word
122 # define word size_t
123 #endif
124
125 /* The signed integer type of a line number. Since files are read
126 into main memory, ptrdiff_t should be wide enough. pI is for
127 printing line numbers. */
128
129 typedef ptrdiff_t lin;
130 #define LIN_MAX PTRDIFF_MAX
131 #define pI "t"
132
133 /* Limit so that 2 * CONTEXT + 1 does not overflow. */
134
135 #define CONTEXT_MAX ((LIN_MAX - 1) / 2)
136
137
138 /* This section contains POSIX-compliant defaults for macros
139 that are meant to be overridden by hand in config.h as needed. */
140
141 #ifndef file_name_cmp
142 # define file_name_cmp strcmp
143 #endif
144
145 #ifndef initialize_main
146 # define initialize_main(argcp, argvp)
147 #endif
148
149 #ifndef NULL_DEVICE
150 # define NULL_DEVICE "/dev/null"
151 #endif
152
153 /* Do struct stat *S, *T describe the same special file? */
154 #ifndef same_special_file
155 # if HAVE_STRUCT_STAT_ST_RDEV && defined S_ISBLK && defined S_ISCHR
156 # define same_special_file(s, t) \
157 (((S_ISBLK ((s)->st_mode) && S_ISBLK ((t)->st_mode)) \
158 || (S_ISCHR ((s)->st_mode) && S_ISCHR ((t)->st_mode))) \
159 && (s)->st_rdev == (t)->st_rdev)
160 # else
161 # define same_special_file(s, t) 0
162 # endif
163 #endif
164
165 /* Do struct stat *S, *T describe the same file? Answer -1 if unknown. */
166 #ifndef same_file
167 # define same_file(s, t) \
168 ((((s)->st_ino == (t)->st_ino) && ((s)->st_dev == (t)->st_dev)) \
169 || same_special_file (s, t))
170 #endif
171
172 /* Do struct stat *S, *T have the same file attributes?
173
174 POSIX says that two files are identical if st_ino and st_dev are
175 the same, but many file systems incorrectly assign the same (device,
176 inode) pair to two distinct files, including:
177
178 - GNU/Linux NFS servers that export all local file systems as a
179 single NFS file system, if a local device number (st_dev) exceeds
180 255, or if a local inode number (st_ino) exceeds 16777215.
181
182 - Network Appliance NFS servers in snapshot directories; see
183 Network Appliance bug #195.
184
185 - ClearCase MVFS; see bug id ATRia04618.
186
187 Check whether two files that purport to be the same have the same
188 attributes, to work around instances of this common bug. Do not
189 inspect all attributes, only attributes useful in checking for this
190 bug.
191
192 It's possible for two distinct files on a buggy file system to have
193 the same attributes, but it's not worth slowing down all
194 implementations (or complicating the configuration) to cater to
195 these rare cases in buggy implementations. */
196
197 #ifndef same_file_attributes
198 # define same_file_attributes(s, t) \
199 ((s)->st_mode == (t)->st_mode \
200 && (s)->st_nlink == (t)->st_nlink \
201 && (s)->st_uid == (t)->st_uid \
202 && (s)->st_gid == (t)->st_gid \
203 && (s)->st_size == (t)->st_size \
204 && (s)->st_mtime == (t)->st_mtime \
205 && (s)->st_ctime == (t)->st_ctime)
206 #endif
207
208 #define STREQ(a, b) (strcmp (a, b) == 0)