1 #include "MQX_Filesystem.h"
5 #include "ace/OS_NS_unistd.h"
6 #include "ace/OS_NS_sys_stat.h"
15 # error "FOPEN_MAX, the max number of open files, must be defined"
18 # error "FOPEN_MAX is less than 3, no room for standard streams, let alone other files descriptors"
21 #define MQX_FILE_ERROR static_cast<size_t>(-1)
23 MQX_Filesystem
MQX_Filesystem::instance_
;
25 MQX_Filesystem::MQX_Filesystem ()
27 , current_fs_name_len_ (0)
31 current_fs_name_
[0] = '\0';
34 for (unsigned i
= 0; i
< FOPEN_MAX
; i
++)
37 files_
[i
].mqx_file
= 0;
41 void MQX_Filesystem::complete_initialization ()
43 // Set the Standard Streams
44 files_
[0] = {ACE_STDIN
, (MQX_FILE_PTR
) _io_get_handle (IO_STDIN
), true};
45 files_
[1] = {ACE_STDOUT
, (MQX_FILE_PTR
) _io_get_handle (IO_STDOUT
), true};
46 files_
[2] = {ACE_STDERR
, (MQX_FILE_PTR
) _io_get_handle (IO_STDERR
), true};
49 * Try to set the current filesystem. Ignore the error return because if
50 * we're missing a filesystem now, it's okay because a filesystem might be
57 MQX_Filesystem::check_state ()
59 if (!_io_is_fs_valid (current_fs_
))
71 MQX_Filesystem::reset_state ()
73 update_fs (_io_get_first_valid_fs ());
76 return current_fs_
== 0;
80 MQX_Filesystem::update_fs (MQX_FILE_PTR fs
)
86 else if (_io_get_fs_name (fs
, current_fs_name_
, IOCFG_FS_MAX_DEVLEN
) != MQX_OK
)
89 current_fs_name_len_
= strlen (current_fs_name_
);
94 current_fs_name_
[0] = '\0';
95 current_fs_name_len_
= 0;
100 MQX_Filesystem::open (const char *path
, int mode
)
102 if (check_state ()) return -1;
104 // Convert open mode to fopen mode
105 bool r
= ACE_BIT_DISABLED (mode
, O_RDONLY
);
106 bool w
= ACE_BIT_ENABLED (mode
, O_WRONLY
);
107 bool rw
= ACE_BIT_ENABLED (mode
, O_RDWR
);
108 bool a
= ACE_BIT_ENABLED (mode
, O_CREAT
| O_APPEND
);
109 bool t
= ACE_BIT_ENABLED (mode
, O_CREAT
| O_TRUNC
);
110 if (!(r
|| (w
&& (a
|| t
)) || rw
))
115 char cstdlib_mode
[4] = {0}; // r/w/a, t/b, +?, null terminator
116 cstdlib_mode
[0] = r
? 'r' : a
? 'a' : 'w';
117 cstdlib_mode
[1] = 'b';
118 cstdlib_mode
[2] = rw
? '+' : '\0';
120 /// Get Absolute Path
121 char cwd
[FS_FILENAME_SIZE
];
122 int mqx_error
= _io_ioctl (current_fs_
, IO_IOCTL_GET_CURRENT_DIR
, (uint32_t*) cwd
);
123 if (mqx_error
!= MQX_OK
)
125 errno
= ACE_OS::mqx_error_to_errno (mqx_error
);
128 char abspath
[ACE_MQX_ABS_PATH_SIZE
];
129 mqx_error
= _io_rel2abs (abspath
, cwd
, path
, ACE_MQX_ABS_PATH_SIZE
, current_fs_name_
);
130 if (mqx_error
!= MQX_OK
)
132 errno
= ACE_OS::mqx_error_to_errno (mqx_error
);
136 // Set up a new File Entry
137 File
*file
= get_new_file ();
138 if (file
== 0) return -1;
141 file
->mqx_file
= _io_fopen (abspath
, cstdlib_mode
);
142 if (file
->mqx_file
== 0)
144 file
->fd
= -1; // Free File in Our Array
145 errno
= ACE_OS::mqx_error_to_errno (_task_get_error());
146 if (_task_get_error() == FS_FILE_NOT_FOUND
)
147 _task_set_error(MQX_OK
);
154 MQX_Filesystem::close (int fd
)
156 File
*file
= get_file (fd
);
157 if (file
== 0) return -1;
158 int mqx_error
= _io_fclose (file
->mqx_file
);
159 if (mqx_error
!= MQX_OK
)
161 errno
= ACE_OS::mqx_error_to_errno (mqx_error
);
168 MQX_Filesystem::read (int fd
, unsigned char *buffer
, size_t size
)
170 File
*file
= get_file (fd
);
171 if (file
== 0) return MQX_FILE_ERROR
;
172 int result
= _io_read (file
->mqx_file
, buffer
, size
);
173 if (result
== IO_ERROR
)
176 return MQX_FILE_ERROR
;
182 MQX_Filesystem::write (int fd
, const unsigned char *buffer
, size_t size
)
184 File
*file
= get_file (fd
);
185 if (file
== 0) return MQX_FILE_ERROR
;
186 int result
= _io_write (file
->mqx_file
, const_cast<unsigned char *> (buffer
), size
);
187 if (result
== IO_ERROR
)
190 return MQX_FILE_ERROR
;
196 MQX_Filesystem::lseek (int fd
, long offset
, int whence
)
201 whence
= IO_SEEK_SET
;
204 whence
= IO_SEEK_CUR
;
207 whence
= IO_SEEK_END
;
213 File
*file
= get_file (fd
);
214 if (file
== 0) return -1;
215 return _io_fseek (file
->mqx_file
, offset
, whence
) == MQX_OK
? 0 : -1;
219 MQX_Filesystem::getcwd (char *buf
, size_t size
)
221 if (check_state ()) return 0;
228 char curdirtmp
[FS_FILENAME_SIZE
];
229 int mqx_error
= _io_ioctl (current_fs_
, IO_IOCTL_GET_CURRENT_DIR
, (uint32_t*) curdirtmp
);
230 if (mqx_error
!= MFS_NO_ERROR
)
232 errno
= ACE_OS::mqx_error_to_errno (mqx_error
);
235 if ((current_fs_name_len_
+ strlen (curdirtmp
) + 1) > size
)
240 strcpy (buf
, current_fs_name_
);
241 strcat (buf
, curdirtmp
);
246 MQX_Filesystem::resolve_fs (const char *path
, int *fs_name_len
)
248 if (check_state ()) return 0;
250 if (fs_name_len
== 0 || path
== 0 || path
[0] == '\0')
256 char fs_name
[IOCFG_FS_MAX_DEVLEN
];
258 *fs_name_len
= _io_get_dev_for_path (
259 fs_name
, &fs_in_path
, IOCFG_FS_MAX_DEVLEN
, path
, current_fs_name_
);
262 fs
= _io_get_fs_by_name (fs_name
);
264 else if (*fs_name_len
)
278 MQX_Filesystem::mkdir (const char *path
)
281 MQX_FILE_PTR fs
= resolve_fs (path
, &fs_name_len
);
282 if (fs
== 0) return -1;
283 int mqx_error
= _io_ioctl (
284 fs
, IO_IOCTL_CREATE_SUBDIR
, (uint32_t*) (path
+ fs_name_len
));
285 if (mqx_error
!= MQX_OK
)
287 errno
= ACE_OS::mqx_error_to_errno (mqx_error
);
294 MQX_Filesystem::chdir (const char *path
)
297 MQX_FILE_PTR fs
= resolve_fs (path
, &fs_name_len
);
298 if (fs
== 0) return -1;
299 if (fs
!= current_fs_
) update_fs(fs
);
300 int mqx_error
= _io_ioctl (fs
, IO_IOCTL_CHANGE_CURRENT_DIR
,
301 (uint32_t*) (path
+ fs_name_len
));
302 if (mqx_error
!= MQX_OK
)
304 errno
= ACE_OS::mqx_error_to_errno (mqx_error
);
311 MQX_Filesystem::rmdir (const char *path
)
314 MQX_FILE_PTR fs
= resolve_fs (path
, &fs_name_len
);
315 if (fs
== 0) return -1;
316 int mqx_error
= _io_ioctl (fs
, IO_IOCTL_REMOVE_SUBDIR
,
317 (uint32_t*) (path
+ fs_name_len
));
318 if (mqx_error
!= MQX_OK
)
320 errno
= ACE_OS::mqx_error_to_errno (mqx_error
);
327 MQX_Filesystem::unlink (const char *path
)
330 MQX_FILE_PTR fs
= resolve_fs (path
, &fs_name_len
);
331 if (fs
== 0) return -1;
332 int mqx_error
= _io_ioctl (fs
, IO_IOCTL_DELETE_FILE
,
333 (uint32_t*) (path
+ fs_name_len
));
334 if (mqx_error
!= MQX_OK
)
336 errno
= ACE_OS::mqx_error_to_errno (mqx_error
);
343 MQX_Filesystem::rename (const char *oldpath
, const char *newpath
)
345 // TODO: Handle Moving Directories?
347 MQX_FILE_PTR fs
= resolve_fs (oldpath
, &old_fs_name_len
);
349 MQX_FILE_PTR other_fs
= resolve_fs (newpath
, &new_fs_name_len
);
350 if (fs
== 0 || other_fs
== 0) return -1;
357 ACE_stat file_status
;
358 if (this->stat (newpath
, &file_status
) == 0)
360 // New path already exists...
361 if (file_status
.st_mode
& S_IFREG
)
363 // It's a file, we can delete it.
364 if (this->unlink (newpath
))
369 else if (file_status
.st_mode
& S_IFDIR
)
371 // It's a directory, we can't delete that.
377 // Unknown type, error
383 MFS_RENAME_PARAM mfs_rename
;
384 char oldtmp
[FS_FILENAME_SIZE
];
385 strcpy (oldtmp
, oldpath
+ old_fs_name_len
);
386 mfs_rename
.OLD_PATHNAME
= oldtmp
;
387 char newtmp
[FS_FILENAME_SIZE
];
388 strcpy (newtmp
, newpath
+ new_fs_name_len
);
389 mfs_rename
.NEW_PATHNAME
= newtmp
;
391 int mqx_error
= _io_ioctl (fs
, IO_IOCTL_RENAME_FILE
, (uint32_t*) &mfs_rename
);
392 if (mqx_error
!= MQX_OK
)
394 errno
= ACE_OS::mqx_error_to_errno (mqx_error
);
400 MQX_Filesystem::File
*
401 MQX_Filesystem::get_file (int fd
)
403 for (int i
= 0; i
< FOPEN_MAX
; i
++)
405 if (files_
[i
].fd
== fd
) return &files_
[i
];
411 MQX_Filesystem::File
*
412 MQX_Filesystem::get_new_file ()
414 // Get Unused File Struct
415 File
*file
= get_file (-1);
419 // Get Unused File Descriptor
420 for (int fd
= last_fd_
+ 1; fd
!= last_fd_
; fd
++)
422 if (get_file (fd
) == 0)
428 if (fd
== max_fd_
) fd
= 0;
436 mfs_file_attrs_to_stat_mode (int attributes
)
438 int mode
= (attributes
& MFS_ATTR_DIR_NAME
) ? S_IFDIR
: S_IFREG
;
443 MQX_Filesystem::stat (const char * path
, ACE_stat
*statbuf
)
452 MQX_FILE_PTR fs
= resolve_fs (path
, &fs_name_len
);
453 if (fs
== 0) return -1;
455 statbuf
->st_size
= 0;
456 statbuf
->st_mtime
= 0;
457 statbuf
->st_mode
= 0;
458 statbuf
->st_nlink
= 0;
460 MFS_SEARCH_PARAM search
;
461 search
.ATTRIBUTE
= MFS_SEARCH_ANY
;
462 char tmppath
[ACE_MQX_ABS_PATH_SIZE
];
463 strcpy (&tmppath
[0], path
);
464 search
.WILDCARD
= &tmppath
[fs_name_len
];
465 MFS_SEARCH_DATA search_results
;
466 search
.SEARCH_DATA_PTR
= &search_results
;
467 int mqx_error
= _io_ioctl (fs
, IO_IOCTL_FIND_FIRST_FILE
, (uint32_t *) &search
);
468 if (mqx_error
== MFS_NO_ERROR
)
470 statbuf
->st_size
= search_results
.FILE_SIZE
;
471 statbuf
->st_mode
= mfs_file_attrs_to_stat_mode (search_results
.ATTRIBUTE
);
472 statbuf
->st_nlink
= 1;
473 // TODO: statbuf->st_mtime
476 errno
= ACE_OS::mqx_error_to_errno (mqx_error
);
481 MQX_Filesystem::fstat (int fd
, ACE_stat
*statbuf
)
489 File
*file
= get_file (fd
);
490 if (file
== 0) return -1;
492 statbuf
->st_size
= 0;
493 statbuf
->st_mtime
= 0;
494 statbuf
->st_mode
= 0;
495 statbuf
->st_nlink
= 0;
497 if (file
->chardev_file
)
499 statbuf
->st_mode
&= S_IFCHR
;
504 int mqx_error
= _io_ioctl (file
->mqx_file
, IO_IOCTL_GET_FILE_ATTR
, (uint32_t *) &attributes
);
505 if (mqx_error
!= MQX_OK
)
507 errno
= ACE_OS::mqx_error_to_errno (mqx_error
);
510 statbuf
->st_mode
= mfs_file_attrs_to_stat_mode (attributes
);
511 statbuf
->st_nlink
= 1;
513 // TODO: statbuf->st_mtime
518 /* The following are the function definitions that DLib will use to access MQX
519 * IO through MQX_Filesystem.
523 int __open (const char *filename
, int mode
)
525 return MQX_Filesystem::inst ().open (filename
, mode
);
528 size_t __read (int handle
, unsigned char *buffer
, size_t size
)
530 return MQX_Filesystem::inst ().read (handle
, buffer
, size
);
533 size_t __write (int handle
, const unsigned char *buffer
, size_t size
)
535 return MQX_Filesystem::inst ().write (handle
, buffer
, size
);
538 long __lseek (int handle
, long offset
, int whence
)
540 return MQX_Filesystem::inst ().lseek (handle
, offset
, whence
);
543 int __close (int handle
)
545 return MQX_Filesystem::inst ().close (handle
);