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 * The mmap( ) function shall fail if:
8 * [ENOMEM] MAP_FIXED was specified,
9 * and the range [addr,addr+len) exceeds that allowed
10 * for the address space of a process; or, if MAP_FIXED was not specified and
11 * there is insufficient room in the address space to effect the mapping.
12 *
13 * Test Step:
14 * 1. Map a shared memory object, with size exceeding the value get from
15 *    rlim_cur of resource RLIMIT_AS, setting MAP_FIXED;
16 * 3. Should get ENOMEM.
17 */
18
19#define _XOPEN_SOURCE 600
20#include <pthread.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include <sys/mman.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/resource.h>
28#include <fcntl.h>
29#include <string.h>
30#include <errno.h>
31#include "posixtest.h"
32
33#define TNAME "mmap/24-2.c"
34
35int main()
36{
37  char tmpfname[256];
38  int shm_fd;
39
40  void *pa = NULL;
41  void *addr = NULL;
42  size_t len;
43  int prot = PROT_READ | PROT_WRITE;
44  int flag = MAP_SHARED;
45  int fd;
46  off_t off = 0;
47
48  /* Size of the shared memory object */
49  size_t shm_size;
50  struct rlimit rlim;
51  unsigned long page_size = sysconf(_SC_PAGE_SIZE);
52
53  shm_size = 2 * page_size;
54  snprintf(tmpfname, sizeof(tmpfname), "pts_mmap_24_2_%ld",
55           (long)getpid());
56
57  /* Create shared object */
58  shm_unlink(tmpfname);
59  shm_fd = shm_open(tmpfname, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
60  if(shm_fd == -1)
61  {
62    printf(TNAME " Error at shm_open(): %s\n", strerror(errno));
63    return PTS_UNRESOLVED;
64  }
65  shm_unlink(tmpfname);
66  if(ftruncate(shm_fd, shm_size) == -1) {
67    printf(TNAME " Error at ftruncate(): %s\n", strerror(errno));
68    return PTS_UNRESOLVED;
69  }
70
71  /* Currentlly total available memory of this process, in bytes */
72  if (getrlimit (RLIMIT_AS, &rlim) == -1)
73  {
74		printf(TNAME " Error at getrlimit(): %s\n", strerror(errno));
75		return PTS_UNRESOLVED;
76  }
77  printf("available memory: %lu\n", rlim.rlim_cur);
78
79  /* First mmap, just to get a legal addr for second mmap */
80  fd = shm_fd;
81  len = shm_size;
82  pa = mmap (addr, len, prot, flag, fd, off);
83  if (pa == MAP_FAILED)
84  {
85    printf ("Test Fail: " TNAME " Error at first mmap(): %s\n",
86            strerror(errno));
87    exit(PTS_FAIL);
88  }
89
90  fd = shm_fd;
91  len = rlim.rlim_cur;
92  flag = MAP_FIXED | MAP_SHARED;
93  addr = pa;
94  printf("addr: %lx, len: %lx\n", (unsigned long)addr,
95		(unsigned long)len);
96  /* Make sure addr and len is aligned to page size */
97  if ((unsigned long)addr % page_size)
98  {
99    /* Upper boundary */
100    addr += page_size;
101    addr = (void *)((unsigned long)addr & ~(page_size - 1));
102  }
103  if (len % page_size)
104  {
105    /* Lower boundary */
106    len &= ~(page_size - 1);
107  }
108  printf("addr: %lx, len: %lx\n", (unsigned long)addr,
109		(unsigned long)len);
110  pa = mmap (addr, len, prot, flag, fd, off);
111  if (pa == MAP_FAILED && errno == ENOMEM)
112  {
113    printf ("Test Pass: " TNAME " Get ENOMEM: %s\n",
114            strerror(errno));
115    exit(PTS_PASS);
116  }
117
118  if (pa == MAP_FAILED)
119    perror("Error at mmap()");
120  else
121    munmap(pa, len);
122  close(fd);
123  printf ("Test Fail: Did not get ENOMEM as expected\n");
124  return PTS_FAIL;
125}
126