diff --git a/src/dosfs.c b/src/dosfs.c index 007838b..d6b289d 100644 --- a/src/dosfs.c +++ b/src/dosfs.c @@ -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); } diff --git a/src/dosfs.h b/src/dosfs.h index 5f2d012..d422818 100644 --- a/src/dosfs.h +++ b/src/dosfs.h @@ -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 */