package java.io;\r
\r
+//import lejos.nxt.comm.RConsole;\r
import lejos.nxt.Flash;\r
-import java.io.IOException;\r
+\r
+/*\r
+ * DEVELOPER NOTES:\r
+ * - Requirement is for all files to be contiguous (unfragmented) so\r
+ * that they can be executed.\r
+ * - Files are stored in the flash memory one file after another.\r
+ * - If a user opens a file and wants to write to it, the file system\r
+ * shuffles the file to the end so that it has open space to write.\r
+ * - This File system is currently unthreaded, so all functions are\r
+ * blocked until each call completes. If someone starts writing to\r
+ * a file and it needs to be shuffled, a significant pause can\r
+ * occur to shuffle files around. If this was threaded it might be\r
+ * possible to avoid this pause.\r
+ */\r
\r
/**\r
* Implements a file system using pages of flash memory.\r
//static int count; Used for anything?\r
// CONSTANTS:\r
/**\r
+ * MS-DOS File attribute constants:\r
+ */\r
+ private static final byte READ_ONLY_ATTR = 0x01;\r
+ private static final byte HIDDEN_ATTR = 0x02;\r
+ //private static final byte SYSTEM_ATTR = 0x04; // System file\r
+ //private static final byte VOLUME_LABEL_ATTR = 0x08;\r
+ //private static final byte DIRECTORY_ATTR = 0x10;\r
+ //private static final byte ARCHIVE_ATTR = 0x20;\r
+ \r
+ /**\r
* Number of files the file system can store. \r
* Defines the size of the files array. If leJOS gets a garbage\r
* collector we can get rid of this limitation.\r
* version number/string, the users file system will reformat automatically.\r
* (i.e. Restarting file system and erasing their current stored classes) \r
*/\r
- private static final String TABLE_ID = "V_0.3"; \r
+ private static final String TABLE_ID = "V_0.4"; \r
\r
/**\r
* Indicates the starting page of the file table.\r
*/\r
- private static byte TABLE_START_PAGE = 0;\r
+ private static byte TABLE_START_PAGE = 1;\r
\r
/**\r
* Number of pages reserved for storing file table information.\r
* If we want to allow more files to be stored in system, increase\r
- * this number. (!! File table data currently only writes to page 0.)\r
+ * this number.\r
*/\r
private static byte FILE_TABLE_PAGES = 2;\r
\r
boolean exists = false;\r
\r
/**\r
+ * Byte that stores bit-wise data of file attributes, like hidden,\r
+ * locked, compressed, delete on exit, etc...\r
+ * See file attribute constants above\r
+ */\r
+ byte file_attributes;\r
+ \r
+ /**\r
* Creates a new File object. If this file exists on disk it will\r
* represent that file. If the file does not exist, you will need to\r
* use createNewFile() before writing to the file.\r
public boolean exists() {\r
return exists;\r
}\r
+ \r
+ public boolean canRead() {\r
+ return true; // All files can be read in NXJ\r
+ }\r
+ \r
+ public boolean canWrite() {\r
+ return !((file_attributes & READ_ONLY_ATTR) == READ_ONLY_ATTR);\r
+ }\r
+ \r
+ public boolean isHidden() {\r
+ return (file_attributes & HIDDEN_ATTR) == HIDDEN_ATTR;\r
+ }\r
+ \r
+ public boolean setReadOnly() {\r
+ file_attributes = (byte)(file_attributes | READ_ONLY_ATTR);\r
+ return true; // Supposed to return false if unsuccessful\r
+ }\r
\r
/**\r
* Reads the file information in the table from flash memory and\r
for(int i=0;i<File.totalFiles;i++) {\r
short pageLocation = (short)((0xFF & readNextByte()) | ((0xFF & readNextByte())<<8));\r
int fileLength = (0xFF & readNextByte()) | ((0xFF & readNextByte()) <<8) | ((0xFF & readNextByte())<<16) | ((0xFF & readNextByte())<<24);\r
- \r
+ byte fileAttributes = readNextByte();\r
// The following code attempts to reuse String's. If leJOS gets\r
// a garbage collector we can create new strings and reduce this\r
// code. It assumes that if files[i] is NOT null then the filename\r
}\r
files[i].page_location = pageLocation;\r
files[i].file_length = fileLength;\r
+ files[i].file_attributes = fileAttributes;\r
} \r
}\r
\r
writeNextByte((byte)(files[arrayIndex].file_length>>8));\r
writeNextByte((byte)(files[arrayIndex].file_length>>16));\r
writeNextByte((byte)(files[arrayIndex].file_length>>24));\r
+ // Write file attributes:\r
+ writeNextByte(files[arrayIndex].file_attributes);\r
// Write length of name:\r
writeNextByte((byte)(files[arrayIndex].file_name.length()));\r
// Write name:\r
writeBufftoFlash();\r
++page_pointer;\r
// Throw exception here if > FILE_TABLE_PAGES - 1:\r
- if(page_pointer >= FILE_TABLE_PAGES)\r
+ if(page_pointer >= FILE_TABLE_PAGES){\r
+ File.dumpFileTable();\r
throw new IOException("File table is full. Try deleting some files.");\r
+ }\r
byte_pointer = 0;\r
}\r
\r
}\r
\r
/**\r
+ * Debugger method. Comment out when no longer buggy.\r
+ *\r
+ */\r
+ public static void dumpFileTable() {\r
+ if(files == null) listFiles(); // Fill list\r
+ /*\r
+ RConsole.print("byte_pointer = " + byte_pointer + "\n");\r
+ RConsole.print("page_pointer = " + page_pointer + "\n");\r
+ RConsole.print("FILE_TABLE_PAGES = " + FILE_TABLE_PAGES + "\n");\r
+ RConsole.print("files.length = " + files.length + "\n");\r
+ RConsole.print("totalFiles = " + totalFiles + "\n");\r
+ \r
+ for(int i=TABLE_START_PAGE;i<FILE_START_PAGE;i++) {\r
+ Flash.readPage(buff, i);\r
+ for(int j=0;j<Flash.BYTES_PER_PAGE;j++) {\r
+ if(j % 8 == 0) RConsole.print("\n");\r
+ RConsole.print(buff[j] + ", ");\r
+ }\r
+ \r
+ for(int k=0;k<Flash.BYTES_PER_PAGE;k++) {\r
+ if(k % 8 == 0) RConsole.print("\n");\r
+ RConsole.print((char)buff[k] + " | ");\r
+ }\r
+ }\r
+ RConsole.print("Please copy and paste this into an email to bbagnall@mts.net");\r
+ */\r
+ }\r
+ \r
+ /**\r
* Writes the current page in buff[] to flash\r
*\r
*/\r