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