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:
parent
9bce32e727
commit
9d18bc84d0
45
src/dosfs.c
45
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;
|
||||
/* get the offset in the fat chain */
|
||||
coff = f_offset / csz;
|
||||
|
||||
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 (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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue