~ubuntu-branches/ubuntu/utopic/gettext/utopic

« back to all changes in this revision

Viewing changes to gettext-tools/gnulib-tests/test-dup-safer.c

  • Committer: Colin Watson
  • Date: 2010-08-01 21:36:08 UTC
  • mfrom: (2.1.10 sid)
  • Revision ID: cjwatson@canonical.com-20100801213608-yy7vkm8lpatep3ci
merge from Debian 0.18.1.1-1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Test that dup_safer leaves standard fds alone.
 
2
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
 
3
 
 
4
   This program is free software: you can redistribute it and/or modify
 
5
   it under the terms of the GNU General Public License as published by
 
6
   the Free Software Foundation; either version 3 of the License, or
 
7
   (at your option) any later version.
 
8
 
 
9
   This program is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
   GNU General Public License for more details.
 
13
 
 
14
   You should have received a copy of the GNU General Public License
 
15
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
16
 
 
17
/* Written by Eric Blake <ebb9@byu.net>, 2009.  */
 
18
 
 
19
#include <config.h>
 
20
 
 
21
#include "unistd--.h"
 
22
 
 
23
#include <fcntl.h>
 
24
#include <errno.h>
 
25
#include <stdbool.h>
 
26
#include <stdio.h>
 
27
 
 
28
#include "binary-io.h"
 
29
#include "cloexec.h"
 
30
 
 
31
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
 
32
/* Get declarations of the Win32 API functions.  */
 
33
# define WIN32_LEAN_AND_MEAN
 
34
# include <windows.h>
 
35
#endif
 
36
 
 
37
#if !O_BINARY
 
38
# define setmode(f,m) zero ()
 
39
static int zero (void) { return 0; }
 
40
#endif
 
41
#ifndef O_CLOEXEC
 
42
# define O_CLOEXEC 0
 
43
#endif
 
44
 
 
45
/* This test intentionally closes stderr.  So, we arrange to have fd 10
 
46
   (outside the range of interesting fd's during the test) set up to
 
47
   duplicate the original stderr.  */
 
48
 
 
49
#define BACKUP_STDERR_FILENO 10
 
50
#define ASSERT_STREAM myerr
 
51
#include "macros.h"
 
52
 
 
53
static FILE *myerr;
 
54
 
 
55
/* Return true if FD is open.  */
 
56
static bool
 
57
is_open (int fd)
 
58
{
 
59
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
 
60
  /* On Win32, the initial state of unassigned standard file
 
61
     descriptors is that they are open but point to an
 
62
     INVALID_HANDLE_VALUE, and there is no fcntl.  */
 
63
  return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
 
64
#else
 
65
# ifndef F_GETFL
 
66
#  error Please port fcntl to your platform
 
67
# endif
 
68
  return 0 <= fcntl (fd, F_GETFL);
 
69
#endif
 
70
}
 
71
 
 
72
/* Return true if FD is open and inheritable across exec/spawn.  */
 
73
static bool
 
74
is_inheritable (int fd)
 
75
{
 
76
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
 
77
  /* On Win32, the initial state of unassigned standard file
 
78
     descriptors is that they are open but point to an
 
79
     INVALID_HANDLE_VALUE, and there is no fcntl.  */
 
80
  HANDLE h = (HANDLE) _get_osfhandle (fd);
 
81
  DWORD flags;
 
82
  if (h == INVALID_HANDLE_VALUE || GetHandleInformation (h, &flags) == 0)
 
83
    return 0;
 
84
  return (flags & HANDLE_FLAG_INHERIT) != 0;
 
85
#else
 
86
# ifndef F_GETFD
 
87
#  error Please port fcntl to your platform
 
88
# endif
 
89
  int i = fcntl (fd, F_GETFD);
 
90
  return 0 <= i && (i & FD_CLOEXEC) == 0;
 
91
#endif
 
92
}
 
93
 
 
94
/* Return true if FD is open in the given MODE, which is either
 
95
   O_TEXT or O_BINARY.  */
 
96
static bool
 
97
is_mode (int fd, int mode)
 
98
{
 
99
  int value = setmode (fd, O_BINARY);
 
100
  setmode (fd, value);
 
101
  return mode == value;
 
102
}
 
103
 
 
104
#define witness "test-dup-safer.txt"
 
105
 
 
106
int
 
107
main (void)
 
108
{
 
109
  int i;
 
110
  int fd;
 
111
 
 
112
  /* We close fd 2 later, so save it in fd 10.  */
 
113
  if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO
 
114
      || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL)
 
115
    return 2;
 
116
 
 
117
  /* Create file for later checks.  */
 
118
  fd = creat (witness, 0600);
 
119
  ASSERT (STDERR_FILENO < fd);
 
120
 
 
121
  /* Four iterations, with progressively more standard descriptors
 
122
     closed.  */
 
123
  for (i = -1; i <= STDERR_FILENO; i++)
 
124
    {
 
125
      if (0 <= i)
 
126
        ASSERT (close (i) == 0);
 
127
 
 
128
      /* Detect errors.  */
 
129
      errno = 0;
 
130
      ASSERT (dup (-1) == -1);
 
131
      ASSERT (errno == EBADF);
 
132
      errno = 0;
 
133
      ASSERT (dup (10000000) == -1);
 
134
      ASSERT (errno == EBADF);
 
135
      close (fd + 1);
 
136
      errno = 0;
 
137
      ASSERT (dup (fd + 1) == -1);
 
138
      ASSERT (errno == EBADF);
 
139
 
 
140
      /* Preserve text vs. binary.  */
 
141
      setmode (fd, O_BINARY);
 
142
      ASSERT (dup (fd) == fd + 1);
 
143
      ASSERT (is_open (fd + 1));
 
144
      ASSERT (is_inheritable (fd + 1));
 
145
      ASSERT (is_mode (fd + 1, O_BINARY));
 
146
 
 
147
      ASSERT (close (fd + 1) == 0);
 
148
      setmode (fd, O_TEXT);
 
149
      ASSERT (dup (fd) == fd + 1);
 
150
      ASSERT (is_open (fd + 1));
 
151
      ASSERT (is_inheritable (fd + 1));
 
152
      ASSERT (is_mode (fd + 1, O_TEXT));
 
153
 
 
154
      /* Create cloexec copy.  */
 
155
      ASSERT (close (fd + 1) == 0);
 
156
      ASSERT (fd_safer_flag (dup_cloexec (fd), O_CLOEXEC) == fd + 1);
 
157
      ASSERT (set_cloexec_flag (fd + 1, true) == 0);
 
158
      ASSERT (is_open (fd + 1));
 
159
      ASSERT (!is_inheritable (fd + 1));
 
160
      ASSERT (close (fd) == 0);
 
161
 
 
162
      /* dup always creates inheritable copies.  Also, check that
 
163
         earliest slot past std fds is used.  */
 
164
      ASSERT (dup (fd + 1) == fd);
 
165
      ASSERT (is_open (fd));
 
166
      ASSERT (is_inheritable (fd));
 
167
      ASSERT (close (fd + 1) == 0);
 
168
    }
 
169
 
 
170
  /* Cleanup.  */
 
171
  ASSERT (close (fd) == 0);
 
172
  ASSERT (unlink (witness) == 0);
 
173
 
 
174
  return 0;
 
175
}