mFS file system library for EEPROM memory chips.

Committer:
HBP
Date:
Thu Feb 24 00:02:36 2011 +0000
Revision:
12:928346513c87
Parent:
11:6c4fcb9d6193
Child:
13:142b6be3e3c8
-16 bit block pointers
-Improved file writing capabilities
-Lot of bug fixes

See mfs.h for almost complete list of updates.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
HBP 10:211cb54339a0 1 /** @file mfs.cpp */
HBP 5:a0fe74dce80d 2 /*CPP**************************************************************************
HBP 7:5ac5121bb4e0 3 * FILENAME : mfs.cpp *
HBP 7:5ac5121bb4e0 4 * *
HBP 7:5ac5121bb4e0 5 * DESCRIPTION : *
HBP 7:5ac5121bb4e0 6 * mFS file system implementation for mBED with external I2C EEEPROM. *
HBP 7:5ac5121bb4e0 7 * *
HBP 7:5ac5121bb4e0 8 * AUTHOR : Olli Vanhoja START DATE : 2011-02-21 *
HBP 7:5ac5121bb4e0 9 *****************************************************************************/
HBP 0:cbf45dde2b49 10
HBP 0:cbf45dde2b49 11 #include "mbed.h"
HBP 0:cbf45dde2b49 12 #include "mfs.h"
HBP 0:cbf45dde2b49 13 #include "i2c_eeprom.h"
HBP 0:cbf45dde2b49 14
HBP 12:928346513c87 15 #define BLOCK_LLEN 2 /**< Block number link length in bytes */
HBP 12:928346513c87 16 #define RB 1+2*BLOCK_LLEN /**< Reseved bytes per block (1 attrb B, 2 B for next/prev pointers */
HBP 12:928346513c87 17 #define I2C_SPEED 200000 /**< I2C bus speed in Hz */
HBP 12:928346513c87 18 #define DEBUG /**< Adds extra safety in reading and writing */
HBP 0:cbf45dde2b49 19
HBP 10:211cb54339a0 20 DigitalOut FlushLed(LED2); /**< Flush led */
HBP 0:cbf45dde2b49 21
HBP 0:cbf45dde2b49 22 mfs::mfs(int i2c_address)
HBP 0:cbf45dde2b49 23 {
HBP 10:211cb54339a0 24 mem = new i2c_eeprom(i2c_address, I2C_SPEED);
HBP 0:cbf45dde2b49 25 }
HBP 0:cbf45dde2b49 26
HBP 10:211cb54339a0 27 char mfs::read(char *data, uint32_t block, uint32_t byte, uint32_t n)
HBP 0:cbf45dde2b49 28 {
HBP 0:cbf45dde2b49 29 // Faster reading without DEBUG mode
HBP 0:cbf45dde2b49 30 #ifdef DEBUG
HBP 0:cbf45dde2b49 31 if ((byte+n-1 >= BS))
HBP 0:cbf45dde2b49 32 return 1;
HBP 0:cbf45dde2b49 33 #endif
HBP 0:cbf45dde2b49 34 mem->read(BS*block+byte, n, data);
HBP 12:928346513c87 35
HBP 0:cbf45dde2b49 36 return 0;
HBP 0:cbf45dde2b49 37 }
HBP 0:cbf45dde2b49 38
HBP 10:211cb54339a0 39 char mfs::write(char *data, uint32_t block, uint32_t byte, uint32_t n)
HBP 0:cbf45dde2b49 40 {
HBP 0:cbf45dde2b49 41 // Faster writing without DEBUG mode
HBP 0:cbf45dde2b49 42 #ifdef DEBUG
HBP 0:cbf45dde2b49 43 if (byte+n >= BS)
HBP 0:cbf45dde2b49 44 return 1;
HBP 0:cbf45dde2b49 45 #endif
HBP 0:cbf45dde2b49 46 mem->write(data, BS*block+byte, n);
HBP 12:928346513c87 47
HBP 0:cbf45dde2b49 48 return 0;
HBP 0:cbf45dde2b49 49 }
HBP 0:cbf45dde2b49 50
HBP 10:211cb54339a0 51 char mfs::getNextFreeBlock(uint32_t *blockOut)
HBP 0:cbf45dde2b49 52 {
HBP 0:cbf45dde2b49 53 // Locate free block by seeking EERPOM
HBP 0:cbf45dde2b49 54 char cFlags[1];
HBP 0:cbf45dde2b49 55
HBP 0:cbf45dde2b49 56 for (*blockOut=0; *blockOut < BC; (*blockOut)++)
HBP 0:cbf45dde2b49 57 {
HBP 0:cbf45dde2b49 58 read(cFlags, *blockOut, 0, 1);
HBP 0:cbf45dde2b49 59 if (cFlags[0] == 0x04)
HBP 0:cbf45dde2b49 60 break;
HBP 0:cbf45dde2b49 61 if (*blockOut >= BC-1)
HBP 0:cbf45dde2b49 62 return 1;
HBP 0:cbf45dde2b49 63 }
HBP 0:cbf45dde2b49 64
HBP 0:cbf45dde2b49 65 return 0;
HBP 0:cbf45dde2b49 66 }
HBP 0:cbf45dde2b49 67
HBP 10:211cb54339a0 68 char mfs::findNextFile(uint32_t block, char *filenameOut, uint32_t *blockOut)
HBP 0:cbf45dde2b49 69 {
HBP 9:52c01cb100ac 70 uint32_t i=block;
HBP 0:cbf45dde2b49 71 char cFlags[1];
HBP 0:cbf45dde2b49 72
HBP 0:cbf45dde2b49 73 while (i < BC)
HBP 0:cbf45dde2b49 74 {
HBP 0:cbf45dde2b49 75 read(cFlags, i, 0, 1);
HBP 0:cbf45dde2b49 76
HBP 0:cbf45dde2b49 77 if ((cFlags[0] & 0x8C) == 0x8C)
HBP 0:cbf45dde2b49 78 break; // File found
HBP 0:cbf45dde2b49 79 else
HBP 0:cbf45dde2b49 80 i++;
HBP 0:cbf45dde2b49 81 }
HBP 0:cbf45dde2b49 82
HBP 0:cbf45dde2b49 83 if(i == BC)
HBP 0:cbf45dde2b49 84 {
HBP 0:cbf45dde2b49 85 strcpy(filenameOut, "");
HBP 10:211cb54339a0 86 return 1; // Empty fs
HBP 0:cbf45dde2b49 87 }
HBP 0:cbf45dde2b49 88
HBP 0:cbf45dde2b49 89 // Read filename
HBP 10:211cb54339a0 90 read(filenameOut, i, RB, 20);
HBP 10:211cb54339a0 91 *blockOut = i; // Return block number
HBP 10:211cb54339a0 92 return 0;
HBP 0:cbf45dde2b49 93 }
HBP 0:cbf45dde2b49 94
HBP 10:211cb54339a0 95 char mfs::getFirstBlockOfFile(char filename[20], uint32_t *blockOut)
HBP 0:cbf45dde2b49 96 {
HBP 10:211cb54339a0 97 *blockOut=0;
HBP 0:cbf45dde2b49 98 char tmpFilename[20]="";
HBP 0:cbf45dde2b49 99
HBP 10:211cb54339a0 100 while (1)
HBP 0:cbf45dde2b49 101 {
HBP 10:211cb54339a0 102 if (findNextFile(*blockOut, tmpFilename, blockOut) == 0)
HBP 0:cbf45dde2b49 103 {
HBP 0:cbf45dde2b49 104 if(strcmp(tmpFilename, filename) == 0)
HBP 10:211cb54339a0 105 return 0; // File exists
HBP 0:cbf45dde2b49 106 }
HBP 10:211cb54339a0 107 else return 1; // File doesn't exist
HBP 10:211cb54339a0 108 (*blockOut)++;
HBP 0:cbf45dde2b49 109 }
HBP 0:cbf45dde2b49 110 }
HBP 0:cbf45dde2b49 111
HBP 0:cbf45dde2b49 112 char mfs::createFile(char filename[20])
HBP 0:cbf45dde2b49 113 {
HBP 0:cbf45dde2b49 114 char tmpFilename[20];
HBP 9:52c01cb100ac 115 uint32_t n;
HBP 10:211cb54339a0 116 uint32_t fb;
HBP 0:cbf45dde2b49 117
HBP 0:cbf45dde2b49 118 for (n=0; n < BC; n++)
HBP 0:cbf45dde2b49 119 {
HBP 10:211cb54339a0 120 if(findNextFile(n, tmpFilename, &n) == 0)
HBP 0:cbf45dde2b49 121 {
HBP 0:cbf45dde2b49 122 if(strcmp(tmpFilename, filename) == 0)
HBP 0:cbf45dde2b49 123 return 1; // File exist
HBP 0:cbf45dde2b49 124 }
HBP 0:cbf45dde2b49 125 else break; // We already reached the edge of the universe
HBP 0:cbf45dde2b49 126 n++;
HBP 0:cbf45dde2b49 127 }
HBP 0:cbf45dde2b49 128
HBP 10:211cb54339a0 129 if(getNextFreeBlock(&fb) != 0)
HBP 0:cbf45dde2b49 130 return 2; // Out of space
HBP 0:cbf45dde2b49 131
HBP 10:211cb54339a0 132 char cData[RB+20];
HBP 12:928346513c87 133 cData[0] = '\xCC'; // Necessary flags for a file
HBP 12:928346513c87 134 cData[1] = '\0'; // Only this block yet
HBP 12:928346513c87 135 cData[2] = '\0';
HBP 12:928346513c87 136 cData[3] = '\0'; // First block there could't be prev blocks
HBP 12:928346513c87 137 cData[4] = '\0';
HBP 0:cbf45dde2b49 138
HBP 0:cbf45dde2b49 139 for (char i=0; i < 20; i++)
HBP 10:211cb54339a0 140 cData[RB+i] = filename[i];
HBP 0:cbf45dde2b49 141
HBP 0:cbf45dde2b49 142 // Create file
HBP 10:211cb54339a0 143 write(cData, fb, 0, RB+20);
HBP 0:cbf45dde2b49 144
HBP 0:cbf45dde2b49 145 return 0;
HBP 0:cbf45dde2b49 146 }
HBP 0:cbf45dde2b49 147
HBP 0:cbf45dde2b49 148 char mfs::removeFile(char filename[20])
HBP 0:cbf45dde2b49 149 {
HBP 9:52c01cb100ac 150 uint32_t block;
HBP 12:928346513c87 151 char cData[RB-BLOCK_LLEN];
HBP 12:928346513c87 152 char cDataNew[RB] = {'\x04', '\0', '\0', '\0', '\0'};
HBP 12:928346513c87 153 uint32_t i=0;
HBP 0:cbf45dde2b49 154
HBP 0:cbf45dde2b49 155 // Check if file exists
HBP 11:6c4fcb9d6193 156 if (getFirstBlockOfFile(filename, &block) != 0)
HBP 0:cbf45dde2b49 157 return 1; // File not found
HBP 0:cbf45dde2b49 158
HBP 12:928346513c87 159 read(cData, block, 0, RB-BLOCK_LLEN);
HBP 12:928346513c87 160
HBP 12:928346513c87 161 // Check credentials
HBP 12:928346513c87 162 if (((cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3) & 0x04) != 0)
HBP 12:928346513c87 163 return 2; // RO file
HBP 12:928346513c87 164
HBP 12:928346513c87 165 // Clear blocks reserved by the file
HBP 0:cbf45dde2b49 166 while(1)
HBP 0:cbf45dde2b49 167 {
HBP 12:928346513c87 168 write(cDataNew, block, 0, RB);
HBP 12:928346513c87 169 if ((cData[0] & 0x4C) == 0x4C)
HBP 12:928346513c87 170 break; // End of file found
HBP 12:928346513c87 171 else block = (uint32_t)(cData[1])<<8|cData[2]; // Set next block number
HBP 0:cbf45dde2b49 172 i++;
HBP 12:928346513c87 173 if (i > BC)
HBP 12:928346513c87 174 return 1; // fs is corrupted
HBP 12:928346513c87 175 read(cData, block, 0, RB-BLOCK_LLEN);
HBP 0:cbf45dde2b49 176 }
HBP 0:cbf45dde2b49 177
HBP 0:cbf45dde2b49 178 return 0; // Everything went better than expected
HBP 0:cbf45dde2b49 179 }
HBP 0:cbf45dde2b49 180
HBP 7:5ac5121bb4e0 181 char mfs::renameFile(char oldFilename[20], char newFilename[20])
HBP 7:5ac5121bb4e0 182 {
HBP 9:52c01cb100ac 183 uint32_t block;
HBP 12:928346513c87 184 char cData[1];
HBP 7:5ac5121bb4e0 185
HBP 7:5ac5121bb4e0 186 // Check if file exists
HBP 10:211cb54339a0 187 if (getFirstBlockOfFile(oldFilename, &block) != 0)
HBP 7:5ac5121bb4e0 188 return 1; // File not found
HBP 7:5ac5121bb4e0 189
HBP 12:928346513c87 190 // Check credentials
HBP 12:928346513c87 191 read(cData, block, 0, 1);
HBP 12:928346513c87 192 char flags = (cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3);
HBP 12:928346513c87 193 if ((flags & 0x04) != 0)
HBP 12:928346513c87 194 return 2; // RO file
HBP 12:928346513c87 195
HBP 10:211cb54339a0 196 write(newFilename, block, RB, 20);
HBP 7:5ac5121bb4e0 197
HBP 7:5ac5121bb4e0 198 return 0; // Everything went better than expected
HBP 7:5ac5121bb4e0 199 }
HBP 7:5ac5121bb4e0 200
HBP 0:cbf45dde2b49 201 char mfs::setFileFlags(char *flags, char filename[20])
HBP 0:cbf45dde2b49 202 {
HBP 0:cbf45dde2b49 203 /* RO|HIDDEN|LOCK *
HBP 0:cbf45dde2b49 204 * H L */
HBP 0:cbf45dde2b49 205
HBP 9:52c01cb100ac 206 uint32_t n;
HBP 0:cbf45dde2b49 207 char cData[1] = {'\0'};
HBP 12:928346513c87 208 char cFlags;
HBP 0:cbf45dde2b49 209
HBP 0:cbf45dde2b49 210 // Check if file exists
HBP 10:211cb54339a0 211 if (getFirstBlockOfFile(filename, &n) != 0)
HBP 0:cbf45dde2b49 212 return 1; // File not found
HBP 0:cbf45dde2b49 213
HBP 0:cbf45dde2b49 214 read(cData, n, 0, 1);
HBP 12:928346513c87 215 cFlags = ((flags[0] & 0x01)|((flags[0] & 0x02) << 3)|((flags[0] & 0x04) << 3));
HBP 12:928346513c87 216 cData[0] = cData[0] & (~0x31) | cFlags;
HBP 0:cbf45dde2b49 217 write(cData, n, 0, 1);
HBP 0:cbf45dde2b49 218
HBP 0:cbf45dde2b49 219 return 0;
HBP 0:cbf45dde2b49 220 }
HBP 0:cbf45dde2b49 221
HBP 0:cbf45dde2b49 222 char mfs::getFileFlags(char *flags, char filename[20])
HBP 0:cbf45dde2b49 223 {
HBP 0:cbf45dde2b49 224 /* RO|HIDDEN|LOCK *
HBP 0:cbf45dde2b49 225 * H L */
HBP 0:cbf45dde2b49 226
HBP 9:52c01cb100ac 227 uint32_t n;
HBP 0:cbf45dde2b49 228 char cData[1] = {'\0'};
HBP 0:cbf45dde2b49 229
HBP 0:cbf45dde2b49 230 // Check if file exists
HBP 10:211cb54339a0 231 if (getFirstBlockOfFile(filename, &n) != 0)
HBP 0:cbf45dde2b49 232 return 1; // File not found
HBP 0:cbf45dde2b49 233
HBP 0:cbf45dde2b49 234 read(cData, n, 0, 1);
HBP 0:cbf45dde2b49 235 flags[0] = (cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3);
HBP 0:cbf45dde2b49 236
HBP 0:cbf45dde2b49 237 return 0;
HBP 0:cbf45dde2b49 238 }
HBP 0:cbf45dde2b49 239
HBP 0:cbf45dde2b49 240 // Return number of free blocks
HBP 10:211cb54339a0 241 uint32_t mfs::free()
HBP 0:cbf45dde2b49 242 {
HBP 10:211cb54339a0 243 uint32_t blocks=0;
HBP 10:211cb54339a0 244 uint32_t r;
HBP 0:cbf45dde2b49 245 char cFlags[1];
HBP 0:cbf45dde2b49 246
HBP 0:cbf45dde2b49 247 for (r=0; r < BC; r++)
HBP 0:cbf45dde2b49 248 {
HBP 0:cbf45dde2b49 249 read(cFlags, r, 0, 1);
HBP 0:cbf45dde2b49 250 if (cFlags[0] == 0x04)
HBP 0:cbf45dde2b49 251 blocks++;
HBP 0:cbf45dde2b49 252 if (r >= BC-1)
HBP 0:cbf45dde2b49 253 return blocks;
HBP 0:cbf45dde2b49 254 }
HBP 0:cbf45dde2b49 255
HBP 0:cbf45dde2b49 256 return 0;
HBP 0:cbf45dde2b49 257 }
HBP 0:cbf45dde2b49 258
HBP 10:211cb54339a0 259 uint32_t mfs::mkfs(bool createLabel)
HBP 0:cbf45dde2b49 260 {
HBP 10:211cb54339a0 261 uint32_t iAddr = 0;
HBP 10:211cb54339a0 262 uint32_t i = 0;
HBP 10:211cb54339a0 263 uint32_t bad = 0; // For counting bad block headers
HBP 12:928346513c87 264 char cFlags[RB] = {'\0', '\0', '\0', '\0', '\0'}, o[1];
HBP 0:cbf45dde2b49 265
HBP 10:211cb54339a0 266 if (createLabel == true)
HBP 0:cbf45dde2b49 267 {
HBP 0:cbf45dde2b49 268 // Write Volume label
HBP 0:cbf45dde2b49 269 cFlags[0] = '\x0E';
HBP 12:928346513c87 270 mem->write(cFlags, iAddr, RB);
HBP 0:cbf45dde2b49 271 iAddr = BS;
HBP 0:cbf45dde2b49 272 i = 1;
HBP 0:cbf45dde2b49 273 }
HBP 0:cbf45dde2b49 274
HBP 0:cbf45dde2b49 275 cFlags[0] = '\x04';
HBP 0:cbf45dde2b49 276 for (; i < BC; i++)
HBP 0:cbf45dde2b49 277 {
HBP 12:928346513c87 278 mem->write(cFlags, iAddr, RB);
HBP 12:928346513c87 279 mem->read(iAddr, 1, o);
HBP 12:928346513c87 280 if (o[0] != cFlags[0])
HBP 0:cbf45dde2b49 281 bad++;
HBP 0:cbf45dde2b49 282 iAddr += BS;
HBP 0:cbf45dde2b49 283 }
HBP 0:cbf45dde2b49 284
HBP 0:cbf45dde2b49 285 return bad;
HBP 0:cbf45dde2b49 286 }
HBP 0:cbf45dde2b49 287
HBP 12:928346513c87 288 file::file(mfs *fs_ref, char filename[20], FileOpenMode operation)
HBP 0:cbf45dde2b49 289 {
HBP 12:928346513c87 290 fMode = operation;
HBP 0:cbf45dde2b49 291
HBP 0:cbf45dde2b49 292 fs = fs_ref; // Don't forget this :)
HBP 0:cbf45dde2b49 293
HBP 9:52c01cb100ac 294 uint32_t n;
HBP 12:928346513c87 295 char cData[1] = {'\0'};
HBP 0:cbf45dde2b49 296
HBP 0:cbf45dde2b49 297 // Check if file exists
HBP 10:211cb54339a0 298 if (fs->getFirstBlockOfFile(filename, &n) != 0)
HBP 0:cbf45dde2b49 299 error("Oops, file \"%s\" not found! n=0x%X", filename, n); // File not found
HBP 0:cbf45dde2b49 300
HBP 0:cbf45dde2b49 301 fs->read(cData, n, 0, 1);
HBP 0:cbf45dde2b49 302 char flags = (cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3);
HBP 0:cbf45dde2b49 303
HBP 12:928346513c87 304 if ((fMode != RO) && ((flags & 0x04) != 0))
HBP 12:928346513c87 305 error("Oops, cant open in RW mode!");
HBP 0:cbf45dde2b49 306
HBP 0:cbf45dde2b49 307 // Store FBOF number
HBP 0:cbf45dde2b49 308 firstBlock = n;
HBP 0:cbf45dde2b49 309 currBlock = n;
HBP 0:cbf45dde2b49 310 blockPos = RB+20; // skip flags + pointers + filename
HBP 12:928346513c87 311 byteCount = 0; // First byte of the file
HBP 0:cbf45dde2b49 312
HBP 0:cbf45dde2b49 313 // Initialize buffer
HBP 0:cbf45dde2b49 314 for (unsigned int i=0; i < BUF; i++)
HBP 0:cbf45dde2b49 315 buffer[i] = '\0';
HBP 0:cbf45dde2b49 316 bufPos = 0;
HBP 0:cbf45dde2b49 317 }
HBP 0:cbf45dde2b49 318
HBP 0:cbf45dde2b49 319 file::~file()
HBP 0:cbf45dde2b49 320 {
HBP 0:cbf45dde2b49 321 flush();
HBP 0:cbf45dde2b49 322 }
HBP 0:cbf45dde2b49 323
HBP 12:928346513c87 324 char file::getBlockLink(BlockLinkType linkSelection, uint32_t *blockOut)
HBP 12:928346513c87 325 {
HBP 12:928346513c87 326 char cData[1+BLOCK_LLEN];
HBP 12:928346513c87 327
HBP 12:928346513c87 328 if (linkSelection == NEXT)
HBP 12:928346513c87 329 {
HBP 12:928346513c87 330 // Fetch link to next block
HBP 12:928346513c87 331 fs->read(cData, currBlock, 0, 1+BLOCK_LLEN);
HBP 12:928346513c87 332 if ((cData[0] & 0x40) == 0)
HBP 12:928346513c87 333 {
HBP 12:928346513c87 334 *blockOut = ((uint32_t)(cData[1])) << 8; // Hbyte of next block link
HBP 12:928346513c87 335 *blockOut |= (uint32_t)cData[2]; // Lbyte of next block link
HBP 12:928346513c87 336 return 0;
HBP 12:928346513c87 337 } else return 1; // Already at last block
HBP 12:928346513c87 338 } else if (linkSelection == PREV)
HBP 12:928346513c87 339 {
HBP 12:928346513c87 340 if (currBlock != firstBlock)
HBP 12:928346513c87 341 {
HBP 12:928346513c87 342 fs->read(cData, currBlock, 1+BLOCK_LLEN, BLOCK_LLEN);
HBP 12:928346513c87 343 *blockOut = ((uint32_t)(cData[0])) << 8; // Hbyte of next block link
HBP 12:928346513c87 344 *blockOut |= (uint32_t)cData[1]; // Lbyte of next block link
HBP 12:928346513c87 345 return 0;
HBP 12:928346513c87 346 } else return 1; // Already at first block
HBP 12:928346513c87 347 }
HBP 12:928346513c87 348
HBP 12:928346513c87 349 return 0;
HBP 12:928346513c87 350 }
HBP 12:928346513c87 351
HBP 12:928346513c87 352 char file::removeFollowingBlocks(uint32_t block)
HBP 12:928346513c87 353 {
HBP 12:928346513c87 354 char cData[RB-BLOCK_LLEN];
HBP 12:928346513c87 355 char cDataNew[RB] = {'\x04', '\0', '\0', '\0', '\0'};
HBP 12:928346513c87 356 uint32_t i=0;
HBP 12:928346513c87 357
HBP 12:928346513c87 358 while(1)
HBP 12:928346513c87 359 {
HBP 12:928346513c87 360 fs->read(cData, block, 0, RB-BLOCK_LLEN);
HBP 12:928346513c87 361 fs->write(cDataNew, block, 0, RB);
HBP 12:928346513c87 362 if ((cData[0] & 0x4C) == 0x4C)
HBP 12:928346513c87 363 break; // End of file found
HBP 12:928346513c87 364 else block = (uint32_t)(cData[0])<<8|cData[1]; // Set next block number
HBP 12:928346513c87 365 i++;
HBP 12:928346513c87 366 if (i > BC)
HBP 12:928346513c87 367 return 1; // fs is corrupted
HBP 12:928346513c87 368 }
HBP 12:928346513c87 369
HBP 12:928346513c87 370 return 0;
HBP 12:928346513c87 371 }
HBP 12:928346513c87 372
HBP 0:cbf45dde2b49 373 void file::rewind()
HBP 0:cbf45dde2b49 374 {
HBP 0:cbf45dde2b49 375 flush();
HBP 0:cbf45dde2b49 376 currBlock = firstBlock;
HBP 0:cbf45dde2b49 377 blockPos = RB+20; // skip flags & pointers + filename
HBP 12:928346513c87 378 byteCount = 0;
HBP 0:cbf45dde2b49 379 }
HBP 0:cbf45dde2b49 380
HBP 9:52c01cb100ac 381 char file::rewind(uint32_t n)
HBP 5:a0fe74dce80d 382 {
HBP 9:52c01cb100ac 383 uint32_t i;
HBP 12:928346513c87 384 uint32_t block;
HBP 12:928346513c87 385 uint32_t varBlockOffset;
HBP 5:a0fe74dce80d 386
HBP 9:52c01cb100ac 387 flush(); // Check if flush is needed
HBP 5:a0fe74dce80d 388
HBP 5:a0fe74dce80d 389 for (i=0; i < n; i++)
HBP 5:a0fe74dce80d 390 {
HBP 5:a0fe74dce80d 391 blockPos--;
HBP 12:928346513c87 392 byteCount--;
HBP 5:a0fe74dce80d 393
HBP 5:a0fe74dce80d 394 // Change Block?
HBP 12:928346513c87 395 if (blockPos == firstBlock)
HBP 12:928346513c87 396 varBlockOffset = RB+20;
HBP 12:928346513c87 397 else
HBP 12:928346513c87 398 varBlockOffset = RB;
HBP 12:928346513c87 399 if ((blockPos < varBlockOffset) && (currBlock > firstBlock))
HBP 5:a0fe74dce80d 400 {
HBP 12:928346513c87 401 // Fetch link to previous block
HBP 12:928346513c87 402 if(getBlockLink(PREV, &block) == 0)
HBP 5:a0fe74dce80d 403 {
HBP 12:928346513c87 404 currBlock = block;
HBP 12:928346513c87 405 blockPos = BS-1; // blockPos should be set at the end of block
HBP 5:a0fe74dce80d 406 } else {
HBP 5:a0fe74dce80d 407 blockPos++;
HBP 12:928346513c87 408 byteCount++;
HBP 12:928346513c87 409 return 1; // This is the first block and byte
HBP 5:a0fe74dce80d 410 }
HBP 5:a0fe74dce80d 411 }
HBP 5:a0fe74dce80d 412 }
HBP 5:a0fe74dce80d 413
HBP 5:a0fe74dce80d 414 return 0; // OK
HBP 5:a0fe74dce80d 415 }
HBP 5:a0fe74dce80d 416
HBP 0:cbf45dde2b49 417 char file::forward()
HBP 0:cbf45dde2b49 418 {
HBP 5:a0fe74dce80d 419 return forward(1);
HBP 5:a0fe74dce80d 420 }
HBP 5:a0fe74dce80d 421
HBP 9:52c01cb100ac 422 char file::forward(uint32_t n)
HBP 5:a0fe74dce80d 423 {
HBP 9:52c01cb100ac 424 uint32_t i;
HBP 12:928346513c87 425 uint32_t block; // Next block number
HBP 12:928346513c87 426 char cData[1];
HBP 0:cbf45dde2b49 427
HBP 9:52c01cb100ac 428 flush(); // Check if flush is needed
HBP 5:a0fe74dce80d 429
HBP 5:a0fe74dce80d 430 for (i=0; i < n; i++)
HBP 5:a0fe74dce80d 431 {
HBP 5:a0fe74dce80d 432 blockPos++;
HBP 12:928346513c87 433 byteCount++;
HBP 0:cbf45dde2b49 434
HBP 5:a0fe74dce80d 435 // Change Block?
HBP 12:928346513c87 436 if (blockPos >= BS)
HBP 5:a0fe74dce80d 437 {
HBP 5:a0fe74dce80d 438 // Fetch link to next block
HBP 12:928346513c87 439 if (getBlockLink(NEXT, &block) == 0)
HBP 5:a0fe74dce80d 440 {
HBP 12:928346513c87 441 currBlock = block;
HBP 5:a0fe74dce80d 442 blockPos = RB; // Reset block position offset
HBP 5:a0fe74dce80d 443 } else {
HBP 5:a0fe74dce80d 444 blockPos--;
HBP 12:928346513c87 445 byteCount--;
HBP 12:928346513c87 446 return 1; // This is the last block & byte
HBP 5:a0fe74dce80d 447 }
HBP 5:a0fe74dce80d 448 }
HBP 5:a0fe74dce80d 449 fs->read(cData, currBlock, blockPos, 1);
HBP 5:a0fe74dce80d 450 if (cData[0] == mEOF)
HBP 10:211cb54339a0 451 {
HBP 12:928346513c87 452 rewind(1); // Get back to the byte before EOF
HBP 5:a0fe74dce80d 453 return 1;
HBP 10:211cb54339a0 454 }
HBP 5:a0fe74dce80d 455 }
HBP 0:cbf45dde2b49 456
HBP 0:cbf45dde2b49 457 return 0; // OK
HBP 0:cbf45dde2b49 458 }
HBP 0:cbf45dde2b49 459
HBP 12:928346513c87 460 char file::seek(uint32_t byte)
HBP 12:928346513c87 461 {
HBP 12:928346513c87 462 if (byte > byteCount)
HBP 12:928346513c87 463 return forward(byte-byteCount);
HBP 12:928346513c87 464 else if (byte < byteCount)
HBP 12:928346513c87 465 return rewind(byteCount-byte);
HBP 12:928346513c87 466 else return 0;
HBP 12:928346513c87 467 }
HBP 12:928346513c87 468
HBP 0:cbf45dde2b49 469 // Respects mEOF and automatically sets '\0' at the end of string
HBP 9:52c01cb100ac 470 void file::read(char *data, uint32_t n)
HBP 0:cbf45dde2b49 471 {
HBP 9:52c01cb100ac 472 uint32_t i;
HBP 12:928346513c87 473 uint32_t block;
HBP 12:928346513c87 474 char cData[1];
HBP 0:cbf45dde2b49 475
HBP 9:52c01cb100ac 476 flush();
HBP 0:cbf45dde2b49 477
HBP 0:cbf45dde2b49 478 for (i=0; i < n; i++)
HBP 0:cbf45dde2b49 479 {
HBP 0:cbf45dde2b49 480 // Change block?
HBP 12:928346513c87 481 if (blockPos >= BS-1)
HBP 0:cbf45dde2b49 482 {
HBP 0:cbf45dde2b49 483 // Fetch link to next block
HBP 12:928346513c87 484 if (getBlockLink(NEXT, &block) == 0)
HBP 0:cbf45dde2b49 485 {
HBP 12:928346513c87 486 currBlock = block;
HBP 12:928346513c87 487 blockPos = RB; // Reset block position offset
HBP 0:cbf45dde2b49 488 } else goto stop;
HBP 0:cbf45dde2b49 489 }
HBP 0:cbf45dde2b49 490
HBP 0:cbf45dde2b49 491 // Read data
HBP 0:cbf45dde2b49 492 fs->read(cData, currBlock, blockPos, 1);
HBP 0:cbf45dde2b49 493 if (cData[0] == mEOF)
HBP 0:cbf45dde2b49 494 {
HBP 0:cbf45dde2b49 495 stop:
HBP 0:cbf45dde2b49 496 data[i]='\0';
HBP 0:cbf45dde2b49 497 return;
HBP 5:a0fe74dce80d 498 } else {
HBP 5:a0fe74dce80d 499 data[i] = cData[0];
HBP 5:a0fe74dce80d 500 blockPos++;
HBP 12:928346513c87 501 byteCount++;
HBP 5:a0fe74dce80d 502 }
HBP 0:cbf45dde2b49 503 }
HBP 12:928346513c87 504 if (data[n-1] != '\0')
HBP 12:928346513c87 505 data[n-1] = '\0';
HBP 0:cbf45dde2b49 506 }
HBP 0:cbf45dde2b49 507
HBP 0:cbf45dde2b49 508 // Ignores mEOF and doesn't set '\0' markings
HBP 9:52c01cb100ac 509 void file::readBin(char *data, uint32_t n)
HBP 0:cbf45dde2b49 510 {
HBP 9:52c01cb100ac 511 uint32_t i;
HBP 12:928346513c87 512 uint32_t block;
HBP 12:928346513c87 513 char cData[1];
HBP 0:cbf45dde2b49 514
HBP 0:cbf45dde2b49 515 for (i=0; i < n; i++)
HBP 0:cbf45dde2b49 516 {
HBP 0:cbf45dde2b49 517 // Change block?
HBP 0:cbf45dde2b49 518 if (blockPos == BS-1)
HBP 0:cbf45dde2b49 519 {
HBP 0:cbf45dde2b49 520 // Fetch link to next block
HBP 12:928346513c87 521 if (getBlockLink(NEXT, &block) == 0)
HBP 0:cbf45dde2b49 522 {
HBP 12:928346513c87 523 currBlock = block;
HBP 0:cbf45dde2b49 524 blockPos = RB; // Reset block position offset
HBP 0:cbf45dde2b49 525 } else return;
HBP 0:cbf45dde2b49 526 }
HBP 0:cbf45dde2b49 527
HBP 0:cbf45dde2b49 528 // Read data
HBP 0:cbf45dde2b49 529 fs->read(cData, currBlock, blockPos, 1);
HBP 0:cbf45dde2b49 530 data[i] = cData[0];
HBP 0:cbf45dde2b49 531
HBP 0:cbf45dde2b49 532 blockPos++;
HBP 12:928346513c87 533 byteCount++;
HBP 0:cbf45dde2b49 534 }
HBP 0:cbf45dde2b49 535 }
HBP 0:cbf45dde2b49 536
HBP 0:cbf45dde2b49 537 // Always binary
HBP 9:52c01cb100ac 538 char file::write(char *data, uint32_t n)
HBP 0:cbf45dde2b49 539 {
HBP 12:928346513c87 540 if (fMode == RO) return 1;
HBP 0:cbf45dde2b49 541
HBP 9:52c01cb100ac 542 for (uint32_t i=0; i < n; i++)
HBP 0:cbf45dde2b49 543 {
HBP 0:cbf45dde2b49 544 // write to the buffer
HBP 0:cbf45dde2b49 545 buffer[bufPos] = data[i];
HBP 0:cbf45dde2b49 546 bufPos++;
HBP 0:cbf45dde2b49 547
HBP 0:cbf45dde2b49 548 // If the buffer is full then flush
HBP 0:cbf45dde2b49 549 if(bufPos == BUF)
HBP 0:cbf45dde2b49 550 {
HBP 0:cbf45dde2b49 551 if(flush() != 0);
HBP 0:cbf45dde2b49 552 return 1; // Flush failed
HBP 0:cbf45dde2b49 553 }
HBP 0:cbf45dde2b49 554 }
HBP 0:cbf45dde2b49 555
HBP 0:cbf45dde2b49 556 return 0;
HBP 0:cbf45dde2b49 557 }
HBP 0:cbf45dde2b49 558
HBP 0:cbf45dde2b49 559 char file::flush()
HBP 0:cbf45dde2b49 560 {
HBP 12:928346513c87 561 char cData[RB], cDataOB[RB-BLOCK_LLEN], c[1];
HBP 10:211cb54339a0 562 uint32_t nextFree;
HBP 9:52c01cb100ac 563 uint32_t i;
HBP 12:928346513c87 564 uint32_t leftSpaceEOF;
HBP 12:928346513c87 565
HBP 12:928346513c87 566 bool destructiveFlag = false; // Set this true if there is any data to be removed
HBP 12:928346513c87 567 uint32_t destructiveBlock=0; // First block to be removed by DWRITE
HBP 0:cbf45dde2b49 568
HBP 0:cbf45dde2b49 569 if (bufPos == 0) return 0; // File up-to date
HBP 12:928346513c87 570 if (fMode == RO) return 1;
HBP 0:cbf45dde2b49 571
HBP 12:928346513c87 572 for (i=0; i <= bufPos; i++)
HBP 0:cbf45dde2b49 573 {
HBP 0:cbf45dde2b49 574 if(i%2)
HBP 0:cbf45dde2b49 575 FlushLed = 1;
HBP 0:cbf45dde2b49 576 else
HBP 0:cbf45dde2b49 577 FlushLed = 0;
HBP 0:cbf45dde2b49 578
HBP 0:cbf45dde2b49 579 // Change Block?
HBP 12:928346513c87 580 if ((bufPos - i) == 1)
HBP 12:928346513c87 581 leftSpaceEOF = 1;
HBP 12:928346513c87 582 else
HBP 12:928346513c87 583 leftSpaceEOF = 0;
HBP 12:928346513c87 584 if (blockPos >= BS-leftSpaceEOF)
HBP 0:cbf45dde2b49 585 {
HBP 0:cbf45dde2b49 586 // Fetch new unused block number
HBP 0:cbf45dde2b49 587 if(fs->getNextFreeBlock(&nextFree) != 0)
HBP 12:928346513c87 588 return 2; // No free space left
HBP 0:cbf45dde2b49 589
HBP 12:928346513c87 590 // Read flags from current block
HBP 12:928346513c87 591 fs->read(cDataOB, currBlock, 0, RB-BLOCK_LLEN);
HBP 9:52c01cb100ac 592
HBP 12:928346513c87 593 /* If destructive write is set then check if there is something
HBP 12:928346513c87 594 to be marked for removal */
HBP 12:928346513c87 595 if (((cDataOB[0] & 0x40) != 0x40) && (fMode == DWRITE))
HBP 12:928346513c87 596 {
HBP 12:928346513c87 597 destructiveFlag = true;
HBP 12:928346513c87 598 destructiveBlock = (uint32_t)cDataOB[1]<<8|cDataOB[2];
HBP 12:928346513c87 599 goto allocate_new_block;
HBP 12:928346513c87 600 } else if ((cDataOB[0] & 0x40) != 0x40) // fMode == AWRITE
HBP 12:928346513c87 601 {
HBP 12:928346513c87 602 // Update current block info
HBP 12:928346513c87 603 currBlock = (uint32_t)cDataOB[1]<<8|cDataOB[2];
HBP 12:928346513c87 604 blockPos = RB; // Reset block position offset
HBP 12:928346513c87 605 } else // There is no block to append so we allocate a new one
HBP 12:928346513c87 606 {
HBP 12:928346513c87 607 allocate_new_block:
HBP 12:928346513c87 608 // Allocate new block for use
HBP 12:928346513c87 609 cData[0] = 0x4C; // New flags
HBP 12:928346513c87 610 cData[1] = '\0'; // Hbyte of Next Block link
HBP 12:928346513c87 611 cData[2] = '\0'; // Lbyte of Next Block link
HBP 12:928346513c87 612 cData[3] = (char)((currBlock & 0xff00) >> 8); // Hbyte of Prev Block link
HBP 12:928346513c87 613 cData[4] = (char)(currBlock & 0x00ff); // Lbyte of Prev Block link
HBP 12:928346513c87 614 fs->write(cData, nextFree, 0, RB); // Update Block Data
HBP 0:cbf45dde2b49 615
HBP 12:928346513c87 616 // Link old block with new block
HBP 12:928346513c87 617 cDataOB[0] &= ~0x40; // Clear LBOF flag if set
HBP 12:928346513c87 618 cDataOB[1] = (char)((nextFree & 0xff00) >> 8); // Hbyte of Next Block link
HBP 12:928346513c87 619 cDataOB[2] = (char)(nextFree & 0x00ff); // Lbyte of Next Block link
HBP 12:928346513c87 620 fs->write(cDataOB, currBlock, 0, RB-BLOCK_LLEN); // Update Block Data
HBP 9:52c01cb100ac 621
HBP 12:928346513c87 622 // Update current block info
HBP 12:928346513c87 623 currBlock = nextFree;
HBP 12:928346513c87 624 blockPos = RB; // Reset block position offset
HBP 12:928346513c87 625 }
HBP 0:cbf45dde2b49 626 }
HBP 0:cbf45dde2b49 627
HBP 0:cbf45dde2b49 628 // Write file
HBP 0:cbf45dde2b49 629 c[0]=buffer[i];
HBP 0:cbf45dde2b49 630 fs->write(c, currBlock, blockPos, 1);
HBP 0:cbf45dde2b49 631 blockPos++;
HBP 12:928346513c87 632 byteCount++;
HBP 0:cbf45dde2b49 633 }
HBP 0:cbf45dde2b49 634 // Write mEOF
HBP 0:cbf45dde2b49 635 fs->write((char[]){mEOF}, currBlock, blockPos+1, 1);
HBP 0:cbf45dde2b49 636
HBP 0:cbf45dde2b49 637 bufPos = 0; // Reset buffer position counter
HBP 0:cbf45dde2b49 638
HBP 12:928346513c87 639 /* If destructive write flag is set
HBP 12:928346513c87 640 and there is data to be removed then remove data now */
HBP 12:928346513c87 641 if (destructiveFlag == true)
HBP 12:928346513c87 642 if(removeFollowingBlocks(destructiveBlock) != 0)
HBP 12:928346513c87 643 return 3;
HBP 12:928346513c87 644
HBP 0:cbf45dde2b49 645 FlushLed = 0;
HBP 0:cbf45dde2b49 646 return 0;
HBP 0:cbf45dde2b49 647 }