diff options
Diffstat (limited to 'firmware/export/fat.h')
-rw-r--r-- | firmware/export/fat.h | 225 |
1 files changed, 135 insertions, 90 deletions
diff --git a/firmware/export/fat.h b/firmware/export/fat.h index a0d52acc35..3aa1e254dc 100644 --- a/firmware/export/fat.h +++ b/firmware/export/fat.h | |||
@@ -18,123 +18,168 @@ | |||
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | |||
22 | #ifndef FAT_H | 21 | #ifndef FAT_H |
23 | #define FAT_H | 22 | #define FAT_H |
24 | 23 | ||
25 | #include <stdbool.h> | 24 | #include <stdbool.h> |
26 | #include "mv.h" /* for volume definitions */ | 25 | #include <sys/types.h> |
26 | #include <time.h> | ||
27 | #include "config.h" | 27 | #include "config.h" |
28 | #include "system.h" | 28 | #include "system.h" |
29 | #include "mv.h" /* for volume definitions */ | ||
30 | |||
31 | /******** | ||
32 | **** DO NOT use these functions directly unless otherwise noted. Required | ||
33 | **** synchronization is done by higher-level interfaces to minimize locking | ||
34 | **** overhead. | ||
35 | **** | ||
36 | **** Volume, drive, string, etc. parameters should also be checked by | ||
37 | **** callers for gross violations-- NULL strings, out-of-bounds values, | ||
38 | **** etc. | ||
39 | ****/ | ||
40 | |||
41 | /**************************************************************************** | ||
42 | ** Values that can be overridden by a target in config-[target].h | ||
43 | **/ | ||
44 | |||
45 | /* if your ATA implementation can do better, go right ahead and increase this | ||
46 | * value */ | ||
47 | #ifndef FAT_MAX_TRANSFER_SIZE | ||
48 | #define FAT_MAX_TRANSFER_SIZE 256 | ||
49 | #endif | ||
29 | 50 | ||
30 | /* This value can be overwritten by a target in config-[target].h, but | 51 | /* still experimental? */ |
31 | that behaviour is still experimental */ | 52 | /* increasing this will increase the total memory used by the cache; the |
53 | cache, as noted in disk_cache.h, has other minimum requirements that may | ||
54 | prevent reducing its number of entries in order to compensate */ | ||
32 | #ifndef SECTOR_SIZE | 55 | #ifndef SECTOR_SIZE |
33 | #define SECTOR_SIZE 512 | 56 | #define SECTOR_SIZE 512 |
34 | #endif | 57 | #endif |
35 | 58 | ||
59 | /** | ||
60 | ****************************************************************************/ | ||
61 | |||
62 | #define INVALID_SECNUM (0xfffffffeul) /* sequential, not FAT */ | ||
63 | #define FAT_MAX_FILE_SIZE (0xfffffffful) /* 2^32-1 bytes */ | ||
64 | #define MAX_DIRENTRIES 65536 | ||
65 | #define MAX_DIRECTORY_SIZE (MAX_DIRENTRIES*32) /* 2MB max size */ | ||
66 | |||
67 | /* these aren't I/O error conditions, so define specially; failure rc's | ||
68 | * shouldn't return the last digit as "0", therefore this is unambiguous */ | ||
69 | #define FAT_RC_ENOSPC (-10) | ||
70 | #define FAT_SEEK_EOF (-20) | ||
71 | |||
36 | /* Number of bytes reserved for a file name (including the trailing \0). | 72 | /* Number of bytes reserved for a file name (including the trailing \0). |
37 | Since names are stored in the entry as UTF-8, we won't be able to | 73 | Since names are stored in the entry as UTF-8, we won't be ble to |
38 | store all names allowed by FAT. In FAT, a name can have max 255 | 74 | store all names allowed by FAT. In FAT, a name can have max 255 |
39 | characters (not bytes!). Since the UTF-8 encoding of a char may take | 75 | characters (not bytes!). Since the UTF-8 encoding of a char may take |
40 | up to 4 bytes, there will be names that we won't be able to store | 76 | up to 4 bytes, there will be names that we won't be able to store |
41 | completely. For such names, the short DOS name is used. */ | 77 | completely. For such names, the short DOS name is used. */ |
42 | #define FAT_FILENAME_BYTES 256 | 78 | #define FAT_DIRENTRY_NAME_MAX 255 |
43 | |||
44 | struct fat_direntry | 79 | struct fat_direntry |
45 | { | 80 | { |
46 | unsigned char name[FAT_FILENAME_BYTES]; /* UTF-8 encoded name plus \0 */ | 81 | union { |
47 | unsigned short attr; /* Attributes */ | 82 | uint8_t name[255+1+4]; /* UTF-8 name plus \0 plus parse slop */ |
48 | unsigned char crttimetenth; /* Millisecond creation | 83 | uint16_t ucssegs[5+20][13]; /* UTF-16 segment buffer - layout saves... */ |
49 | time stamp (0-199) */ | 84 | }; /* ...130 bytes (important if stacked) */ |
50 | unsigned short crttime; /* Creation time */ | 85 | uint16_t ucsterm; /* allow one NULL-term after ucssegs */ |
51 | unsigned short crtdate; /* Creation date */ | 86 | uint8_t shortname[13]; /* DOS filename (OEM charset) */ |
52 | unsigned short lstaccdate; /* Last access date */ | 87 | uint8_t attr; /* file attributes */ |
53 | unsigned short wrttime; /* Last write time */ | 88 | uint8_t crttimetenth; /* millisecond creation time stamp (0-199) */ |
54 | unsigned short wrtdate; /* Last write date */ | 89 | uint16_t crttime; /* creation time */ |
55 | unsigned long filesize; /* File size in bytes */ | 90 | uint16_t crtdate; /* creation date */ |
56 | long firstcluster; /* fstclusterhi<<16 + fstcluslo */ | 91 | uint16_t lstaccdate; /* last access date */ |
92 | uint16_t wrttime; /* last write time */ | ||
93 | uint16_t wrtdate; /* last write date */ | ||
94 | uint32_t filesize; /* file size in bytes */ | ||
95 | int32_t firstcluster; /* first FAT cluster of file, 0 if empty */ | ||
57 | }; | 96 | }; |
58 | 97 | ||
59 | #define FAT_ATTR_READ_ONLY 0x01 | 98 | /* cursor structure used for scanning directories; holds the last-returned |
60 | #define FAT_ATTR_HIDDEN 0x02 | 99 | entry information */ |
61 | #define FAT_ATTR_SYSTEM 0x04 | 100 | struct fat_dirscan_info |
62 | #define FAT_ATTR_VOLUME_ID 0x08 | 101 | { |
63 | #define FAT_ATTR_DIRECTORY 0x10 | 102 | unsigned int entry; /* short dir entry index in parent */ |
64 | #define FAT_ATTR_ARCHIVE 0x20 | 103 | unsigned int entries; /* number of dir entries used */ |
65 | #define FAT_ATTR_VOLUME 0x40 /* this is a volume, not a real directory */ | 104 | }; |
105 | |||
106 | #define FAT_RW_VAL (0u - 1) | ||
66 | 107 | ||
108 | /* basic FAT file information about where to find a file and who houses it */ | ||
67 | struct fat_file | 109 | struct fat_file |
68 | { | 110 | { |
69 | long firstcluster; /* first cluster in file */ | ||
70 | long lastcluster; /* cluster of last access */ | ||
71 | long lastsector; /* sector of last access */ | ||
72 | long clusternum; /* current clusternum */ | ||
73 | long sectornum; /* sector number in this cluster */ | ||
74 | unsigned int direntry; /* short dir entry index from start of dir */ | ||
75 | unsigned int direntries; /* number of dir entries used by this file */ | ||
76 | long dircluster; /* first cluster of dir */ | ||
77 | bool eof; | ||
78 | #ifdef HAVE_MULTIVOLUME | 111 | #ifdef HAVE_MULTIVOLUME |
79 | int volume; /* file resides on which volume */ | 112 | int volume; /* file resides on which volume (first!) */ |
80 | #endif | 113 | #endif |
114 | long firstcluster; /* first cluster in file */ | ||
115 | long dircluster; /* first cluster of parent directory */ | ||
116 | struct fat_dirscan_info e; /* entry information */ | ||
81 | }; | 117 | }; |
82 | 118 | ||
83 | struct fat_dir | 119 | /* this stores what was last accessed when read or writing a file's data */ |
120 | struct fat_filestr | ||
84 | { | 121 | { |
85 | unsigned char sectorcache[SECTOR_SIZE] CACHEALIGN_ATTR; | 122 | struct fat_file *fatfilep; /* common file information */ |
86 | unsigned int entry; | 123 | long lastcluster; /* cluster of last access */ |
87 | unsigned int entrycount; | 124 | unsigned long lastsector; /* sector of last access */ |
88 | long sector; | 125 | long clusternum; /* cluster number of last access */ |
89 | struct fat_file file; | 126 | unsigned long sectornum; /* sector number within current cluster */ |
90 | /* There are 2-bytes per characters. We don't want to bother too much, as LFN entries are | 127 | bool eof; /* end-of-file reached */ |
91 | * at much 255 characters longs, that's at most 20 LFN entries. Each entry hold at most | 128 | }; |
92 | * 13 characters, that a total of 260 characters. So we keep a buffer of that size. | 129 | |
93 | * Keep coherent with fat.c code. */ | 130 | /** File entity functions **/ |
94 | unsigned char longname[260 * 2]; | 131 | int fat_create_file(struct fat_file *parent, const char *name, |
95 | } CACHEALIGN_ATTR; | 132 | uint8_t attr, struct fat_file *file, |
96 | 133 | struct fat_direntry *fatent); | |
97 | #ifdef HAVE_HOTSWAP | 134 | bool fat_dir_is_parent(const struct fat_file *dir, const struct fat_file *file); |
98 | extern void fat_lock(void); | 135 | bool fat_file_is_same(const struct fat_file *file1, const struct fat_file *file2); |
99 | extern void fat_unlock(void); | 136 | int fat_fstat(struct fat_file *file, struct fat_direntry *entry); |
100 | #endif | 137 | int fat_open(const struct fat_file *parent, long startcluster, |
138 | struct fat_file *file); | ||
139 | int fat_open_rootdir(IF_MV(int volume,) struct fat_file *dir); | ||
140 | enum fat_remove_op /* what should fat_remove(), remove? */ | ||
141 | { | ||
142 | FAT_RM_DIRENTRIES = 0x1, /* remove only directory entries */ | ||
143 | FAT_RM_DATA = 0x2, /* remove only file data */ | ||
144 | FAT_RM_ALL = 0x3, /* remove all of above */ | ||
145 | }; | ||
146 | int fat_remove(struct fat_file *file, enum fat_remove_op what); | ||
147 | int fat_rename(struct fat_file *parent, struct fat_file *file, | ||
148 | const unsigned char *newname); | ||
101 | 149 | ||
102 | extern void fat_init(void); | 150 | /** File stream functions **/ |
103 | extern int fat_get_bytes_per_sector(IF_MV_NONVOID(int volume)); | 151 | int fat_closewrite(struct fat_filestr *filestr, uint32_t size, |
104 | extern int fat_mount(IF_MV(int volume,) IF_MD(int drive,) long startsector); | 152 | struct fat_direntry *fatentp); |
105 | extern int fat_unmount(int volume, bool flush); | 153 | void fat_filestr_init(struct fat_filestr *filestr, struct fat_file *file); |
106 | extern void fat_size(IF_MV(int volume,) /* public for info */ | 154 | unsigned long fat_query_sectornum(const struct fat_filestr *filestr); |
107 | unsigned long* size, | 155 | long fat_readwrite(struct fat_filestr *filestr, unsigned long sectorcount, |
108 | unsigned long* free); | 156 | void *buf, bool write); |
109 | extern void fat_recalc_free(IF_MV_NONVOID(int volume)); /* public for debug info screen */ | 157 | void fat_rewind(struct fat_filestr *filestr); |
110 | extern int fat_create_dir(const char* name, | 158 | int fat_seek(struct fat_filestr *filestr, unsigned long sector); |
111 | struct fat_dir* newdir, | 159 | int fat_truncate(const struct fat_filestr *filestr); |
112 | struct fat_dir* dir); | ||
113 | extern int fat_open(IF_MV(int volume,) | ||
114 | long cluster, | ||
115 | struct fat_file* ent, | ||
116 | const struct fat_dir* dir); | ||
117 | extern int fat_create_file(const char* name, | ||
118 | struct fat_file* ent, | ||
119 | struct fat_dir* dir); | ||
120 | extern long fat_readwrite(struct fat_file *ent, long sectorcount, | ||
121 | void* buf, bool write ); | ||
122 | extern int fat_closewrite(struct fat_file *ent, long size, int attr); | ||
123 | extern int fat_seek(struct fat_file *ent, unsigned long sector ); | ||
124 | extern int fat_remove(struct fat_file *ent); | ||
125 | extern int fat_truncate(const struct fat_file *ent); | ||
126 | extern int fat_rename(struct fat_file* file, | ||
127 | struct fat_dir* dir, | ||
128 | const unsigned char* newname, | ||
129 | long size, int attr); | ||
130 | |||
131 | extern int fat_opendir(IF_MV(int volume,) | ||
132 | struct fat_dir *ent, unsigned long startcluster, | ||
133 | const struct fat_dir *parent_dir); | ||
134 | extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry); | ||
135 | extern unsigned int fat_get_cluster_size(IF_MV_NONVOID(int volume)); /* public for debug info screen */ | ||
136 | extern bool fat_ismounted(int volume); | ||
137 | extern void* fat_get_sector_buffer(void); | ||
138 | extern void fat_release_sector_buffer(void); | ||
139 | 160 | ||
140 | #endif | 161 | /** Directory stream functions **/ |
162 | struct filestr_cache; | ||
163 | int fat_readdir(struct fat_filestr *dirstr, struct fat_dirscan_info *scan, | ||
164 | struct filestr_cache *cachep, struct fat_direntry *entry); | ||
165 | void fat_rewinddir(struct fat_dirscan_info *scan); | ||
166 | |||
167 | /** Mounting and unmounting functions **/ | ||
168 | bool fat_ismounted(IF_MV_NONVOID(int volume)); | ||
169 | int fat_mount(IF_MV(int volume,) IF_MD(int drive,) unsigned long startsector); | ||
170 | int fat_unmount(IF_MV_NONVOID(int volume)); | ||
171 | |||
172 | /** Debug screen stuff **/ | ||
173 | #ifdef MAX_LOG_SECTOR_SIZE | ||
174 | int fat_get_bytes_per_sector(IF_MV_NONVOID(int volume)); | ||
175 | #endif /* MAX_LOG_SECTOR_SIZE */ | ||
176 | unsigned int fat_get_cluster_size(IF_MV_NONVOID(int volume)); | ||
177 | void fat_recalc_free(IF_MV_NONVOID(int volume)); | ||
178 | bool fat_size(IF_MV(int volume,) unsigned long *size, unsigned long *free); | ||
179 | |||
180 | /** Misc. **/ | ||
181 | time_t fattime_mktime(uint16_t fatdate, uint16_t fattime); | ||
182 | void fat_empty_fat_direntry(struct fat_direntry *entry); | ||
183 | void fat_init(void); | ||
184 | |||
185 | #endif /* FAT_H */ | ||