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 unsigned param[4]; 00050 00051 param[0] = (unsigned long)pattern; 00052 param[1] = (unsigned long)strlen(pattern); 00053 param[2] = (unsigned long)info; 00054 param[3] = (unsigned long)sizeof(XFINFO); 00055 00056 return __semihost(USR_XFFIND, param); 00057 } 00058 00059 #define OPEN_R 0 00060 #define OPEN_B 1 00061 #define OPEN_PLUS 2 00062 #define OPEN_W 4 00063 #define OPEN_A 8 00064 #define OPEN_INVALID -1 00065 00066 int posix_to_semihost_open_flags(int flags) { 00067 /* POSIX flags -> semihosting open mode */ 00068 int openmode; 00069 if (flags & O_RDWR) { 00070 /* a plus mode */ 00071 openmode = OPEN_PLUS; 00072 if (flags & O_APPEND) { 00073 openmode |= OPEN_A; 00074 } else if (flags & O_TRUNC) { 00075 openmode |= OPEN_W; 00076 } else { 00077 openmode |= OPEN_R; 00078 } 00079 } else if (flags & O_WRONLY) { 00080 /* write or append */ 00081 if (flags & O_APPEND) { 00082 openmode = OPEN_A; 00083 } else { 00084 openmode = OPEN_W; 00085 } 00086 } else if (flags == O_RDONLY) { 00087 /* read mode */ 00088 openmode = OPEN_R; 00089 } else { 00090 /* invalid flags */ 00091 openmode = OPEN_INVALID; 00092 } 00093 00094 return openmode; 00095 } 00096 00097 FILEHANDLE local_file_open(const char* name, int flags) { 00098 int openmode = posix_to_semihost_open_flags(flags); 00099 if (openmode == OPEN_INVALID) { 00100 return (FILEHANDLE)NULL; 00101 } 00102 00103 FILEHANDLE fh = semihost_open(name, openmode); 00104 if (fh == -1) { 00105 return (FILEHANDLE)NULL; 00106 } 00107 00108 return fh; 00109 } 00110 00111 LocalFileHandle::LocalFileHandle(FILEHANDLE fh) : _fh(fh), pos(0) { 00112 // No lock needed in constructor 00113 } 00114 00115 int LocalFileHandle::close() { 00116 int retval = semihost_close(_fh); 00117 delete this; 00118 return retval; 00119 } 00120 00121 ssize_t LocalFileHandle::write(const void *buffer, size_t length) { 00122 lock(); 00123 ssize_t n = semihost_write(_fh, (const unsigned char*)buffer, length, 0); // number of characters not written 00124 n = length - n; // number of characters written 00125 pos += n; 00126 unlock(); 00127 return n; 00128 } 00129 00130 ssize_t LocalFileHandle::read(void *buffer, size_t length) { 00131 lock(); 00132 ssize_t n = semihost_read(_fh, (unsigned char*)buffer, length, 0); // number of characters not read 00133 n = length - n; // number of characters read 00134 pos += n; 00135 unlock(); 00136 return n; 00137 } 00138 00139 int LocalFileHandle::isatty() { 00140 lock(); 00141 int ret = semihost_istty(_fh); 00142 unlock(); 00143 return ret; 00144 } 00145 00146 off_t LocalFileHandle::seek(off_t position, int whence) { 00147 lock(); 00148 if (whence == SEEK_CUR) { 00149 position += pos; 00150 } else if (whence == SEEK_END) { 00151 position += semihost_flen(_fh); 00152 } /* otherwise SEEK_SET, so position is fine */ 00153 00154 /* Always seems to return -1, so just ignore for now. */ 00155 semihost_seek(_fh, position); 00156 pos = position; 00157 unlock(); 00158 return position; 00159 } 00160 00161 int LocalFileHandle::sync() { 00162 lock(); 00163 int ret = semihost_ensure(_fh); 00164 unlock(); 00165 return ret; 00166 } 00167 00168 off_t LocalFileHandle::size() { 00169 lock(); 00170 off_t off = semihost_flen(_fh); 00171 unlock(); 00172 return off; 00173 } 00174 00175 void LocalFileHandle::lock() { 00176 _mutex.lock(); 00177 } 00178 00179 void LocalFileHandle::unlock() { 00180 _mutex.unlock(); 00181 } 00182 00183 class LocalDirHandle : public DirHandle { 00184 00185 public: 00186 XFINFO info; 00187 00188 LocalDirHandle() : info() { 00189 } 00190 00191 virtual int close() { 00192 // No lock can be used in destructor 00193 delete this; 00194 return 0; 00195 } 00196 00197 virtual int read(struct dirent *ent) { 00198 lock(); 00199 if (xffind("*", &info)!=0) { 00200 unlock(); 00201 return 0; 00202 } 00203 memcpy(ent->d_name, info.name, sizeof(info.name)); 00204 unlock(); 00205 return 1; 00206 } 00207 00208 virtual void rewind() { 00209 lock(); 00210 info.fileID = 0; 00211 unlock(); 00212 } 00213 00214 virtual off_t tell() { 00215 lock(); 00216 int fileId = info.fileID; 00217 unlock(); 00218 return fileId; 00219 } 00220 00221 virtual void seek(off_t offset) { 00222 lock(); 00223 info.fileID = offset; 00224 unlock(); 00225 } 00226 00227 protected: 00228 PlatformMutex _mutex; 00229 00230 virtual void lock() { 00231 _mutex.lock(); 00232 } 00233 00234 virtual void unlock() { 00235 _mutex.unlock(); 00236 } 00237 }; 00238 00239 int LocalFileSystem::open(FileHandle **file, const char* name, int flags) { 00240 // No global state modified so function is thread safe 00241 00242 /* reject filenames with / in them */ 00243 for (const char *tmp = name; *tmp; tmp++) { 00244 if (*tmp == '/') { 00245 return -EINVAL; 00246 } 00247 } 00248 00249 int openmode = posix_to_semihost_open_flags(flags); 00250 if (openmode == OPEN_INVALID) { 00251 return -EINVAL; 00252 } 00253 00254 FILEHANDLE fh = semihost_open(name, openmode); 00255 if (fh == -1) { 00256 return -EIO; 00257 } 00258 00259 *file = new LocalFileHandle(fh); 00260 return 0; 00261 } 00262 00263 int LocalFileSystem::remove(const char *filename) { 00264 // No global state modified so function is thread safe 00265 00266 return semihost_remove(filename); 00267 } 00268 00269 int LocalFileSystem::open(DirHandle **dir, const char *name) { 00270 // No global state modified so function is thread safe 00271 00272 *dir = new LocalDirHandle(); 00273 return 0; 00274 } 00275 00276 } // namespace mbed 00277 00278 #endif
Generated on Tue Jul 12 2022 14:23:51 by
