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 file  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 file 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-4.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), "/tmp/pts_mmap_11_5_%ld",
73             (long)getpid());
74  child = fork();
75  if (child == 0)
76  {
77    /* Create shared object */
78    unlink(tmpfname);
79    fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL,
80              S_IRUSR | S_IWUSR);
81    if (fd == -1)
82    {
83      printf(TNAME " Error at open(): %s\n",
84             strerror(errno));
85      exit(PTS_UNRESOLVED);
86    }
87    if(ftruncate(fd, total_size) == -1) {
88      printf(TNAME " Error at ftruncate(): %s\n", strerror(errno));
89      return PTS_UNRESOLVED;
90    }
91
92    prot = PROT_READ | PROT_WRITE;
93    flag = MAP_SHARED;
94    off = 0;
95    pa = mmap(addr, len, prot, flag, fd, off);
96    if (pa == MAP_FAILED)
97    {
98      printf("Test FAIL: " TNAME " Error at mmap(): %s\n",
99      	     strerror(errno));
100      return PTS_FAIL;
101    }
102    printf("pa: %p\n", pa);
103    /* Check the patial page is ZERO filled */
104    ch = pa + len + 1;
105    if (*ch != 0)
106    {
107      printf("Test Fail: " TNAME " The partial page at the end of an object "
108              "is not zero-filled\n");
109      return PTS_FAIL;
110    }
111
112    /* Write the partial page */
113    *ch = 'b';
114    munmap (pa, len);
115    close (fd);
116    return PTS_PASS;
117  }
118  wait(&exit_val);
119  if (!(WIFEXITED(exit_val) &&
120	(WEXITSTATUS(exit_val) == PTS_PASS)))
121  {
122    unlink(tmpfname);
123    return PTS_FAIL;
124  }
125
126  fd_2 = open(tmpfname, O_RDWR, 0);
127  unlink(tmpfname);
128
129  prot = PROT_READ | PROT_WRITE;
130  flag = MAP_SHARED;
131  off = 0;
132  pa = mmap(addr, len, prot, flag, fd_2, off);
133  pa_2 = mmap(addr, len, prot, flag, fd_2, off);
134  if (pa_2 == MAP_FAILED)
135  {
136    printf("Test FAIL: " TNAME " Error at 2nd mmap(): %s\n",
137            strerror(errno));
138    exit(PTS_FAIL);
139  }
140
141  printf("pa_2: %p\n", pa_2);
142  ch_2 = pa_2 + len + 1;
143  if (*ch_2 == 'b')
144  {
145    	printf("Test Fail: " TNAME " Modification of the partial page "
146     	   "at the end of an object is written out\n");
147  	exit(PTS_FAIL);
148  }
149  close (fd_2);
150  munmap (pa_2, len);
151  printf("Test Passed\n");
152  return PTS_PASS;
153}
154