summaryrefslogtreecommitdiffstats
path: root/tests/bugs/write-behind/bug-1279730.c
blob: 535d289c58278d3524483d4ad6ff175a38afd02e (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
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>

int
main (int argc, char *argv[])
{
        int          fd                = -1, ret = -1, len = 0;
        char        *path              = NULL, buf[128] = {0, }, *cmd = NULL;
        struct stat  stbuf             = {0, };
        int          write_to_child[2] = {0, }, write_to_parent[2] = {0, };

        path = argv[1];
        cmd = argv[2];

        assert (argc == 3);

        ret = pipe (write_to_child);
        if (ret < 0) {
                fprintf (stderr, "creation of write-to-child pipe failed "
                         "(%s)\n", strerror (errno));
                goto out;
        }

        ret = pipe (write_to_parent);
        if (ret < 0) {
                fprintf (stderr, "creation of write-to-parent pipe failed "
                         "(%s)\n", strerror (errno));
                goto out;
        }

        ret = fork ();
        switch (ret) {
        case 0:
                close (write_to_child[1]);
                close (write_to_parent[0]);

                /* child, wait for instructions to execute command */
                ret = read (write_to_child[0], buf, 128);
                if (ret < 0) {
                        fprintf (stderr, "child: read on pipe failed (%s)\n",
                                 strerror (errno));
                        goto out;
                }

                system (cmd);

                ret = write (write_to_parent[1], "1", 2);
                if (ret < 0) {
                        fprintf (stderr, "child: write to pipe failed (%s)\n",
                                 strerror (errno));
                        goto out;
                }
                break;

        case -1:
                fprintf (stderr, "fork failed (%s)\n", strerror (errno));
                goto out;

        default:
                close (write_to_parent[1]);
                close (write_to_child[0]);

                fd = open (path, O_CREAT | O_RDWR | O_APPEND, S_IRWXU);
                if (fd < 0) {
                        fprintf (stderr, "open failed (%s)\n",
                                 strerror (errno));
                        goto out;
                }

                len = strlen ("test-content") + 1;
                ret = write (fd, "test-content", len);

                if (ret < len) {
                        fprintf (stderr, "write failed %d (%s)\n", ret,
                                 strerror (errno));
                }

                ret = pread (fd, buf, 128, 0);
                if ((ret == len) && (strcmp (buf, "test-content") == 0)) {
                        fprintf (stderr, "read should've failed as previous "
                                 "write would've failed with EDQUOT, but its "
                                 "successful");
                        ret = -1;
                        goto out;
                }

                ret = write (write_to_child[1], "1", 2);
                if (ret < 0) {
                        fprintf (stderr, "parent: write to pipe failed (%s)\n",
                                 strerror (errno));
                        goto out;
                }

                ret = read (write_to_parent[0], buf, 128);
                if (ret < 0) {
                        fprintf (stderr, "parent: read from pipe failed (%s)\n",
                                 strerror (errno));
                        goto out;
                }

                /* this will force a sync on cached-write and now that quota
                   limit is increased, sync will be successful. ignore return
                   value as fstat would fail with EDQUOT (picked up from
                   cached-write because of previous sync failure.
                */
                fstat (fd, &stbuf);

                ret = pread (fd, buf, 128, 0);
                if (ret != len) {
                        fprintf (stderr, "post cmd read failed %d (data:%s) "
                                 "(error:%s)\n", ret, buf, strerror (errno));
                        goto out;
                }

                if (strcmp (buf, "test-content")) {
                        fprintf (stderr, "wrong data (%s)\n", buf);
                        goto out;
                }
        }

        ret = 0;

out:
        return ret;
}