Home | History | Annotate | Download | only in mmap
      1 /*
      2  * Copyright (c) 2002, Intel Corporation. All rights reserved.
      3  * Copyright (c) 2012, Cyril Hrubis <chrubis (at) suse.cz>
      4  *
      5  * This file is licensed under the GPL license.  For the full content
      6  * of this license, see the COPYING file at the top level of this
      7  * source tree.
      8  *
      9  * Implementation performs mapping operations over whole pages.
     10  * Thus, while the argument len
     11  * need not meet a size or alignment constraint,
     12  * the implementation shall include, in any mapping
     13  * operation, any partial page specified by the range [pa,pa+len).
     14  * The system shall always zero-fill any partial page at the end of an object.
     15  * Further, the system shall never write out any modified portions of
     16  * the last page of an object which are beyond its end.
     17  *
     18  * Test Steps:
     19  * 1. Create a process, in this process:
     20  *    a. map a shared memory object with size of 1/2 * page_size,
     21  *       set len = 1/2 * page_size
     22  *    b. Read the partial page beyond the object size.
     23  *       Make sure the partial page is zero-filled;
     24  *    c. Modify a byte in the partial page, then un-map the and close the
     25  *       file descriptor.
     26  * 2. Wait for the child proces to exit, then read the file using read()
     27  *    and check that change wasn't written.
     28  */
     29 
     30 #define _XOPEN_SOURCE 600
     31 
     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 int main(void)
     45 {
     46 	char tmpfname[256];
     47 	long page_size;
     48 
     49 	char *pa, ch;
     50 	ssize_t len;
     51 	int fd;
     52 
     53 	pid_t child;
     54 	int i, exit_val, ret, size;
     55 
     56 	page_size = sysconf(_SC_PAGE_SIZE);
     57 
     58 	/* mmap will create a partial page */
     59 	len = page_size / 2;
     60 
     61 	snprintf(tmpfname, sizeof(tmpfname), "pts_mmap_11_5_%d", getpid());
     62 	child = fork();
     63 	switch (child) {
     64 	case 0:
     65 		/* Create shared object */
     66 		shm_unlink(tmpfname);
     67 		fd = shm_open(tmpfname, O_RDWR | O_CREAT | O_EXCL,
     68 			      S_IRUSR | S_IWUSR);
     69 		if (fd == -1) {
     70 			printf("Error at shm_open(): %s\n", strerror(errno));
     71 			return PTS_UNRESOLVED;
     72 		}
     73 		if (ftruncate(fd, len) == -1) {
     74 			printf("Error at ftruncate(): %s\n", strerror(errno));
     75 			return PTS_UNRESOLVED;
     76 		}
     77 
     78 		pa = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     79 		if (pa == MAP_FAILED) {
     80 			printf("Error at mmap(): %s\n", strerror(errno));
     81 			return PTS_FAIL;
     82 		}
     83 
     84 		/* Check the patial page is ZERO filled */
     85 		for (i = len; i < page_size; i++)
     86 			if (pa[i] != 0) {
     87 				printf("Test FAILED: The partial page at the "
     88 				       "end of an object is not zero-filled\n");
     89 				return PTS_FAIL;
     90 			}
     91 
     92 		/* Write the partial page */
     93 		pa[len + 1] = 'b';
     94 		munmap(pa, len);
     95 		close(fd);
     96 		return PTS_PASS;
     97 	case -1:
     98 		printf("Error at fork(): %s\n", strerror(errno));
     99 		return PTS_UNRESOLVED;
    100 	default:
    101 		break;
    102 	}
    103 
    104 	wait(&exit_val);
    105 	if (!(WIFEXITED(exit_val) && (WEXITSTATUS(exit_val) == PTS_PASS))) {
    106 		unlink(tmpfname);
    107 
    108 		if (WIFEXITED(exit_val))
    109 			return WEXITSTATUS(exit_val);
    110 
    111 		printf("Child exited abnormally\n");
    112 		return PTS_UNRESOLVED;
    113 	}
    114 
    115 	fd = shm_open(tmpfname, O_RDWR, 0);
    116 	shm_unlink(tmpfname);
    117 
    118 	size = 0;
    119 
    120 	while ((ret = read(fd, &ch, 1)) == 1) {
    121 
    122 		if (ch != 0) {
    123 			printf("File is not zeroed\n");
    124 			return PTS_FAIL;
    125 		}
    126 
    127 		size += ret;
    128 	}
    129 
    130 	if (ret == -1) {
    131 		printf("Error at read(): %s\n", strerror(errno));
    132 		return PTS_UNRESOLVED;
    133 	}
    134 
    135 	if (size != len) {
    136 		printf("File has wrong size\n");
    137 		return PTS_UNRESOLVED;
    138 	}
    139 
    140 	close(fd);
    141 
    142 	printf("Test PASSED\n");
    143 	return PTS_PASS;
    144 }
    145