1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "file_image.h"
25 
26 #include <unistd.h>
27 
28 #include <errno.h>
29 #include <fcntl.h>
30 
31 #if defined(LINUX)
32 #  ifndef __USE_BSD
33 #    define __USE_BSD /* madvise, MADV_WILLNEED */
34 #  endif
35 #endif /* Linux */
36 
37 #include <sys/mman.h>
38 #include <sys/stat.h>
39 
40 #include <string.h>
41 
42 /*
43  * file_image_open
44  */
45 int file_image_open (file_image * image, const char * filename)
46 {
47     int         result = 0;
48     int         fd;
49     struct stat st;
50     void *      p;
51 
52     if (image == 0)
53         return (EINVAL);
54 
55     image->m_base = MAP_FAILED, image->m_size = 0;
56 
57     if ((fd = open (filename, O_RDONLY)) == -1)
58         return (errno);
59 
60     if (fstat (fd, &st) == -1)
61     {
62         result = errno;
63         goto cleanup_and_leave;
64     }
65 
66     p = mmap (0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
67 	if (p == MAP_FAILED)
68     {
69         result = errno;
70         goto cleanup_and_leave;
71     }
72 
73     image->m_base = p, image->m_size = st.st_size;
74 
75 cleanup_and_leave:
76 	close (fd);
77     return (result);
78 }
79 
80 /*
81  * file_image_pagein.
82  */
83 int file_image_pagein (file_image * image)
84 {
85 	file_image    w;
86 	long          s;
87 	size_t        k;
88 	volatile char c = 0;
89 
90 	if (image == 0)
91 		return (EINVAL);
92 
93 	if ((w.m_base = image->m_base) == 0)
94 		return (EINVAL);
95 	if ((w.m_size = image->m_size) == 0)
96 		return (0);
97 
98 	if (madvise (w.m_base, w.m_size, MADV_WILLNEED) == -1)
99 	{
100 #ifndef MACOSX
101 		return (errno);
102 #else
103 		/* madvise MADV_WILLNEED need not succeed here */
104 		/* but that is fine */
105 #endif
106 	}
107 
108 
109 #ifndef MACOSX
110 	if ((s = sysconf (_SC_PAGESIZE)) == -1)
111 		s = 0x1000;
112 #else
113 	s = getpagesize();
114 #endif
115 
116 	k = (size_t)(s);
117 	while (w.m_size > k)
118 	{
119 		c ^= ((char*)(w.m_base))[0];
120 		w.m_base  = (char*)(w.m_base) + k;
121 		w.m_size -= k;
122 	}
123 	if (w.m_size > 0)
124 	{
125 		c ^= ((char*)(w.m_base))[0];
126 		w.m_base  = (char*)(w.m_base) + w.m_size;
127 		w.m_size -= w.m_size;
128 	}
129 
130 	return (0);
131 }
132 
133 /*
134  * file_image_close
135  */
136 int file_image_close (file_image * image)
137 {
138     if (image == 0)
139         return (EINVAL);
140 
141     if (munmap (image->m_base, image->m_size) == -1)
142 		return (errno);
143 
144 	image->m_base = 0, image->m_size = 0;
145     return (0);
146 }
147