mbed library sources

Dependents:   PA_Boost_test

Fork of mbed-src by mbed official

Committer:
emilmont
Date:
Fri Jun 14 17:49:17 2013 +0100
Revision:
10:3bc89ef62ce7
Parent:
9:0ce32e54c9a7
Child:
13:0645d8841f51
Unify mbed library sources

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emilmont 10:3bc89ef62ce7 1 /* mbed Microcontroller Library
emilmont 10:3bc89ef62ce7 2 * Copyright (c) 2006-2013 ARM Limited
emilmont 10:3bc89ef62ce7 3 *
emilmont 10:3bc89ef62ce7 4 * Licensed under the Apache License, Version 2.0 (the "License");
emilmont 10:3bc89ef62ce7 5 * you may not use this file except in compliance with the License.
emilmont 10:3bc89ef62ce7 6 * You may obtain a copy of the License at
emilmont 10:3bc89ef62ce7 7 *
emilmont 10:3bc89ef62ce7 8 * http://www.apache.org/licenses/LICENSE-2.0
emilmont 10:3bc89ef62ce7 9 *
emilmont 10:3bc89ef62ce7 10 * Unless required by applicable law or agreed to in writing, software
emilmont 10:3bc89ef62ce7 11 * distributed under the License is distributed on an "AS IS" BASIS,
emilmont 10:3bc89ef62ce7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
emilmont 10:3bc89ef62ce7 13 * See the License for the specific language governing permissions and
emilmont 10:3bc89ef62ce7 14 * limitations under the License.
emilmont 10:3bc89ef62ce7 15 */
emilmont 10:3bc89ef62ce7 16 #include "LocalFileSystem.h"
emilmont 10:3bc89ef62ce7 17
emilmont 10:3bc89ef62ce7 18 #if DEVICE_LOCALFILESYSTEM
emilmont 10:3bc89ef62ce7 19
emilmont 10:3bc89ef62ce7 20 #include "semihost_api.h"
emilmont 10:3bc89ef62ce7 21 #include <string.h>
emilmont 10:3bc89ef62ce7 22 #include <stdio.h>
emilmont 10:3bc89ef62ce7 23
emilmont 10:3bc89ef62ce7 24 namespace mbed {
emilmont 10:3bc89ef62ce7 25
emilmont 10:3bc89ef62ce7 26 /* Extension to FINFO type defined in RTL.h (in Keil RL) - adds 'create time'. */
emilmont 10:3bc89ef62ce7 27 typedef struct {
emilmont 10:3bc89ef62ce7 28 unsigned char hr; /* Hours [0..23] */
emilmont 10:3bc89ef62ce7 29 unsigned char min; /* Minutes [0..59] */
emilmont 10:3bc89ef62ce7 30 unsigned char sec; /* Seconds [0..59] */
emilmont 10:3bc89ef62ce7 31 unsigned char day; /* Day [1..31] */
emilmont 10:3bc89ef62ce7 32 unsigned char mon; /* Month [1..12] */
emilmont 10:3bc89ef62ce7 33 unsigned short year; /* Year [1980..2107] */
emilmont 10:3bc89ef62ce7 34 } FTIME;
emilmont 10:3bc89ef62ce7 35
emilmont 10:3bc89ef62ce7 36 typedef struct { /* File Search info record */
emilmont 10:3bc89ef62ce7 37 char name[32]; /* File name */
emilmont 10:3bc89ef62ce7 38 long size; /* File size in bytes */
emilmont 10:3bc89ef62ce7 39 int fileID; /* System File Identification */
emilmont 10:3bc89ef62ce7 40 FTIME create_time; /* Date & time file was created */
emilmont 10:3bc89ef62ce7 41 FTIME write_time; /* Date & time of last write */
emilmont 10:3bc89ef62ce7 42 } XFINFO;
emilmont 10:3bc89ef62ce7 43
emilmont 10:3bc89ef62ce7 44 #define RESERVED_FOR_USER_APPLICATIONS (0x100) /* 0x100 - 0x1ff */
emilmont 10:3bc89ef62ce7 45 #define USR_XFFIND (RESERVED_FOR_USER_APPLICATIONS + 0)
emilmont 10:3bc89ef62ce7 46
emilmont 10:3bc89ef62ce7 47 static int xffind (const char *pattern, XFINFO *info) {
emilmont 10:3bc89ef62ce7 48 unsigned param[4];
emilmont 10:3bc89ef62ce7 49
emilmont 10:3bc89ef62ce7 50 param[0] = (unsigned long)pattern;
emilmont 10:3bc89ef62ce7 51 param[1] = (unsigned long)strlen(pattern);
emilmont 10:3bc89ef62ce7 52 param[2] = (unsigned long)info;
emilmont 10:3bc89ef62ce7 53 param[3] = (unsigned long)sizeof(XFINFO);
emilmont 10:3bc89ef62ce7 54
emilmont 10:3bc89ef62ce7 55 return __semihost(USR_XFFIND, param);
emilmont 10:3bc89ef62ce7 56 }
emilmont 10:3bc89ef62ce7 57
emilmont 10:3bc89ef62ce7 58 #define OPEN_R 0
emilmont 10:3bc89ef62ce7 59 #define OPEN_B 1
emilmont 10:3bc89ef62ce7 60 #define OPEN_PLUS 2
emilmont 10:3bc89ef62ce7 61 #define OPEN_W 4
emilmont 10:3bc89ef62ce7 62 #define OPEN_A 8
emilmont 10:3bc89ef62ce7 63 #define OPEN_INVALID -1
emilmont 10:3bc89ef62ce7 64
emilmont 10:3bc89ef62ce7 65 int posix_to_semihost_open_flags(int flags) {
emilmont 10:3bc89ef62ce7 66 /* POSIX flags -> semihosting open mode */
emilmont 10:3bc89ef62ce7 67 int openmode;
emilmont 10:3bc89ef62ce7 68 if (flags & O_RDWR) {
emilmont 10:3bc89ef62ce7 69 /* a plus mode */
emilmont 10:3bc89ef62ce7 70 openmode = OPEN_PLUS;
emilmont 10:3bc89ef62ce7 71 if (flags & O_APPEND) {
emilmont 10:3bc89ef62ce7 72 openmode |= OPEN_A;
emilmont 10:3bc89ef62ce7 73 } else if (flags & O_TRUNC) {
emilmont 10:3bc89ef62ce7 74 openmode |= OPEN_W;
emilmont 10:3bc89ef62ce7 75 } else {
emilmont 10:3bc89ef62ce7 76 openmode |= OPEN_R;
emilmont 10:3bc89ef62ce7 77 }
emilmont 10:3bc89ef62ce7 78 } else if (flags & O_WRONLY) {
emilmont 10:3bc89ef62ce7 79 /* write or append */
emilmont 10:3bc89ef62ce7 80 if (flags & O_APPEND) {
emilmont 10:3bc89ef62ce7 81 openmode = OPEN_A;
emilmont 10:3bc89ef62ce7 82 } else {
emilmont 10:3bc89ef62ce7 83 openmode = OPEN_W;
emilmont 10:3bc89ef62ce7 84 }
emilmont 10:3bc89ef62ce7 85 } else if (flags == O_RDONLY) {
emilmont 10:3bc89ef62ce7 86 /* read mode */
emilmont 10:3bc89ef62ce7 87 openmode = OPEN_R;
emilmont 10:3bc89ef62ce7 88 } else {
emilmont 10:3bc89ef62ce7 89 /* invalid flags */
emilmont 10:3bc89ef62ce7 90 openmode = OPEN_INVALID;
emilmont 10:3bc89ef62ce7 91 }
emilmont 10:3bc89ef62ce7 92
emilmont 10:3bc89ef62ce7 93 return openmode;
emilmont 10:3bc89ef62ce7 94 }
emilmont 10:3bc89ef62ce7 95
emilmont 10:3bc89ef62ce7 96 FILEHANDLE local_file_open(const char* name, int flags) {
emilmont 10:3bc89ef62ce7 97 int openmode = posix_to_semihost_open_flags(flags);
emilmont 10:3bc89ef62ce7 98 if (openmode == OPEN_INVALID) {
emilmont 10:3bc89ef62ce7 99 return (FILEHANDLE)NULL;
emilmont 10:3bc89ef62ce7 100 }
emilmont 10:3bc89ef62ce7 101
emilmont 10:3bc89ef62ce7 102 FILEHANDLE fh = semihost_open(name, openmode);
emilmont 10:3bc89ef62ce7 103 if (fh == -1) {
emilmont 10:3bc89ef62ce7 104 return (FILEHANDLE)NULL;
emilmont 10:3bc89ef62ce7 105 }
emilmont 10:3bc89ef62ce7 106
emilmont 10:3bc89ef62ce7 107 return fh;
emilmont 10:3bc89ef62ce7 108 }
emilmont 10:3bc89ef62ce7 109
emilmont 10:3bc89ef62ce7 110 LocalFileHandle::LocalFileHandle(FILEHANDLE fh) {
emilmont 10:3bc89ef62ce7 111 _fh = fh;
emilmont 10:3bc89ef62ce7 112 pos = 0;
emilmont 10:3bc89ef62ce7 113 }
emilmont 10:3bc89ef62ce7 114
emilmont 10:3bc89ef62ce7 115 int LocalFileHandle::close() {
emilmont 10:3bc89ef62ce7 116 int retval = semihost_close(_fh);
emilmont 10:3bc89ef62ce7 117 delete this;
emilmont 10:3bc89ef62ce7 118 return retval;
emilmont 10:3bc89ef62ce7 119 }
emilmont 10:3bc89ef62ce7 120
emilmont 10:3bc89ef62ce7 121 ssize_t LocalFileHandle::write(const void *buffer, size_t length) {
emilmont 10:3bc89ef62ce7 122 ssize_t n = semihost_write(_fh, (const unsigned char*)buffer, length, 0); // number of characters not written
emilmont 10:3bc89ef62ce7 123 n = length - n; // number of characters written
emilmont 10:3bc89ef62ce7 124 pos += n;
emilmont 10:3bc89ef62ce7 125 return n;
emilmont 10:3bc89ef62ce7 126 }
emilmont 10:3bc89ef62ce7 127
emilmont 10:3bc89ef62ce7 128 ssize_t LocalFileHandle::read(void *buffer, size_t length) {
emilmont 10:3bc89ef62ce7 129 ssize_t n = semihost_read(_fh, (unsigned char*)buffer, length, 0); // number of characters not read
emilmont 10:3bc89ef62ce7 130 n = length - n; // number of characters read
emilmont 10:3bc89ef62ce7 131 pos += n;
emilmont 10:3bc89ef62ce7 132 return n;
emilmont 10:3bc89ef62ce7 133 }
emilmont 10:3bc89ef62ce7 134
emilmont 10:3bc89ef62ce7 135 int LocalFileHandle::isatty() {
emilmont 10:3bc89ef62ce7 136 return semihost_istty(_fh);
emilmont 10:3bc89ef62ce7 137 }
emilmont 10:3bc89ef62ce7 138
emilmont 10:3bc89ef62ce7 139 off_t LocalFileHandle::lseek(off_t position, int whence) {
emilmont 10:3bc89ef62ce7 140 if (whence == SEEK_CUR) {
emilmont 10:3bc89ef62ce7 141 position += pos;
emilmont 10:3bc89ef62ce7 142 } else if (whence == SEEK_END) {
emilmont 10:3bc89ef62ce7 143 position += semihost_flen(_fh);
emilmont 10:3bc89ef62ce7 144 } /* otherwise SEEK_SET, so position is fine */
emilmont 10:3bc89ef62ce7 145
emilmont 10:3bc89ef62ce7 146 /* Always seems to return -1, so just ignore for now. */
emilmont 10:3bc89ef62ce7 147 semihost_seek(_fh, position);
emilmont 10:3bc89ef62ce7 148 pos = position;
emilmont 10:3bc89ef62ce7 149 return position;
emilmont 10:3bc89ef62ce7 150 }
emilmont 10:3bc89ef62ce7 151
emilmont 10:3bc89ef62ce7 152 int LocalFileHandle::fsync() {
emilmont 10:3bc89ef62ce7 153 return semihost_ensure(_fh);
emilmont 10:3bc89ef62ce7 154 }
emilmont 10:3bc89ef62ce7 155
emilmont 10:3bc89ef62ce7 156 off_t LocalFileHandle::flen() {
emilmont 10:3bc89ef62ce7 157 return semihost_flen(_fh);
emilmont 10:3bc89ef62ce7 158 }
emilmont 10:3bc89ef62ce7 159
emilmont 10:3bc89ef62ce7 160 class LocalDirHandle : public DirHandle {
emilmont 10:3bc89ef62ce7 161
emilmont 10:3bc89ef62ce7 162 public:
emilmont 10:3bc89ef62ce7 163 struct dirent cur_entry;
emilmont 10:3bc89ef62ce7 164 XFINFO info;
emilmont 10:3bc89ef62ce7 165
emilmont 10:3bc89ef62ce7 166 LocalDirHandle() {
emilmont 10:3bc89ef62ce7 167 info.fileID = 0;
emilmont 10:3bc89ef62ce7 168 }
emilmont 10:3bc89ef62ce7 169
emilmont 10:3bc89ef62ce7 170 virtual int closedir() {
emilmont 10:3bc89ef62ce7 171 delete this;
emilmont 10:3bc89ef62ce7 172 return 0;
emilmont 10:3bc89ef62ce7 173 }
emilmont 10:3bc89ef62ce7 174
emilmont 10:3bc89ef62ce7 175 virtual struct dirent *readdir() {
emilmont 10:3bc89ef62ce7 176 if (xffind("*", &info)!=0) {
emilmont 10:3bc89ef62ce7 177 return NULL;
emilmont 10:3bc89ef62ce7 178 }
emilmont 10:3bc89ef62ce7 179 memcpy(cur_entry.d_name, info.name, sizeof(info.name));
emilmont 10:3bc89ef62ce7 180 return &cur_entry;
emilmont 10:3bc89ef62ce7 181 }
emilmont 10:3bc89ef62ce7 182
emilmont 10:3bc89ef62ce7 183 virtual void rewinddir() {
emilmont 10:3bc89ef62ce7 184 info.fileID = 0;
emilmont 10:3bc89ef62ce7 185 }
emilmont 10:3bc89ef62ce7 186
emilmont 10:3bc89ef62ce7 187 virtual off_t telldir() {
emilmont 10:3bc89ef62ce7 188 return info.fileID;
emilmont 10:3bc89ef62ce7 189 }
emilmont 10:3bc89ef62ce7 190
emilmont 10:3bc89ef62ce7 191 virtual void seekdir(off_t offset) {
emilmont 10:3bc89ef62ce7 192 info.fileID = offset;
emilmont 10:3bc89ef62ce7 193 }
emilmont 10:3bc89ef62ce7 194 };
emilmont 10:3bc89ef62ce7 195
emilmont 10:3bc89ef62ce7 196 FileHandle *LocalFileSystem::open(const char* name, int flags) {
emilmont 10:3bc89ef62ce7 197 /* reject filenames with / in them */
emilmont 10:3bc89ef62ce7 198 for (const char *tmp = name; *tmp; tmp++) {
emilmont 10:3bc89ef62ce7 199 if (*tmp == '/') {
emilmont 10:3bc89ef62ce7 200 return NULL;
emilmont 10:3bc89ef62ce7 201 }
emilmont 10:3bc89ef62ce7 202 }
emilmont 10:3bc89ef62ce7 203
emilmont 10:3bc89ef62ce7 204 int openmode = posix_to_semihost_open_flags(flags);
emilmont 10:3bc89ef62ce7 205 if (openmode == OPEN_INVALID) {
emilmont 10:3bc89ef62ce7 206 return NULL;
emilmont 10:3bc89ef62ce7 207 }
emilmont 10:3bc89ef62ce7 208
emilmont 10:3bc89ef62ce7 209 FILEHANDLE fh = semihost_open(name, openmode);
emilmont 10:3bc89ef62ce7 210 if (fh == -1) {
emilmont 10:3bc89ef62ce7 211 return NULL;
emilmont 10:3bc89ef62ce7 212 }
emilmont 10:3bc89ef62ce7 213 return new LocalFileHandle(fh);
emilmont 10:3bc89ef62ce7 214 }
emilmont 10:3bc89ef62ce7 215
emilmont 10:3bc89ef62ce7 216 int LocalFileSystem::remove(const char *filename) {
emilmont 10:3bc89ef62ce7 217 return semihost_remove(filename);
emilmont 10:3bc89ef62ce7 218 }
emilmont 10:3bc89ef62ce7 219
emilmont 10:3bc89ef62ce7 220 DirHandle *LocalFileSystem::opendir(const char *name) {
emilmont 10:3bc89ef62ce7 221 return new LocalDirHandle();
emilmont 10:3bc89ef62ce7 222 }
emilmont 10:3bc89ef62ce7 223
emilmont 10:3bc89ef62ce7 224 } // namespace mbed
emilmont 10:3bc89ef62ce7 225
emilmont 10:3bc89ef62ce7 226 #endif