Implement delete. Fix a pile of bugs.

This commit is contained in:
David Given
2022-09-12 00:56:34 +02:00
parent 55b8a62f64
commit 1fea200582

View File

@@ -94,9 +94,9 @@ public:
if (buffer[0] == 0xf0) if (buffer[0] == 0xf0)
continue; continue;
auto de = std::make_unique<Brother120Dirent>(buffer); auto de = std::make_shared<Brother120Dirent>(buffer);
usedSectors += de->sectorLength; usedSectors += de->sectorLength;
dirents.push_back(std::move(de)); dirents.push_back(de);
} }
} }
@@ -122,7 +122,7 @@ public:
int i = 0; int i = 0;
for (const auto& de : dirents) for (const auto& de : dirents)
{ {
bw.append(Bytes(de->filename).slice(0, 8)); bw.append(Bytes(de->filename + " ").slice(0, 8));
bw.write_8(de->brotherType); bw.write_8(de->brotherType);
bw.write_be16(de->startSector); bw.write_be16(de->startSector);
bw.write_8(de->sectorLength); bw.write_8(de->sectorLength);
@@ -144,7 +144,7 @@ public:
fs->putLogicalSector(0, bytes); fs->putLogicalSector(0, bytes);
} }
std::unique_ptr<Brother120Dirent> findFile(const Path& path) std::shared_ptr<Brother120Dirent> findFile(const Path& path)
{ {
if (path.size() != 1) if (path.size() != 1)
throw BadPathException(); throw BadPathException();
@@ -152,7 +152,34 @@ public:
for (auto& dirent : dirents) for (auto& dirent : dirents)
{ {
if (dirent->filename == path[0]) if (dirent->filename == path[0])
return std::move(dirent); return dirent;
}
throw FileNotFoundException();
}
void deleteFile(const Path& path)
{
if (path.size() != 1)
throw BadPathException();
for (auto it = dirents.begin(); it != dirents.end(); it++)
{
auto& dirent = *it;
if (dirent->filename == path[0])
{
int sector = dirent->startSector;
while ((sector != 0) && (sector != 0xffff))
{
int nextSector = fat.at(sector);
freeSector(sector);
sector = nextSector;
}
dirents.erase(it);
return;
}
} }
throw FileNotFoundException(); throw FileNotFoundException();
@@ -163,16 +190,25 @@ public:
for (int i = 0; i < fat.size(); i++) for (int i = 0; i < fat.size(); i++)
if (fat[i] == 0) if (fat[i] == 0)
{ {
fat[i] = 0xffff; fat[i] = 0xffff;
usedSectors++; usedSectors++;
return i; return i;
} }
throw DiskFullException(); throw DiskFullException();
} }
void freeSector(uint16_t i)
{
if (fat[i])
{
fat[i] = 0;
usedSectors--;
}
}
public: public:
std::vector<uint16_t> fat; std::vector<uint16_t> fat;
std::vector<std::unique_ptr<Brother120Dirent>> dirents; std::vector<std::shared_ptr<Brother120Dirent>> dirents;
uint32_t usedSectors = 0; uint32_t usedSectors = 0;
}; };
@@ -188,7 +224,8 @@ public:
uint32_t capabilities() const uint32_t capabilities() const
{ {
return OP_GETFSDATA | OP_LIST | OP_GETFILE | OP_PUTFILE | OP_GETDIRENT; return OP_GETFSDATA | OP_LIST | OP_GETFILE | OP_PUTFILE | OP_GETDIRENT |
OP_DELETE;
} }
std::map<std::string, std::string> getMetadata() override std::map<std::string, std::string> getMetadata() override
@@ -217,7 +254,7 @@ public:
std::vector<std::shared_ptr<Dirent>> result; std::vector<std::shared_ptr<Dirent>> result;
for (auto& dirent : dir.dirents) for (auto& dirent : dir.dirents)
result.push_back(std::move(dirent)); result.push_back(dirent);
return result; return result;
} }
@@ -252,9 +289,13 @@ public:
{ {
} }
auto& filename = path.back();
if (filename.size() > 8)
throw CannotWriteException("filename too long (eight characters maximum)");
int sectorLength = (data.size() + SECTOR_SIZE - 1) / SECTOR_SIZE; int sectorLength = (data.size() + SECTOR_SIZE - 1) / SECTOR_SIZE;
if (sectorLength > 0xff) if (sectorLength > 0xff)
throw CannotWriteException("file is too big (64kB is the maximum)"); throw CannotWriteException("file is too big (64kB is the maximum)");
ByteReader br(data); ByteReader br(data);
@@ -272,11 +313,16 @@ public:
previousSector = currentSector; previousSector = currentSector;
} }
auto dirent = std::make_unique<Brother120Dirent>(path.back(), auto dirent = std::make_shared<Brother120Dirent>(
0, filename, 0, firstSector, sectorLength);
firstSector, dir.dirents.push_back(dirent);
sectorLength); dir.write(this);
dir.dirents.push_back(std::move(dirent)); }
void deleteFile(const Path& path) override
{
BrotherDirectory dir(this);
dir.deleteFile(path);
dir.write(this); dir.write(this);
} }