Point Cloud Library (PCL)  1.10.0-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 #include <cstddef>
65 
66 namespace pcl
67 {
68  namespace io
69  {
70 #ifdef _WIN32
71  inline int raw_open(const char * pathname, int flags, int mode)
72  {
73  return ::_open(pathname, flags, mode);
74  }
75 
76  inline int raw_open(const char * pathname, int flags)
77  {
78  return ::_open(pathname, flags);
79  }
80 
81  inline int raw_close(int fd)
82  {
83  return ::_close(fd);
84  }
85 
86  inline int raw_lseek(int fd, long offset, int whence)
87  {
88  return ::_lseek(fd, offset, whence);
89  }
90 
91  inline int raw_read(int fd, void * buffer, std::size_t count)
92  {
93  return ::_read(fd, buffer, count);
94  }
95 
96  inline int raw_write(int fd, const void * buffer, std::size_t count)
97  {
98  return ::_write(fd, buffer, count);
99  }
100 
101  inline int raw_ftruncate(int fd, long length)
102  {
103  return ::_chsize(fd, length);
104  }
105 
106  inline int raw_fallocate(int fd, long length)
107  {
108  // Doesn't actually allocate, but best we can do?
109  return raw_ftruncate(fd, length);
110  }
111 #else
112  inline int raw_open(const char * pathname, int flags, int mode)
113  {
114  return ::open(pathname, flags, mode);
115  }
116 
117  inline int raw_open(const char * pathname, int flags)
118  {
119  return ::open(pathname, flags);
120  }
121 
122  inline int raw_close(int fd)
123  {
124  return ::close(fd);
125  }
126 
127  inline off_t raw_lseek(int fd, off_t offset, int whence)
128  {
129  return ::lseek(fd, offset, whence);
130  }
131 
132  inline ssize_t raw_read(int fd, void * buffer, std::size_t count)
133  {
134  return ::read(fd, buffer, count);
135  }
136 
137  inline ssize_t raw_write(int fd, const void * buffer, std::size_t count)
138  {
139  return ::write(fd, buffer, count);
140  }
141 
142  inline int raw_ftruncate(int fd, off_t length)
143  {
144  return ::ftruncate(fd, length);
145  }
146 
147 # ifdef __APPLE__
148  inline int raw_fallocate(int fd, off_t length)
149  {
150  // OS X doesn't have posix_fallocate, but it has a fcntl that does the job.
151  // It may make the file too big though, so we truncate before returning.
152 
153  // Try to allocate contiguous space first.
154  ::fstore_t store = {F_ALLOCATEALL | F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, length, 0};
155  if (::fcntl(fd, F_PREALLOCATE, &store) != -1)
156  return raw_ftruncate(fd, length);
157 
158  // Try fragmented if it failed.
159  store.fst_flags = F_ALLOCATEALL;
160  if (::fcntl(fd, F_PREALLOCATE, &store) != -1)
161  return raw_ftruncate(fd, length);
162 
163  // Fragmented also failed.
164  return -1;
165  }
166 
167 # else // __APPLE__
168  inline int raw_fallocate(int fd, off_t length)
169  {
170 # ifdef ANDROID
171  // Android's libc doesn't have posix_fallocate.
172  if (::fallocate(fd, 0, 0, length) == 0)
173  return 0;
174 # else
175  // Conforming POSIX systems have posix_fallocate.
176  if (::posix_fallocate(fd, 0, length) == 0)
177  return 0;
178 # endif
179 
180  // EINVAL should indicate an unsupported filesystem.
181  // All other errors are passed up.
182  if (errno != EINVAL)
183  return -1;
184 
185  // Try to deal with unsupported filesystems by simply seeking + writing.
186  // This may not really allocate space, but the file size will be set.
187  // Writes to the mmapped file may still trigger SIGBUS errors later.
188 
189  // Remember the old position and seek to the desired length.
190  off_t old_pos = raw_lseek(fd, 0, SEEK_CUR);
191  if (old_pos == -1)
192  return -1;
193  if (raw_lseek(fd, length - 1, SEEK_SET) == -1)
194  return -1;
195 
196  // Write a single byte to resize the file.
197  char buffer = 0;
198  ssize_t written = raw_write(fd, &buffer, 1);
199 
200  // Seek back to the old position.
201  if (raw_lseek(fd, old_pos, SEEK_SET) == -1)
202  return -1;
203 
204  // Fail if we didn't write exactly one byte,
205  if (written != 1)
206  return -1;
207 
208  return 0;
209  }
210 # endif // __APPLE
211 #endif // _WIN32
212 
213  }
214 }
int raw_ftruncate(int fd, off_t length)
Definition: low_level_io.h:142
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:112
int raw_close(int fd)
Definition: low_level_io.h:122
int raw_fallocate(int fd, off_t length)
Definition: low_level_io.h:168
ssize_t raw_read(int fd, void *buffer, std::size_t count)
Definition: low_level_io.h:132
off_t raw_lseek(int fd, off_t offset, int whence)
Definition: low_level_io.h:127
ssize_t raw_write(int fd, const void *buffer, std::size_t count)
Definition: low_level_io.h:137