summaryrefslogtreecommitdiff
path: root/libio/bug-fclose1.c
blob: f1e09f5d4764b8423fdb7ee17a4a878254c90585 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// BZ #12724

static void do_prepare (void);
#define PREPARE(argc, argv) do_prepare ()
static int do_test (void);
#define TEST_FUNCTION do_test()
#include "../test-skeleton.c"


static int fd;


static void
do_prepare (void)
{
  fd = create_temp_file ("bug-fclose1.", NULL);
  if (fd == -1)
    {
      printf ("cannot create temporary file: %m\n");
      exit (1);
    }
}


static int
do_test (void)
{
  static const char pattern[] = "hello world";

  /* Prepare a seekable file.  */
  if (write (fd, pattern, sizeof pattern) != sizeof pattern)
    {
      printf ("cannot write pattern: %m\n");
      return 1;
    }
  if (lseek (fd, 1, SEEK_SET) != 1)
    {
      printf ("cannot seek after write: %m\n");
      return 1;
    }

  /* Create an output stream visiting the file; when it is closed, all
     other file descriptors visiting the file must see the new file
     position.  */
  int fd2 = dup (fd);
  if (fd2 < 0)
    {
      printf ("cannot duplicate descriptor for writing: %m\n");
      return 1;
    }
  FILE *f = fdopen (fd2, "w");
  if (f == NULL)
    {
      printf ("first fdopen failed: %m\n");
      return 1;
    }
  if (fputc (pattern[1], f) != pattern[1])
    {
      printf ("fputc failed: %m\n");
      return 1;
    }
  if (fclose (f) != 0)
    {
      printf ("first fclose failed: %m\n");
      return 1;
    }
  errno = 0;
  if (lseek (fd2, 0, SEEK_CUR) != -1)
    {
      printf ("lseek after fclose after write did not fail\n");
      return 1;
    }
  if (errno != EBADF)
    {
      printf ("lseek after fclose after write did not fail with EBADF: %m\n");
      return 1;
    }
  off_t o = lseek (fd, 0, SEEK_CUR);
  if (o != 2)
    {
      printf ("\
lseek on original descriptor after first fclose returned %ld, expected 2\n",
	      (long int) o);
      return 1;
    }

  /* Likewise for an input stream.  */
  fd2 = dup (fd);
  if (fd2 < 0)
     {
      printf ("cannot duplicate descriptor for reading: %m\n");
      return 1;
    }
  f = fdopen (fd2, "r");
   if (f == NULL)
    {
      printf ("second fdopen failed: %m\n");
      return 1;
    }
   char c = fgetc (f);
   if (c != pattern[2])
     {
       printf ("getc returned %c, expected %c\n", c, pattern[2]);
       return 1;
     }
  if (fclose (f) != 0)
    {
      printf ("second fclose failed: %m\n");
      return 1;
    }
  errno = 0;
  if (lseek (fd2, 0, SEEK_CUR) != -1)
    {
      printf ("lseek after fclose after read did not fail\n");
      return 1;
    }
  if (errno != EBADF)
    {
      printf ("lseek after fclose after read did not fail with EBADF: %m\n");
      return 1;
    }
  o = lseek (fd, 0, SEEK_CUR);
  if (o != 3)
    {
      printf ("\
lseek on original descriptor after second fclose returned %ld, expected 3\n",
	      (long int) o);
      return 1;
    }

  return 0;
}