F´ Flight Software - C/C++ Documentation  NASA-v1.5.0
A framework for building embedded system applications to NASA flight quality standards.
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