20 #include "FatDirectory.h" 22 #include "FatFilesystem.h" 23 #include "FatSymlink.h" 25 #include "modules/system/vfs/File.h" 26 #include "pedigree/kernel/LockGuard.h" 27 #include "pedigree/kernel/Log.h" 28 #include "pedigree/kernel/time/Time.h" 29 #include "pedigree/kernel/utilities/PointerGuard.h" 30 #include "pedigree/kernel/utilities/StaticString.h" 31 #include "pedigree/kernel/utilities/utility.h" 37 FatFileInfo &info, uint32_t dirClus, uint32_t dirOffset)
39 name, LITTLE_TO_HOST32(info.accessedTime),
40 LITTLE_TO_HOST32(info.modifiedTime),
41 LITTLE_TO_HOST32(info.creationTime), inode_num,
42 static_cast<
Filesystem *>(pFs), LITTLE_TO_HOST32(0), pParent),
43 m_DirClus(dirClus), m_DirOffset(dirOffset), m_Type(FAT16), m_BlockSize(0),
44 m_bRootDir(false), m_Lock(false), m_DirBlockSize(0)
46 uint32_t permissions = 0777;
48 setPermissions(permissions);
49 setUid(LITTLE_TO_HOST16(0));
50 setGid(LITTLE_TO_HOST16(0));
66 uintptr_t clus = m_Inode;
71 if (clus == 0 && m_Type != FAT32)
76 else if (pFs->
m_Type == FAT32)
77 if (clus == pFs->m_Superblock32.BPB_RootClus)
86 NOTICE(
"FatDirectory::addEntry(" << filename <<
")");
91 uint32_t clus = m_Inode;
99 size_t numRequired = 1;
100 size_t fnLength = filename.length();
104 static_cast<const char *>(filename),
".", filename.length()) ||
106 static_cast<const char *>(filename),
"..", filename.length()))
114 size_t numSplit = (fnLength + 12) / 13;
115 numRequired += numSplit;
118 size_t longFilenameOffset = fnLength;
121 bool spaceFound =
false;
123 size_t consecutiveFree = 0;
131 for (offset = 0; offset < m_BlockSize; offset +=
sizeof(
Dir))
133 if (buffer[offset] == 0 || buffer[offset] == 0xE5)
140 if (consecutiveFree == numRequired)
154 if (m_Type != FAT32 && clus == 0)
158 uint32_t prev = clus;
161 if (pFs->
isEof(clus))
173 pFs->
readCluster(clus, reinterpret_cast<uintptr_t>(buffer));
180 size_t currOffset = offset - ((numRequired - 1) *
sizeof(
Dir));
182 for (i = 0; i < (numRequired - 1); i++)
186 &buffer[currOffset]);
190 lfn->LDIR_Ord = 0x40 | (numRequired - 1);
192 lfn->LDIR_Ord = (numRequired - 1 - i);
193 lfn->LDIR_Attr = ATTR_LONG_NAME;
197 if (longFilenameOffset >= 13)
198 longFilenameOffset -= nChars;
203 nChars = longFilenameOffset - 1;
204 longFilenameOffset = 0;
207 size_t nOffset = longFilenameOffset;
211 for (n = 0; n < 10; n += 2)
213 if (nWritten > nChars)
215 lfn->LDIR_Name1[n] = filename[nOffset++];
218 for (n = 0; n < 12; n += 2)
220 if (nWritten > nChars)
222 lfn->LDIR_Name2[n] = filename[nOffset++];
225 for (n = 0; n < 4; n += 2)
227 if (nWritten > nChars)
229 lfn->LDIR_Name3[n] = filename[nOffset++];
233 currOffset +=
sizeof(
Dir);
238 Dir *ent =
reinterpret_cast<Dir *
>(&buffer[offset]);
239 ByteSet(ent, 0,
sizeof(
Dir));
240 ent->DIR_Attr = type ? ATTR_DIRECTORY : 0;
244 ent->DIR_Name, static_cast<const char *>(shortFilename), 11);
245 ent->DIR_FstClusLO = pFile->getInode() & 0xFFFF;
246 ent->DIR_FstClusHI = (pFile->getInode() >> 16) & 0xFFFF;
255 fatDir->setDirCluster(clus);
256 fatDir->setDirOffset(offset);
262 fatLink->setDirCluster(clus);
263 fatLink->setDirOffset(offset);
269 fatFile->setDirCluster(clus);
270 fatFile->setDirOffset(offset);
283 " -> FatFilesystem::addEntry(" << filename
284 <<
") is successful");
292 " -> FatFilesystem::addEntry(" << filename <<
") is not successful");
303 String real_filename(filename);
307 filename += symlinkSuffix();
309 uint32_t dirClus, dirOffset;
312 dirClus = fatDir->getDirCluster();
313 dirOffset = fatDir->getDirOffset();
317 dirClus = fatLink->getDirCluster();
318 dirOffset = fatLink->getDirOffset();
322 dirClus = fatFile->getDirCluster();
323 dirOffset = fatFile->getDirOffset();
333 dir->DIR_Name[0] = 0xE5;
336 if (dirOffset >=
sizeof(
Dir))
340 size_t numLfnEntries = (filename.length() / 13) + 1;
350 if ((dir_prev->DIR_Attr & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME)
356 for (
size_t ent = 0; ent < numLfnEntries; ent++)
358 uint32_t bytesBack =
sizeof(
Dir) * (ent + 1);
359 if (bytesBack > dirOffset)
362 ERROR(
"LFN set crosses a cluster boundary!");
366 uint32_t newOffset = dirOffset - bytesBack;
370 ((lfn->DIR_Attr & ATTR_LONG_NAME_MASK) != ATTR_LONG_NAME))
373 lfn->DIR_Name[0] = 0xE5;
382 remove(real_filename);
394 uint32_t clus = m_Inode;
398 NOTICE(
"Adding root directory");
400 info.creationTime = info.modifiedTime = info.accessedTime = 0;
412 WARNING(
"FatDirectory::cacheDirectoryContents() - got a null buffer " 413 "from readDirectoryPortion!");
420 longFileName.clear();
421 int32_t longFileNameIndex = 0;
426 bool endOfDir =
false;
429 for (i = 0; i < sz; i +=
sizeof(
Dir))
431 Dir *ent =
reinterpret_cast<Dir *
>(&buffer[i]);
433 uint8_t firstChar = ent->DIR_Name[0];
440 if (firstChar == 0xE5)
443 longFileNameIndex = 0;
444 longFileName.clear();
449 if ((ent->DIR_Attr & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME)
451 if (firstChar & 0x40)
453 longFileNameIndex = firstChar ^ 0x40;
455 char *entBuffer =
reinterpret_cast<char *
>(&buffer[i]);
460 for (a = 1; a < 11; a += 2)
461 tmp[b++] = entBuffer[a];
462 for (a = 14; a < 26; a += 2)
463 tmp[b++] = entBuffer[a];
464 for (a = 28; a < 32; a += 2)
465 tmp[b++] = entBuffer[a];
472 longFileName += latterString;
475 if ((longFileNameIndex == 0) || (--longFileNameIndex <= 1))
483 uint8_t attr = ent->DIR_Attr;
484 if (attr != ATTR_VOLUME_ID)
486 uint32_t fileCluster =
487 ent->DIR_FstClusLO | (ent->DIR_FstClusHI << 16);
490 filename =
static_cast<const char *
>(
498 String(reinterpret_cast<const char *>(ent->DIR_Name)));
501 Time::Timestamp writeTime =
503 Time::Timestamp accTime =
505 Time::Timestamp createTime =
509 info.accessedTime = accTime;
510 info.modifiedTime = writeTime;
511 info.creationTime = createTime;
514 if ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY)
516 filename, fileCluster, pFs,
this, info);
519 if (filename.
endswith(symlinkSuffix()))
524 for (
size_t z = 0; z < symlinkSuffix().length(); ++z)
528 filename, accTime, writeTime, createTime,
529 fileCluster, pFs, ent->DIR_FileSize, clus, i,
this);
534 filename, accTime, writeTime, createTime,
535 fileCluster, pFs, ent->DIR_FileSize, clus, i,
this);
544 longFileNameIndex = 0;
545 longFileName.clear();
553 if (clus == 0 && m_Type != FAT32)
562 if (pFs->
isEof(clus))
566 pFs->
readCluster(clus, reinterpret_cast<uintptr_t>(buffer));
void writeDirectoryEntry(Dir *dir, uint32_t clus, uint32_t offset)
uint32_t setClusterEntry(uint32_t cluster, uint32_t value, bool bLock=true)
void fileAttributeChanged()
void writeDirectoryPortion(uint32_t clus, void *p)
virtual bool removeEntry(File *pFile)
Dir * getDirectoryEntry(uint32_t clus, uint32_t offset) const
uint32_t findFreeCluster(bool bLock=false)
virtual void setInode(uintptr_t inode)
uint32_t getClusterEntry(uint32_t cluster, bool bLock=true)
void * readDirectoryPortion(uint32_t clus) const
void addDirectoryEntry(const String &name, File *pTarget)
String convertFilenameFrom(String filename) const
bool readCluster(uint32_t block, uintptr_t buffer) const
FatDirectory(const FatDirectory &file)
virtual void cacheDirectoryContents()
String convertFilenameTo(String filename) const
Time::Timestamp getUnixTimestamp(uint16_t time, uint16_t date) const
virtual bool isDirectory()
bool isEof(uint32_t cluster) const
virtual bool addEntry(String filename, File *pFile, size_t type)
bool endswith(const char c) const
uint32_t eofValue() const
void markCachePopulated()
virtual bool isCachePopulated() const