📄 fatfs.java
字号:
/*---------------------------------------------------------------------------
* Copyright (C) 2008 Maxim Integrated Products, Inc., All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED PRODUCTS INC. BE LIABLE FOR ANY CLAIM,
* DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated Products,
* Inc. shall not be used except as stated in the Maxim Integrated Products,
* Inc. Branding Policy.
* ---------------------------------------------------------------------------
*/
//TODO - keep track of all open files. Don't allow opening a file for writing that is already open for reading or writing. (Maybe I can allow those that are open for reading if I update the pointers of the reading file descriptors)
// Should I allow opening a file for reading that is open for writing? I think it is OK as long as the read and write routines are protected by the 'lock'.
package com.dalsemi.fs.fat;
import com.dalsemi.fs.*;
import java.io.*;
import java.util.*;
public class FATFS implements FileSystemDriver
{
public static void sendMessage(String str)
{
((com.dalsemi.slush.Slush)com.dalsemi.system.TINIOS.getShell()).broadcast(" ****DEBUG MESSAGE**** " + str);
}
public void init(String[] args) throws Exception
{
// // Create the interface object.
// Class diskClass = Class.forName(args[0]);
// disk = (DiskInterface)diskClass.newInstance();
disk = (DiskInterface)(new SDCard());
// Initialize the disk.
// String[] dArgs = new String[args.length - 1];
// System.arraycopy(args, 1, dArgs, 0, dArgs.length);
// disk.init(dArgs);
// Get all the necessary file system info.
sector = new byte[512];
if(!disk.read(0, sector, 0, 512))
{
throw new FATException("Error reading disk");
}
if(sector[0] != (byte)0xEB && sector[0] != (byte)0xE9)
{
int lba = ArrayUtils.getInt(sector, 454) * 512;
disk.setOffset(lba);
if(!disk.read(0, sector, 0, 512))
{
throw new FATException("Error reading disk");
}
}
parseBootSector(sector);
// Recreate the buffer if necessary.
if(bytesPerSector != 512)
{
sector = new byte[bytesPerSector];
}
sector2 = new byte[bytesPerSector];
}
public boolean exists(String fileName)
{
return exists(fileName, false);
}
private boolean exists(String fileName, boolean create)
{
try
{
synchronized(lock)
{
// Split the file name up into its various pieces.
// The name will be stored in the fileParts array.
// The length is stored in filePartsLength.
parseFileName(fileName);
// This is a request for the root directory.
if(filePartsLength == 0)
{
currentFileSector = 0;
currentFileOffset = 0;
return true;
}
int currentDirSector = firstRootDirSector;
boolean writable = true;
// Go through all of the directories to get to the file.
for(int i = 0; i < filePartsLength - 1; i++)
{
// Look for a directory with the given name.
if(!findFile(fileParts[i], currentDirSector, create & writable, false))
{
return false;
}
// Verify this file is a directory and not a file.
if(!isDirectory())
{
return false;
}
writable = isWritable();
// Point to the contents of this directory.
currentDirSector = getFirstSector();
}
// Look for file with the given name.
return findFile(fileParts[filePartsLength - 1], currentDirSector, create & writable, true);
}
}
catch(FATException x)
{
return false;
}
}
public boolean canWrite(String fileName, byte uid)
{
synchronized(lock)
{
exists(fileName, false);
if(currentFileSector == 0 && currentFileOffset == 0)
{
return true;
}
else
{
synchronized(sector)
{
disk.read((currentFileSector << shiftBytesPerSector) + currentFileOffset + OFFSET_DIR_ATTRIBUTES, sector, 0, 1);
return (sector[0] & ATTR_READ_ONLY) != ATTR_READ_ONLY;
}
}
}
}
public boolean canRead(String fileName, byte uid)
{
// FAT file system doesn't support permissions, so if the file exists assume it is readable.
return exists(fileName);
}
public boolean canExec(String fileName, byte uid)
{
// FAT file system doesn't support permissions, so if the file exists assume it is accessible.
return exists(fileName);
}
public boolean isFile(String fileName)
{
synchronized(lock)
{
return exists(fileName) && !isDirectory();
}
}
public boolean isDirectory(String fileName)
{
synchronized(lock)
{
return exists(fileName) && isDirectory();
}
}
public long lastModified(String fileName)
{
synchronized (lock)
{
if(exists(fileName))
{
if(calendar == null)
{
calendar = Calendar.getInstance();
}
int date;
int time;
if(currentFileSector == 0 && currentFileOffset == 0)
{
//TODO - this is the root directory, how do I get last modified time.
return 0L;
}
synchronized (sector)
{
if(!disk.read(currentFileSector << shiftBytesPerSector, sector, 0, DIR_ENTRY_SIZE))
{
return 0L;
}
date = ArrayUtils.getShort(sector, OFFSET_DIR_WRITE_DATE);
time = ArrayUtils.getShort(sector, OFFSET_DIR_WRITE_TIME);
}
int year = 1980 + ((date >> 9) & 0x7F);
int month = ((date >> 5) & 0x0F) - 1;
int day = (date & 0x1F);
int hour = (time >> 11) & 0x1F;
int minute = (time >> 5) & 0x3F;
int second = (time & 0x1F) * 2;
calendar.set(year, month, day, hour, minute, second);
return calendar.getTime().getTime();
}
else
{
return 0L;
}
}
}
public long length(String fileName)
{
synchronized (lock)
{
if(exists(fileName))
{
if(isDirectory())
{
// Start at the beginning of the directory's contents.
int dirSector = getFirstSector();
int fileCount = 0;
do
{
synchronized (sector)
{
// Read the complete sector.
if(!disk.read(dirSector << shiftBytesPerSector, sector, 0, bytesPerSector))
{
return 0L;
}
// Check each entry in the sector.
for(int i = 0; i < bytesPerSector; i += DIR_ENTRY_SIZE)
{
// Found the end of this directory.
if(sector[i + OFFSET_DIR_NAME] == DIR_LAST_ENTRY)
{
return fileCount;
}
// If this is a valid file entry...
if((ArrayUtils.getByte(sector, i + OFFSET_DIR_NAME) != DIR_SLOT_DELETED) &&
(ArrayUtils.getByte(sector, i + OFFSET_DIR_ATTRIBUTES) != ATTR_LONG_NAME))
{
if(!com.dalsemi.system.ArrayUtils.arrayComp(sector, i + OFFSET_DIR_NAME, dotBytes, 0, 11) &&
!com.dalsemi.system.ArrayUtils.arrayComp(sector, i + OFFSET_DIR_NAME, dotdotBytes, 0, 11))
{
// ...increment the count of files.
fileCount++;
}
}
}
}
try
{
// Keep going until we reach the end of the cluster chain.
dirSector = nextSector(dirSector, false, false);
}
catch(FATException ex)
{
return 0L;
}
} while(dirSector != 0);
return fileCount;
}
else
{
synchronized (sector)
{
if(!disk.read((currentFileSector << shiftBytesPerSector) + currentFileOffset, sector, 0, DIR_ENTRY_SIZE))
{
return 0L;
}
return (long)ArrayUtils.getInt(sector, OFFSET_DIR_FILE_SIZE);
}
}
}
else
{
return 0L;
}
}
}
public boolean mkdir(String fileName, byte uid)
{
try
{
synchronized(lock)
{
// Split the file name up into its various pieces.
// The name will be stored in the fileParts array.
// The length is stored in filePartsLength.
parseFileName(fileName);
// This is a request for the root directory which must already exist.
if(filePartsLength == 0)
{
return false;
}
int currentDirSector = firstRootDirSector;
// Go through all of the directories to get to the file.
for(int i = 0; i < filePartsLength - 1; i++)
{
// Look for a directory with the given name.
if(!findFile(fileParts[i], currentDirSector, false, false))
{
return false;
}
// Verify this file is a directory and not a file.
if(!isDirectory())
{
return false;
}
// Point to the contents of this directory.
currentDirSector = getFirstSector();
}
// Look for file with the given name.
if(findFile(fileParts[filePartsLength - 1], currentDirSector, false, false))
{
return false;
}
String nName = normalizeName(fileParts[filePartsLength - 1]);
if(makeFile(currentDirSector, nName, ATTR_DIRECTORY, -1))
{
int firstSector = getFirstSector();
synchronized (sector)
{
com.dalsemi.system.ArrayUtils.arrayFill(sector, 0, bytesPerSector, (byte)DIR_LAST_ENTRY);
for(int iSector = 0; iSector < sectorsPerCluster; iSector++)
{
if(!disk.write((firstSector + iSector) << shiftBytesPerSector, sector, 0, bytesPerSector))
{
return false;
}
}
}
return makeFile(firstSector, ". ", ATTR_DIRECTORY, sectorToCluster(firstSector)) &&
makeFile(firstSector, ".. ", ATTR_DIRECTORY, sectorToCluster(currentDirSector));
}
return false;
}
}
catch(FATException x)
{
return false;
}
}
public boolean rename(String srcname, String destname, byte uid)
{
return false;
/*TODO*/
}
public String[] list(String fileName, byte uid)
{
synchronized (lock)
{
if(listVector == null)
{
listVector = new Vector();
}
listVector.removeAllElements();
if(isDirectory(fileName))
{
//TODO - handle long file names.
// Start at the beginning of the directory's contents.
int dirSector = getFirstSector();
do
{
synchronized (sector)
{
// Read the complete sector.
if(!disk.read(dirSector << shiftBytesPerSector, sector, 0, bytesPerSector))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -