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 * If MAP_FIXED is set,
8 * mmap( ) may return MAP_FAILED and set errno to [EINVAL].
9 *
10 * [EINVAL] The addr argument (if MAP_FIXED was specified) or off is not a multiple of
11 * the page size as returned by sysconf( ), or is considered invalid by the
12 * implementation.
13 *
14 * Test step:
15 * 1. Set 'addr' as an illegal address, which is not a multiple of page size;
16 * 2. Call mmap() and get EINVAL;
17 */
18
19#define _XOPEN_SOURCE 600
20
21#include <pthread.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <sys/mman.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <sys/wait.h>
29#include <fcntl.h>
30#include <string.h>
31#include <errno.h>
32#include "posixtest.h"
33
34#define TNAME "mmap/9-1.c"
35
36int main()
37{
38  char tmpfname[256];
39  long  page_size;
40  long total_size;
41
42  void *illegal_addr;
43  void *pa = NULL;
44  void *addr = NULL;
45  size_t size;
46  int flag;
47  int fd;
48  off_t off = 0;
49  int prot;
50
51  page_size = sysconf(_SC_PAGE_SIZE);
52  total_size = page_size;
53  size = total_size;
54
55  /* Create tmp file */
56
57  snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_mmap_9_1_%ld",
58           (long)getpid());
59  unlink(tmpfname);
60  fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL,
61            S_IRUSR | S_IWUSR);
62  if (fd == -1)
63  {
64    printf(TNAME " Error at open(): %s\n",
65           strerror(errno));
66    exit(PTS_UNRESOLVED);
67  }
68  unlink(tmpfname);
69  if (ftruncate(fd, total_size) == -1)
70  {
71    printf(TNAME "Error at ftruncate(): %s\n",
72            strerror(errno));
73    exit(PTS_UNRESOLVED);
74  }
75
76  /* Map the file for the first time, to get a legal address, pa */
77
78  flag = MAP_SHARED;
79  prot = PROT_READ | PROT_WRITE;
80  pa = mmap(addr, size, prot, flag, fd, off);
81
82  if ((unsigned long)pa % page_size)
83  {
84    printf("pa is not multiple of page_size\n");
85    illegal_addr = pa;
86  }
87  else
88  {
89    printf("pa is a multiple of page_size\n");
90    illegal_addr = pa + 1;
91  }
92
93  munmap (pa, size);
94
95  /* Mmap again using the illegal address, setting MAP_FIXED */
96  prot = PROT_READ | PROT_WRITE;
97  flag = MAP_FIXED;
98  addr = illegal_addr;
99  pa = mmap(addr, size, prot, flag, fd, off);
100  if (pa == MAP_FAILED && errno == EINVAL)
101  {
102    printf("Test Pass: " TNAME " Set MAP_FIXED and get "
103    	   "EINVAL when 'addr' is illegal\n");
104    exit(PTS_PASS);
105  }
106
107  close (fd);
108  munmap (pa, size);
109  printf ("Test FAIL, Set MAP_FIXED but did not get EINVAL"
110          " when 'addr' is illegal\n");
111  return PTS_FAIL;
112}
113