mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LocalFileSystem.cpp Source File

LocalFileSystem.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "LocalFileSystem.h"
00017 
00018 #if DEVICE_LOCALFILESYSTEM
00019 
00020 #include "semihost_api.h"
00021 #include <string.h>
00022 #include <stdio.h>
00023 
00024 namespace mbed {
00025 
00026 /* Extension to FINFO type defined in RTL.h (in Keil RL) - adds 'create time'. */
00027 typedef struct {
00028     unsigned char  hr;   /* Hours    [0..23]                  */
00029     unsigned char  min;  /* Minutes  [0..59]                  */
00030     unsigned char  sec;  /* Seconds  [0..59]                  */
00031     unsigned char  day;  /* Day      [1..31]                  */
00032     unsigned char  mon;  /* Month    [1..12]                  */
00033     unsigned short year; /* Year     [1980..2107]             */
00034 } FTIME;
00035 
00036 typedef struct {         /* File Search info record           */
00037     char  name[32];      /* File name                         */
00038     long  size;          /* File size in bytes                */
00039     int   fileID;        /* System File Identification        */
00040     FTIME create_time;   /* Date & time file was created      */
00041     FTIME write_time;    /* Date & time of last write         */
00042 } XFINFO;
00043 
00044 #define RESERVED_FOR_USER_APPLICATIONS (0x100) /* 0x100 - 0x1ff */
00045 #define USR_XFFIND (RESERVED_FOR_USER_APPLICATIONS + 0)
00046 
00047 static int xffind (const char *pattern, XFINFO *info) {
00048     unsigned param[4];
00049 
00050     param[0] = (unsigned long)pattern;
00051     param[1] = (unsigned long)strlen(pattern);
00052     param[2] = (unsigned long)info;
00053     param[3] = (unsigned long)sizeof(XFINFO);
00054 
00055     return __semihost(USR_XFFIND, param);
00056 }
00057 
00058 #define OPEN_R          0
00059 #define OPEN_B          1
00060 #define OPEN_PLUS       2
00061 #define OPEN_W          4
00062 #define OPEN_A          8
00063 #define OPEN_INVALID   -1
00064 
00065 int posix_to_semihost_open_flags(int flags) {
00066     /* POSIX flags -> semihosting open mode */
00067     int openmode;
00068     if (flags & O_RDWR) {
00069         /* a plus mode */
00070         openmode = OPEN_PLUS;
00071         if (flags & O_APPEND) {
00072             openmode |= OPEN_A;
00073         } else if (flags & O_TRUNC) {
00074             openmode |= OPEN_W;
00075         } else {
00076             openmode |= OPEN_R;
00077         }
00078     } else if (flags & O_WRONLY) {
00079         /* write or append */
00080         if (flags & O_APPEND) {
00081             openmode = OPEN_A;
00082         } else {
00083             openmode = OPEN_W;
00084         }
00085     } else if (flags == O_RDONLY) {
00086         /* read mode */
00087         openmode = OPEN_R;
00088     } else {
00089         /* invalid flags */
00090         openmode = OPEN_INVALID;
00091     }
00092 
00093     return openmode;
00094 }
00095 
00096 FILEHANDLE local_file_open(const char* name, int flags) {
00097     int openmode = posix_to_semihost_open_flags(flags);
00098     if (openmode == OPEN_INVALID) {
00099         return (FILEHANDLE)NULL;
00100     }
00101 
00102     FILEHANDLE fh = semihost_open(name, openmode);
00103     if (fh == -1) {
00104         return (FILEHANDLE)NULL;
00105     }
00106 
00107     return fh;
00108 }
00109 
00110 LocalFileHandle::LocalFileHandle(FILEHANDLE fh) : _fh(fh), pos(0) {
00111 }
00112 
00113 int LocalFileHandle::close() {
00114     int retval = semihost_close(_fh);
00115     delete this;
00116     return retval;
00117 }
00118 
00119 ssize_t LocalFileHandle::write(const void *buffer, size_t length) {
00120     ssize_t n = semihost_write(_fh, (const unsigned char*)buffer, length, 0); // number of characters not written
00121     n = length - n; // number of characters written
00122     pos += n;
00123     return n;
00124 }
00125 
00126 ssize_t LocalFileHandle::read(void *buffer, size_t length) {
00127     ssize_t n = semihost_read(_fh, (unsigned char*)buffer, length, 0); // number of characters not read
00128     n = length - n; // number of characters read
00129     pos += n;
00130     return n;
00131 }
00132 
00133 int LocalFileHandle::isatty() {
00134     return semihost_istty(_fh);
00135 }
00136 
00137 off_t LocalFileHandle::lseek(off_t position, int whence) {
00138     if (whence == SEEK_CUR) {
00139         position += pos;
00140     } else if (whence == SEEK_END) {
00141         position += semihost_flen(_fh);
00142     } /* otherwise SEEK_SET, so position is fine */
00143 
00144     /* Always seems to return -1, so just ignore for now. */
00145     semihost_seek(_fh, position);
00146     pos = position;
00147     return position;
00148 }
00149 
00150 int LocalFileHandle::fsync() {
00151     return semihost_ensure(_fh);
00152 }
00153 
00154 off_t LocalFileHandle::flen() {
00155     return semihost_flen(_fh);
00156 }
00157 
00158 class LocalDirHandle : public DirHandle {
00159 
00160 public:
00161     struct dirent cur_entry;
00162     XFINFO info;
00163 
00164     LocalDirHandle() : cur_entry(), info() {
00165     }
00166 
00167     virtual int closedir() {
00168         delete this;
00169         return 0;
00170     }
00171 
00172     virtual struct dirent *readdir() {
00173         if (xffind("*", &info)!=0) {
00174             return NULL;
00175         }
00176         memcpy(cur_entry.d_name, info.name, sizeof(info.name));
00177         return &cur_entry;
00178     }
00179 
00180     virtual void rewinddir() {
00181         info.fileID = 0;
00182     }
00183 
00184     virtual off_t telldir() {
00185         return info.fileID;
00186     }
00187 
00188     virtual void seekdir(off_t offset) {
00189         info.fileID = offset;
00190     }
00191 };
00192 
00193 FileHandle *LocalFileSystem::open(const char* name, int flags) {
00194     /* reject filenames with / in them */
00195     for (const char *tmp = name; *tmp; tmp++) {
00196         if (*tmp == '/') {
00197             return NULL;
00198         }
00199     }
00200 
00201     int openmode = posix_to_semihost_open_flags(flags);
00202     if (openmode == OPEN_INVALID) {
00203         return NULL;
00204     }
00205 
00206     FILEHANDLE fh = semihost_open(name, openmode);
00207     if (fh == -1) {
00208         return NULL;
00209     }
00210     return new LocalFileHandle(fh);
00211 }
00212 
00213 int LocalFileSystem::remove(const char *filename) {
00214     return semihost_remove(filename);
00215 }
00216 
00217 DirHandle *LocalFileSystem::opendir(const char *name) {
00218     return new LocalDirHandle();
00219 }
00220 
00221 } // namespace mbed
00222 
00223 #endif