initial

Dependencies:   mbed

Committer:
yihui
Date:
Mon Jan 11 02:32:24 2016 +0000
Revision:
0:638edba3adf6
initial

Who changed what in which revision?

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