Compare commits

...

2 commits

Author SHA1 Message Date
snow flurry 546ed596d4 TODO: use fopen(3), using read_fat_chain is done 2020-11-14 15:06:27 -08:00
snow flurry 9d18bc84d0 dosfs: Remove dos_fread(), add get_byte_offset()
A read() analogue wouldn't be particularly useful here since we're
just poking at bytes, but having a way to get the "real" offset in
a file sure would be!
2020-11-14 14:11:34 -08:00
3 changed files with 25 additions and 28 deletions

3
TODO
View file

@ -1,4 +1,5 @@
Implement randomness (xorshift? https://www.jstatsoft.org/article/view/v008i14)
Maybe extract file "read"/"write" operations with read_fat_chain()
Config parser (config.c)
Do the actual corrupty things
Use fopen(3) and friends instead of open(2)

View file

@ -8,6 +8,8 @@
#include "dosfs.h"
#include "debug.h"
static unsigned int *read_fat_chain(dosfs_t *, unsigned int, int *);
/*
* Opens an image a la open(2). Returns 0 on success, or
* some error number on failure.
@ -151,6 +153,9 @@ dos_listdir(dosfs_t *fsd, unsigned int offset)
(void)memcpy(&cur->ent, &dirs[i], sizeof(struct dos_dirent));
/* useful for get_byte_offset() */
cur->fat_chain = read_fat_chain(fsd, cur->ent.low_loc,
&cur->fc_len);
res = 0;
}
@ -234,39 +239,29 @@ read_fat_chain(dosfs_t *fsd, unsigned int first, int *length)
}
/*
* TODO: reads a file to a given buffer
* Converts the byte offset of a file into the "real"
* offset, i.e. one that can be used with lseek()/pread().
*/
int
dos_fread(dosfs_t *fsd, dosfile_t *file, void *buf, int max_size)
get_byte_offset(dosfs_t *fsd, dosfile_t *file, int f_offset)
{
unsigned int *chain = NULL;
int clen = 0, i, left, chunk, cbytes, off, res;
int coff, csz;
chain = read_fat_chain(fsd, file->ent.low_loc, &clen);
if (chain == NULL) {
return -1; /* XXX */
if (f_offset > file->ent.size) {
DPRINTF("offset requested is out of bounds!\n");
return -EINVAL;
}
cbytes = fsd->ib.sect_size * fsd->ib.sect_per_cluster;
left = max_size;
/* size in bytes of a cluster */
csz = fsd->ib.sect_per_cluster * fsd->ib.sect_size;
for (i = 0; i < clen; i++) {
/* only copy as much as we can hold */
chunk = (left < cbytes) ? left : cbytes;
res = pread(fsd->ifd, buf + (i * cbytes),
chunk, fsd->data_loc + (chain[i] * cbytes));
if (res == -1) {
DPRINTF("pread failed\n");
free(chain);
return -1;
}
/* get the offset in the fat chain */
coff = f_offset / csz;
left -= chunk;
if (left <= 0)
break;
if (coff > file->fc_len) {
DPRINTF("offset is within filesize, but not enough clusters??\n");
return -EINVAL;
}
return 0;
return (file->fat_chain[coff] * csz) + (f_offset % csz);
}

View file

@ -69,16 +69,17 @@ typedef struct dosfile_t {
struct dos_dirent ent;
char fname[9];
char fext[4];
unsigned int *fat_chain;
int fc_len;
struct dosfile_t *next;
} dosfile_t;
int open_image(const char *, int, dosfs_t *);
void close_image(dosfs_t *);
dosfile_t *dos_listdir(dosfs_t *, unsigned int);
int dos_fread(dosfs_t *, dosfile_t *, void *, int);
void dos_freedir(dosfile_t *);
int get_byte_offset(dosfs_t *, dosfile_t *, int);
#endif /* !_FAT12_H */