/*
* Copyright (c) 1996, 1998 Robert Nordier
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
__FBSDID("$FreeBSD$");
/*
* also supports VFAT.
*/
#include <string.h>
#include <stddef.h>
#include "stand.h"
#include "dosfs.h"
"dosfs",
};
/* DOS "BIOS Parameter Block" */
typedef struct {
} DOS_BPB;
/* Initial portion of DOS boot sector */
typedef struct {
} DOS_BS;
/* Supply missing "." and ".." root directory entries */
{0, 0}, {0x21, 0}, {0, 0}, {0, 0, 0, 0}},
{0, 0}, {0x21, 0}, {0, 0}, {0, 0, 0, 0}}
};
/* The usual conversion macros to avoid multiplication and division */
/* Convert cluster number to offset within filesystem */
/* Convert cluster number to logical sector number */
/* Convert cluster number to offset within FAT */
(c) << 2)
/* Does cluster number reference a valid data cluster? */
/* Get start cluster from directory entry */
/*
* fat cache metadata
*/
struct fatcache {
};
static int dosunmount(DOS_FS *);
static void
{
}
}
return;
}
}
}
/*
* Mount DOS filesystem
*/
static int
{
int err;
(void)dosunmount(fs);
return(err);
}
}
return 0;
}
/*
* Unmount mounted filesystem
*/
static int
{
int err;
return(EBUSY);
return(err);
return 0;
}
/*
* Common code shared by dos_mount() and dos_unmount()
*/
static int
{
return(0);
}
/*
* Open DOS file
*/
static int
{
DOS_FILE *f;
int err = 0;
/* Allocate mount structure, associate with open */
goto out;
goto out;
goto out;
}
out:
return(err);
}
/*
* Read from file
*/
static int
{
int err = 0;
/*
* as ioget() can be called *a lot*, use twiddle here.
* also 4 seems to be good value not to slow loading down too much:
* with 270MB file (~540k ioget() calls, twiddle can easily waste 4-5sec.
*/
twiddle(4);
return EINVAL;
nb = n;
c = f->c;
while (cnt) {
n = 0;
if (!c) {
if ((c = clus))
} else if (!off)
n++;
while (n--) {
goto out;
goto out;
}
}
n = cnt;
goto out;
f->offset += n;
f->c = c;
off = 0;
cnt -= n;
}
out:
if (resid)
return(err);
}
/*
* Reposition within file
*/
static off_t
{
switch (whence) {
case SEEK_SET:
off = 0;
break;
case SEEK_CUR:
break;
case SEEK_END:
break;
default:
return(-1);
}
return(-1);
}
f->c = 0;
return(off);
}
/*
* Close open file
*/
static int
{
free(f);
return 0;
}
/*
* Return some stat information on a file.
*/
static int
{
/* only important stuff */
return EINVAL;
return (0);
}
static int
{
int x, i;
x = 0;
for (i = 0; i < 11; i++) {
x = ((x & 1) << 7) | (x >> 1);
x += buf[i];
x &= 0xff;
}
return (x);
}
static int
{
/* DOS_FILE *f = (DOS_FILE *)fd->f_fsdata; */
int err;
x = chk = 0;
while (1) {
xdn = x;
x = 0;
if (err)
return (err);
return (ENOENT);
return (ENOENT);
/* Skip deleted entries */
continue;
/* Check if directory entry is volume label */
/*
* If volume label set, check if the current entry is
* extended entry (FA_XDE) for long file names.
*/
/*
* Read through all following extended entries
* to get the long file name. 0x40 marks the
* last entry containing part of long file name.
*/
continue;
if (x < 1 || x > 20) {
x = 0;
continue;
}
} else {
/* skip only volume label entries */
continue;
}
} else {
if (xdn == 1) {
if (x == chk)
break;
} else {
break;
}
x = 0;
}
}
d->d_reclen = sizeof(*d);
return(0);
}
/*
* Parse DOS boot sector
*/
static int
{
return EINVAL;
return EINVAL;
return EINVAL;
return EINVAL;
return EINVAL;
} else {
return EINVAL;
return EINVAL;
return EINVAL;
}
return EINVAL;
return EINVAL;
return EINVAL;
return EINVAL;
return 0;
}
/*
* Return directory entry from path
*/
static int
{
char *s;
size_t n;
int err;
err = 0;
while (*path) {
while (*path == '/')
path++;
if (*path == '\0')
break;
if ((n = s - path) > 255)
return ENAMETOOLONG;
name[n] = 0;
path = s;
return ENOTDIR;
return err;
}
return 0;
}
/*
* Lookup path segment
*/
static int
{
if (!clus)
return 0;
}
lsec = 0;
for (;;) {
else
return EINVAL;
return err;
return ENOENT;
if (x & 0x40) {
x &= ~0x40;
}
if (x >= 1 && x <= 20) {
xdn = x;
continue;
}
}
}
if (!ok) {
}
if (ok) {
return 0;
}
}
}
xdn = 0;
}
}
if (!clus)
break;
return err;
break;
}
return ENOENT;
}
/*
* Copy name from extended directory entry
*/
static void
{
static struct {
};
u_char *p;
u_int n, x, c;
for (n = 0; n < 3; n++)
p += 2, x--) {
c = '?';
if (!(*lfn++ = c))
return;
}
*lfn = 0;
}
/*
* Copy short filename
*/
static void
{
u_char *p;
int j, i;
p = sfn;
for (i = 0; i <= j; i++)
*p++ = '.';
for (i = 0; i <= j; i++)
}
}
*p = 0;
if (*sfn == 5)
*sfn = 0xe5;
}
/*
* Return size of file in bytes
*/
static off_t
{
u_int c;
int n;
else {
return n;
}
}
return size;
}
/*
* Count number of clusters in chain
*/
static int
{
int n;
return -1;
}
/*
* Get next cluster in cluster chain. Use in core fat cache unless another
* device replaced it.
*/
static int
{
u_char *s;
int err = 0;
/* fat cache was changed to another device, don't use it */
if (err)
return (err);
} else {
s = buf;
n = nbyte;
s += n;
nbyte -= n;
}
if (nbyte -= n) {
s += nbyte;
}
if (n)
}
return (0);
}
/*
* Is cluster an end-of-chain marker?
*/
static int
{
}
/*
* Offset-based I/O primitive
*/
static int
{
char *s;
int err;
s = buf;
n = nbyte;
return err;
s += n;
nbyte -= n;
}
if (nbyte -= n) {
return err;
s += nbyte;
}
if (n) {
return err;
}
return 0;
}
/*
* Sector-based I/O primitive
*/
static int
{
}