F´ Flight Software - C/C++ Documentation  NASA-v1.5.0
A framework for building embedded system applications to NASA flight quality standards.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FileStub.cpp
Go to the documentation of this file.
1 #include <FpConfig.hpp>
3 #include <Os/File.hpp>
4 #include <Fw/Types/Assert.hpp>
5 #include <Os/Stubs/FileStubs.hpp>
6 
7 #include <cerrno>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 
13 #include <string.h>
14 #include <stdio.h>
15 
16 namespace Os {
17 
19  static void *readInterceptorPtr = 0;
20 
22  static void *writeInterceptorPtr = 0;
23 
25  static void *openInterceptorPtr = 0;
26 
28  static void *seekInterceptorPtr = 0;
29 
31 
32  void registerReadInterceptor(ReadInterceptor funcPtr, void *ptr) {
33  readInterceptor = funcPtr;
34  readInterceptorPtr = ptr;
35  }
36 
37  void clearReadInterceptor(void) {
38  readInterceptor = 0;
39  }
40 
41  void registerWriteInterceptor(WriteInterceptor funcPtr, void *ptr) {
42  writeInterceptor = funcPtr;
43  writeInterceptorPtr = ptr;
44  }
45 
46  void clearWriteInterceptor(void) {
47  writeInterceptor = 0;
48  }
49 
50  void registerOpenInterceptor(OpenInterceptor funcPtr, void *ptr) {
51  openInterceptor = funcPtr;
52  openInterceptorPtr = ptr;
53  }
54 
55  void clearOpenInterceptor(void) {
56  openInterceptor = 0;
57  }
58 
59  void registerSeekInterceptor(SeekInterceptor funcPtr, void *ptr) {
60  seekInterceptor = funcPtr;
61  seekInterceptorPtr = ptr;
62  }
63 
64  void clearSeekInterceptor(void) {
65  seekInterceptor = 0;
66  }
67 
69  lastError = error;
70  }
71 
72 
73  File::File() :m_fd(0),m_mode(OPEN_NO_MODE),m_lastError(0) {
74  }
75 
76  File::~File() {
77  if (this->m_mode != OPEN_NO_MODE) {
78  this->close();
79  }
80  }
81 
82  File::Status File::open(const char* fileName, File::Mode mode) {
83  return this->open(fileName, mode, true);
84  }
85 
86  File::Status File::open(const char* fileName, File::Mode mode, bool include_excl) {
87 
88  if (openInterceptor) {
89  File::Status stat;
90  if (not openInterceptor(stat,fileName,mode,openInterceptorPtr)) {
91  return stat;
92  }
93  }
94 
95  NATIVE_INT_TYPE flags = 0;
96  Status stat = OP_OK;
97 
98  switch (mode) {
99  case OPEN_READ:
100  flags = O_RDONLY;
101  break;
102  case OPEN_WRITE:
103  flags = O_WRONLY | O_CREAT | O_TRUNC;
104  break;
105  case OPEN_SYNC_WRITE:
106  flags = O_WRONLY | O_CREAT | O_SYNC;
107  break;
108  case OPEN_SYNC_DIRECT_WRITE:
109  flags = O_WRONLY | O_CREAT | O_DSYNC
110 #ifdef __linux__
111  | O_DIRECT;
112 #else
113  ;
114 #endif
115  case OPEN_CREATE:
116  flags = O_WRONLY | O_CREAT | O_TRUNC;
117  break;
118  default:
119  FW_ASSERT(0,(NATIVE_INT_TYPE)mode);
120  break;
121  }
122 
123  NATIVE_INT_TYPE userFlags =
124 #ifdef __VXWORKS__
125  0;
126 #else
127  S_IRUSR|S_IWRITE;
128 #endif
129  NATIVE_INT_TYPE fd = ::open(fileName,flags,userFlags);
130 
131  if (-1 == fd) {
132  this->m_lastError = errno;
133  switch (errno) {
134  case ENOSPC:
135  stat = NO_SPACE;
136  break;
137  case ENOENT:
138  stat = DOESNT_EXIST;
139  break;
140  case EACCES:
141  stat = NO_PERMISSION;
142  break;
143  default:
144  stat = OTHER_ERROR;
145  break;
146  }
147  }
148 
149  this->m_mode = mode;
150  this->m_fd = fd;
151  return stat;
152  }
153 
154  File::Status File::prealloc(NATIVE_INT_TYPE offset, NATIVE_INT_TYPE len) {
155  // make sure it has been opened
156  if (OPEN_NO_MODE == this->m_mode) {
157  return NOT_OPENED;
158  }
159 
160  File::Status fileStatus = OP_OK;
161 
162 #ifdef __linux__
163  NATIVE_INT_TYPE stat = posix_fallocate(this->m_fd, offset, len);
164 
165  if (stat) {
166  switch (stat) {
167  case ENOSPC:
168  case EFBIG:
169  fileStatus = NO_SPACE;
170  break;
171  case EBADF:
172  fileStatus = DOESNT_EXIST;
173  break;
174  default:
175  fileStatus = OTHER_ERROR;
176  break;
177  }
178  }
179 #endif
180 
181  return fileStatus;
182  }
183 
184  File::Status File::seek(NATIVE_INT_TYPE offset, bool absolute) {
185 
186  if (seekInterceptor) {
187  File::Status stat;
188  if (not seekInterceptor(stat,offset,absolute,seekInterceptorPtr)) {
189  return stat;
190  }
191  }
192 
193 
194  // make sure it has been opened
195  if (OPEN_NO_MODE == this->m_mode) {
196  return NOT_OPENED;
197  }
198 
199  Status stat = OP_OK;
200  NATIVE_INT_TYPE whence = absolute?SEEK_SET:SEEK_CUR;
201 
202  off_t act_off = ::lseek(this->m_fd,offset,whence);
203 
204  // No error would be a normal one for this simple
205  // class, so return other error
206  if (act_off != offset) {
207  if (-1 == act_off) {
208  this->m_lastError = errno;
209  stat = OTHER_ERROR;
210  } else {
211  stat = BAD_SIZE;
212  }
213  }
214 
215  return stat;
216  }
217 
218  File::Status File::read(void * buffer, NATIVE_INT_TYPE &size, bool waitForFull) {
219 
220  FW_ASSERT(buffer);
221 
222  if (readInterceptor) {
223  File::Status stat;
224  if (not readInterceptor(stat,buffer,size,waitForFull,readInterceptorPtr)) {
225  return stat;
226  }
227  }
228 
229  // make sure it has been opened
230  if (OPEN_NO_MODE == this->m_mode) {
231  return NOT_OPENED;
232  }
233 
234  NATIVE_INT_TYPE accSize = 0; // accumulated size
235 
236  Status stat = OP_OK;
237 
238  NATIVE_INT_TYPE maxIters = size*2; // loop limit; couldn't block more times than number of bytes
239 
240  while (maxIters > 0) {
241 
242  ssize_t readSize = ::read(this->m_fd,
243 #ifdef __VXWORKS__
244  static_cast<char*>(buffer)
245 #else
246  buffer
247 #endif
248  ,size-accSize);
249 
250  if (readSize != size-accSize) {
251  // could be an error
252  if (-1 == readSize) {
253  switch (errno) {
254  case EINTR: // read was interrupted
255  maxIters--; // decrement loop count
256  continue;
257  default:
258  stat = OTHER_ERROR;
259  break;
260  }
261  this->m_lastError = errno;
262  accSize = 0;
263  break; // break out of while loop
264  } else if (0 == readSize) { // end of file
265  accSize = 0;
266  break;
267  } else { // partial read so adjust read point and size
268  accSize += readSize;
269  if (not waitForFull) {
270  break; // break out of while loop
271  } else {
272  // in order to move the pointer ahead, we need to cast it
273  U8* charPtr = (U8*)buffer;
274  charPtr = &charPtr[readSize];
275  buffer = (void*)charPtr;
276  }
277  maxIters--; // decrement loop count
278  }
279 
280  } else { // got number we wanted
281  accSize += readSize;
282  break; // break out of while loop
283  }
284 
285  maxIters--; // decrement loop count
286 
287  } // end read while loop
288 
289  // make sure we didn't exceed loop count
290  FW_ASSERT(maxIters > 0);
291 
292  size = accSize;
293 
294  return stat;
295  }
296 
297  File::Status File::write(const void * buffer, NATIVE_INT_TYPE &size, bool waitForDone) {
298 
299  if (writeInterceptor) {
300  File::Status stat;
301  if (not writeInterceptor(stat,buffer,size,waitForDone,writeInterceptorPtr)) {
302  return stat;
303  }
304  }
305 
306  // make sure it has been opened
307  if (OPEN_NO_MODE == this->m_mode) {
308  return NOT_OPENED;
309  }
310 
311  Status stat = OP_OK;
312  // just check for EINTR
313  NATIVE_INT_TYPE maxIters = size*2; // loop limit; couldn't block more times than number of bytes
314  while (maxIters > 0) {
315  NATIVE_INT_TYPE writeSize = ::write(this->m_fd,
316 #ifdef __VXWORKS__
317  static_cast<char*>(const_cast<void*>(buffer)) // Ugly, but that's how VxWorks likes to roll...
318 #else
319  buffer
320 #endif
321  ,size);
322  if (-1 == writeSize) {
323  switch (errno) {
324  case EINTR: // write was interrupted
325  maxIters--; // decrement loop count
326  continue;
327  case ENOSPC:
328  stat = NO_SPACE;
329  break;
330  default:
331  stat = OTHER_ERROR;
332  break;
333  }
334  this->m_lastError = errno;
335  break; // break out of while loop
336  } else {
337  size = writeSize;
338  break; // break out of while loop
339  }
340  }
341 
342  return stat;
343  }
344 
345  // NOTE(mereweth) - see http://lkml.iu.edu/hypermail/linux/kernel/1005.2/01845.html
346  // recommendation from Linus Torvalds, but doesn't seem to be that fast
347  File::Status File::bulkWrite(const void * buffer, NATIVE_UINT_TYPE &totalSize,
348  NATIVE_INT_TYPE chunkSize) {
349 #ifdef __linux__
350  const NATIVE_UINT_TYPE startPosition = lseek(this->m_fd, 0, SEEK_CUR);
351 #endif
352  NATIVE_UINT_TYPE newBytesWritten = 0;
353 
354  for (NATIVE_UINT_TYPE idx = 0; idx < totalSize; idx += chunkSize) {
355  NATIVE_INT_TYPE size = chunkSize;
356  // if we're on the last iteration and length isn't a multiple of chunkSize
357  if (idx + chunkSize > totalSize) {
358  size = totalSize - idx;
359  }
360  const NATIVE_INT_TYPE toWrite = size;
361  const Os::File::Status fileStatus = this->write(buffer, size, false);
362  if (!(fileStatus == Os::File::OP_OK
363  && size == static_cast<NATIVE_INT_TYPE>(toWrite))) {
364  totalSize = newBytesWritten;
365  return fileStatus;
366  }
367 
368 #ifdef __linux__
369  sync_file_range(this->m_fd,
370  startPosition + newBytesWritten,
371  chunkSize,
372  SYNC_FILE_RANGE_WRITE);
373 
374  if (newBytesWritten) {
375  sync_file_range(this->m_fd,
376  startPosition + newBytesWritten - chunkSize,
377  chunkSize,
378  SYNC_FILE_RANGE_WAIT_BEFORE
379  | SYNC_FILE_RANGE_WRITE
380  | SYNC_FILE_RANGE_WAIT_AFTER);
381  }
382 #endif
383 
384  newBytesWritten += toWrite;
385  }
386 
387  totalSize = newBytesWritten;
388  return OP_OK;
389  }
390 
391  File::Status File::flush() {
392  // make sure it has been opened
393  if (OPEN_NO_MODE == this->m_mode) {
394  return NOT_OPENED;
395  }
396 
397  File::Status stat = OP_OK;
398 
399  if (-1 == fsync(this->m_fd)) {
400  switch (errno) {
401  case ENOSPC:
402  stat = NO_SPACE;
403  break;
404  default:
405  stat = OTHER_ERROR;
406  break;
407  }
408  }
409 
410  return stat;
411  }
412 
413  void File::close(void) {
414  (void)::close(this->m_fd);
415  this->m_mode = OPEN_NO_MODE;
416  }
417 
418  NATIVE_INT_TYPE File::getLastError(void) {
419  return lastError;
420  }
421 
422  const char* File::getLastErrorString(void) {
423  return strerror(this->m_lastError);
424  }
425 
426 
427 
428 }
Os
Definition: File.cpp:7
Os::registerOpenInterceptor
void registerOpenInterceptor(OpenInterceptor funcPtr, void *ptr)
Definition: FileStub.cpp:50
Os::setLastError
void setLastError(NATIVE_INT_TYPE error)
Definition: FileStub.cpp:68
Os::FileSystem::Status
Status
Definition: FileSystem.hpp:15
Os::openInterceptorPtr
static void * openInterceptorPtr
Definition: FileStub.cpp:25
Os::clearReadInterceptor
void clearReadInterceptor(void)
Definition: FileStub.cpp:37
Os::clearOpenInterceptor
void clearOpenInterceptor(void)
Definition: FileStub.cpp:55
Os::ReadInterceptor
bool(* ReadInterceptor)(Os::File::Status &status, void *buffer, NATIVE_INT_TYPE &size, bool waitForFull, void *ptr)
Definition: FileStubs.hpp:25
Os::readInterceptor
static ReadInterceptor readInterceptor
Definition: FileStub.cpp:18
Os::FileSystem::NO_SPACE
@ NO_SPACE
No space left.
Definition: FileSystem.hpp:18
U8
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.hpp:76
FileStubs.hpp
Os::writeInterceptorPtr
static void * writeInterceptorPtr
Definition: FileStub.cpp:22
Os::seekInterceptorPtr
static void * seekInterceptorPtr
Definition: FileStub.cpp:28
Os::OpenInterceptor
bool(* OpenInterceptor)(Os::File::Status &status, const char *fileName, Os::File::Mode mode, void *ptr)
Definition: FileStubs.hpp:24
Os::registerSeekInterceptor
void registerSeekInterceptor(SeekInterceptor funcPtr, void *ptr)
Definition: FileStub.cpp:59
Os::SeekInterceptor
bool(* SeekInterceptor)(Os::File::Status &status, NATIVE_INT_TYPE offset, bool absolute, void *ptr)
Definition: FileStubs.hpp:27
Os::File::File
File()
Constructor.
Definition: File.cpp:9
Os::lastError
static NATIVE_INT_TYPE lastError
Definition: FileStub.cpp:30
Assert.hpp
Os::FileSystem::OTHER_ERROR
@ OTHER_ERROR
other OS-specific error
Definition: FileSystem.hpp:26
Os::FileSystem::OP_OK
@ OP_OK
Operation was successful.
Definition: FileSystem.hpp:16
Os::registerReadInterceptor
void registerReadInterceptor(ReadInterceptor funcPtr, void *ptr)
Definition: FileStub.cpp:32
Os::registerWriteInterceptor
void registerWriteInterceptor(WriteInterceptor funcPtr, void *ptr)
Definition: FileStub.cpp:41
NATIVE_UINT_TYPE
unsigned int NATIVE_UINT_TYPE
native unsigned integer type declaration
Definition: BasicTypes.hpp:30
Os::readInterceptorPtr
static void * readInterceptorPtr
Definition: FileStub.cpp:19
FW_ASSERT
#define FW_ASSERT(...)
Definition: Assert.hpp:9
Os::seekInterceptor
static SeekInterceptor seekInterceptor
Definition: FileStub.cpp:27
File.hpp
Os::openInterceptor
static OpenInterceptor openInterceptor
Definition: FileStub.cpp:24
FpConfig.hpp
ISF configuration file.
Os::clearSeekInterceptor
void clearSeekInterceptor(void)
Definition: FileStub.cpp:64
Os::clearWriteInterceptor
void clearWriteInterceptor(void)
Definition: FileStub.cpp:46
Os::File::Status
Status
Definition: File.hpp:24
Os::FileSystem::NO_PERMISSION
@ NO_PERMISSION
No permission to write.
Definition: FileSystem.hpp:19
BasicTypes.hpp
Declares ISF basic types.
Os::writeInterceptor
static WriteInterceptor writeInterceptor
Definition: FileStub.cpp:21
Os::File::OP_OK
@ OP_OK
Operation was successful.
Definition: File.hpp:25
NATIVE_INT_TYPE
int NATIVE_INT_TYPE
native integer type declaration
Definition: BasicTypes.hpp:29
Os::WriteInterceptor
bool(* WriteInterceptor)(Os::File::Status &status, const void *buffer, NATIVE_INT_TYPE &size, bool waitForDone, void *ptr)
Definition: FileStubs.hpp:26