a0f1236e88
Change-Id: Ic22908e249f2db85c029e1644c9531a12ed87993
185 lines
7.6 KiB
C
185 lines
7.6 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2002 by Linus Nielsen Feltzing
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
#ifndef FAT_H
|
|
#define FAT_H
|
|
|
|
#include <stdbool.h>
|
|
#include <sys/types.h>
|
|
#if defined(__PCTOOL__) || defined(SIMULATOR) || ((CONFIG_PLATFORM & PLATFORM_HOSTED) == PLATFORM_HOSTED)
|
|
#include <utime.h>
|
|
#endif
|
|
#include <time.h>
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "mv.h" /* for volume definitions */
|
|
|
|
/********
|
|
**** DO NOT use these functions directly unless otherwise noted. Required
|
|
**** synchronization is done by higher-level interfaces to minimize locking
|
|
**** overhead.
|
|
****
|
|
**** Volume, drive, string, etc. parameters should also be checked by
|
|
**** callers for gross violations-- NULL strings, out-of-bounds values,
|
|
**** etc.
|
|
****/
|
|
|
|
/****************************************************************************
|
|
** Values that can be overridden by a target in config-[target].h
|
|
**/
|
|
|
|
/* if your ATA implementation can do better, go right ahead and increase this
|
|
* value */
|
|
#ifndef FAT_MAX_TRANSFER_SIZE
|
|
#define FAT_MAX_TRANSFER_SIZE 256
|
|
#endif
|
|
|
|
/**
|
|
****************************************************************************/
|
|
|
|
#define INVALID_SECNUM (0xfffffffeul) /* sequential, not FAT */
|
|
#define FAT_MAX_FILE_SIZE (0xfffffffful) /* 2^32-1 bytes */
|
|
#define MAX_DIRENTRIES 65536
|
|
#define MAX_DIRECTORY_SIZE (MAX_DIRENTRIES*32) /* 2MB max size */
|
|
|
|
/* these aren't I/O error conditions, so define specially; failure rc's
|
|
* shouldn't return the last digit as "0", therefore this is unambiguous */
|
|
#define FAT_RC_ENOSPC (-10)
|
|
#define FAT_SEEK_EOF (-20)
|
|
|
|
/* Number of bytes reserved for a file name (including the trailing \0).
|
|
Since names are stored in the entry as UTF-8, we won't be ble to
|
|
store all names allowed by FAT. In FAT, a name can have max 255
|
|
characters (not bytes!). Since the UTF-8 encoding of a char may take
|
|
up to 4 bytes, there will be names that we won't be able to store
|
|
completely. For such names, the short DOS name is used. */
|
|
#define FAT_DIRENTRY_NAME_MAX 255
|
|
struct fat_direntry
|
|
{
|
|
union {
|
|
uint8_t name[255+1+4]; /* UTF-8 name plus \0 plus parse slop */
|
|
uint16_t ucssegs[5+20][13]; /* UTF-16 segment buffer - layout saves... */
|
|
}; /* ...130 bytes (important if stacked) */
|
|
uint16_t ucsterm; /* allow one NULL-term after ucssegs */
|
|
uint8_t shortname[13]; /* DOS filename (OEM charset) */
|
|
uint8_t attr; /* file attributes */
|
|
uint8_t crttimetenth; /* millisecond creation time stamp (0-199) */
|
|
uint16_t crttime; /* creation time */
|
|
uint16_t crtdate; /* creation date */
|
|
uint16_t lstaccdate; /* last access date */
|
|
uint16_t wrttime; /* last write time */
|
|
uint16_t wrtdate; /* last write date */
|
|
uint32_t filesize; /* file size in bytes */
|
|
int32_t firstcluster; /* first FAT cluster of file, 0 if empty */
|
|
};
|
|
|
|
/* cursor structure used for scanning directories; holds the last-returned
|
|
entry information */
|
|
#define FAT_DIRSCAN_RW_VAL (0u - 1u)
|
|
|
|
struct fat_dirscan_info
|
|
{
|
|
unsigned int entry; /* short dir entry index in parent */
|
|
unsigned int entries; /* number of dir entries used */
|
|
};
|
|
|
|
#define FAT_FILE_RW_VAL (0ul - 1ul)
|
|
|
|
/* basic FAT file information about where to find a file and who houses it */
|
|
struct fat_file
|
|
{
|
|
#ifdef HAVE_MULTIVOLUME
|
|
int volume; /* file resides on which volume (first!) */
|
|
#endif
|
|
long firstcluster; /* first cluster in file */
|
|
long dircluster; /* first cluster of parent directory */
|
|
struct fat_dirscan_info e; /* entry information */
|
|
};
|
|
|
|
/* this stores what was last accessed when read or writing a file's data */
|
|
struct fat_filestr
|
|
{
|
|
struct fat_file *fatfilep; /* common file information */
|
|
long lastcluster; /* cluster of last access */
|
|
unsigned long lastsector; /* sector of last access */
|
|
long clusternum; /* cluster number of last access */
|
|
unsigned long sectornum; /* sector number within current cluster */
|
|
bool eof; /* end-of-file reached */
|
|
};
|
|
|
|
/** File entity functions **/
|
|
int fat_create_file(struct fat_file *parent, const char *name,
|
|
uint8_t attr, struct fat_file *file,
|
|
struct fat_direntry *fatent);
|
|
bool fat_dir_is_parent(const struct fat_file *dir, const struct fat_file *file);
|
|
bool fat_file_is_same(const struct fat_file *file1, const struct fat_file *file2);
|
|
int fat_fstat(struct fat_file *file, struct fat_direntry *entry);
|
|
int fat_open(const struct fat_file *parent, long startcluster,
|
|
struct fat_file *file);
|
|
int fat_open_rootdir(IF_MV(int volume,) struct fat_file *dir);
|
|
enum fat_remove_op /* what should fat_remove(), remove? */
|
|
{
|
|
FAT_RM_DIRENTRIES = 0x1, /* remove only directory entries */
|
|
FAT_RM_DATA = 0x2, /* remove only file data */
|
|
FAT_RM_ALL = 0x3, /* remove all of above */
|
|
};
|
|
int fat_remove(struct fat_file *file, enum fat_remove_op what);
|
|
int fat_rename(struct fat_file *parent, struct fat_file *file,
|
|
const unsigned char *newname);
|
|
int fat_utime(struct fat_file *parent, struct fat_file *file,
|
|
const struct utimbuf *utimes);
|
|
|
|
/** File stream functions **/
|
|
int fat_closewrite(struct fat_filestr *filestr, uint32_t size,
|
|
struct fat_direntry *fatentp);
|
|
void fat_filestr_init(struct fat_filestr *filestr, struct fat_file *file);
|
|
unsigned long fat_query_sectornum(const struct fat_filestr *filestr);
|
|
long fat_readwrite(struct fat_filestr *filestr, unsigned long sectorcount,
|
|
void *buf, bool write);
|
|
void fat_rewind(struct fat_filestr *filestr);
|
|
int fat_seek(struct fat_filestr *filestr, unsigned long sector);
|
|
void fat_seek_to_stream(struct fat_filestr *filestr,
|
|
const struct fat_filestr *filestr_seek_to);
|
|
int fat_truncate(const struct fat_filestr *filestr);
|
|
|
|
/** Directory stream functions **/
|
|
struct filestr_cache;
|
|
int fat_readdir(struct fat_filestr *dirstr, struct fat_dirscan_info *scan,
|
|
struct filestr_cache *cachep, struct fat_direntry *entry);
|
|
void fat_rewinddir(struct fat_dirscan_info *scan);
|
|
|
|
/** Mounting and unmounting functions **/
|
|
bool fat_ismounted(IF_MV_NONVOID(int volume));
|
|
int fat_mount(IF_MV(int volume,) IF_MD(int drive,) unsigned long startsector);
|
|
int fat_unmount(IF_MV_NONVOID(int volume));
|
|
|
|
/** Debug screen stuff **/
|
|
#ifdef MAX_LOG_SECTOR_SIZE
|
|
int fat_get_bytes_per_sector(IF_MV_NONVOID(int volume));
|
|
#endif /* MAX_LOG_SECTOR_SIZE */
|
|
unsigned int fat_get_cluster_size(IF_MV_NONVOID(int volume));
|
|
void fat_recalc_free(IF_MV_NONVOID(int volume));
|
|
bool fat_size(IF_MV(int volume,) unsigned long *size, unsigned long *free);
|
|
|
|
/** Misc. **/
|
|
void fat_empty_fat_direntry(struct fat_direntry *entry);
|
|
void fat_init(void);
|
|
|
|
#endif /* FAT_H */
|