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!
This commit is contained in:
snow flurry 2020-11-14 14:11:34 -08:00
parent 9bce32e727
commit 9d18bc84d0
2 changed files with 23 additions and 27 deletions

View file

@ -8,6 +8,8 @@
#include "dosfs.h" #include "dosfs.h"
#include "debug.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 * Opens an image a la open(2). Returns 0 on success, or
* some error number on failure. * 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)); (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; 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 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 coff, csz;
int clen = 0, i, left, chunk, cbytes, off, res;
chain = read_fat_chain(fsd, file->ent.low_loc, &clen); if (f_offset > file->ent.size) {
if (chain == NULL) { DPRINTF("offset requested is out of bounds!\n");
return -1; /* XXX */ return -EINVAL;
} }
cbytes = fsd->ib.sect_size * fsd->ib.sect_per_cluster; /* size in bytes of a cluster */
left = max_size; csz = fsd->ib.sect_per_cluster * fsd->ib.sect_size;
for (i = 0; i < clen; i++) { /* get the offset in the fat chain */
/* only copy as much as we can hold */ coff = f_offset / csz;
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;
}
left -= chunk; if (coff > file->fc_len) {
DPRINTF("offset is within filesize, but not enough clusters??\n");
if (left <= 0) return -EINVAL;
break;
} }
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; struct dos_dirent ent;
char fname[9]; char fname[9];
char fext[4]; char fext[4];
unsigned int *fat_chain;
int fc_len;
struct dosfile_t *next; struct dosfile_t *next;
} dosfile_t; } dosfile_t;
int open_image(const char *, int, dosfs_t *); int open_image(const char *, int, dosfs_t *);
void close_image(dosfs_t *); void close_image(dosfs_t *);
dosfile_t *dos_listdir(dosfs_t *, unsigned int); dosfile_t *dos_listdir(dosfs_t *, unsigned int);
int dos_fread(dosfs_t *, dosfile_t *, void *, int);
void dos_freedir(dosfile_t *); void dos_freedir(dosfile_t *);
int get_byte_offset(dosfs_t *, dosfile_t *, int);
#endif /* !_FAT12_H */ #endif /* !_FAT12_H */