~ubuntu-branches/ubuntu/natty/diffutils/natty

« back to all changes in this revision

Viewing changes to gnulib-tests/test-fcntl.c

  • Committer: Bazaar Package Importer
  • Author(s): Santiago Vila
  • Date: 2010-05-04 20:38:00 UTC
  • mfrom: (2.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100504203800-f67xd9rsa9xl9qqj
Tags: 1:3.0-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- buffer-read-only: t -*- vi: set ro: */
 
2
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
 
3
/* Test of fcntl(2).
 
4
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
 
5
 
 
6
   This program is free software: you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 3 of the License, or
 
9
   (at your option) any later version.
 
10
 
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
18
 
 
19
/* Written by Eric Blake <ebb9@byu.net>, 2009.  */
 
20
 
 
21
#include <config.h>
 
22
 
 
23
/* Specification.  */
 
24
#include <fcntl.h>
 
25
 
 
26
#include "signature.h"
 
27
SIGNATURE_CHECK (fcntl, int, (int, int, ...));
 
28
 
 
29
/* Helpers.  */
 
30
#include <errno.h>
 
31
#include <stdarg.h>
 
32
#include <stdbool.h>
 
33
#include <unistd.h>
 
34
 
 
35
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
 
36
/* Get declarations of the Win32 API functions.  */
 
37
# define WIN32_LEAN_AND_MEAN
 
38
# include <windows.h>
 
39
#endif
 
40
 
 
41
#include "binary-io.h"
 
42
#include "macros.h"
 
43
 
 
44
/* Use O_CLOEXEC if available, but test works without it.  */
 
45
#ifndef O_CLOEXEC
 
46
# define O_CLOEXEC 0
 
47
#endif
 
48
 
 
49
#if !O_BINARY
 
50
# define setmode(f,m) zero ()
 
51
static int zero (void) { return 0; }
 
52
#endif
 
53
 
 
54
/* Return true if FD is open.  */
 
55
static bool
 
56
is_open (int fd)
 
57
{
 
58
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
 
59
  /* On Win32, the initial state of unassigned standard file
 
60
     descriptors is that they are open but point to an
 
61
     INVALID_HANDLE_VALUE, and there is no fcntl.  */
 
62
  return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
 
63
#else
 
64
# ifndef F_GETFL
 
65
#  error Please port fcntl to your platform
 
66
# endif
 
67
  return 0 <= fcntl (fd, F_GETFL);
 
68
#endif
 
69
}
 
70
 
 
71
/* Return true if FD is open and inheritable across exec/spawn.  */
 
72
static bool
 
73
is_inheritable (int fd)
 
74
{
 
75
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
 
76
  /* On Win32, the initial state of unassigned standard file
 
77
     descriptors is that they are open but point to an
 
78
     INVALID_HANDLE_VALUE, and there is no fcntl.  */
 
79
  HANDLE h = (HANDLE) _get_osfhandle (fd);
 
80
  DWORD flags;
 
81
  if (h == INVALID_HANDLE_VALUE || GetHandleInformation (h, &flags) == 0)
 
82
    return false;
 
83
  return (flags & HANDLE_FLAG_INHERIT) != 0;
 
84
#else
 
85
# ifndef F_GETFD
 
86
#  error Please port fcntl to your platform
 
87
# endif
 
88
  int i = fcntl (fd, F_GETFD);
 
89
  return 0 <= i && (i & FD_CLOEXEC) == 0;
 
90
#endif
 
91
}
 
92
 
 
93
/* Return non-zero if FD is open in the given MODE, which is either
 
94
   O_TEXT or O_BINARY.  */
 
95
static bool
 
96
is_mode (int fd, int mode)
 
97
{
 
98
  int value = setmode (fd, O_BINARY);
 
99
  setmode (fd, value);
 
100
  return mode == value;
 
101
}
 
102
 
 
103
/* Since native fcntl can have more supported operations than our
 
104
   replacement is aware of, and since various operations assign
 
105
   different types to the vararg argument, a wrapper around fcntl must
 
106
   be able to pass a vararg of unknown type on through to the original
 
107
   fcntl.  Make sure that this works properly: func1 behaves like the
 
108
   original fcntl interpreting the vararg as an int or a pointer to a
 
109
   struct, and func2 behaves like rpl_fcntl that doesn't know what
 
110
   type to forward.  */
 
111
struct dummy_struct
 
112
{
 
113
  long filler;
 
114
  int value;
 
115
};
 
116
static int
 
117
func1 (int a, ...)
 
118
{
 
119
  va_list arg;
 
120
  int i;
 
121
  va_start (arg, a);
 
122
  if (a < 4)
 
123
    i = va_arg (arg, int);
 
124
  else
 
125
    {
 
126
      struct dummy_struct *s = va_arg (arg, struct dummy_struct *);
 
127
      i = s->value;
 
128
    }
 
129
  va_end (arg);
 
130
  return i;
 
131
}
 
132
static int
 
133
func2 (int a, ...)
 
134
{
 
135
  va_list arg;
 
136
  void *p;
 
137
  va_start (arg, a);
 
138
  p = va_arg (arg, void *);
 
139
  va_end (arg);
 
140
  return func1 (a, p);
 
141
}
 
142
 
 
143
/* Ensure that all supported fcntl actions are distinct, and
 
144
   usable in preprocessor expressions.  */
 
145
static void
 
146
check_flags (void)
 
147
{
 
148
  switch (0)
 
149
    {
 
150
    case F_DUPFD:
 
151
#if F_DUPFD
 
152
#endif
 
153
 
 
154
    case F_DUPFD_CLOEXEC:
 
155
#if F_DUPFD_CLOEXEC
 
156
#endif
 
157
 
 
158
    case F_GETFD:
 
159
#if F_GETFD
 
160
#endif
 
161
 
 
162
#ifdef F_SETFD
 
163
    case F_SETFD:
 
164
# if F_SETFD
 
165
# endif
 
166
#endif
 
167
 
 
168
#ifdef F_GETFL
 
169
    case F_GETFL:
 
170
# if F_GETFL
 
171
# endif
 
172
#endif
 
173
 
 
174
#ifdef F_SETFL
 
175
    case F_SETFL:
 
176
# if F_SETFL
 
177
# endif
 
178
#endif
 
179
 
 
180
#ifdef F_GETOWN
 
181
    case F_GETOWN:
 
182
# if F_GETOWN
 
183
# endif
 
184
#endif
 
185
 
 
186
#ifdef F_SETOWN
 
187
    case F_SETOWN:
 
188
# if F_SETOWN
 
189
# endif
 
190
#endif
 
191
 
 
192
#ifdef F_GETLK
 
193
    case F_GETLK:
 
194
# if F_GETLK
 
195
# endif
 
196
#endif
 
197
 
 
198
#ifdef F_SETLK
 
199
    case F_SETLK:
 
200
# if F_SETLK
 
201
# endif
 
202
#endif
 
203
 
 
204
#ifdef F_SETLKW
 
205
    case F_SETLKW:
 
206
# if F_SETLKW
 
207
# endif
 
208
#endif
 
209
 
 
210
      ;
 
211
    }
 
212
}
 
213
 
 
214
int
 
215
main (void)
 
216
{
 
217
  const char *file = "test-fcntl.tmp";
 
218
  int fd;
 
219
 
 
220
  /* Sanity check that rpl_fcntl is likely to work.  */
 
221
  ASSERT (func2 (1, 2) == 2);
 
222
  ASSERT (func2 (2, -2) == -2);
 
223
  ASSERT (func2 (3, 0x80000000) == 0x80000000);
 
224
  {
 
225
    struct dummy_struct s = { 0L, 4 };
 
226
    ASSERT (func2 (4, &s) == 4);
 
227
  }
 
228
  check_flags ();
 
229
 
 
230
  /* Assume std descriptors were provided by invoker, and ignore fds
 
231
     that might have been inherited.  */
 
232
  fd = creat (file, 0600);
 
233
  ASSERT (STDERR_FILENO < fd);
 
234
  close (fd + 1);
 
235
  close (fd + 2);
 
236
 
 
237
  /* For F_DUPFD*, the source must be valid.  */
 
238
  errno = 0;
 
239
  ASSERT (fcntl (-1, F_DUPFD, 0) == -1);
 
240
  ASSERT (errno == EBADF);
 
241
  errno = 0;
 
242
  ASSERT (fcntl (fd + 1, F_DUPFD, 0) == -1);
 
243
  ASSERT (errno == EBADF);
 
244
  errno = 0;
 
245
  ASSERT (fcntl (10000000, F_DUPFD, 0) == -1);
 
246
  ASSERT (errno == EBADF);
 
247
  errno = 0;
 
248
  ASSERT (fcntl (-1, F_DUPFD_CLOEXEC, 0) == -1);
 
249
  ASSERT (errno == EBADF);
 
250
  errno = 0;
 
251
  ASSERT (fcntl (fd + 1, F_DUPFD_CLOEXEC, 0) == -1);
 
252
  ASSERT (errno == EBADF);
 
253
  errno = 0;
 
254
  ASSERT (fcntl (10000000, F_DUPFD_CLOEXEC, 0) == -1);
 
255
  ASSERT (errno == EBADF);
 
256
 
 
257
  /* For F_DUPFD*, the destination must be valid.  */
 
258
  ASSERT (getdtablesize () < 10000000);
 
259
  errno = 0;
 
260
  ASSERT (fcntl (fd, F_DUPFD, -1) == -1);
 
261
  ASSERT (errno == EINVAL);
 
262
  errno = 0;
 
263
  ASSERT (fcntl (fd, F_DUPFD, 10000000) == -1);
 
264
  ASSERT (errno == EINVAL);
 
265
  ASSERT (getdtablesize () < 10000000);
 
266
  errno = 0;
 
267
  ASSERT (fcntl (fd, F_DUPFD_CLOEXEC, -1) == -1);
 
268
  ASSERT (errno == EINVAL);
 
269
  errno = 0;
 
270
  ASSERT (fcntl (fd, F_DUPFD_CLOEXEC, 10000000) == -1);
 
271
  ASSERT (errno == EINVAL);
 
272
 
 
273
  /* For F_DUPFD*, check for correct inheritance, as well as
 
274
     preservation of text vs. binary.  */
 
275
  setmode (fd, O_BINARY);
 
276
  ASSERT (is_open (fd));
 
277
  ASSERT (!is_open (fd + 1));
 
278
  ASSERT (!is_open (fd + 2));
 
279
  ASSERT (is_inheritable (fd));
 
280
  ASSERT (is_mode (fd, O_BINARY));
 
281
 
 
282
  ASSERT (fcntl (fd, F_DUPFD, fd) == fd + 1);
 
283
  ASSERT (is_open (fd));
 
284
  ASSERT (is_open (fd + 1));
 
285
  ASSERT (!is_open (fd + 2));
 
286
  ASSERT (is_inheritable (fd + 1));
 
287
  ASSERT (is_mode (fd, O_BINARY));
 
288
  ASSERT (is_mode (fd + 1, O_BINARY));
 
289
  ASSERT (close (fd + 1) == 0);
 
290
 
 
291
  ASSERT (fcntl (fd, F_DUPFD_CLOEXEC, fd + 2) == fd + 2);
 
292
  ASSERT (is_open (fd));
 
293
  ASSERT (!is_open (fd + 1));
 
294
  ASSERT (is_open (fd + 2));
 
295
  ASSERT (is_inheritable (fd));
 
296
  ASSERT (!is_inheritable (fd + 2));
 
297
  ASSERT (is_mode (fd, O_BINARY));
 
298
  ASSERT (is_mode (fd + 2, O_BINARY));
 
299
  ASSERT (close (fd) == 0);
 
300
 
 
301
  setmode (fd + 2, O_TEXT);
 
302
  ASSERT (fcntl (fd + 2, F_DUPFD, fd + 1) == fd + 1);
 
303
  ASSERT (!is_open (fd));
 
304
  ASSERT (is_open (fd + 1));
 
305
  ASSERT (is_open (fd + 2));
 
306
  ASSERT (is_inheritable (fd + 1));
 
307
  ASSERT (!is_inheritable (fd + 2));
 
308
  ASSERT (is_mode (fd + 1, O_TEXT));
 
309
  ASSERT (is_mode (fd + 2, O_TEXT));
 
310
  ASSERT (close (fd + 1) == 0);
 
311
 
 
312
  ASSERT (fcntl (fd + 2, F_DUPFD_CLOEXEC, 0) == fd);
 
313
  ASSERT (is_open (fd));
 
314
  ASSERT (!is_open (fd + 1));
 
315
  ASSERT (is_open (fd + 2));
 
316
  ASSERT (!is_inheritable (fd));
 
317
  ASSERT (!is_inheritable (fd + 2));
 
318
  ASSERT (is_mode (fd, O_TEXT));
 
319
  ASSERT (is_mode (fd + 2, O_TEXT));
 
320
  ASSERT (close (fd + 2) == 0);
 
321
 
 
322
  /* Test F_GETFD.  */
 
323
  errno = 0;
 
324
  ASSERT (fcntl (-1, F_GETFD) == -1);
 
325
  ASSERT (errno == EBADF);
 
326
  errno = 0;
 
327
  ASSERT (fcntl (fd + 1, F_GETFD) == -1);
 
328
  ASSERT (errno == EBADF);
 
329
  errno = 0;
 
330
  ASSERT (fcntl (10000000, F_GETFD) == -1);
 
331
  ASSERT (errno == EBADF);
 
332
  {
 
333
    int result = fcntl (fd, F_GETFD);
 
334
    ASSERT (0 <= result);
 
335
    ASSERT ((result & FD_CLOEXEC) == FD_CLOEXEC);
 
336
    ASSERT (dup (fd) == fd + 1);
 
337
    result = fcntl (fd + 1, F_GETFD);
 
338
    ASSERT (0 <= result);
 
339
    ASSERT ((result & FD_CLOEXEC) == 0);
 
340
    ASSERT (close (fd + 1) == 0);
 
341
  }
 
342
 
 
343
  /* Cleanup.  */
 
344
  ASSERT (close (fd) == 0);
 
345
  ASSERT (unlink (file) == 0);
 
346
 
 
347
  return 0;
 
348
}