1/*
2 * Copyright (c) 2002, Intel Corporation. All rights reserved.
3 * This file is licensed under the GPL license.  For the full content
4 * of this license, see the COPYING file at the top level of this
5 * source tree.
6 *
7 * Implementation performs mapping operations over whole pages.
8 * Thus, while the argument len
9 * need not meet a size or alignment constraint,
10 * the implementation shall include, in any mapping
11 * operation, any partial page specified by the range [pa,pa+len).
12 * The system shall always zero-fill any partial page at the end of an object.
13 * Further, the system shall never write out any modified portions of
14 * the last page of an object which are beyond its end.
15 *
16 * Test step:
17 * 1. Create a process, in this process:
18      a. map a shared memory object with size of 1/2 * page_size,
19 *       set len = 1/2 * page_size
20 *    b. Read the partial page beyond the object size.
21 *       Make sure the partial page is zero-filled;
22 *    c. Modify a byte in the partial page, then un-map the and close the
23 *       file descriptor.
24 * 2. Wait for the child proces to exit, then
25 *    Map the shared memory object again,
26 *    read the byte from the position modified at step 1-c and check.
27 */
28
29#define _XOPEN_SOURCE 600
30
31#include <pthread.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <sys/mman.h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <sys/wait.h>
39#include <fcntl.h>
40#include <string.h>
41#include <errno.h>
42#include "posixtest.h"
43
44#define TNAME "mmap/11-5.c"
45
46int main()
47{
48  char tmpfname[256];
49  long  page_size;
50  long total_size;
51
52  void *pa = NULL, *pa_2 = NULL;
53  void *addr = NULL;
54  size_t len;
55  int flag;
56  int fd, fd_2;
57  off_t off = 0;
58  int prot;
59
60  pid_t child;
61  char *ch = NULL, *ch_2 = NULL;
62  int exit_val;
63
64  page_size = sysconf(_SC_PAGE_SIZE);
65
66  /* Size of the file to be mapped */
67  total_size = page_size / 2;
68
69  /* mmap will create a partial page */
70  len = page_size / 2;
71
72  snprintf(tmpfname, sizeof(tmpfname), "pts_mmap_11_5_%ld",
73             (long)getpid());
74  child = fork();
75  if (child == 0)
76  {
77    /* Create shared object */
78    shm_unlink(tmpfname);
79    fd = shm_open(tmpfname, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
80    if(fd == -1)
81    {
82      printf(TNAME " Error at shm_open(): %s\n", strerror(errno));
83      return PTS_UNRESOLVED;
84    }
85    if(ftruncate(fd, total_size) == -1) {
86      printf(TNAME " Error at ftruncate(): %s\n", strerror(errno));
87      return PTS_UNRESOLVED;
88    }
89
90    prot = PROT_READ | PROT_WRITE;
91    flag = MAP_SHARED;
92    off = 0;
93    pa = mmap(addr, len, prot, flag, fd, off);
94    if (pa == MAP_FAILED)
95    {
96      printf("Test FAIL: " TNAME " Error at mmap(): %s\n",
97      	     strerror(errno));
98      return PTS_FAIL;
99    }
100    /* Check the patial page is ZERO filled */
101    ch = pa + len + 1;
102    if (*ch != 0)
103    {
104      printf("Test Fail: " TNAME " The partial page at the end of an object "
105              "is not zero-filled\n");
106      return PTS_FAIL;
107    }
108
109    /* Write the partial page */
110    *ch = 'b';
111    munmap (pa, len);
112    close (fd);
113    return PTS_PASS;
114  }
115  wait(&exit_val);
116  if (!(WIFEXITED(exit_val) &&
117	(WEXITSTATUS(exit_val) == PTS_PASS)))
118  {
119    shm_unlink(tmpfname);
120    return PTS_FAIL;
121  }
122
123  fd_2 = shm_open(tmpfname, O_RDWR, 0);
124  shm_unlink(tmpfname);
125
126  prot = PROT_READ | PROT_WRITE;
127  flag = MAP_SHARED;
128  off = 0;
129  pa_2 = mmap(addr, len, prot, flag, fd_2, off);
130  if (pa_2 == MAP_FAILED)
131  {
132    printf("Test FAIL: " TNAME " Error at 2nd mmap(): %s\n",
133            strerror(errno));
134    exit(PTS_FAIL);
135  }
136
137  ch_2 = pa_2 + len + 1;
138  if (*ch_2 == 'b')
139  {
140    	printf("Test Fail: " TNAME " Modification of the partial page "
141     	   "at the end of an object is written out\n");
142  	exit(PTS_FAIL);
143  }
144  close (fd_2);
145  munmap (pa_2, len);
146  printf("Test Passed\n");
147  return PTS_PASS;
148}
149