mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... 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  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #include "platform/LocalFileSystem.h"
00018 
00019 #if DEVICE_LOCALFILESYSTEM
00020 
00021 #include "platform/mbed_semihost_api.h"
00022 #include <string.h>
00023 #include <stdio.h>
00024 #include <errno.h>
00025 
00026 namespace mbed {
00027 
00028 /* Extension to FINFO type defined in RTL.h (in Keil RL) - adds 'create time'. */
00029 typedef struct {
00030     unsigned char  hr;   /* Hours    [0..23]                  */
00031     unsigned char  min;  /* Minutes  [0..59]                  */
00032     unsigned char  sec;  /* Seconds  [0..59]                  */
00033     unsigned char  day;  /* Day      [1..31]                  */
00034     unsigned char  mon;  /* Month    [1..12]                  */
00035     unsigned short year; /* Year     [1980..2107]             */
00036 } FTIME;
00037 
00038 typedef struct {         /* File Search info record           */
00039     char  name[32];      /* File name                         */
00040     long  size;          /* File size in bytes                */
00041     int   fileID;        /* System File Identification        */
00042     FTIME create_time;   /* Date & time file was created      */
00043     FTIME write_time;    /* Date & time of last write         */
00044 } XFINFO;
00045 
00046 #define RESERVED_FOR_USER_APPLICATIONS (0x100) /* 0x100 - 0x1ff */
00047 #define USR_XFFIND (RESERVED_FOR_USER_APPLICATIONS + 0)
00048 
00049 static int xffind(const char *pattern, XFINFO *info)
00050 {
00051     unsigned param[4];
00052 
00053     param[0] = (unsigned long)pattern;
00054     param[1] = (unsigned long)strlen(pattern);
00055     param[2] = (unsigned long)info;
00056     param[3] = (unsigned long)sizeof(XFINFO);
00057 
00058     return __semihost(USR_XFFIND, param);
00059 }
00060 
00061 #define OPEN_R          0
00062 #define OPEN_B          1
00063 #define OPEN_PLUS       2
00064 #define OPEN_W          4
00065 #define OPEN_A          8
00066 #define OPEN_INVALID   -1
00067 
00068 int posix_to_semihost_open_flags(int flags)
00069 {
00070     /* POSIX flags -> semihosting open mode */
00071     int openmode;
00072     if (flags & O_RDWR) {
00073         /* a plus mode */
00074         openmode = OPEN_PLUS;
00075         if (flags & O_APPEND) {
00076             openmode |= OPEN_A;
00077         } else if (flags & O_TRUNC) {
00078             openmode |= OPEN_W;
00079         } else {
00080             openmode |= OPEN_R;
00081         }
00082     } else if (flags & O_WRONLY) {
00083         /* write or append */
00084         if (flags & O_APPEND) {
00085             openmode = OPEN_A;
00086         } else {
00087             openmode = OPEN_W;
00088         }
00089     } else if (flags == O_RDONLY) {
00090         /* read mode */
00091         openmode = OPEN_R;
00092     } else {
00093         /* invalid flags */
00094         openmode = OPEN_INVALID;
00095     }
00096 
00097     return openmode;
00098 }
00099 
00100 FILEHANDLE local_file_open(const char *name, int flags)
00101 {
00102     int openmode = posix_to_semihost_open_flags(flags);
00103     if (openmode == OPEN_INVALID) {
00104         return (FILEHANDLE)NULL;
00105     }
00106 
00107     FILEHANDLE fh = semihost_open(name, openmode);
00108     if (fh == -1) {
00109         return (FILEHANDLE)NULL;
00110     }
00111 
00112     return fh;
00113 }
00114 
00115 LocalFileHandle::LocalFileHandle(FILEHANDLE fh) : _fh(fh), pos(0)
00116 {
00117     // No lock needed in constructor
00118 }
00119 
00120 int LocalFileHandle::close()
00121 {
00122     int retval = semihost_close(_fh);
00123     delete this;
00124     return retval;
00125 }
00126 
00127 ssize_t LocalFileHandle::write(const void *buffer, size_t length)
00128 {
00129     lock();
00130     ssize_t n = semihost_write(_fh, (const unsigned char *)buffer, length, 0); // number of characters not written
00131     n = length - n; // number of characters written
00132     pos += n;
00133     unlock();
00134     return n;
00135 }
00136 
00137 ssize_t LocalFileHandle::read(void *buffer, size_t length)
00138 {
00139     lock();
00140     ssize_t n = semihost_read(_fh, (unsigned char *)buffer, length, 0); // number of characters not read
00141     n = length - n; // number of characters read
00142     pos += n;
00143     unlock();
00144     return n;
00145 }
00146 
00147 int LocalFileHandle::isatty()
00148 {
00149     lock();
00150     int ret = semihost_istty(_fh);
00151     unlock();
00152     return ret;
00153 }
00154 
00155 off_t LocalFileHandle::seek(off_t position, int whence)
00156 {
00157     lock();
00158     if (whence == SEEK_CUR) {
00159         position += pos;
00160     } else if (whence == SEEK_END) {
00161         position += semihost_flen(_fh);
00162     } /* otherwise SEEK_SET, so position is fine */
00163 
00164     /* Always seems to return -1, so just ignore for now. */
00165     semihost_seek(_fh, position);
00166     pos = position;
00167     unlock();
00168     return position;
00169 }
00170 
00171 int LocalFileHandle::sync()
00172 {
00173     lock();
00174     int ret = semihost_ensure(_fh);
00175     unlock();
00176     return ret;
00177 }
00178 
00179 off_t LocalFileHandle::size()
00180 {
00181     lock();
00182     off_t off = semihost_flen(_fh);
00183     unlock();
00184     return off;
00185 }
00186 
00187 void LocalFileHandle::lock()
00188 {
00189     _mutex.lock();
00190 }
00191 
00192 void LocalFileHandle::unlock()
00193 {
00194     _mutex.unlock();
00195 }
00196 
00197 class LocalDirHandle : public DirHandle {
00198 
00199 public:
00200     XFINFO info;
00201 
00202     LocalDirHandle() : info()
00203     {
00204     }
00205 
00206     virtual int close()
00207     {
00208         // No lock can be used in destructor
00209         delete this;
00210         return 0;
00211     }
00212 
00213     virtual int read(struct dirent *ent)
00214     {
00215         lock();
00216         if (xffind("*", &info) != 0) {
00217             unlock();
00218             return 0;
00219         }
00220         memcpy(ent->d_name, info.name, sizeof(info.name));
00221         unlock();
00222         return 1;
00223     }
00224 
00225     virtual void rewind()
00226     {
00227         lock();
00228         info.fileID = 0;
00229         unlock();
00230     }
00231 
00232     virtual off_t tell()
00233     {
00234         lock();
00235         int fileId = info.fileID;
00236         unlock();
00237         return fileId;
00238     }
00239 
00240     virtual void seek(off_t offset)
00241     {
00242         lock();
00243         info.fileID = offset;
00244         unlock();
00245     }
00246 
00247 protected:
00248     PlatformMutex _mutex;
00249 
00250     virtual void lock()
00251     {
00252         _mutex.lock();
00253     }
00254 
00255     virtual void unlock()
00256     {
00257         _mutex.unlock();
00258     }
00259 };
00260 
00261 int LocalFileSystem::open(FileHandle **file, const char *name, int flags)
00262 {
00263     // No global state modified so function is thread safe
00264 
00265     /* reject filenames with / in them */
00266     for (const char *tmp = name; *tmp; tmp++) {
00267         if (*tmp == '/') {
00268             return -EINVAL;
00269         }
00270     }
00271 
00272     int openmode = posix_to_semihost_open_flags(flags);
00273     if (openmode == OPEN_INVALID) {
00274         return -EINVAL;
00275     }
00276 
00277     FILEHANDLE fh = semihost_open(name, openmode);
00278     if (fh == -1) {
00279         return -EIO;
00280     }
00281 
00282     *file = new LocalFileHandle(fh);
00283     return 0;
00284 }
00285 
00286 int LocalFileSystem::remove(const char *filename)
00287 {
00288     // No global state modified so function is thread safe
00289 
00290     return semihost_remove(filename);
00291 }
00292 
00293 int LocalFileSystem::open(DirHandle **dir, const char *name)
00294 {
00295     // No global state modified so function is thread safe
00296 
00297     *dir = new LocalDirHandle();
00298     return 0;
00299 }
00300 
00301 } // namespace mbed
00302 
00303 #endif