Changeset View
Changeset View
Standalone View
Standalone View
head/lib/libstand/dosfs.c
Show First 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | |||||
static int lookup(DOS_FS *, u_int, const char *, DOS_DE **); | static int lookup(DOS_FS *, u_int, const char *, DOS_DE **); | ||||
static void cp_xdnm(u_char *, DOS_XDE *); | static void cp_xdnm(u_char *, DOS_XDE *); | ||||
static void cp_sfn(u_char *, DOS_DE *); | static void cp_sfn(u_char *, DOS_DE *); | ||||
static off_t fsize(DOS_FS *, DOS_DE *); | static off_t fsize(DOS_FS *, DOS_DE *); | ||||
static int fatcnt(DOS_FS *, u_int); | static int fatcnt(DOS_FS *, u_int); | ||||
static int fatget(DOS_FS *, u_int *); | static int fatget(DOS_FS *, u_int *); | ||||
static int fatend(u_int, u_int); | static int fatend(u_int, u_int); | ||||
static int ioread(DOS_FS *, u_int, void *, u_int); | static int ioread(DOS_FS *, u_int, void *, u_int); | ||||
static int ioget(struct open_file *, daddr_t, size_t, void *, u_int); | static int ioget(struct open_file *, daddr_t, void *, u_int); | ||||
static void | static void | ||||
dos_read_fat(DOS_FS *fs, struct open_file *fd) | dos_read_fat(DOS_FS *fs, struct open_file *fd) | ||||
{ | { | ||||
struct devdesc *dd = fd->f_devdata; | struct devdesc *dd = fd->f_devdata; | ||||
if (fat.buf != NULL) { /* can we reuse old buffer? */ | if (fat.buf != NULL) { /* can we reuse old buffer? */ | ||||
if (fat.size != fs->spf) { | if (fat.size != fs->spf) { | ||||
free(fat.buf); /* no, free old buffer */ | free(fat.buf); /* no, free old buffer */ | ||||
fat.buf = NULL; | fat.buf = NULL; | ||||
} | } | ||||
} | } | ||||
if (fat.buf == NULL) | if (fat.buf == NULL) | ||||
fat.buf = malloc(secbyt(fs->spf)); | fat.buf = malloc(secbyt(fs->spf)); | ||||
if (fat.buf != NULL) { | if (fat.buf != NULL) { | ||||
if (ioget(fd, fs->lsnfat, 0, fat.buf, secbyt(fs->spf)) == 0) { | if (ioget(fd, fs->lsnfat, fat.buf, secbyt(fs->spf)) == 0) { | ||||
fat.size = fs->spf; | fat.size = fs->spf; | ||||
fat.unit = dd->d_unit; | fat.unit = dd->d_unit; | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
if (fat.buf != NULL) /* got IO error */ | if (fat.buf != NULL) /* got IO error */ | ||||
free(fat.buf); | free(fat.buf); | ||||
fat.buf = NULL; | fat.buf = NULL; | ||||
Show All 10 Lines | dos_mount(DOS_FS *fs, struct open_file *fd) | ||||
int err; | int err; | ||||
struct devdesc *dd = fd->f_devdata; | struct devdesc *dd = fd->f_devdata; | ||||
u_char *buf; | u_char *buf; | ||||
bzero(fs, sizeof(DOS_FS)); | bzero(fs, sizeof(DOS_FS)); | ||||
fs->fd = fd; | fs->fd = fd; | ||||
if ((err = !(buf = malloc(secbyt(1))) ? errno : 0) || | if ((err = !(buf = malloc(secbyt(1))) ? errno : 0) || | ||||
(err = ioget(fs->fd, 0, 0, buf, secbyt(1))) || | (err = ioget(fs->fd, 0, buf, secbyt(1))) || | ||||
(err = parsebs(fs, (DOS_BS *)buf))) { | (err = parsebs(fs, (DOS_BS *)buf))) { | ||||
if (buf != NULL) | if (buf != NULL) | ||||
free(buf); | free(buf); | ||||
(void)dosunmount(fs); | (void)dosunmount(fs); | ||||
return (err); | return (err); | ||||
} | } | ||||
free(buf); | free(buf); | ||||
▲ Show 20 Lines • Show All 403 Lines • ▼ Show 20 Lines | lookup(DOS_FS *fs, u_int clus, const char *name, DOS_DE **dep) | ||||
for (;;) { | for (;;) { | ||||
if (!clus && !lsec) | if (!clus && !lsec) | ||||
lsec = fs->lsndir; | lsec = fs->lsndir; | ||||
else if (okclus(fs, clus)) | else if (okclus(fs, clus)) | ||||
lsec = blklsn(fs, clus); | lsec = blklsn(fs, clus); | ||||
else | else | ||||
return (EINVAL); | return (EINVAL); | ||||
for (sec = 0; sec < nsec; sec++) { | for (sec = 0; sec < nsec; sec++) { | ||||
if ((err = ioget(fs->fd, lsec + sec, 0, dir, secbyt(1)))) | if ((err = ioget(fs->fd, lsec + sec, dir, secbyt(1)))) | ||||
return (err); | return (err); | ||||
for (ent = 0; ent < DEPSEC; ent++) { | for (ent = 0; ent < DEPSEC; ent++) { | ||||
if (!*dir[ent].de.name) | if (!*dir[ent].de.name) | ||||
return (ENOENT); | return (ENOENT); | ||||
if (*dir[ent].de.name != 0xe5) { | if (*dir[ent].de.name != 0xe5) { | ||||
if ((dir[ent].de.attr & FA_MASK) == FA_XDE) { | if ((dir[ent].de.attr & FA_MASK) == FA_XDE) { | ||||
x = dir[ent].xde.seq; | x = dir[ent].xde.seq; | ||||
if (x & 0x40 || (x + 1 == xdn && | if (x & 0x40 || (x + 1 == xdn && | ||||
▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Get next cluster in cluster chain. Use in core fat cache unless another | * Get next cluster in cluster chain. Use in core fat cache unless another | ||||
* device replaced it. | * device replaced it. | ||||
*/ | */ | ||||
static int | static int | ||||
fatget(DOS_FS *fs, u_int *c) | fatget(DOS_FS *fs, u_int *c) | ||||
{ | { | ||||
u_char buf[4]; | u_char buf[4]; | ||||
u_char *s; | u_int x, offset, n, nbyte; | ||||
u_int x, offset, off, n, nbyte, lsec; | |||||
struct devdesc *dd = fs->fd->f_devdata; | struct devdesc *dd = fs->fd->f_devdata; | ||||
int err = 0; | int err = 0; | ||||
if (fat.unit != dd->d_unit) { | if (fat.unit != dd->d_unit) { | ||||
/* fat cache was changed to another device, don't use it */ | /* fat cache was changed to another device, don't use it */ | ||||
err = ioread(fs, secbyt(fs->lsnfat) + fatoff(fs->fatsz, *c), buf, | err = ioread(fs, secbyt(fs->lsnfat) + fatoff(fs->fatsz, *c), buf, | ||||
fs->fatsz != 32 ? 2 : 4); | fs->fatsz != 32 ? 2 : 4); | ||||
if (err) | if (err) | ||||
return (err); | return (err); | ||||
} else { | } else { | ||||
offset = fatoff(fs->fatsz, *c); | offset = fatoff(fs->fatsz, *c); | ||||
nbyte = fs->fatsz != 32 ? 2 : 4; | nbyte = fs->fatsz != 32 ? 2 : 4; | ||||
s = buf; | if (offset + nbyte > secbyt(fat.size)) | ||||
if ((off = offset & (SECSIZ - 1))) { | return (EINVAL); | ||||
offset -= off; | memcpy(buf, fat.buf + offset, nbyte); | ||||
lsec = bytsec(offset); | |||||
offset += SECSIZ; | |||||
if ((n = SECSIZ - off) > nbyte) | |||||
n = nbyte; | |||||
memcpy(s, fat.buf + secbyt(lsec) + off, n); | |||||
s += n; | |||||
nbyte -= n; | |||||
} | } | ||||
n = nbyte & (SECSIZ - 1); | |||||
if (nbyte -= n) { | |||||
memcpy(s, fat.buf + secbyt(bytsec(offset)), nbyte); | |||||
offset += nbyte; | |||||
s += nbyte; | |||||
} | |||||
if (n) | |||||
memcpy(s, fat.buf + secbyt(bytsec(offset)), n); | |||||
} | |||||
x = fs->fatsz != 32 ? cv2(buf) : cv4(buf); | x = fs->fatsz != 32 ? cv2(buf) : cv4(buf); | ||||
*c = fs->fatsz == 12 ? *c & 1 ? x >> 4 : x & 0xfff : x; | *c = fs->fatsz == 12 ? *c & 1 ? x >> 4 : x & 0xfff : x; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Is cluster an end-of-chain marker? | * Is cluster an end-of-chain marker? | ||||
*/ | */ | ||||
static int | static int | ||||
fatend(u_int sz, u_int c) | fatend(u_int sz, u_int c) | ||||
{ | { | ||||
return (c > (sz == 12 ? 0xff7U : sz == 16 ? 0xfff7U : 0xffffff7)); | return (c > (sz == 12 ? 0xff7U : sz == 16 ? 0xfff7U : 0xffffff7)); | ||||
} | } | ||||
/* | /* | ||||
* Offset-based I/O primitive | * Offset-based I/O primitive | ||||
*/ | */ | ||||
static int | static int | ||||
ioread(DOS_FS *fs, u_int offset, void *buf, u_int nbyte) | ioread(DOS_FS *fs, u_int offset, void *buf, u_int nbyte) | ||||
{ | { | ||||
char *s; | char *s; | ||||
u_int off, n; | u_int off, n; | ||||
int err; | int err; | ||||
u_char local_buf[SECSIZ]; | |||||
s = buf; | s = buf; | ||||
if ((off = offset & (SECSIZ - 1))) { | if ((off = offset & (SECSIZ - 1))) { | ||||
offset -= off; | offset -= off; | ||||
if ((n = SECSIZ - off) > nbyte) | if ((n = SECSIZ - off) > nbyte) | ||||
n = nbyte; | n = nbyte; | ||||
if ((err = ioget(fs->fd, bytsec(offset), off, s, n))) | if ((err = ioget(fs->fd, bytsec(offset), local_buf, sizeof(local_buf)))) | ||||
return (err); | return (err); | ||||
memcpy(s, local_buf + off, n); | |||||
offset += SECSIZ; | offset += SECSIZ; | ||||
s += n; | s += n; | ||||
nbyte -= n; | nbyte -= n; | ||||
} | } | ||||
n = nbyte & (SECSIZ - 1); | n = nbyte & (SECSIZ - 1); | ||||
if (nbyte -= n) { | if (nbyte -= n) { | ||||
if ((err = ioget(fs->fd, bytsec(offset), 0, s, nbyte))) | if ((err = ioget(fs->fd, bytsec(offset), s, nbyte))) | ||||
return (err); | return (err); | ||||
offset += nbyte; | offset += nbyte; | ||||
s += nbyte; | s += nbyte; | ||||
} | } | ||||
if (n) { | if (n) { | ||||
if ((err = ioget(fs->fd, bytsec(offset), 0, s, n))) | if ((err = ioget(fs->fd, bytsec(offset), local_buf, sizeof(local_buf)))) | ||||
return (err); | return (err); | ||||
memcpy(s, local_buf, n); | |||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Sector-based I/O primitive | * Sector-based I/O primitive | ||||
*/ | */ | ||||
static int | static int | ||||
ioget(struct open_file *fd, daddr_t lsec, size_t offset, void *buf, u_int size) | ioget(struct open_file *fd, daddr_t lsec, void *buf, u_int size) | ||||
{ | { | ||||
return ((fd->f_dev->dv_strategy)(fd->f_devdata, F_READ, lsec, offset, | return ((fd->f_dev->dv_strategy)(fd->f_devdata, F_READ, lsec, | ||||
size, buf, NULL)); | size, buf, NULL)); | ||||
} | } |