12c28215423293e443469a07ae7011135d058b671Garrett Cooper/*
20dc076565f772bb1953209fb69ea150b494aaa40robbiew * Copyright (c) 2002, Intel Corporation. All rights reserved.
344de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis * Copyright (c) 2012, Cyril Hrubis <chrubis@suse.cz>
444de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis *
50dc076565f772bb1953209fb69ea150b494aaa40robbiew * This file is licensed under the GPL license.  For the full content
62c28215423293e443469a07ae7011135d058b671Garrett Cooper * of this license, see the COPYING file at the top level of this
70dc076565f772bb1953209fb69ea150b494aaa40robbiew * source tree.
80dc076565f772bb1953209fb69ea150b494aaa40robbiew *
92c28215423293e443469a07ae7011135d058b671Garrett Cooper * The off argument is constrained to be aligned and sized
100dc076565f772bb1953209fb69ea150b494aaa40robbiew * according to the value returned by
112c28215423293e443469a07ae7011135d058b671Garrett Cooper * sysconf() when passed _SC_PAGESIZE or _SC_PAGE_SIZE.
122c28215423293e443469a07ae7011135d058b671Garrett Cooper *
1343c1224558e7ea2df04e16ba6b88b4945c750dfaCyril Hrubis * The mmap() function shall fail if: [EINVAL] The addr argument (if MAP_FIXED
1443c1224558e7ea2df04e16ba6b88b4945c750dfaCyril Hrubis * was specified) or off is not a multiple of the page size as returned by
1543c1224558e7ea2df04e16ba6b88b4945c750dfaCyril Hrubis * sysconf(), or is considered invalid by the implementation.
160dc076565f772bb1953209fb69ea150b494aaa40robbiew *
1743c1224558e7ea2df04e16ba6b88b4945c750dfaCyril Hrubis * Test Steps:
180dc076565f772bb1953209fb69ea150b494aaa40robbiew * 1. Set 'off' a value which is not a multiple of page size;
190dc076565f772bb1953209fb69ea150b494aaa40robbiew * 2. Call mmap() and get EINVAL;
200dc076565f772bb1953209fb69ea150b494aaa40robbiew *
210dc076565f772bb1953209fb69ea150b494aaa40robbiew */
220dc076565f772bb1953209fb69ea150b494aaa40robbiew
230dc076565f772bb1953209fb69ea150b494aaa40robbiew#define _XOPEN_SOURCE 600
240dc076565f772bb1953209fb69ea150b494aaa40robbiew
250dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <stdio.h>
260dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <stdlib.h>
270dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <unistd.h>
280dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <sys/mman.h>
290dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <sys/types.h>
300dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <sys/stat.h>
310dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <sys/wait.h>
320dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <fcntl.h>
330dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <string.h>
340dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <errno.h>
350dc076565f772bb1953209fb69ea150b494aaa40robbiew#include "posixtest.h"
362c28215423293e443469a07ae7011135d058b671Garrett Cooper
3744de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubisint main(void)
380dc076565f772bb1953209fb69ea150b494aaa40robbiew{
3944de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	char tmpfname[256];
4044de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	long page_size;
4144de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	long total_size;
420dc076565f772bb1953209fb69ea150b494aaa40robbiew
4344de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	void *pa;
4444de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	size_t size;
4544de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	int fd, saved_errno;
4644de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	off_t off;
472c28215423293e443469a07ae7011135d058b671Garrett Cooper
4844de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	page_size = sysconf(_SC_PAGE_SIZE);
4944de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	total_size = 3 * page_size;
5044de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	size = page_size;
512c28215423293e443469a07ae7011135d058b671Garrett Cooper
5244de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_mmap_11_1_%d", getpid());
5344de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	unlink(tmpfname);
5444de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
5544de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	if (fd == -1) {
5644de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis		printf("Error at open(): %s\n", strerror(errno));
5744de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis		return PTS_UNRESOLVED;
5844de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	}
5944de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	unlink(tmpfname);
602c28215423293e443469a07ae7011135d058b671Garrett Cooper
6144de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	if (ftruncate(fd, total_size) == -1) {
6244de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis		printf("Error at ftruncate(): %s\n", strerror(errno));
6344de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis		return PTS_UNRESOLVED;
6444de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	}
652c28215423293e443469a07ae7011135d058b671Garrett Cooper
6644de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	/* This offset is considered illegal, not a multiple of page_size,
6744de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	 * unless the page_size is 1 byte, which is considered impossible.
6844de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	 */
6944de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	off = page_size + 1;
7044de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	errno = 0;
7144de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	pa = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, off);
7243c1224558e7ea2df04e16ba6b88b4945c750dfaCyril Hrubis
7344de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	saved_errno = errno;
7443c1224558e7ea2df04e16ba6b88b4945c750dfaCyril Hrubis
7544de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	close(fd);
7644de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	munmap(pa, size);
770dc076565f772bb1953209fb69ea150b494aaa40robbiew
7844de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	if (pa == MAP_FAILED && saved_errno == EINVAL) {
7944de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis		printf("Got EINVAL when 'off' is not multiple of page size\n");
8044de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis		printf("Test PASSED\n");
8144de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis		return PTS_PASS;
8244de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	}
832c28215423293e443469a07ae7011135d058b671Garrett Cooper
8444de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	printf("Test FAILED: Did not get EINVAL"
8544de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	       " when 'off' is not a multiple of page size, get: %s\n",
8644de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	       strerror(saved_errno));
8743c1224558e7ea2df04e16ba6b88b4945c750dfaCyril Hrubis
8844de8a350c48dcf079d2871493d8d635fe1d7de0Cyril Hrubis	return PTS_FAIL;
89ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
90