Skip to content

Commit 5c8d8e0

Browse files
committed
Merge pull request #410 from fwsGonzo/dev
fs: Tests and fixes for FAT
2 parents 0befda3 + 7b0302a commit 5c8d8e0

16 files changed

Lines changed: 323 additions & 82 deletions

File tree

api/fs/disk.inl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ Disk<FS>::mount(on_mount_func func)
6666
auto* mbr = (MBR::mbr*) data.get();
6767
MBR::BPB* bpb = mbr->bpb();
6868

69-
if (bpb->bytes_per_sector != 0
69+
if (bpb->bytes_per_sector >= 512
7070
&& bpb->fa_tables != 0
71-
&& bpb->sectors_per_fat != 0)
71+
&& bpb->signature != 0) // check MBR signature too
7272
{
7373
// we have FAT on MBR (and we are assuming mount FAT)
7474
mount(MBR, func);
@@ -100,7 +100,9 @@ Disk<FS>::mount(partition_t part, on_mount_func func) {
100100
if (part == INVALID)
101101
{
102102
// Something bad happened maybe in auto-detect
103-
panic("Disk::mount(): Trying to mount invalid partition");
103+
// Either way, no partition was found
104+
func(true);
105+
return;
104106
}
105107
else if (part == MBR)
106108
{

api/fs/fat.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,11 @@ namespace fs
112112
Enttype type() const
113113
{
114114
if (attrib & ATTR_VOLUME_ID)
115-
return VOLUME_ID;
115+
return VOLUME_ID;
116116
else if (attrib & ATTR_DIRECTORY)
117117
return DIR;
118118
else
119-
return FILE;
119+
return FILE;
120120
}
121121

122122
uint32_t size() const
@@ -137,10 +137,13 @@ namespace fs
137137
uint16_t zero;
138138
uint16_t third[2];
139139

140+
// the index value for this long entry
141+
// starting with the highest (hint: read manual)
140142
uint8_t long_index() const
141143
{
142144
return index & ~0x40;
143145
}
146+
// true if this is the last long index
144147
uint8_t is_last() const
145148
{
146149
return (index & LAST_LONG_ENTRY) != 0;

api/info

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
// See the License for the specific language governing permissions and
1717
// limitations under the License.
1818

19-
#ifndef ___API_INFO___
20-
#define ___API_INFO___
19+
#ifndef API_INFO_HEADER
20+
#define API_INFO_HEADER
2121

2222
#define LINEWIDTH 80
2323

api/memdisk

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@
2727
namespace fs
2828
{
2929
// describe a disk with a FAT filesystem
30-
using FatDisk = fs::Disk<FAT>;
30+
using FatDisk = Disk<FAT>;
3131
// its not really a shared memdisk right now,
3232
// but we are only using this in conjunction with
3333
// new_shared_memdisk() which very likely contains FAT
34-
using MountedDisk = std::shared_ptr<fs::FatDisk>;
34+
using MountedDisk = std::shared_ptr<FatDisk>;
3535

3636
inline MountedDisk new_shared_memdisk()
3737
{
38-
static fs::MemDisk device;
39-
return std::make_shared<fs::FatDisk> (device);
38+
static MemDisk device;
39+
return std::make_shared<FatDisk> (device);
4040
}
4141
}
4242

etc/run.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@ then
3232
echo " gdb -i=mi service -x service.gdb"
3333
echo "------------------------------------------------------------"
3434

35-
sudo $QEMU -s -S $QEMU_OPTS
35+
echo $QEMU -s -S $QEMU_OPTS $QEMU_EXTRA
36+
sudo $QEMU -s -S $QEMU_OPTS $QEMU_EXTRA
3637
else
3738

3839
echo "------------------------------------------------------------"
3940
echo "Starting VM: '$1'"
4041
echo "------------------------------------------------------------"
41-
sudo $QEMU $QEMU_OPTS
42+
echo $QEMU $QEMU_OPTS $QEMU_EXTRA
43+
sudo $QEMU $QEMU_OPTS $QEMU_EXTRA
4244
fi
4345

4446
echo "NOTE: To run your image in another VMM, such as VirtualBox, check out IncludeOS/etc/convert_image.sh"

src/debug/run_test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ echo "Building system $SERVICE..."
1414
# Get the Qemu-command (in-source, so we can use it elsewhere)
1515
. ../etc/qemu_cmd.sh
1616
export SERIAL="" #"-monitor none -virtioconsole stdio"
17-
QEMU_OPTS+=" -drive file=./smalldisk,if=virtio,index=1,media=disk $SERIAL"
17+
QEMU_OPTS+=" -drive file=./smalldisk,if=ide,media=disk $SERIAL"
1818

1919
# Qemu with gdb debugging:
2020
if [ "$DEBUG" -ne 0 ]

src/debug/test_disk.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
#include <os>
2+
#include <cassert>
23
const char* service_name__ = "...";
34

4-
#include <memdisk>
5+
//#include <memdisk>
6+
//auto disk = fs::new_shared_memdisk();
57

6-
// memdisk with FAT filesystem
7-
fs::MountedDisk disk;
8+
#include <ide>
9+
#include <fs/fat.hpp>
10+
using FatDisk = fs::Disk<fs::FAT>;
11+
std::shared_ptr<FatDisk> disk;
812

9-
void list_partitions(fs::MountedDisk);
13+
void list_partitions(decltype(disk));
1014

1115
void Service::start()
1216
{
1317
// instantiate memdisk with FAT filesystem
14-
disk = fs::new_shared_memdisk();
18+
auto& device = hw::Dev::disk<0, hw::IDE>(hw::IDE::SLAVE);
19+
disk = std::make_shared<FatDisk> (device);
20+
assert(disk);
1521

1622
// if the disk is empty, we can't mount a filesystem anyways
17-
if (disk->empty()) panic("Oops! The memdisk is empty!\n");
23+
if (disk->empty()) panic("Oops! The disk is empty!\n");
1824

1925
// list extended partitions
2026
list_partitions(disk);
@@ -54,6 +60,10 @@ void Service::start()
5460
ent.name().c_str(), buf.len, contents.c_str());
5561

5662
}
63+
else
64+
{
65+
printf("Invalid entity for /test.txt\n");
66+
}
5767
return;
5868

5969
disk->fs().ls("/",
@@ -121,7 +131,7 @@ void Service::start()
121131
printf("*** TEST SERVICE STARTED *** \n");
122132
}
123133

124-
void list_partitions(fs::MountedDisk disk)
134+
void list_partitions(decltype(disk) disk)
125135
{
126136
disk->partitions(
127137
[] (fs::error_t err, auto& parts)

src/fs/fat.cpp

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -64,23 +64,17 @@ namespace fs
6464

6565
debug("System ID: \t%.8s\n", bpb->system_id);
6666

67-
// initialize FAT
68-
if (bpb->small_sectors) // FAT16
69-
{
70-
this->fat_type = FAT::T_FAT16;
71-
this->sectors = bpb->small_sectors;
72-
this->sectors_per_fat = bpb->sectors_per_fat;
73-
this->root_dir_sectors = ((bpb->root_entries * 32) + (sector_size - 1)) / sector_size;
74-
//printf("Root dir sectors: %u\n", this->root_dir_sectors);
75-
//this->root_dir_sectors = 0;
76-
}
67+
// sector count
68+
if (bpb->small_sectors)
69+
this->sectors = bpb->small_sectors;
7770
else
78-
{
79-
this->fat_type = FAT::T_FAT32;
80-
this->sectors = bpb->large_sectors;
71+
this->sectors = bpb->large_sectors;
72+
// sectors per FAT (not sure about the rule here)
73+
this->sectors_per_fat = bpb->sectors_per_fat;
74+
if (this->sectors_per_fat == 0)
8175
this->sectors_per_fat = *(uint32_t*) &mbr->boot[25];
82-
this->root_dir_sectors = 0;
83-
}
76+
// root dir sectors from root entries
77+
this->root_dir_sectors = ((bpb->root_entries * 32) + (sector_size - 1)) / sector_size;
8478
// calculate index of first data sector
8579
this->data_index = bpb->reserved_sectors + (bpb->fa_tables * this->sectors_per_fat) + this->root_dir_sectors;
8680
debug("First data sector: %u\n", this->data_index);
@@ -115,7 +109,12 @@ namespace fs
115109
{
116110
this->fat_type = FAT::T_FAT32;
117111
this->root_cluster = *(uint32_t*) &mbr->boot[33];
112+
this->root_cluster = 2;
118113
debug("The image is type FAT32, with %u clusters\n", this->clusters);
114+
//printf("Root dir entries: %u clusters\n", bpb->root_entries);
115+
//assert(bpb->root_entries == 0);
116+
//this->root_dir_sectors = 0;
117+
//this->data_index = bpb->reserved_sectors + bpb->fa_tables * this->sectors_per_fat;
119118
}
120119
debug("Root cluster index: %u (sector %u)\n", this->root_cluster, cl_to_sector(root_cluster));
121120
debug("System ID: %.8s\n", bpb->system_id);
@@ -234,7 +233,7 @@ namespace fs
234233
}
235234

236235
final_name[final_count] = 0;
237-
//printf("Long name: %s\n", final_name);
236+
debug("Long name: %s\n", final_name);
238237

239238
i++; // skip over the long version
240239
// to the short version for the stats and cluster
@@ -254,7 +253,8 @@ namespace fs
254253
else
255254
{
256255
auto* D = &root[i];
257-
//printf("Short name: %.11s\n", D->shortname);
256+
debug("Short name: %.11s\n", D->shortname);
257+
258258
std::string dirname((char*) D->shortname, 11);
259259
dirname = trim_right_copy(dirname);
260260

@@ -277,13 +277,16 @@ namespace fs
277277
dirvec_t dirents,
278278
on_internal_ls_func callback)
279279
{
280-
std::function<void(uint32_t)> next;
280+
// list contents of meme sector by sector
281+
typedef std::function<void(uint32_t)> next_func_t;
281282

282-
next = [this, sector, callback, &dirents, next] (uint32_t sector)
283+
auto next = std::make_shared<next_func_t> ();
284+
*next =
285+
[this, sector, callback, dirents, next] (uint32_t sector)
283286
{
284-
//printf("int_ls: sec=%u\n", sector);
287+
debug("int_ls: sec=%u\n", sector);
285288
device.read(sector,
286-
[this, sector, callback, &dirents, next] (buffer_t data)
289+
[this, sector, callback, dirents, next] (buffer_t data)
287290
{
288291
if (!data)
289292
{
@@ -302,14 +305,14 @@ namespace fs
302305
else
303306
{
304307
// go to next sector
305-
next(sector+1);
308+
(*next)(sector+1);
306309
}
307310

308311
}); // read root dir
309312
};
310313

311314
// start reading sectors asynchronously
312-
next(sector);
315+
(*next)(sector);
313316
}
314317

315318
void FAT::traverse(std::shared_ptr<Path> path, cluster_func callback)
@@ -318,9 +321,9 @@ namespace fs
318321
typedef std::function<void(uint32_t)> next_func_t;
319322

320323
// asynch stack traversal
321-
next_func_t next;
322-
next =
323-
[this, path, &next, callback] (uint32_t cluster)
324+
auto next = std::make_shared<next_func_t> ();
325+
*next =
326+
[this, path, next, callback] (uint32_t cluster)
324327
{
325328
if (path->empty())
326329
{
@@ -350,7 +353,7 @@ namespace fs
350353

351354
// list directory contents
352355
int_ls(S, dirents,
353-
[name, dirents, &next, callback] (error_t error, dirvec_t ents)
356+
[name, dirents, next, callback] (error_t error, dirvec_t ents)
354357
{
355358
if (unlikely(error))
356359
{
@@ -370,7 +373,7 @@ namespace fs
370373
debug("\t\t cluster: %llu\n", e.block);
371374
// only follow directories
372375
if (e.type() == DIR)
373-
next(e.block);
376+
(*next)(e.block);
374377
else
375378
callback(true, dirents);
376379
return;
@@ -382,9 +385,8 @@ namespace fs
382385
});
383386

384387
};
385-
386388
// start by reading root directory
387-
next(0);
389+
(*next)(0);
388390
}
389391

390392
void FAT::ls(const std::string& path, on_ls_func on_ls)
@@ -412,13 +414,13 @@ namespace fs
412414
// number of sectors to read ahead
413415
size_t chunks = ent.size / sector_size + 1;
414416
// allocate buffer
415-
uint8_t* buffer = new uint8_t[chunks * sector_size];
417+
auto* buffer = new uint8_t[chunks * sector_size];
416418
// at which sector we will stop
417419
size_t total = chunks;
418420
size_t current = 0;
419421

420422
typedef std::function<void(uint32_t, size_t, size_t)> next_func_t;
421-
auto* next = new next_func_t;
423+
auto next = std::make_shared<next_func_t> ();
422424

423425
*next =
424426
[this, buffer, ent, callback, next] (uint32_t sector, size_t current, size_t total)
@@ -432,8 +434,6 @@ namespace fs
432434
auto buffer_ptr = buffer_t(buffer, std::default_delete<uint8_t[]>());
433435
// notify caller
434436
callback(no_error, buffer_ptr, ent.size);
435-
// cleanup (after callback)
436-
delete next;
437437
return;
438438
}
439439
device.read(sector,
@@ -444,7 +444,6 @@ namespace fs
444444
// general I/O error occurred
445445
debug("Failed to read sector %u for read()", sector);
446446
// cleanup
447-
delete next;
448447
delete[] buffer;
449448
callback(true, buffer_t(), 0);
450449
return;
@@ -498,28 +497,31 @@ namespace fs
498497
});
499498
} // readFile()
500499

501-
void FAT::stat(const std::string& strpath, on_stat_func callback)
500+
void FAT::stat(const std::string& strpath, on_stat_func func)
502501
{
503502
auto path = std::make_shared<Path> (strpath);
504503
if (unlikely(path->empty()))
505504
{
506-
// root doesn't have any stat anyways (except ATTR_VOLUME_ID in FAT)
507-
callback(true, Dirent(INVALID_ENTITY, strpath));
505+
// root doesn't have any stat anyways
506+
// Note: could use ATTR_VOLUME_ID in FAT
507+
func(true, Dirent(INVALID_ENTITY, strpath));
508508
return;
509509
}
510510

511511
debug("stat: %s\n", path->back().c_str());
512512
// extract file we are looking for
513513
std::string filename = path->back();
514514
path->pop_back();
515+
// we need to remember this later
516+
auto callback = std::make_shared<on_stat_func> (func);
515517

516518
traverse(path,
517-
[this, filename, &callback] (error_t error, dirvec_t dirents)
519+
[this, filename, callback] (error_t error, dirvec_t dirents)
518520
{
519521
if (unlikely(error))
520522
{
521523
// no path, no file!
522-
callback(error, Dirent(INVALID_ENTITY, filename));
524+
(*callback)(error, Dirent(INVALID_ENTITY, filename));
523525
return;
524526
}
525527

@@ -529,13 +531,13 @@ namespace fs
529531
if (unlikely(e.name() == filename))
530532
{
531533
// read this file
532-
callback(no_error, e);
534+
(*callback)(no_error, e);
533535
return;
534536
}
535537
}
536538

537539
// not found
538-
callback(true, Dirent(INVALID_ENTITY, filename));
540+
(*callback)(true, Dirent(INVALID_ENTITY, filename));
539541
});
540542
}
541543
}

0 commit comments

Comments
 (0)