blob: 22c5d4ce5ad88a4bec39a3d875f5a10e48dc0664 [file] [log] [blame]
Caspar Zhang905095e2012-07-12 17:21:18 +08001/*
2 * Copyright (c) International Business Machines Corp., 2012
3 * Copyright (c) Linux Test Project, 2012
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Caspar Zhang905095e2012-07-12 17:21:18 +080018 */
19
20#define _GNU_SOURCE
21#include <sys/types.h>
22#include <sys/uio.h>
23#include <sys/wait.h>
24#include <errno.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29
30#include "test.h"
31#include "usctest.h"
32#include "safe_macros.h"
33#include "process_vm.h"
34
35char *TCID = "process_vm_readv02";
36int TST_TOTAL = 1;
37
38static char *tst_string = "THIS IS A TEST";
39static int len;
40static int pipe_fd[2];
41static pid_t pids[2];
42static int semid;
43
44static void child_alloc(void);
45static void child_invoke(void);
46static void setup(void);
47static void cleanup(void);
48
49int main(int argc, char **argv)
50{
51 int lc, status;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020052 const char *msg;
Caspar Zhang905095e2012-07-12 17:21:18 +080053
54 msg = parse_opts(argc, argv, NULL, NULL);
55 if (msg != NULL)
56 tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
57
58 setup();
59 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +080060 tst_count = 0;
Caspar Zhang905095e2012-07-12 17:21:18 +080061 len = strlen(tst_string);
62
63 if (pipe(pipe_fd) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +080064 tst_brkm(TBROK | TERRNO, cleanup, "pipe");
Caspar Zhang905095e2012-07-12 17:21:18 +080065
66 /* the start of child_alloc and child_invoke is already
67 * synchronized via pipe */
68 pids[0] = fork();
69 switch (pids[0]) {
70 case -1:
Wanlong Gao354ebb42012-12-07 10:10:04 +080071 tst_brkm(TBROK | TERRNO, cleanup, "fork #0");
Caspar Zhang905095e2012-07-12 17:21:18 +080072 case 0:
73 child_alloc();
74 exit(0);
75 }
76
77 pids[1] = fork();
78 switch (pids[1]) {
79 case -1:
Wanlong Gao354ebb42012-12-07 10:10:04 +080080 tst_brkm(TBROK | TERRNO, cleanup, "fork #1");
Caspar Zhang905095e2012-07-12 17:21:18 +080081 case 0:
82 child_invoke();
83 exit(0);
84 }
85
86 /* wait until child_invoke reads from child_alloc's VM */
87 if (waitpid(pids[1], &status, 0) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +080088 tst_brkm(TBROK | TERRNO, cleanup, "waitpid");
Caspar Zhang905095e2012-07-12 17:21:18 +080089 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
90 tst_resm(TFAIL, "child 1 returns %d", status);
91
92 /* child_alloc is free to exit now */
93 safe_semop(semid, 0, 1);
94
95 if (waitpid(pids[0], &status, 0) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +080096 tst_brkm(TBROK | TERRNO, cleanup, "waitpid");
Caspar Zhang905095e2012-07-12 17:21:18 +080097 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
98 tst_resm(TFAIL, "child 0 returns %d", status);
99 }
100
101 cleanup();
102 tst_exit();
103}
104
105static void child_alloc(void)
106{
107 char *foo;
108 char buf[BUFSIZ];
109
110 foo = SAFE_MALLOC(tst_exit, len + 1);
111 strncpy(foo, tst_string, len);
112 foo[len] = '\0';
113 tst_resm(TINFO, "child 0: memory allocated and initialized.");
114
115 /* passing addr of string "foo" via pipe */
116 SAFE_CLOSE(tst_exit, pipe_fd[0]);
117 snprintf(buf, BUFSIZ, "%p", foo);
118 SAFE_WRITE(tst_exit, 1, pipe_fd[1], buf, strlen(buf));
119 SAFE_CLOSE(tst_exit, pipe_fd[1]);
120
121 /* wait until child_invoke is done reading from our VM */
122 safe_semop(semid, 0, -1);
123}
124
125static void child_invoke(void)
126{
127 char *lp, *rp;
128 char buf[BUFSIZ];
129 struct iovec local, remote;
130
131 /* get addr from pipe */
132 SAFE_CLOSE(tst_exit, pipe_fd[1]);
133 SAFE_READ(tst_exit, 0, pipe_fd[0], buf, BUFSIZ);
134 SAFE_CLOSE(tst_exit, pipe_fd[0]);
135 if (sscanf(buf, "%p", &rp) != 1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800136 tst_brkm(TBROK | TERRNO, tst_exit, "sscanf");
Caspar Zhang905095e2012-07-12 17:21:18 +0800137
138 lp = SAFE_MALLOC(tst_exit, len + 1);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800139 local.iov_base = lp;
140 local.iov_len = len;
Caspar Zhang905095e2012-07-12 17:21:18 +0800141 remote.iov_base = rp;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800142 remote.iov_len = len;
Caspar Zhang905095e2012-07-12 17:21:18 +0800143
144 tst_resm(TINFO, "child 1: reading string from same memory location.");
145 TEST(test_process_vm_readv(pids[0], &local, 1, &remote, 1, 0));
146 if (TEST_RETURN != len)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800147 tst_brkm(TFAIL | TERRNO, tst_exit, "process_vm_readv");
Caspar Zhang905095e2012-07-12 17:21:18 +0800148 if (strncmp(lp, tst_string, len) != 0)
149 tst_brkm(TFAIL, tst_exit, "child 1: expected string: %s, "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800150 "received string: %256s", tst_string, lp);
Caspar Zhang905095e2012-07-12 17:21:18 +0800151 else
152 tst_resm(TPASS, "expected string received.");
153}
154
155static void setup(void)
156{
157 tst_require_root(NULL);
158
159#if !defined(__NR_process_vm_readv)
160 tst_brkm(TCONF, NULL, "process_vm_readv does not exist "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800161 "on your system");
Caspar Zhang905095e2012-07-12 17:21:18 +0800162#endif
163 semid = init_sem(1);
164
165 TEST_PAUSE;
166}
167
168static void cleanup(void)
169{
170 clean_sem(semid);
Caspar Zhang905095e2012-07-12 17:21:18 +0800171}