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.
Diff: mfs.cpp
- Revision:
- 12:928346513c87
- Parent:
- 11:6c4fcb9d6193
- Child:
- 13:142b6be3e3c8
diff -r 6c4fcb9d6193 -r 928346513c87 mfs.cpp
--- a/mfs.cpp Tue Feb 22 21:39:41 2011 +0000
+++ b/mfs.cpp Thu Feb 24 00:02:36 2011 +0000
@@ -12,10 +12,10 @@
#include "mfs.h"
#include "i2c_eeprom.h"
-#define BLOCK_NLEN 1 /**< Block number length in bytes */
-#define RB 1+2*BLOCK_NLEN /**< Reseved bytes per block (1 attrb B, 2 B for next/prev pointers */
-#define I2C_SPEED 200000 /**< I2C bus speed in Hz */
-#define DEBUG /**< Adds extra safety in reading and writing */
+#define BLOCK_LLEN 2 /**< Block number link length in bytes */
+#define RB 1+2*BLOCK_LLEN /**< Reseved bytes per block (1 attrb B, 2 B for next/prev pointers */
+#define I2C_SPEED 200000 /**< I2C bus speed in Hz */
+#define DEBUG /**< Adds extra safety in reading and writing */
DigitalOut FlushLed(LED2); /**< Flush led */
@@ -32,7 +32,7 @@
return 1;
#endif
mem->read(BS*block+byte, n, data);
- //wait_ms(1);
+
return 0;
}
@@ -44,6 +44,7 @@
return 1;
#endif
mem->write(data, BS*block+byte, n);
+
return 0;
}
@@ -129,9 +130,11 @@
return 2; // Out of space
char cData[RB+20];
- cData[0] = '\xCC'; // Necessary flags for file
- cData[1] = '\0'; // Only this block yet
- cData[2] = '\0'; // First block there could't be prev blocks
+ cData[0] = '\xCC'; // Necessary flags for a file
+ cData[1] = '\0'; // Only this block yet
+ cData[2] = '\0';
+ cData[3] = '\0'; // First block there could't be prev blocks
+ cData[4] = '\0';
for (char i=0; i < 20; i++)
cData[RB+i] = filename[i];
@@ -145,32 +148,31 @@
char mfs::removeFile(char filename[20])
{
uint32_t block;
- char cData[3] = {'\0','\0','\0'};
+ char cData[RB-BLOCK_LLEN];
+ char cDataNew[RB] = {'\x04', '\0', '\0', '\0', '\0'};
+ uint32_t i=0;
// Check if file exists
if (getFirstBlockOfFile(filename, &block) != 0)
return 1; // File not found
- // Clear blocks reserver by the file
- uint32_t i=0;
- char tmp_cData[2];
+ read(cData, block, 0, RB-BLOCK_LLEN);
+
+ // Check credentials
+ if (((cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3) & 0x04) != 0)
+ return 2; // RO file
+
+ // Clear blocks reserved by the file
while(1)
{
- read(cData, block, 0, 2);
- tmp_cData[0] = cData[0];
- tmp_cData[1] = cData[1];
-
- // Clear the block
- cData[0] = '\x04';
- write(cData, block, 0, 3);
-
- if ((tmp_cData[0] & 0x4C) != 0)
- break; // End of File found
- else if (i >= BC)
- return 2; // fs is corrupted
- block = tmp_cData[1];
-
+ write(cDataNew, block, 0, RB);
+ if ((cData[0] & 0x4C) == 0x4C)
+ break; // End of file found
+ else block = (uint32_t)(cData[1])<<8|cData[2]; // Set next block number
i++;
+ if (i > BC)
+ return 1; // fs is corrupted
+ read(cData, block, 0, RB-BLOCK_LLEN);
}
return 0; // Everything went better than expected
@@ -179,11 +181,18 @@
char mfs::renameFile(char oldFilename[20], char newFilename[20])
{
uint32_t block;
+ char cData[1];
// Check if file exists
if (getFirstBlockOfFile(oldFilename, &block) != 0)
return 1; // File not found
+ // Check credentials
+ read(cData, block, 0, 1);
+ char flags = (cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3);
+ if ((flags & 0x04) != 0)
+ return 2; // RO file
+
write(newFilename, block, RB, 20);
return 0; // Everything went better than expected
@@ -196,13 +205,15 @@
uint32_t n;
char cData[1] = {'\0'};
+ char cFlags;
// Check if file exists
if (getFirstBlockOfFile(filename, &n) != 0)
return 1; // File not found
read(cData, n, 0, 1);
- cData[0] |= (flags[0] & 0x01)|((flags[0] & 0x02) << 3)|((flags[0] & 0x04) << 3);
+ cFlags = ((flags[0] & 0x01)|((flags[0] & 0x02) << 3)|((flags[0] & 0x04) << 3));
+ cData[0] = cData[0] & (~0x31) | cFlags;
write(cData, n, 0, 1);
return 0;
@@ -250,13 +261,13 @@
uint32_t iAddr = 0;
uint32_t i = 0;
uint32_t bad = 0; // For counting bad block headers
- char cFlags[] = {'\0', '\0', '\0'}, a[1];
+ char cFlags[RB] = {'\0', '\0', '\0', '\0', '\0'}, o[1];
if (createLabel == true)
{
// Write Volume label
cFlags[0] = '\x0E';
- mem->write(cFlags, iAddr, 3);
+ mem->write(cFlags, iAddr, RB);
iAddr = BS;
i = 1;
}
@@ -264,9 +275,9 @@
cFlags[0] = '\x04';
for (; i < BC; i++)
{
- mem->write(cFlags, iAddr, 3);
- mem->read(iAddr, 1, a);
- if (a[0] != cFlags[0])
+ mem->write(cFlags, iAddr, RB);
+ mem->read(iAddr, 1, o);
+ if (o[0] != cFlags[0])
bad++;
iAddr += BS;
}
@@ -274,17 +285,14 @@
return bad;
}
-file::file(mfs *fs_ref, char filename[20], char operation)
+file::file(mfs *fs_ref, char filename[20], FileOpenMode operation)
{
- // Operations:
- // 0 = Open in RO
- // 1 = Open in RW
- attr = operation;
+ fMode = operation;
fs = fs_ref; // Don't forget this :)
uint32_t n;
- char cData[3] = {'\0','\0','\0'};
+ char cData[1] = {'\0'};
// Check if file exists
if (fs->getFirstBlockOfFile(filename, &n) != 0)
@@ -293,16 +301,14 @@
fs->read(cData, n, 0, 1);
char flags = (cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3);
- if (attr == 1)
- {
- if ((flags & 0x04) != 0)
- error("Oops, cant open in RW mode!");
- }
+ if ((fMode != RO) && ((flags & 0x04) != 0))
+ error("Oops, cant open in RW mode!");
// Store FBOF number
firstBlock = n;
currBlock = n;
blockPos = RB+20; // skip flags + pointers + filename
+ byteCount = 0; // First byte of the file
// Initialize buffer
for (unsigned int i=0; i < BUF; i++)
@@ -315,36 +321,92 @@
flush();
}
+char file::getBlockLink(BlockLinkType linkSelection, uint32_t *blockOut)
+{
+ char cData[1+BLOCK_LLEN];
+
+ if (linkSelection == NEXT)
+ {
+ // Fetch link to next block
+ fs->read(cData, currBlock, 0, 1+BLOCK_LLEN);
+ if ((cData[0] & 0x40) == 0)
+ {
+ *blockOut = ((uint32_t)(cData[1])) << 8; // Hbyte of next block link
+ *blockOut |= (uint32_t)cData[2]; // Lbyte of next block link
+ return 0;
+ } else return 1; // Already at last block
+ } else if (linkSelection == PREV)
+ {
+ if (currBlock != firstBlock)
+ {
+ fs->read(cData, currBlock, 1+BLOCK_LLEN, BLOCK_LLEN);
+ *blockOut = ((uint32_t)(cData[0])) << 8; // Hbyte of next block link
+ *blockOut |= (uint32_t)cData[1]; // Lbyte of next block link
+ return 0;
+ } else return 1; // Already at first block
+ }
+
+ return 0;
+}
+
+char file::removeFollowingBlocks(uint32_t block)
+{
+ char cData[RB-BLOCK_LLEN];
+ char cDataNew[RB] = {'\x04', '\0', '\0', '\0', '\0'};
+ uint32_t i=0;
+
+ while(1)
+ {
+ fs->read(cData, block, 0, RB-BLOCK_LLEN);
+ fs->write(cDataNew, block, 0, RB);
+ if ((cData[0] & 0x4C) == 0x4C)
+ break; // End of file found
+ else block = (uint32_t)(cData[0])<<8|cData[1]; // Set next block number
+ i++;
+ if (i > BC)
+ return 1; // fs is corrupted
+ }
+
+ return 0;
+}
+
void file::rewind()
{
flush();
currBlock = firstBlock;
blockPos = RB+20; // skip flags & pointers + filename
+ byteCount = 0;
}
char file::rewind(uint32_t n)
{
uint32_t i;
- char cData[3];
+ uint32_t block;
+ uint32_t varBlockOffset;
flush(); // Check if flush is needed
for (i=0; i < n; i++)
{
blockPos--;
+ byteCount--;
// Change Block?
- if (blockPos < 3)
+ if (blockPos == firstBlock)
+ varBlockOffset = RB+20;
+ else
+ varBlockOffset = RB;
+ if ((blockPos < varBlockOffset) && (currBlock > firstBlock))
{
- // Fetch link to next block
- fs->read(cData, currBlock, 0, RB);
- if (!(cData[0] & 0x80))
+ // Fetch link to previous block
+ if(getBlockLink(PREV, &block) == 0)
{
- currBlock = cData[2];
- blockPos = BS-1; // Set block postion offset at end of the block
+ currBlock = block;
+ blockPos = BS-1; // blockPos should be set at the end of block
} else {
blockPos++;
- return 1; // This is the first block
+ byteCount++;
+ return 1; // This is the first block and byte
}
}
}
@@ -360,32 +422,34 @@
char file::forward(uint32_t n)
{
uint32_t i;
- char cData[2];
+ uint32_t block; // Next block number
+ char cData[1];
flush(); // Check if flush is needed
for (i=0; i < n; i++)
{
blockPos++;
+ byteCount++;
// Change Block?
- if (blockPos > BS-1)
+ if (blockPos >= BS)
{
// Fetch link to next block
- fs->read(cData, currBlock, 0, 2);
- if (!(cData[0] & 0x40))
+ if (getBlockLink(NEXT, &block) == 0)
{
- currBlock = cData[1];
+ currBlock = block;
blockPos = RB; // Reset block position offset
} else {
blockPos--;
- return 1; // This is the last block
+ byteCount--;
+ return 1; // This is the last block & byte
}
}
fs->read(cData, currBlock, blockPos, 1);
if (cData[0] == mEOF)
{
- rewind(1);
+ rewind(1); // Get back to the byte before EOF
return 1;
}
}
@@ -393,25 +457,34 @@
return 0; // OK
}
+char file::seek(uint32_t byte)
+{
+ if (byte > byteCount)
+ return forward(byte-byteCount);
+ else if (byte < byteCount)
+ return rewind(byteCount-byte);
+ else return 0;
+}
+
// Respects mEOF and automatically sets '\0' at the end of string
void file::read(char *data, uint32_t n)
{
uint32_t i;
- char cData[2];
+ uint32_t block;
+ char cData[1];
flush();
for (i=0; i < n; i++)
{
// Change block?
- if (blockPos == BS-1)
+ if (blockPos >= BS-1)
{
// Fetch link to next block
- fs->read(cData, currBlock, 0, 2);
- if (!(cData[0] & 0x40))
+ if (getBlockLink(NEXT, &block) == 0)
{
- currBlock = cData[1];
- blockPos = RB; // Reset block position offset
+ currBlock = block;
+ blockPos = RB; // Reset block position offset
} else goto stop;
}
@@ -425,17 +498,19 @@
} else {
data[i] = cData[0];
blockPos++;
+ byteCount++;
}
}
- if (data[i] != '\0')
- data[i] = '\0';
+ if (data[n-1] != '\0')
+ data[n-1] = '\0';
}
// Ignores mEOF and doesn't set '\0' markings
void file::readBin(char *data, uint32_t n)
{
uint32_t i;
- char cData[2];
+ uint32_t block;
+ char cData[1];
for (i=0; i < n; i++)
{
@@ -443,10 +518,9 @@
if (blockPos == BS-1)
{
// Fetch link to next block
- fs->read(cData, currBlock, 0, 2);
- if (!(cData[0] & 0x40))
+ if (getBlockLink(NEXT, &block) == 0)
{
- currBlock = cData[1];
+ currBlock = block;
blockPos = RB; // Reset block position offset
} else return;
}
@@ -456,14 +530,14 @@
data[i] = cData[0];
blockPos++;
+ byteCount++;
}
- data[i-1] = '\0';
}
// Always binary
char file::write(char *data, uint32_t n)
{
- if (attr == 0) return 1;
+ if (fMode == RO) return 1;
for (uint32_t i=0; i < n; i++)
{
@@ -484,14 +558,18 @@
char file::flush()
{
- char cData[3], c[1];
+ char cData[RB], cDataOB[RB-BLOCK_LLEN], c[1];
uint32_t nextFree;
uint32_t i;
+ uint32_t leftSpaceEOF;
+
+ bool destructiveFlag = false; // Set this true if there is any data to be removed
+ uint32_t destructiveBlock=0; // First block to be removed by DWRITE
if (bufPos == 0) return 0; // File up-to date
- if (attr == 0) return 1;
+ if (fMode == RO) return 1;
- for (i=0; i < bufPos; i++)
+ for (i=0; i <= bufPos; i++)
{
if(i%2)
FlushLed = 1;
@@ -499,44 +577,71 @@
FlushLed = 0;
// Change Block?
- if (blockPos >= BS-2) // Must left space for mEOF
+ if ((bufPos - i) == 1)
+ leftSpaceEOF = 1;
+ else
+ leftSpaceEOF = 0;
+ if (blockPos >= BS-leftSpaceEOF)
{
// Fetch new unused block number
if(fs->getNextFreeBlock(&nextFree) != 0)
- return 1;
+ return 2; // No free space left
- // Take new block into use
- cData[0] = 0x4C; // New flags
- cData[1] = '\0';
- cData[2] = currBlock; // Prev Block
- fs->write(cData, nextFree, 0, RB); // Update Block Data
+ // Read flags from current block
+ fs->read(cDataOB, currBlock, 0, RB-BLOCK_LLEN);
- // Link old block with new block
- fs->read(cData, currBlock, 0, RB);
- cData[0] &= ~0x40; // Clear LBOF flag if set
- cData[1] = nextFree;
- cData[2] = '\0';
- fs->write(cData, currBlock, 0, RB); // Update Block Data
+ /* If destructive write is set then check if there is something
+ to be marked for removal */
+ if (((cDataOB[0] & 0x40) != 0x40) && (fMode == DWRITE))
+ {
+ destructiveFlag = true;
+ destructiveBlock = (uint32_t)cDataOB[1]<<8|cDataOB[2];
+ goto allocate_new_block;
+ } else if ((cDataOB[0] & 0x40) != 0x40) // fMode == AWRITE
+ {
+ // Update current block info
+ currBlock = (uint32_t)cDataOB[1]<<8|cDataOB[2];
+ blockPos = RB; // Reset block position offset
+ } else // There is no block to append so we allocate a new one
+ {
+ allocate_new_block:
+ // Allocate new block for use
+ cData[0] = 0x4C; // New flags
+ cData[1] = '\0'; // Hbyte of Next Block link
+ cData[2] = '\0'; // Lbyte of Next Block link
+ cData[3] = (char)((currBlock & 0xff00) >> 8); // Hbyte of Prev Block link
+ cData[4] = (char)(currBlock & 0x00ff); // Lbyte of Prev Block link
+ fs->write(cData, nextFree, 0, RB); // Update Block Data
- // Update current block info
- currBlock = nextFree;
- blockPos = RB; // Reset block position offset
+ // Link old block with new block
+ cDataOB[0] &= ~0x40; // Clear LBOF flag if set
+ cDataOB[1] = (char)((nextFree & 0xff00) >> 8); // Hbyte of Next Block link
+ cDataOB[2] = (char)(nextFree & 0x00ff); // Lbyte of Next Block link
+ fs->write(cDataOB, currBlock, 0, RB-BLOCK_LLEN); // Update Block Data
+ // Update current block info
+ currBlock = nextFree;
+ blockPos = RB; // Reset block position offset
+ }
}
- if (blockPos < 3)
- error("");
-
// Write file
c[0]=buffer[i];
fs->write(c, currBlock, blockPos, 1);
blockPos++;
+ byteCount++;
}
// Write mEOF
fs->write((char[]){mEOF}, currBlock, blockPos+1, 1);
bufPos = 0; // Reset buffer position counter
+ /* If destructive write flag is set
+ and there is data to be removed then remove data now */
+ if (destructiveFlag == true)
+ if(removeFollowingBlocks(destructiveBlock) != 0)
+ return 3;
+
FlushLed = 0;
return 0;
}
\ No newline at end of file