Point Cloud Library (PCL)  1.9.1-dev
low_level_io.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2012-, Open Perception, Inc.
6  * Copyright (c) 2018 Fizyr BV. - https://fizyr.com
7  *
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * * Neither the name of the copyright holder(s) nor the names of its
21  * contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 /**
39  * This file defines compatibility wrappers for low level I/O functions.
40  * Implemented as inlinable functions to prevent any performance overhead.
41  */
42 
43 #pragma once
44 
45 #ifdef _WIN32
46 # ifndef WIN32_LEAN_AND_MEAN
47 # define WIN32_LEAN_AND_MEAN
48 # endif
49 # ifndef NOMINMAX
50 # define NOMINMAX
51 # endif
52 # include <io.h>
53 # include <windows.h>
54 # include <BaseTsd.h>
55 using ssize_t = SSIZE_T;
56 #else
57 # include <unistd.h>
58 # include <sys/mman.h>
59 # include <sys/types.h>
60 # include <sys/stat.h>
61 # include <sys/fcntl.h>
62 # include <cerrno>
63 #endif
64 
65 namespace pcl
66 {
67  namespace io
68  {
69 #ifdef _WIN32
70  inline int raw_open(const char * pathname, int flags, int mode)
71  {
72  return ::_open(pathname, flags, mode);
73  }
74 
75  inline int raw_open(const char * pathname, int flags)
76  {
77  return ::_open(pathname, flags);
78  }
79 
80  inline int raw_close(int fd)
81  {
82  return ::_close(fd);
83  }
84 
85  inline int raw_lseek(int fd, long offset, int whence)
86  {
87  return ::_lseek(fd, offset, whence);
88  }
89 
90  inline int raw_read(int fd, void * buffer, size_t count)
91  {
92  return ::_read(fd, buffer, count);
93  }
94 
95  inline int raw_write(int fd, const void * buffer, size_t count)
96  {
97  return ::_write(fd, buffer, count);
98  }
99 
100  inline int raw_ftruncate(int fd, long length)
101  {
102  return ::_chsize(fd, length);
103  }
104 
105  inline int raw_fallocate(int fd, long length)
106  {
107  // Doesn't actually allocate, but best we can do?
108  return raw_ftruncate(fd, length);
109  }
110 #else
111  inline int raw_open(const char * pathname, int flags, int mode)
112  {
113  return ::open(pathname, flags, mode);
114  }
115 
116  inline int raw_open(const char * pathname, int flags)
117  {
118  return ::open(pathname, flags);
119  }
120 
121  inline int raw_close(int fd)
122  {
123  return ::close(fd);
124  }
125 
126  inline off_t raw_lseek(int fd, off_t offset, int whence)
127  {
128  return ::lseek(fd, offset, whence);
129  }
130 
131  inline ssize_t raw_read(int fd, void * buffer, size_t count)
132  {
133  return ::read(fd, buffer, count);
134  }
135 
136  inline ssize_t raw_write(int fd, const void * buffer, size_t count)
137  {
138  return ::write(fd, buffer, count);
139  }
140 
141  inline int raw_ftruncate(int fd, off_t length)
142  {
143  return ::ftruncate(fd, length);
144  }
145 
146 # ifdef __APPLE__
147  inline int raw_fallocate(int fd, off_t length)
148  {
149  // OS X doesn't have posix_fallocate, but it has a fcntl that does the job.
150  // It may make the file too big though, so we truncate before returning.
151 
152  // Try to allocate contiguous space first.
153  ::fstore_t store = {F_ALLOCATEALL | F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, length};
154  if (::fcntl(fd, F_PREALLOCATE, &store) != -1)
155  return raw_ftruncate(fd, length);
156 
157  // Try fragmented if it failed.
158  store.fst_flags = F_ALLOCATEALL;
159  if (::fcntl(fd, F_PREALLOCATE, &store) != -1)
160  return raw_ftruncate(fd, length);
161 
162  // Fragmented also failed.
163  return -1;
164  }
165 
166 # else // __APPLE__
167  inline int raw_fallocate(int fd, off_t length)
168  {
169 # ifdef ANDROID
170  // Android's libc doesn't have posix_fallocate.
171  if (::fallocate(fd, 0, 0, length) == 0)
172  return 0;
173 # else
174  // Conforming POSIX systems have posix_fallocate.
175  if (::posix_fallocate(fd, 0, length) == 0)
176  return 0;
177 # endif
178 
179  // EINVAL should indicate an unsupported filesystem.
180  // All other errors are passed up.
181  if (errno != EINVAL)
182  return -1;
183 
184  // Try to deal with unsupported filesystems by simply seeking + writing.
185  // This may not really allocate space, but the file size will be set.
186  // Writes to the mmapped file may still trigger SIGBUS errors later.
187 
188  // Remember the old position and seek to the desired length.
189  off_t old_pos = raw_lseek(fd, 0, SEEK_CUR);
190  if (old_pos == -1)
191  return -1;
192  if (raw_lseek(fd, length - 1, SEEK_SET) == -1)
193  return -1;
194 
195  // Write a single byte to resize the file.
196  char buffer = 0;
197  ssize_t written = raw_write(fd, &buffer, 1);
198 
199  // Seek back to the old position.
200  if (raw_lseek(fd, old_pos, SEEK_SET) == -1)
201  return -1;
202 
203  // Fail if we didn't write exactly one byte,
204  if (written != 1)
205  return -1;
206 
207  return 0;
208  }
209 # endif // __APPLE
210 #endif // _WIN32
211 
212  }
213 }
int raw_ftruncate(int fd, off_t length)
Definition: low_level_io.h:141
This file defines compatibility wrappers for low level I/O functions.
Definition: convolution.h:45
int raw_open(const char *pathname, int flags, int mode)
Definition: low_level_io.h:111
int raw_close(int fd)
Definition: low_level_io.h:121
int raw_fallocate(int fd, off_t length)
Definition: low_level_io.h:167
ssize_t raw_read(int fd, void *buffer, size_t count)
Definition: low_level_io.h:131
ssize_t raw_write(int fd, const void *buffer, size_t count)
Definition: low_level_io.h:136
off_t raw_lseek(int fd, off_t offset, int whence)
Definition: low_level_io.h:126