Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
dadigang
Ventoy
Commits
b0568922
Commit
b0568922
authored
Nov 12, 2021
by
longpanda
Browse files
1.0.60 release
parent
69b6bb8f
Changes
86
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
5872 additions
and
0 deletions
+5872
-0
vtoycli/fat_io_lib/release/fat_access.c
vtoycli/fat_io_lib/release/fat_access.c
+904
-0
vtoycli/fat_io_lib/release/fat_access.h
vtoycli/fat_io_lib/release/fat_access.h
+133
-0
vtoycli/fat_io_lib/release/fat_cache.c
vtoycli/fat_io_lib/release/fat_cache.c
+91
-0
vtoycli/fat_io_lib/release/fat_cache.h
vtoycli/fat_io_lib/release/fat_cache.h
+13
-0
vtoycli/fat_io_lib/release/fat_defs.h
vtoycli/fat_io_lib/release/fat_defs.h
+128
-0
vtoycli/fat_io_lib/release/fat_filelib.c
vtoycli/fat_io_lib/release/fat_filelib.c
+1603
-0
vtoycli/fat_io_lib/release/fat_filelib.h
vtoycli/fat_io_lib/release/fat_filelib.h
+146
-0
vtoycli/fat_io_lib/release/fat_format.c
vtoycli/fat_io_lib/release/fat_format.c
+532
-0
vtoycli/fat_io_lib/release/fat_format.h
vtoycli/fat_io_lib/release/fat_format.h
+15
-0
vtoycli/fat_io_lib/release/fat_list.h
vtoycli/fat_io_lib/release/fat_list.h
+161
-0
vtoycli/fat_io_lib/release/fat_misc.c
vtoycli/fat_io_lib/release/fat_misc.c
+505
-0
vtoycli/fat_io_lib/release/fat_misc.h
vtoycli/fat_io_lib/release/fat_misc.h
+63
-0
vtoycli/fat_io_lib/release/fat_opts.h
vtoycli/fat_io_lib/release/fat_opts.h
+90
-0
vtoycli/fat_io_lib/release/fat_string.c
vtoycli/fat_io_lib/release/fat_string.c
+514
-0
vtoycli/fat_io_lib/release/fat_string.h
vtoycli/fat_io_lib/release/fat_string.h
+20
-0
vtoycli/fat_io_lib/release/fat_table.c
vtoycli/fat_io_lib/release/fat_table.c
+478
-0
vtoycli/fat_io_lib/release/fat_table.h
vtoycli/fat_io_lib/release/fat_table.h
+20
-0
vtoycli/fat_io_lib/release/fat_types.h
vtoycli/fat_io_lib/release/fat_types.h
+69
-0
vtoycli/fat_io_lib/release/fat_write.c
vtoycli/fat_io_lib/release/fat_write.c
+373
-0
vtoycli/fat_io_lib/release/fat_write.h
vtoycli/fat_io_lib/release/fat_write.h
+14
-0
No files found.
vtoycli/fat_io_lib/release/fat_access.c
0 → 100644
View file @
b0568922
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include "fat_defs.h"
#include "fat_access.h"
#include "fat_table.h"
#include "fat_write.h"
#include "fat_string.h"
#include "fat_misc.h"
//-----------------------------------------------------------------------------
// fatfs_init: Load FAT Parameters
//-----------------------------------------------------------------------------
int
fatfs_init
(
struct
fatfs
*
fs
)
{
uint8
num_of_fats
;
uint16
reserved_sectors
;
uint32
FATSz
;
uint32
root_dir_sectors
;
uint32
total_sectors
;
uint32
data_sectors
;
uint32
count_of_clusters
;
uint8
valid_partition
=
0
;
fs
->
currentsector
.
address
=
FAT32_INVALID_CLUSTER
;
fs
->
currentsector
.
dirty
=
0
;
fs
->
next_free_cluster
=
0
;
// Invalid
fatfs_fat_init
(
fs
);
// Make sure we have a read function (write function is optional)
if
(
!
fs
->
disk_io
.
read_media
)
return
FAT_INIT_MEDIA_ACCESS_ERROR
;
// MBR: Sector 0 on the disk
// NOTE: Some removeable media does not have this.
// Load MBR (LBA 0) into the 512 byte buffer
if
(
!
fs
->
disk_io
.
read_media
(
0
,
fs
->
currentsector
.
sector
,
1
))
return
FAT_INIT_MEDIA_ACCESS_ERROR
;
// Make Sure 0x55 and 0xAA are at end of sector
// (this should be the case regardless of the MBR or boot sector)
if
(
fs
->
currentsector
.
sector
[
SIGNATURE_POSITION
]
!=
0x55
||
fs
->
currentsector
.
sector
[
SIGNATURE_POSITION
+
1
]
!=
0xAA
)
return
FAT_INIT_INVALID_SIGNATURE
;
// Now check again using the access function to prove endian conversion function
if
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
SIGNATURE_POSITION
)
!=
SIGNATURE_VALUE
)
return
FAT_INIT_ENDIAN_ERROR
;
// Verify packed structures
if
(
sizeof
(
struct
fat_dir_entry
)
!=
FAT_DIR_ENTRY_SIZE
)
return
FAT_INIT_STRUCT_PACKING
;
// Check the partition type code
switch
(
fs
->
currentsector
.
sector
[
PARTITION1_TYPECODE_LOCATION
])
{
case
0x0B
:
case
0x06
:
case
0x0C
:
case
0x0E
:
case
0x0F
:
case
0x05
:
valid_partition
=
1
;
break
;
case
0x00
:
valid_partition
=
0
;
break
;
default:
if
(
fs
->
currentsector
.
sector
[
PARTITION1_TYPECODE_LOCATION
]
<=
0x06
)
valid_partition
=
1
;
break
;
}
// Read LBA Begin for the file system
if
(
valid_partition
)
fs
->
lba_begin
=
GET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
PARTITION1_LBA_BEGIN_LOCATION
);
// Else possibly MBR less disk
else
fs
->
lba_begin
=
0
;
// Load Volume 1 table into sector buffer
// (We may already have this in the buffer if MBR less drive!)
if
(
!
fs
->
disk_io
.
read_media
(
fs
->
lba_begin
,
fs
->
currentsector
.
sector
,
1
))
return
FAT_INIT_MEDIA_ACCESS_ERROR
;
// Make sure there are 512 bytes per cluster
if
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
0x0B
)
!=
FAT_SECTOR_SIZE
)
return
FAT_INIT_INVALID_SECTOR_SIZE
;
// Load Parameters of FAT partition
fs
->
sectors_per_cluster
=
fs
->
currentsector
.
sector
[
BPB_SECPERCLUS
];
reserved_sectors
=
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_RSVDSECCNT
);
num_of_fats
=
fs
->
currentsector
.
sector
[
BPB_NUMFATS
];
fs
->
root_entry_count
=
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_ROOTENTCNT
);
if
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FATSZ16
)
!=
0
)
fs
->
fat_sectors
=
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FATSZ16
);
else
fs
->
fat_sectors
=
GET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FAT32_FATSZ32
);
// For FAT32 (which this may be)
fs
->
rootdir_first_cluster
=
GET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FAT32_ROOTCLUS
);
fs
->
fs_info_sector
=
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FAT32_FSINFO
);
// For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector
fs
->
rootdir_first_sector
=
reserved_sectors
+
(
num_of_fats
*
fs
->
fat_sectors
);
fs
->
rootdir_sectors
=
((
fs
->
root_entry_count
*
32
)
+
(
FAT_SECTOR_SIZE
-
1
))
/
FAT_SECTOR_SIZE
;
// First FAT LBA address
fs
->
fat_begin_lba
=
fs
->
lba_begin
+
reserved_sectors
;
// The address of the first data cluster on this volume
fs
->
cluster_begin_lba
=
fs
->
fat_begin_lba
+
(
num_of_fats
*
fs
->
fat_sectors
);
if
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
0x1FE
)
!=
0xAA55
)
// This signature should be AA55
return
FAT_INIT_INVALID_SIGNATURE
;
// Calculate the root dir sectors
root_dir_sectors
=
((
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_ROOTENTCNT
)
*
32
)
+
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_BYTSPERSEC
)
-
1
))
/
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_BYTSPERSEC
);
if
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FATSZ16
)
!=
0
)
FATSz
=
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FATSZ16
);
else
FATSz
=
GET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FAT32_FATSZ32
);
if
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_TOTSEC16
)
!=
0
)
total_sectors
=
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_TOTSEC16
);
else
total_sectors
=
GET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_TOTSEC32
);
data_sectors
=
total_sectors
-
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_RSVDSECCNT
)
+
(
fs
->
currentsector
.
sector
[
BPB_NUMFATS
]
*
FATSz
)
+
root_dir_sectors
);
// Find out which version of FAT this is...
if
(
fs
->
sectors_per_cluster
!=
0
)
{
count_of_clusters
=
data_sectors
/
fs
->
sectors_per_cluster
;
if
(
count_of_clusters
<
4085
)
// Volume is FAT12
return
FAT_INIT_WRONG_FILESYS_TYPE
;
else
if
(
count_of_clusters
<
65525
)
{
// Clear this FAT32 specific param
fs
->
rootdir_first_cluster
=
0
;
// Volume is FAT16
fs
->
fat_type
=
FAT_TYPE_16
;
return
FAT_INIT_OK
;
}
else
{
// Volume is FAT32
fs
->
fat_type
=
FAT_TYPE_32
;
return
FAT_INIT_OK
;
}
}
else
return
FAT_INIT_WRONG_FILESYS_TYPE
;
}
//-----------------------------------------------------------------------------
// fatfs_lba_of_cluster: This function converts a cluster number into a sector /
// LBA number.
//-----------------------------------------------------------------------------
uint32
fatfs_lba_of_cluster
(
struct
fatfs
*
fs
,
uint32
Cluster_Number
)
{
if
(
fs
->
fat_type
==
FAT_TYPE_16
)
return
(
fs
->
cluster_begin_lba
+
(
fs
->
root_entry_count
*
32
/
FAT_SECTOR_SIZE
)
+
((
Cluster_Number
-
2
)
*
fs
->
sectors_per_cluster
));
else
return
((
fs
->
cluster_begin_lba
+
((
Cluster_Number
-
2
)
*
fs
->
sectors_per_cluster
)));
}
//-----------------------------------------------------------------------------
// fatfs_sector_read:
//-----------------------------------------------------------------------------
int
fatfs_sector_read
(
struct
fatfs
*
fs
,
uint32
lba
,
uint8
*
target
,
uint32
count
)
{
return
fs
->
disk_io
.
read_media
(
lba
,
target
,
count
);
}
//-----------------------------------------------------------------------------
// fatfs_sector_write:
//-----------------------------------------------------------------------------
int
fatfs_sector_write
(
struct
fatfs
*
fs
,
uint32
lba
,
uint8
*
target
,
uint32
count
)
{
return
fs
->
disk_io
.
write_media
(
lba
,
target
,
count
);
}
//-----------------------------------------------------------------------------
// fatfs_sector_reader: From the provided startcluster and sector offset
// Returns True if success, returns False if not (including if read out of range)
//-----------------------------------------------------------------------------
int
fatfs_sector_reader
(
struct
fatfs
*
fs
,
uint32
start_cluster
,
uint32
offset
,
uint8
*
target
)
{
uint32
sector_to_read
=
0
;
uint32
cluster_to_read
=
0
;
uint32
cluster_chain
=
0
;
uint32
i
;
uint32
lba
;
// FAT16 Root directory
if
(
fs
->
fat_type
==
FAT_TYPE_16
&&
start_cluster
==
0
)
{
if
(
offset
<
fs
->
rootdir_sectors
)
lba
=
fs
->
lba_begin
+
fs
->
rootdir_first_sector
+
offset
;
else
return
0
;
}
// FAT16/32 Other
else
{
// Set start of cluster chain to initial value
cluster_chain
=
start_cluster
;
// Find parameters
cluster_to_read
=
offset
/
fs
->
sectors_per_cluster
;
sector_to_read
=
offset
-
(
cluster_to_read
*
fs
->
sectors_per_cluster
);
// Follow chain to find cluster to read
for
(
i
=
0
;
i
<
cluster_to_read
;
i
++
)
cluster_chain
=
fatfs_find_next_cluster
(
fs
,
cluster_chain
);
// If end of cluster chain then return false
if
(
cluster_chain
==
FAT32_LAST_CLUSTER
)
return
0
;
// Calculate sector address
lba
=
fatfs_lba_of_cluster
(
fs
,
cluster_chain
)
+
sector_to_read
;
}
// User provided target array
if
(
target
)
return
fs
->
disk_io
.
read_media
(
lba
,
target
,
1
);
// Else read sector if not already loaded
else
if
(
lba
!=
fs
->
currentsector
.
address
)
{
fs
->
currentsector
.
address
=
lba
;
return
fs
->
disk_io
.
read_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
else
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_read_sector: Read from the provided cluster and sector offset
// Returns True if success, returns False if not
//-----------------------------------------------------------------------------
int
fatfs_read_sector
(
struct
fatfs
*
fs
,
uint32
cluster
,
uint32
sector
,
uint8
*
target
)
{
// FAT16 Root directory
if
(
fs
->
fat_type
==
FAT_TYPE_16
&&
cluster
==
0
)
{
uint32
lba
;
// In FAT16, there are a limited amount of sectors in root dir!
if
(
sector
<
fs
->
rootdir_sectors
)
lba
=
fs
->
lba_begin
+
fs
->
rootdir_first_sector
+
sector
;
else
return
0
;
// User target buffer passed in
if
(
target
)
{
// Read from disk
return
fs
->
disk_io
.
read_media
(
lba
,
target
,
1
);
}
else
{
// Calculate read address
fs
->
currentsector
.
address
=
lba
;
// Read from disk
return
fs
->
disk_io
.
read_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
}
// FAT16/32 Other
else
{
// User target buffer passed in
if
(
target
)
{
// Calculate read address
uint32
lba
=
fatfs_lba_of_cluster
(
fs
,
cluster
)
+
sector
;
// Read from disk
return
fs
->
disk_io
.
read_media
(
lba
,
target
,
1
);
}
else
{
// Calculate write address
fs
->
currentsector
.
address
=
fatfs_lba_of_cluster
(
fs
,
cluster
)
+
sector
;
// Read from disk
return
fs
->
disk_io
.
read_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
}
}
//-----------------------------------------------------------------------------
// fatfs_write_sector: Write to the provided cluster and sector offset
// Returns True if success, returns False if not
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_write_sector
(
struct
fatfs
*
fs
,
uint32
cluster
,
uint32
sector
,
uint8
*
target
)
{
// No write access?
if
(
!
fs
->
disk_io
.
write_media
)
return
0
;
// FAT16 Root directory
if
(
fs
->
fat_type
==
FAT_TYPE_16
&&
cluster
==
0
)
{
uint32
lba
;
// In FAT16 we cannot extend the root dir!
if
(
sector
<
fs
->
rootdir_sectors
)
lba
=
fs
->
lba_begin
+
fs
->
rootdir_first_sector
+
sector
;
else
return
0
;
// User target buffer passed in
if
(
target
)
{
// Write to disk
return
fs
->
disk_io
.
write_media
(
lba
,
target
,
1
);
}
else
{
// Calculate write address
fs
->
currentsector
.
address
=
lba
;
// Write to disk
return
fs
->
disk_io
.
write_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
}
// FAT16/32 Other
else
{
// User target buffer passed in
if
(
target
)
{
// Calculate write address
uint32
lba
=
fatfs_lba_of_cluster
(
fs
,
cluster
)
+
sector
;
// Write to disk
return
fs
->
disk_io
.
write_media
(
lba
,
target
,
1
);
}
else
{
// Calculate write address
fs
->
currentsector
.
address
=
fatfs_lba_of_cluster
(
fs
,
cluster
)
+
sector
;
// Write to disk
return
fs
->
disk_io
.
write_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
}
}
#endif
//-----------------------------------------------------------------------------
// fatfs_show_details: Show the details about the filesystem
//-----------------------------------------------------------------------------
void
fatfs_show_details
(
struct
fatfs
*
fs
)
{
FAT_PRINTF
((
"FAT details:
\r\n
"
));
FAT_PRINTF
((
" Type =%s"
,
(
fs
->
fat_type
==
FAT_TYPE_32
)
?
"FAT32"
:
"FAT16"
));
FAT_PRINTF
((
" Root Dir First Cluster = %x
\r\n
"
,
fs
->
rootdir_first_cluster
));
FAT_PRINTF
((
" FAT Begin LBA = 0x%x
\r\n
"
,
fs
->
fat_begin_lba
));
FAT_PRINTF
((
" Cluster Begin LBA = 0x%x
\r\n
"
,
fs
->
cluster_begin_lba
));
FAT_PRINTF
((
" Sectors Per Cluster = %d
\r\n
"
,
fs
->
sectors_per_cluster
));
}
//-----------------------------------------------------------------------------
// fatfs_get_root_cluster: Get the root dir cluster
//-----------------------------------------------------------------------------
uint32
fatfs_get_root_cluster
(
struct
fatfs
*
fs
)
{
// NOTE: On FAT16 this will be 0 which has a special meaning...
return
fs
->
rootdir_first_cluster
;
}
//-------------------------------------------------------------
// fatfs_get_file_entry: Find the file entry for a filename
//-------------------------------------------------------------
uint32
fatfs_get_file_entry
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
name_to_find
,
struct
fat_dir_entry
*
sfEntry
)
{
uint8
item
=
0
;
uint16
recordoffset
=
0
;
uint8
i
=
0
;
int
x
=
0
;
char
*
long_filename
=
NULL
;
char
short_filename
[
13
];
struct
lfn_cache
lfn
;
int
dotRequired
=
0
;
struct
fat_dir_entry
*
directoryEntry
;
fatfs_lfn_cache_init
(
&
lfn
,
1
);
// Main cluster following loop
while
(
1
)
{
// Read sector
if
(
fatfs_sector_reader
(
fs
,
Cluster
,
x
++
,
0
))
// If sector read was successfull
{
// Analyse Sector
for
(
item
=
0
;
item
<
FAT_DIR_ENTRIES_PER_SECTOR
;
item
++
)
{
// Create the multiplier for sector access
recordoffset
=
FAT_DIR_ENTRY_SIZE
*
item
;
// Overlay directory entry over buffer
directoryEntry
=
(
struct
fat_dir_entry
*
)(
fs
->
currentsector
.
sector
+
recordoffset
);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if
(
fatfs_entry_lfn_text
(
directoryEntry
)
)
fatfs_lfn_cache_entry
(
&
lfn
,
fs
->
currentsector
.
sector
+
recordoffset
);
// If Invalid record found delete any long file name information collated
else
if
(
fatfs_entry_lfn_invalid
(
directoryEntry
)
)
fatfs_lfn_cache_init
(
&
lfn
,
0
);
// Normal SFN Entry and Long text exists
else
if
(
fatfs_entry_lfn_exists
(
&
lfn
,
directoryEntry
)
)
{
long_filename
=
fatfs_lfn_cache_get
(
&
lfn
);
// Compare names to see if they match
if
(
fatfs_compare_names
(
long_filename
,
name_to_find
))
{
memcpy
(
sfEntry
,
directoryEntry
,
sizeof
(
struct
fat_dir_entry
));
return
1
;
}
fatfs_lfn_cache_init
(
&
lfn
,
0
);
}
else
#endif
// Normal Entry, only 8.3 Text
if
(
fatfs_entry_sfn_only
(
directoryEntry
)
)
{
memset
(
short_filename
,
0
,
sizeof
(
short_filename
));
// Copy name to string
for
(
i
=
0
;
i
<
8
;
i
++
)
short_filename
[
i
]
=
directoryEntry
->
Name
[
i
];
// Extension
dotRequired
=
0
;
for
(
i
=
8
;
i
<
11
;
i
++
)
{
short_filename
[
i
+
1
]
=
directoryEntry
->
Name
[
i
];
if
(
directoryEntry
->
Name
[
i
]
!=
' '
)
dotRequired
=
1
;
}
// Dot only required if extension present
if
(
dotRequired
)
{
// If not . or .. entry
if
(
short_filename
[
0
]
!=
'.'
)
short_filename
[
8
]
=
'.'
;
else
short_filename
[
8
]
=
' '
;
}
else
short_filename
[
8
]
=
' '
;
// Compare names to see if they match
if
(
fatfs_compare_names
(
short_filename
,
name_to_find
))
{
memcpy
(
sfEntry
,
directoryEntry
,
sizeof
(
struct
fat_dir_entry
));
return
1
;
}
fatfs_lfn_cache_init
(
&
lfn
,
0
);
}
}
// End of if
}
else
break
;
}
// End of while loop
return
0
;
}
//-------------------------------------------------------------
// fatfs_sfn_exists: Check if a short filename exists.
// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
//-------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_sfn_exists
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
shortname
)
{
uint8
item
=
0
;
uint16
recordoffset
=
0
;
int
x
=
0
;
struct
fat_dir_entry
*
directoryEntry
;
// Main cluster following loop
while
(
1
)
{
// Read sector
if
(
fatfs_sector_reader
(
fs
,
Cluster
,
x
++
,
0
))
// If sector read was successfull
{
// Analyse Sector
for
(
item
=
0
;
item
<
FAT_DIR_ENTRIES_PER_SECTOR
;
item
++
)
{
// Create the multiplier for sector access
recordoffset
=
FAT_DIR_ENTRY_SIZE
*
item
;
// Overlay directory entry over buffer
directoryEntry
=
(
struct
fat_dir_entry
*
)(
fs
->
currentsector
.
sector
+
recordoffset
);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if
(
fatfs_entry_lfn_text
(
directoryEntry
)
)
;
// If Invalid record found delete any long file name information collated
else
if
(
fatfs_entry_lfn_invalid
(
directoryEntry
)
)
;
else
#endif
// Normal Entry, only 8.3 Text
if
(
fatfs_entry_sfn_only
(
directoryEntry
)
)
{
if
(
strncmp
((
const
char
*
)
directoryEntry
->
Name
,
shortname
,
11
)
==
0
)
return
1
;
}
}
// End of if
}
else
break
;
}
// End of while loop
return
0
;
}
#endif
//-------------------------------------------------------------
// fatfs_update_timestamps: Update date/time details
//-------------------------------------------------------------
#if FATFS_INC_TIME_DATE_SUPPORT
int
fatfs_update_timestamps
(
struct
fat_dir_entry
*
directoryEntry
,
int
create
,
int
modify
,
int
access
)
{
time_t
time_now
;
struct
tm
*
time_info
;
uint16
fat_time
;
uint16
fat_date
;
// Get system time
time
(
&
time_now
);
// Convert to local time
time_info
=
localtime
(
&
time_now
);
// Convert time to FAT format
fat_time
=
fatfs_convert_to_fat_time
(
time_info
->
tm_hour
,
time_info
->
tm_min
,
time_info
->
tm_sec
);
// Convert date to FAT format
fat_date
=
fatfs_convert_to_fat_date
(
time_info
->
tm_mday
,
time_info
->
tm_mon
+
1
,
time_info
->
tm_year
+
1900
);
// Update requested fields
if
(
create
)
{
directoryEntry
->
CrtTime
[
1
]
=
fat_time
>>
8
;
directoryEntry
->
CrtTime
[
0
]
=
fat_time
>>
0
;
directoryEntry
->
CrtDate
[
1
]
=
fat_date
>>
8
;
directoryEntry
->
CrtDate
[
0
]
=
fat_date
>>
0
;
}
if
(
modify
)
{
directoryEntry
->
WrtTime
[
1
]
=
fat_time
>>
8
;
directoryEntry
->
WrtTime
[
0
]
=
fat_time
>>
0
;
directoryEntry
->
WrtDate
[
1
]
=
fat_date
>>
8
;
directoryEntry
->
WrtDate
[
0
]
=
fat_date
>>
0
;
}
if
(
access
)
{
directoryEntry
->
LstAccDate
[
1
]
=
fat_time
>>
8
;
directoryEntry
->
LstAccDate
[
0
]
=
fat_time
>>
0
;
directoryEntry
->
LstAccDate
[
1
]
=
fat_date
>>
8
;
directoryEntry
->
LstAccDate
[
0
]
=
fat_date
>>
0
;
}
return
1
;
}
#endif
//-------------------------------------------------------------
// fatfs_update_file_length: Find a SFN entry and update it
// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
//-------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_update_file_length
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
shortname
,
uint32
fileLength
)
{
uint8
item
=
0
;
uint16
recordoffset
=
0
;
int
x
=
0
;
struct
fat_dir_entry
*
directoryEntry
;
// No write access?
if
(
!
fs
->
disk_io
.
write_media
)
return
0
;
// Main cluster following loop
while
(
1
)
{
// Read sector
if
(
fatfs_sector_reader
(
fs
,
Cluster
,
x
++
,
0
))
// If sector read was successfull
{
// Analyse Sector
for
(
item
=
0
;
item
<
FAT_DIR_ENTRIES_PER_SECTOR
;
item
++
)
{
// Create the multiplier for sector access
recordoffset
=
FAT_DIR_ENTRY_SIZE
*
item
;
// Overlay directory entry over buffer
directoryEntry
=
(
struct
fat_dir_entry
*
)(
fs
->
currentsector
.
sector
+
recordoffset
);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if
(
fatfs_entry_lfn_text
(
directoryEntry
)
)
;
// If Invalid record found delete any long file name information collated
else
if
(
fatfs_entry_lfn_invalid
(
directoryEntry
)
)
;
// Normal Entry, only 8.3 Text
else
#endif
if
(
fatfs_entry_sfn_only
(
directoryEntry
)
)
{
if
(
strncmp
((
const
char
*
)
directoryEntry
->
Name
,
shortname
,
11
)
==
0
)
{
directoryEntry
->
FileSize
=
FAT_HTONL
(
fileLength
);
#if FATFS_INC_TIME_DATE_SUPPORT
// Update access / modify time & date
fatfs_update_timestamps
(
directoryEntry
,
0
,
1
,
1
);
#endif
// Update sfn entry
memcpy
((
uint8
*
)(
fs
->
currentsector
.
sector
+
recordoffset
),
(
uint8
*
)
directoryEntry
,
sizeof
(
struct
fat_dir_entry
));
// Write sector back
return
fs
->
disk_io
.
write_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
}
}
// End of if
}
else
break
;
}
// End of while loop
return
0
;
}
#endif
//-------------------------------------------------------------
// fatfs_mark_file_deleted: Find a SFN entry and mark if as deleted
// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
//-------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_mark_file_deleted
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
shortname
)
{
uint8
item
=
0
;
uint16
recordoffset
=
0
;
int
x
=
0
;
struct
fat_dir_entry
*
directoryEntry
;
// No write access?
if
(
!
fs
->
disk_io
.
write_media
)
return
0
;
// Main cluster following loop
while
(
1
)
{
// Read sector
if
(
fatfs_sector_reader
(
fs
,
Cluster
,
x
++
,
0
))
// If sector read was successfull
{
// Analyse Sector
for
(
item
=
0
;
item
<
FAT_DIR_ENTRIES_PER_SECTOR
;
item
++
)
{
// Create the multiplier for sector access
recordoffset
=
FAT_DIR_ENTRY_SIZE
*
item
;
// Overlay directory entry over buffer
directoryEntry
=
(
struct
fat_dir_entry
*
)(
fs
->
currentsector
.
sector
+
recordoffset
);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if
(
fatfs_entry_lfn_text
(
directoryEntry
)
)
;
// If Invalid record found delete any long file name information collated
else
if
(
fatfs_entry_lfn_invalid
(
directoryEntry
)
)
;
// Normal Entry, only 8.3 Text
else
#endif
if
(
fatfs_entry_sfn_only
(
directoryEntry
)
)
{
if
(
strncmp
((
const
char
*
)
directoryEntry
->
Name
,
shortname
,
11
)
==
0
)
{
// Mark as deleted
directoryEntry
->
Name
[
0
]
=
FILE_HEADER_DELETED
;
#if FATFS_INC_TIME_DATE_SUPPORT
// Update access / modify time & date
fatfs_update_timestamps
(
directoryEntry
,
0
,
1
,
1
);
#endif
// Update sfn entry
memcpy
((
uint8
*
)(
fs
->
currentsector
.
sector
+
recordoffset
),
(
uint8
*
)
directoryEntry
,
sizeof
(
struct
fat_dir_entry
));
// Write sector back
return
fs
->
disk_io
.
write_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
}
}
// End of if
}
else
break
;
}
// End of while loop
return
0
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_list_directory_start: Initialise a directory listing procedure
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
void
fatfs_list_directory_start
(
struct
fatfs
*
fs
,
struct
fs_dir_list_status
*
dirls
,
uint32
StartCluster
)
{
dirls
->
cluster
=
StartCluster
;
dirls
->
sector
=
0
;
dirls
->
offset
=
0
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_list_directory_next: Get the next entry in the directory.
// Returns: 1 = found, 0 = end of listing
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
int
fatfs_list_directory_next
(
struct
fatfs
*
fs
,
struct
fs_dir_list_status
*
dirls
,
struct
fs_dir_ent
*
entry
)
{
uint8
i
,
item
;
uint16
recordoffset
;
struct
fat_dir_entry
*
directoryEntry
;
char
*
long_filename
=
NULL
;
char
short_filename
[
13
];
struct
lfn_cache
lfn
;
int
dotRequired
=
0
;
int
result
=
0
;
// Initialise LFN cache first
fatfs_lfn_cache_init
(
&
lfn
,
0
);
while
(
1
)
{
// If data read OK
if
(
fatfs_sector_reader
(
fs
,
dirls
->
cluster
,
dirls
->
sector
,
0
))
{
// Maximum of 16 directory entries
for
(
item
=
dirls
->
offset
;
item
<
FAT_DIR_ENTRIES_PER_SECTOR
;
item
++
)
{
// Increase directory offset
recordoffset
=
FAT_DIR_ENTRY_SIZE
*
item
;
// Overlay directory entry over buffer
directoryEntry
=
(
struct
fat_dir_entry
*
)(
fs
->
currentsector
.
sector
+
recordoffset
);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if
(
fatfs_entry_lfn_text
(
directoryEntry
)
)
fatfs_lfn_cache_entry
(
&
lfn
,
fs
->
currentsector
.
sector
+
recordoffset
);
// If Invalid record found delete any long file name information collated
else
if
(
fatfs_entry_lfn_invalid
(
directoryEntry
)
)
fatfs_lfn_cache_init
(
&
lfn
,
0
);
// Normal SFN Entry and Long text exists
else
if
(
fatfs_entry_lfn_exists
(
&
lfn
,
directoryEntry
)
)
{
// Get text
long_filename
=
fatfs_lfn_cache_get
(
&
lfn
);
strncpy
(
entry
->
filename
,
long_filename
,
FATFS_MAX_LONG_FILENAME
-
1
);
if
(
fatfs_entry_is_dir
(
directoryEntry
))
entry
->
is_dir
=
1
;
else
entry
->
is_dir
=
0
;
#if FATFS_INC_TIME_DATE_SUPPORT
// Get time / dates
entry
->
create_time
=
((
uint16
)
directoryEntry
->
CrtTime
[
1
]
<<
8
)
|
directoryEntry
->
CrtTime
[
0
];
entry
->
create_date
=
((
uint16
)
directoryEntry
->
CrtDate
[
1
]
<<
8
)
|
directoryEntry
->
CrtDate
[
0
];
entry
->
access_date
=
((
uint16
)
directoryEntry
->
LstAccDate
[
1
]
<<
8
)
|
directoryEntry
->
LstAccDate
[
0
];
entry
->
write_time
=
((
uint16
)
directoryEntry
->
WrtTime
[
1
]
<<
8
)
|
directoryEntry
->
WrtTime
[
0
];
entry
->
write_date
=
((
uint16
)
directoryEntry
->
WrtDate
[
1
]
<<
8
)
|
directoryEntry
->
WrtDate
[
0
];
#endif
entry
->
size
=
FAT_HTONL
(
directoryEntry
->
FileSize
);
entry
->
cluster
=
(
FAT_HTONS
(
directoryEntry
->
FstClusHI
)
<<
16
)
|
FAT_HTONS
(
directoryEntry
->
FstClusLO
);
// Next starting position
dirls
->
offset
=
item
+
1
;
result
=
1
;
return
1
;
}
// Normal Entry, only 8.3 Text
else
#endif
if
(
fatfs_entry_sfn_only
(
directoryEntry
)
)
{
fatfs_lfn_cache_init
(
&
lfn
,
0
);
memset
(
short_filename
,
0
,
sizeof
(
short_filename
));
// Copy name to string
for
(
i
=
0
;
i
<
8
;
i
++
)
short_filename
[
i
]
=
directoryEntry
->
Name
[
i
];
// Extension
dotRequired
=
0
;
for
(
i
=
8
;
i
<
11
;
i
++
)
{
short_filename
[
i
+
1
]
=
directoryEntry
->
Name
[
i
];
if
(
directoryEntry
->
Name
[
i
]
!=
' '
)
dotRequired
=
1
;
}
// Dot only required if extension present
if
(
dotRequired
)
{
// If not . or .. entry
if
(
short_filename
[
0
]
!=
'.'
)
short_filename
[
8
]
=
'.'
;
else
short_filename
[
8
]
=
' '
;
}
else
short_filename
[
8
]
=
' '
;
fatfs_get_sfn_display_name
(
entry
->
filename
,
short_filename
);
if
(
fatfs_entry_is_dir
(
directoryEntry
))
entry
->
is_dir
=
1
;
else
entry
->
is_dir
=
0
;
#if FATFS_INC_TIME_DATE_SUPPORT
// Get time / dates
entry
->
create_time
=
((
uint16
)
directoryEntry
->
CrtTime
[
1
]
<<
8
)
|
directoryEntry
->
CrtTime
[
0
];
entry
->
create_date
=
((
uint16
)
directoryEntry
->
CrtDate
[
1
]
<<
8
)
|
directoryEntry
->
CrtDate
[
0
];
entry
->
access_date
=
((
uint16
)
directoryEntry
->
LstAccDate
[
1
]
<<
8
)
|
directoryEntry
->
LstAccDate
[
0
];
entry
->
write_time
=
((
uint16
)
directoryEntry
->
WrtTime
[
1
]
<<
8
)
|
directoryEntry
->
WrtTime
[
0
];
entry
->
write_date
=
((
uint16
)
directoryEntry
->
WrtDate
[
1
]
<<
8
)
|
directoryEntry
->
WrtDate
[
0
];
#endif
entry
->
size
=
FAT_HTONL
(
directoryEntry
->
FileSize
);
entry
->
cluster
=
(
FAT_HTONS
(
directoryEntry
->
FstClusHI
)
<<
16
)
|
FAT_HTONS
(
directoryEntry
->
FstClusLO
);
// Next starting position
dirls
->
offset
=
item
+
1
;
result
=
1
;
return
1
;
}
}
// end of for
// If reached end of the dir move onto next sector
dirls
->
sector
++
;
dirls
->
offset
=
0
;
}
else
break
;
}
return
result
;
}
#endif
vtoycli/fat_io_lib/release/fat_access.h
0 → 100644
View file @
b0568922
#ifndef __FAT_ACCESS_H__
#define __FAT_ACCESS_H__
#include "fat_defs.h"
#include "fat_opts.h"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
#define FAT_INIT_OK 0
#define FAT_INIT_MEDIA_ACCESS_ERROR (-1)
#define FAT_INIT_INVALID_SECTOR_SIZE (-2)
#define FAT_INIT_INVALID_SIGNATURE (-3)
#define FAT_INIT_ENDIAN_ERROR (-4)
#define FAT_INIT_WRONG_FILESYS_TYPE (-5)
#define FAT_INIT_WRONG_PARTITION_TYPE (-6)
#define FAT_INIT_STRUCT_PACKING (-7)
#define FAT_DIR_ENTRIES_PER_SECTOR (FAT_SECTOR_SIZE / FAT_DIR_ENTRY_SIZE)
//-----------------------------------------------------------------------------
// Function Pointers
//-----------------------------------------------------------------------------
typedef
int
(
*
fn_diskio_read
)
(
uint32
sector
,
uint8
*
buffer
,
uint32
sector_count
);
typedef
int
(
*
fn_diskio_write
)(
uint32
sector
,
uint8
*
buffer
,
uint32
sector_count
);
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct
disk_if
{
// User supplied function pointers for disk IO
fn_diskio_read
read_media
;
fn_diskio_write
write_media
;
};
// Forward declaration
struct
fat_buffer
;
struct
fat_buffer
{
uint8
sector
[
FAT_SECTOR_SIZE
*
FAT_BUFFER_SECTORS
];
uint32
address
;
int
dirty
;
uint8
*
ptr
;
// Next in chain of sector buffers
struct
fat_buffer
*
next
;
};
typedef
enum
eFatType
{
FAT_TYPE_16
,
FAT_TYPE_32
}
tFatType
;
struct
fatfs
{
// Filesystem globals
uint8
sectors_per_cluster
;
uint32
cluster_begin_lba
;
uint32
rootdir_first_cluster
;
uint32
rootdir_first_sector
;
uint32
rootdir_sectors
;
uint32
fat_begin_lba
;
uint16
fs_info_sector
;
uint32
lba_begin
;
uint32
fat_sectors
;
uint32
next_free_cluster
;
uint16
root_entry_count
;
uint16
reserved_sectors
;
uint8
num_of_fats
;
tFatType
fat_type
;
// Disk/Media API
struct
disk_if
disk_io
;
// [Optional] Thread Safety
void
(
*
fl_lock
)(
void
);
void
(
*
fl_unlock
)(
void
);
// Working buffer
struct
fat_buffer
currentsector
;
// FAT Buffer
struct
fat_buffer
*
fat_buffer_head
;
struct
fat_buffer
fat_buffers
[
FAT_BUFFERS
];
};
struct
fs_dir_list_status
{
uint32
sector
;
uint32
cluster
;
uint8
offset
;
};
struct
fs_dir_ent
{
char
filename
[
FATFS_MAX_LONG_FILENAME
];
uint8
is_dir
;
uint32
cluster
;
uint32
size
;
#if FATFS_INC_TIME_DATE_SUPPORT
uint16
access_date
;
uint16
write_time
;
uint16
write_date
;
uint16
create_date
;
uint16
create_time
;
#endif
};
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
int
fatfs_init
(
struct
fatfs
*
fs
);
uint32
fatfs_lba_of_cluster
(
struct
fatfs
*
fs
,
uint32
Cluster_Number
);
int
fatfs_sector_reader
(
struct
fatfs
*
fs
,
uint32
Startcluster
,
uint32
offset
,
uint8
*
target
);
int
fatfs_sector_read
(
struct
fatfs
*
fs
,
uint32
lba
,
uint8
*
target
,
uint32
count
);
int
fatfs_sector_write
(
struct
fatfs
*
fs
,
uint32
lba
,
uint8
*
target
,
uint32
count
);
int
fatfs_read_sector
(
struct
fatfs
*
fs
,
uint32
cluster
,
uint32
sector
,
uint8
*
target
);
int
fatfs_write_sector
(
struct
fatfs
*
fs
,
uint32
cluster
,
uint32
sector
,
uint8
*
target
);
void
fatfs_show_details
(
struct
fatfs
*
fs
);
uint32
fatfs_get_root_cluster
(
struct
fatfs
*
fs
);
uint32
fatfs_get_file_entry
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
nametofind
,
struct
fat_dir_entry
*
sfEntry
);
int
fatfs_sfn_exists
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
shortname
);
int
fatfs_update_file_length
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
shortname
,
uint32
fileLength
);
int
fatfs_mark_file_deleted
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
shortname
);
void
fatfs_list_directory_start
(
struct
fatfs
*
fs
,
struct
fs_dir_list_status
*
dirls
,
uint32
StartCluster
);
int
fatfs_list_directory_next
(
struct
fatfs
*
fs
,
struct
fs_dir_list_status
*
dirls
,
struct
fs_dir_ent
*
entry
);
int
fatfs_update_timestamps
(
struct
fat_dir_entry
*
directoryEntry
,
int
create
,
int
modify
,
int
access
);
#endif
vtoycli/fat_io_lib/release/fat_cache.c
0 → 100644
View file @
b0568922
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include "fat_cache.h"
// Per file cluster chain caching used to improve performance.
// This does not have to be enabled for architectures with low
// memory space.
//-----------------------------------------------------------------------------
// fatfs_cache_init:
//-----------------------------------------------------------------------------
int
fatfs_cache_init
(
struct
fatfs
*
fs
,
FL_FILE
*
file
)
{
#ifdef FAT_CLUSTER_CACHE_ENTRIES
int
i
;
for
(
i
=
0
;
i
<
FAT_CLUSTER_CACHE_ENTRIES
;
i
++
)
{
file
->
cluster_cache_idx
[
i
]
=
0xFFFFFFFF
;
// Not used
file
->
cluster_cache_data
[
i
]
=
0
;
}
#endif
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_cache_get_next_cluster:
//-----------------------------------------------------------------------------
int
fatfs_cache_get_next_cluster
(
struct
fatfs
*
fs
,
FL_FILE
*
file
,
uint32
clusterIdx
,
uint32
*
pNextCluster
)
{
#ifdef FAT_CLUSTER_CACHE_ENTRIES
uint32
slot
=
clusterIdx
%
FAT_CLUSTER_CACHE_ENTRIES
;
if
(
file
->
cluster_cache_idx
[
slot
]
==
clusterIdx
)
{
*
pNextCluster
=
file
->
cluster_cache_data
[
slot
];
return
1
;
}
#endif
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_cache_set_next_cluster:
//-----------------------------------------------------------------------------
int
fatfs_cache_set_next_cluster
(
struct
fatfs
*
fs
,
FL_FILE
*
file
,
uint32
clusterIdx
,
uint32
nextCluster
)
{
#ifdef FAT_CLUSTER_CACHE_ENTRIES
uint32
slot
=
clusterIdx
%
FAT_CLUSTER_CACHE_ENTRIES
;
if
(
file
->
cluster_cache_idx
[
slot
]
==
clusterIdx
)
file
->
cluster_cache_data
[
slot
]
=
nextCluster
;
else
{
file
->
cluster_cache_idx
[
slot
]
=
clusterIdx
;
file
->
cluster_cache_data
[
slot
]
=
nextCluster
;
}
#endif
return
1
;
}
vtoycli/fat_io_lib/release/fat_cache.h
0 → 100644
View file @
b0568922
#ifndef __FAT_CACHE_H__
#define __FAT_CACHE_H__
#include "fat_filelib.h"
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
int
fatfs_cache_init
(
struct
fatfs
*
fs
,
FL_FILE
*
file
);
int
fatfs_cache_get_next_cluster
(
struct
fatfs
*
fs
,
FL_FILE
*
file
,
uint32
clusterIdx
,
uint32
*
pNextCluster
);
int
fatfs_cache_set_next_cluster
(
struct
fatfs
*
fs
,
FL_FILE
*
file
,
uint32
clusterIdx
,
uint32
nextCluster
);
#endif
vtoycli/fat_io_lib/release/fat_defs.h
0 → 100644
View file @
b0568922
#ifndef __FAT_DEFS_H__
#define __FAT_DEFS_H__
#include "fat_opts.h"
#include "fat_types.h"
//-----------------------------------------------------------------------------
// FAT32 Offsets
// Name Offset
//-----------------------------------------------------------------------------
// Boot Sector
#define BS_JMPBOOT 0 // Length = 3
#define BS_OEMNAME 3 // Length = 8
#define BPB_BYTSPERSEC 11 // Length = 2
#define BPB_SECPERCLUS 13 // Length = 1
#define BPB_RSVDSECCNT 14 // Length = 2
#define BPB_NUMFATS 16 // Length = 1
#define BPB_ROOTENTCNT 17 // Length = 2
#define BPB_TOTSEC16 19 // Length = 2
#define BPB_MEDIA 21 // Length = 1
#define BPB_FATSZ16 22 // Length = 2
#define BPB_SECPERTRK 24 // Length = 2
#define BPB_NUMHEADS 26 // Length = 2
#define BPB_HIDDSEC 28 // Length = 4
#define BPB_TOTSEC32 32 // Length = 4
// FAT 12/16
#define BS_FAT_DRVNUM 36 // Length = 1
#define BS_FAT_BOOTSIG 38 // Length = 1
#define BS_FAT_VOLID 39 // Length = 4
#define BS_FAT_VOLLAB 43 // Length = 11
#define BS_FAT_FILSYSTYPE 54 // Length = 8
// FAT 32
#define BPB_FAT32_FATSZ32 36 // Length = 4
#define BPB_FAT32_EXTFLAGS 40 // Length = 2
#define BPB_FAT32_FSVER 42 // Length = 2
#define BPB_FAT32_ROOTCLUS 44 // Length = 4
#define BPB_FAT32_FSINFO 48 // Length = 2
#define BPB_FAT32_BKBOOTSEC 50 // Length = 2
#define BS_FAT32_DRVNUM 64 // Length = 1
#define BS_FAT32_BOOTSIG 66 // Length = 1
#define BS_FAT32_VOLID 67 // Length = 4
#define BS_FAT32_VOLLAB 71 // Length = 11
#define BS_FAT32_FILSYSTYPE 82 // Length = 8
//-----------------------------------------------------------------------------
// FAT Types
//-----------------------------------------------------------------------------
#define FAT_TYPE_FAT12 1
#define FAT_TYPE_FAT16 2
#define FAT_TYPE_FAT32 3
//-----------------------------------------------------------------------------
// FAT32 Specific Statics
//-----------------------------------------------------------------------------
#define SIGNATURE_POSITION 510
#define SIGNATURE_VALUE 0xAA55
#define PARTITION1_TYPECODE_LOCATION 450
#define FAT32_TYPECODE1 0x0B
#define FAT32_TYPECODE2 0x0C
#define PARTITION1_LBA_BEGIN_LOCATION 454
#define PARTITION1_SIZE_LOCATION 458
#define FAT_DIR_ENTRY_SIZE 32
#define FAT_SFN_SIZE_FULL 11
#define FAT_SFN_SIZE_PARTIAL 8
//-----------------------------------------------------------------------------
// FAT32 File Attributes and Types
//-----------------------------------------------------------------------------
#define FILE_ATTR_READ_ONLY 0x01
#define FILE_ATTR_HIDDEN 0x02
#define FILE_ATTR_SYSTEM 0x04
#define FILE_ATTR_SYSHID 0x06
#define FILE_ATTR_VOLUME_ID 0x08
#define FILE_ATTR_DIRECTORY 0x10
#define FILE_ATTR_ARCHIVE 0x20
#define FILE_ATTR_LFN_TEXT 0x0F
#define FILE_HEADER_BLANK 0x00
#define FILE_HEADER_DELETED 0xE5
#define FILE_TYPE_DIR 0x10
#define FILE_TYPE_FILE 0x20
//-----------------------------------------------------------------------------
// Time / Date details
//-----------------------------------------------------------------------------
#define FAT_TIME_HOURS_SHIFT 11
#define FAT_TIME_HOURS_MASK 0x1F
#define FAT_TIME_MINUTES_SHIFT 5
#define FAT_TIME_MINUTES_MASK 0x3F
#define FAT_TIME_SECONDS_SHIFT 0
#define FAT_TIME_SECONDS_MASK 0x1F
#define FAT_TIME_SECONDS_SCALE 2
#define FAT_DATE_YEAR_SHIFT 9
#define FAT_DATE_YEAR_MASK 0x7F
#define FAT_DATE_MONTH_SHIFT 5
#define FAT_DATE_MONTH_MASK 0xF
#define FAT_DATE_DAY_SHIFT 0
#define FAT_DATE_DAY_MASK 0x1F
#define FAT_DATE_YEAR_OFFSET 1980
//-----------------------------------------------------------------------------
// Other Defines
//-----------------------------------------------------------------------------
#define FAT32_LAST_CLUSTER 0xFFFFFFFF
#define FAT32_INVALID_CLUSTER 0xFFFFFFFF
STRUCT_PACK_BEGIN
struct
fat_dir_entry
STRUCT_PACK
{
uint8
Name
[
11
];
uint8
Attr
;
uint8
NTRes
;
uint8
CrtTimeTenth
;
uint8
CrtTime
[
2
];
uint8
CrtDate
[
2
];
uint8
LstAccDate
[
2
];
uint16
FstClusHI
;
uint8
WrtTime
[
2
];
uint8
WrtDate
[
2
];
uint16
FstClusLO
;
uint32
FileSize
;
}
STRUCT_PACKED
;
STRUCT_PACK_END
#endif
vtoycli/fat_io_lib/release/fat_filelib.c
0 → 100644
View file @
b0568922
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <stdlib.h>
#include <string.h>
#include "fat_defs.h"
#include "fat_access.h"
#include "fat_table.h"
#include "fat_write.h"
#include "fat_misc.h"
#include "fat_string.h"
#include "fat_filelib.h"
#include "fat_cache.h"
//-----------------------------------------------------------------------------
// Locals
//-----------------------------------------------------------------------------
static
FL_FILE
_files
[
FATFS_MAX_OPEN_FILES
];
static
int
_filelib_init
=
0
;
static
int
_filelib_valid
=
0
;
static
struct
fatfs
_fs
;
static
struct
fat_list
_open_file_list
;
static
struct
fat_list
_free_file_list
;
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
// Macro for checking if file lib is initialised
#define CHECK_FL_INIT() { if (_filelib_init==0) fl_init(); }
#define FL_LOCK(a) do { if ((a)->fl_lock) (a)->fl_lock(); } while (0)
#define FL_UNLOCK(a) do { if ((a)->fl_unlock) (a)->fl_unlock(); } while (0)
//-----------------------------------------------------------------------------
// Local Functions
//-----------------------------------------------------------------------------
static
void
_fl_init
();
//-----------------------------------------------------------------------------
// _allocate_file: Find a slot in the open files buffer for a new file
//-----------------------------------------------------------------------------
static
FL_FILE
*
_allocate_file
(
void
)
{
// Allocate free file
struct
fat_node
*
node
=
fat_list_pop_head
(
&
_free_file_list
);
// Add to open list
if
(
node
)
fat_list_insert_last
(
&
_open_file_list
,
node
);
return
fat_list_entry
(
node
,
FL_FILE
,
list_node
);
}
//-----------------------------------------------------------------------------
// _check_file_open: Returns true if the file is already open
//-----------------------------------------------------------------------------
static
int
_check_file_open
(
FL_FILE
*
file
)
{
struct
fat_node
*
node
;
// Compare open files
fat_list_for_each
(
&
_open_file_list
,
node
)
{
FL_FILE
*
openFile
=
fat_list_entry
(
node
,
FL_FILE
,
list_node
);
// If not the current file
if
(
openFile
!=
file
)
{
// Compare path and name
if
(
(
fatfs_compare_names
(
openFile
->
path
,
file
->
path
))
&&
(
fatfs_compare_names
(
openFile
->
filename
,
file
->
filename
))
)
return
1
;
}
}
return
0
;
}
//-----------------------------------------------------------------------------
// _free_file: Free open file handle
//-----------------------------------------------------------------------------
static
void
_free_file
(
FL_FILE
*
file
)
{
// Remove from open list
fat_list_remove
(
&
_open_file_list
,
&
file
->
list_node
);
// Add to free list
fat_list_insert_last
(
&
_free_file_list
,
&
file
->
list_node
);
}
//-----------------------------------------------------------------------------
// Low Level
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// _open_directory: Cycle through path string to find the start cluster
// address of the highest subdir.
//-----------------------------------------------------------------------------
static
int
_open_directory
(
char
*
path
,
uint32
*
pathCluster
)
{
int
levels
;
int
sublevel
;
char
currentfolder
[
FATFS_MAX_LONG_FILENAME
];
struct
fat_dir_entry
sfEntry
;
uint32
startcluster
;
// Set starting cluster to root cluster
startcluster
=
fatfs_get_root_cluster
(
&
_fs
);
// Find number of levels
levels
=
fatfs_total_path_levels
(
path
);
// Cycle through each level and get the start sector
for
(
sublevel
=
0
;
sublevel
<
(
levels
+
1
);
sublevel
++
)
{
if
(
fatfs_get_substring
(
path
,
sublevel
,
currentfolder
,
sizeof
(
currentfolder
))
==
-
1
)
return
0
;
// Find clusteraddress for folder (currentfolder)
if
(
fatfs_get_file_entry
(
&
_fs
,
startcluster
,
currentfolder
,
&
sfEntry
))
{
// Check entry is folder
if
(
fatfs_entry_is_dir
(
&
sfEntry
))
startcluster
=
((
FAT_HTONS
((
uint32
)
sfEntry
.
FstClusHI
))
<<
16
)
+
FAT_HTONS
(
sfEntry
.
FstClusLO
);
else
return
0
;
}
else
return
0
;
}
*
pathCluster
=
startcluster
;
return
1
;
}
//-----------------------------------------------------------------------------
// _create_directory: Cycle through path string and create the end directory
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
static
int
_create_directory
(
char
*
path
)
{
FL_FILE
*
file
;
struct
fat_dir_entry
sfEntry
;
char
shortFilename
[
FAT_SFN_SIZE_FULL
];
int
tailNum
=
0
;
int
i
;
// Allocate a new file handle
file
=
_allocate_file
();
if
(
!
file
)
return
0
;
// Clear filename
memset
(
file
->
path
,
'\0'
,
sizeof
(
file
->
path
));
memset
(
file
->
filename
,
'\0'
,
sizeof
(
file
->
filename
));
// Split full path into filename and directory path
if
(
fatfs_split_path
((
char
*
)
path
,
file
->
path
,
sizeof
(
file
->
path
),
file
->
filename
,
sizeof
(
file
->
filename
))
==
-
1
)
{
_free_file
(
file
);
return
0
;
}
// Check if file already open
if
(
_check_file_open
(
file
))
{
_free_file
(
file
);
return
0
;
}
// If file is in the root dir
if
(
file
->
path
[
0
]
==
0
)
file
->
parentcluster
=
fatfs_get_root_cluster
(
&
_fs
);
else
{
// Find parent directory start cluster
if
(
!
_open_directory
(
file
->
path
,
&
file
->
parentcluster
))
{
_free_file
(
file
);
return
0
;
}
}
// Check if same filename exists in directory
if
(
fatfs_get_file_entry
(
&
_fs
,
file
->
parentcluster
,
file
->
filename
,
&
sfEntry
)
==
1
)
{
_free_file
(
file
);
return
0
;
}
file
->
startcluster
=
0
;
// Create the file space for the folder (at least one clusters worth!)
if
(
!
fatfs_allocate_free_space
(
&
_fs
,
1
,
&
file
->
startcluster
,
1
))
{
_free_file
(
file
);
return
0
;
}
// Erase new directory cluster
memset
(
file
->
file_data_sector
,
0x00
,
FAT_SECTOR_SIZE
);
for
(
i
=
0
;
i
<
_fs
.
sectors_per_cluster
;
i
++
)
{
if
(
!
fatfs_write_sector
(
&
_fs
,
file
->
startcluster
,
i
,
file
->
file_data_sector
))
{
_free_file
(
file
);
return
0
;
}
}
#if FATFS_INC_LFN_SUPPORT
// Generate a short filename & tail
tailNum
=
0
;
do
{
// Create a standard short filename (without tail)
fatfs_lfn_create_sfn
(
shortFilename
,
file
->
filename
);
// If second hit or more, generate a ~n tail
if
(
tailNum
!=
0
)
fatfs_lfn_generate_tail
((
char
*
)
file
->
shortfilename
,
shortFilename
,
tailNum
);
// Try with no tail if first entry
else
memcpy
(
file
->
shortfilename
,
shortFilename
,
FAT_SFN_SIZE_FULL
);
// Check if entry exists already or not
if
(
fatfs_sfn_exists
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
shortfilename
)
==
0
)
break
;
tailNum
++
;
}
while
(
tailNum
<
9999
);
// We reached the max number of duplicate short file names (unlikely!)
if
(
tailNum
==
9999
)
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
0
;
}
#else
// Create a standard short filename (without tail)
if
(
!
fatfs_lfn_create_sfn
(
shortFilename
,
file
->
filename
))
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
0
;
}
// Copy to SFN space
memcpy
(
file
->
shortfilename
,
shortFilename
,
FAT_SFN_SIZE_FULL
);
// Check if entry exists already
if
(
fatfs_sfn_exists
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
shortfilename
))
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
0
;
}
#endif
// Add file to disk
if
(
!
fatfs_add_file_entry
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
filename
,
(
char
*
)
file
->
shortfilename
,
file
->
startcluster
,
0
,
1
))
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
0
;
}
// General
file
->
filelength
=
0
;
file
->
bytenum
=
0
;
file
->
file_data_address
=
0xFFFFFFFF
;
file
->
file_data_dirty
=
0
;
file
->
filelength_changed
=
0
;
// Quick lookup for next link in the chain
file
->
last_fat_lookup
.
ClusterIdx
=
0xFFFFFFFF
;
file
->
last_fat_lookup
.
CurrentCluster
=
0xFFFFFFFF
;
fatfs_fat_purge
(
&
_fs
);
_free_file
(
file
);
return
1
;
}
#endif
//-----------------------------------------------------------------------------
// _open_file: Open a file for reading
//-----------------------------------------------------------------------------
static
FL_FILE
*
_open_file
(
const
char
*
path
)
{
FL_FILE
*
file
;
struct
fat_dir_entry
sfEntry
;
// Allocate a new file handle
file
=
_allocate_file
();
if
(
!
file
)
return
NULL
;
// Clear filename
memset
(
file
->
path
,
'\0'
,
sizeof
(
file
->
path
));
memset
(
file
->
filename
,
'\0'
,
sizeof
(
file
->
filename
));
// Split full path into filename and directory path
if
(
fatfs_split_path
((
char
*
)
path
,
file
->
path
,
sizeof
(
file
->
path
),
file
->
filename
,
sizeof
(
file
->
filename
))
==
-
1
)
{
_free_file
(
file
);
return
NULL
;
}
// Check if file already open
if
(
_check_file_open
(
file
))
{
_free_file
(
file
);
return
NULL
;
}
// If file is in the root dir
if
(
file
->
path
[
0
]
==
0
)
file
->
parentcluster
=
fatfs_get_root_cluster
(
&
_fs
);
else
{
// Find parent directory start cluster
if
(
!
_open_directory
(
file
->
path
,
&
file
->
parentcluster
))
{
_free_file
(
file
);
return
NULL
;
}
}
// Using dir cluster address search for filename
if
(
fatfs_get_file_entry
(
&
_fs
,
file
->
parentcluster
,
file
->
filename
,
&
sfEntry
))
// Make sure entry is file not dir!
if
(
fatfs_entry_is_file
(
&
sfEntry
))
{
// Initialise file details
memcpy
(
file
->
shortfilename
,
sfEntry
.
Name
,
FAT_SFN_SIZE_FULL
);
file
->
filelength
=
FAT_HTONL
(
sfEntry
.
FileSize
);
file
->
bytenum
=
0
;
file
->
startcluster
=
((
FAT_HTONS
((
uint32
)
sfEntry
.
FstClusHI
))
<<
16
)
+
FAT_HTONS
(
sfEntry
.
FstClusLO
);
file
->
file_data_address
=
0xFFFFFFFF
;
file
->
file_data_dirty
=
0
;
file
->
filelength_changed
=
0
;
// Quick lookup for next link in the chain
file
->
last_fat_lookup
.
ClusterIdx
=
0xFFFFFFFF
;
file
->
last_fat_lookup
.
CurrentCluster
=
0xFFFFFFFF
;
fatfs_cache_init
(
&
_fs
,
file
);
fatfs_fat_purge
(
&
_fs
);
return
file
;
}
_free_file
(
file
);
return
NULL
;
}
//-----------------------------------------------------------------------------
// _create_file: Create a new file
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
static
FL_FILE
*
_create_file
(
const
char
*
filename
)
{
FL_FILE
*
file
;
struct
fat_dir_entry
sfEntry
;
char
shortFilename
[
FAT_SFN_SIZE_FULL
];
int
tailNum
=
0
;
// No write access?
if
(
!
_fs
.
disk_io
.
write_media
)
return
NULL
;
// Allocate a new file handle
file
=
_allocate_file
();
if
(
!
file
)
return
NULL
;
// Clear filename
memset
(
file
->
path
,
'\0'
,
sizeof
(
file
->
path
));
memset
(
file
->
filename
,
'\0'
,
sizeof
(
file
->
filename
));
// Split full path into filename and directory path
if
(
fatfs_split_path
((
char
*
)
filename
,
file
->
path
,
sizeof
(
file
->
path
),
file
->
filename
,
sizeof
(
file
->
filename
))
==
-
1
)
{
_free_file
(
file
);
return
NULL
;
}
// Check if file already open
if
(
_check_file_open
(
file
))
{
_free_file
(
file
);
return
NULL
;
}
// If file is in the root dir
if
(
file
->
path
[
0
]
==
0
)
file
->
parentcluster
=
fatfs_get_root_cluster
(
&
_fs
);
else
{
// Find parent directory start cluster
if
(
!
_open_directory
(
file
->
path
,
&
file
->
parentcluster
))
{
_free_file
(
file
);
return
NULL
;
}
}
// Check if same filename exists in directory
if
(
fatfs_get_file_entry
(
&
_fs
,
file
->
parentcluster
,
file
->
filename
,
&
sfEntry
)
==
1
)
{
_free_file
(
file
);
return
NULL
;
}
file
->
startcluster
=
0
;
// Create the file space for the file (at least one clusters worth!)
if
(
!
fatfs_allocate_free_space
(
&
_fs
,
1
,
&
file
->
startcluster
,
1
))
{
_free_file
(
file
);
return
NULL
;
}
#if FATFS_INC_LFN_SUPPORT
// Generate a short filename & tail
tailNum
=
0
;
do
{
// Create a standard short filename (without tail)
fatfs_lfn_create_sfn
(
shortFilename
,
file
->
filename
);
// If second hit or more, generate a ~n tail
if
(
tailNum
!=
0
)
fatfs_lfn_generate_tail
((
char
*
)
file
->
shortfilename
,
shortFilename
,
tailNum
);
// Try with no tail if first entry
else
memcpy
(
file
->
shortfilename
,
shortFilename
,
FAT_SFN_SIZE_FULL
);
// Check if entry exists already or not
if
(
fatfs_sfn_exists
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
shortfilename
)
==
0
)
break
;
tailNum
++
;
}
while
(
tailNum
<
9999
);
// We reached the max number of duplicate short file names (unlikely!)
if
(
tailNum
==
9999
)
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
NULL
;
}
#else
// Create a standard short filename (without tail)
if
(
!
fatfs_lfn_create_sfn
(
shortFilename
,
file
->
filename
))
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
NULL
;
}
// Copy to SFN space
memcpy
(
file
->
shortfilename
,
shortFilename
,
FAT_SFN_SIZE_FULL
);
// Check if entry exists already
if
(
fatfs_sfn_exists
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
shortfilename
))
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
NULL
;
}
#endif
// Add file to disk
if
(
!
fatfs_add_file_entry
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
filename
,
(
char
*
)
file
->
shortfilename
,
file
->
startcluster
,
0
,
0
))
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
NULL
;
}
// General
file
->
filelength
=
0
;
file
->
bytenum
=
0
;
file
->
file_data_address
=
0xFFFFFFFF
;
file
->
file_data_dirty
=
0
;
file
->
filelength_changed
=
0
;
// Quick lookup for next link in the chain
file
->
last_fat_lookup
.
ClusterIdx
=
0xFFFFFFFF
;
file
->
last_fat_lookup
.
CurrentCluster
=
0xFFFFFFFF
;
fatfs_cache_init
(
&
_fs
,
file
);
fatfs_fat_purge
(
&
_fs
);
return
file
;
}
#endif
//-----------------------------------------------------------------------------
// _read_sectors: Read sector(s) from disk to file
//-----------------------------------------------------------------------------
static
uint32
_read_sectors
(
FL_FILE
*
file
,
uint32
offset
,
uint8
*
buffer
,
uint32
count
)
{
uint32
Sector
=
0
;
uint32
ClusterIdx
=
0
;
uint32
Cluster
=
0
;
uint32
i
;
uint32
lba
;
// Find cluster index within file & sector with cluster
ClusterIdx
=
offset
/
_fs
.
sectors_per_cluster
;
Sector
=
offset
-
(
ClusterIdx
*
_fs
.
sectors_per_cluster
);
// Limit number of sectors read to the number remaining in this cluster
if
((
Sector
+
count
)
>
_fs
.
sectors_per_cluster
)
count
=
_fs
.
sectors_per_cluster
-
Sector
;
// Quick lookup for next link in the chain
if
(
ClusterIdx
==
file
->
last_fat_lookup
.
ClusterIdx
)
Cluster
=
file
->
last_fat_lookup
.
CurrentCluster
;
// Else walk the chain
else
{
// Starting from last recorded cluster?
if
(
ClusterIdx
&&
ClusterIdx
==
file
->
last_fat_lookup
.
ClusterIdx
+
1
)
{
i
=
file
->
last_fat_lookup
.
ClusterIdx
;
Cluster
=
file
->
last_fat_lookup
.
CurrentCluster
;
}
// Start searching from the beginning..
else
{
// Set start of cluster chain to initial value
i
=
0
;
Cluster
=
file
->
startcluster
;
}
// Follow chain to find cluster to read
for
(
;
i
<
ClusterIdx
;
i
++
)
{
uint32
nextCluster
;
// Does the entry exist in the cache?
if
(
!
fatfs_cache_get_next_cluster
(
&
_fs
,
file
,
i
,
&
nextCluster
))
{
// Scan file linked list to find next entry
nextCluster
=
fatfs_find_next_cluster
(
&
_fs
,
Cluster
);
// Push entry into cache
fatfs_cache_set_next_cluster
(
&
_fs
,
file
,
i
,
nextCluster
);
}
Cluster
=
nextCluster
;
}
// Record current cluster lookup details (if valid)
if
(
Cluster
!=
FAT32_LAST_CLUSTER
)
{
file
->
last_fat_lookup
.
CurrentCluster
=
Cluster
;
file
->
last_fat_lookup
.
ClusterIdx
=
ClusterIdx
;
}
}
// If end of cluster chain then return false
if
(
Cluster
==
FAT32_LAST_CLUSTER
)
return
0
;
// Calculate sector address
lba
=
fatfs_lba_of_cluster
(
&
_fs
,
Cluster
)
+
Sector
;
// Read sector of file
if
(
fatfs_sector_read
(
&
_fs
,
lba
,
buffer
,
count
))
return
count
;
else
return
0
;
}
//-----------------------------------------------------------------------------
// External API
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// fl_init: Initialise library
//-----------------------------------------------------------------------------
void
fl_init
(
void
)
{
int
i
;
fat_list_init
(
&
_free_file_list
);
fat_list_init
(
&
_open_file_list
);
// Add all file objects to free list
for
(
i
=
0
;
i
<
FATFS_MAX_OPEN_FILES
;
i
++
)
fat_list_insert_last
(
&
_free_file_list
,
&
_files
[
i
].
list_node
);
_filelib_init
=
1
;
}
//-----------------------------------------------------------------------------
// fl_attach_locks:
//-----------------------------------------------------------------------------
void
fl_attach_locks
(
void
(
*
lock
)(
void
),
void
(
*
unlock
)(
void
))
{
_fs
.
fl_lock
=
lock
;
_fs
.
fl_unlock
=
unlock
;
}
//-----------------------------------------------------------------------------
// fl_attach_media:
//-----------------------------------------------------------------------------
int
fl_attach_media
(
fn_diskio_read
rd
,
fn_diskio_write
wr
)
{
int
res
;
// If first call to library, initialise
CHECK_FL_INIT
();
_fs
.
disk_io
.
read_media
=
rd
;
_fs
.
disk_io
.
write_media
=
wr
;
// Initialise FAT parameters
if
((
res
=
fatfs_init
(
&
_fs
))
!=
FAT_INIT_OK
)
{
FAT_PRINTF
((
"FAT_FS: Error could not load FAT details (%d)!
\r\n
"
,
res
));
return
res
;
}
_filelib_valid
=
1
;
return
FAT_INIT_OK
;
}
//-----------------------------------------------------------------------------
// fl_shutdown: Call before shutting down system
//-----------------------------------------------------------------------------
void
fl_shutdown
(
void
)
{
// If first call to library, initialise
CHECK_FL_INIT
();
FL_LOCK
(
&
_fs
);
fatfs_fat_purge
(
&
_fs
);
FL_UNLOCK
(
&
_fs
);
}
//-----------------------------------------------------------------------------
// fopen: Open or Create a file for reading or writing
//-----------------------------------------------------------------------------
void
*
fl_fopen
(
const
char
*
path
,
const
char
*
mode
)
{
int
i
;
FL_FILE
*
file
;
uint8
flags
=
0
;
// If first call to library, initialise
CHECK_FL_INIT
();
if
(
!
_filelib_valid
)
return
NULL
;
if
(
!
path
||
!
mode
)
return
NULL
;
// Supported Modes:
// "r" Open a file for reading.
// The file must exist.
// "w" Create an empty file for writing.
// If a file with the same name already exists its content is erased and the file is treated as a new empty file.
// "a" Append to a file.
// Writing operations append data at the end of the file.
// The file is created if it does not exist.
// "r+" Open a file for update both reading and writing.
// The file must exist.
// "w+" Create an empty file for both reading and writing.
// If a file with the same name already exists its content is erased and the file is treated as a new empty file.
// "a+" Open a file for reading and appending.
// All writing operations are performed at the end of the file, protecting the previous content to be overwritten.
// You can reposition (fseek, rewind) the internal pointer to anywhere in the file for reading, but writing operations
// will move it back to the end of file.
// The file is created if it does not exist.
for
(
i
=
0
;
i
<
(
int
)
strlen
(
mode
);
i
++
)
{
switch
(
mode
[
i
])
{
case
'r'
:
case
'R'
:
flags
|=
FILE_READ
;
break
;
case
'w'
:
case
'W'
:
flags
|=
FILE_WRITE
;
flags
|=
FILE_ERASE
;
flags
|=
FILE_CREATE
;
break
;
case
'a'
:
case
'A'
:
flags
|=
FILE_WRITE
;
flags
|=
FILE_APPEND
;
flags
|=
FILE_CREATE
;
break
;
case
'+'
:
if
(
flags
&
FILE_READ
)
flags
|=
FILE_WRITE
;
else
if
(
flags
&
FILE_WRITE
)
{
flags
|=
FILE_READ
;
flags
|=
FILE_ERASE
;
flags
|=
FILE_CREATE
;
}
else
if
(
flags
&
FILE_APPEND
)
{
flags
|=
FILE_READ
;
flags
|=
FILE_WRITE
;
flags
|=
FILE_APPEND
;
flags
|=
FILE_CREATE
;
}
break
;
case
'b'
:
case
'B'
:
flags
|=
FILE_BINARY
;
break
;
}
}
file
=
NULL
;
#if FATFS_INC_WRITE_SUPPORT == 0
// No write support!
flags
&=
~
(
FILE_CREATE
|
FILE_WRITE
|
FILE_APPEND
);
#endif
// No write access - remove write/modify flags
if
(
!
_fs
.
disk_io
.
write_media
)
flags
&=
~
(
FILE_CREATE
|
FILE_WRITE
|
FILE_APPEND
);
FL_LOCK
(
&
_fs
);
// Read
if
(
flags
&
FILE_READ
)
file
=
_open_file
(
path
);
// Create New
#if FATFS_INC_WRITE_SUPPORT
if
(
!
file
&&
(
flags
&
FILE_CREATE
))
file
=
_create_file
(
path
);
#endif
// Write Existing (and not open due to read or create)
if
(
!
(
flags
&
FILE_READ
))
if
((
flags
&
FILE_CREATE
)
&&
!
file
)
if
(
flags
&
(
FILE_WRITE
|
FILE_APPEND
))
file
=
_open_file
(
path
);
if
(
file
)
file
->
flags
=
flags
;
FL_UNLOCK
(
&
_fs
);
return
file
;
}
//-----------------------------------------------------------------------------
// _write_sectors: Write sector(s) to disk
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
static
uint32
_write_sectors
(
FL_FILE
*
file
,
uint32
offset
,
uint8
*
buf
,
uint32
count
)
{
uint32
SectorNumber
=
0
;
uint32
ClusterIdx
=
0
;
uint32
Cluster
=
0
;
uint32
LastCluster
=
FAT32_LAST_CLUSTER
;
uint32
i
;
uint32
lba
;
uint32
TotalWriteCount
=
count
;
// Find values for Cluster index & sector within cluster
ClusterIdx
=
offset
/
_fs
.
sectors_per_cluster
;
SectorNumber
=
offset
-
(
ClusterIdx
*
_fs
.
sectors_per_cluster
);
// Limit number of sectors written to the number remaining in this cluster
if
((
SectorNumber
+
count
)
>
_fs
.
sectors_per_cluster
)
count
=
_fs
.
sectors_per_cluster
-
SectorNumber
;
// Quick lookup for next link in the chain
if
(
ClusterIdx
==
file
->
last_fat_lookup
.
ClusterIdx
)
Cluster
=
file
->
last_fat_lookup
.
CurrentCluster
;
// Else walk the chain
else
{
// Starting from last recorded cluster?
if
(
ClusterIdx
&&
ClusterIdx
==
file
->
last_fat_lookup
.
ClusterIdx
+
1
)
{
i
=
file
->
last_fat_lookup
.
ClusterIdx
;
Cluster
=
file
->
last_fat_lookup
.
CurrentCluster
;
}
// Start searching from the beginning..
else
{
// Set start of cluster chain to initial value
i
=
0
;
Cluster
=
file
->
startcluster
;
}
// Follow chain to find cluster to read
for
(
;
i
<
ClusterIdx
;
i
++
)
{
uint32
nextCluster
;
// Does the entry exist in the cache?
if
(
!
fatfs_cache_get_next_cluster
(
&
_fs
,
file
,
i
,
&
nextCluster
))
{
// Scan file linked list to find next entry
nextCluster
=
fatfs_find_next_cluster
(
&
_fs
,
Cluster
);
// Push entry into cache
fatfs_cache_set_next_cluster
(
&
_fs
,
file
,
i
,
nextCluster
);
}
LastCluster
=
Cluster
;
Cluster
=
nextCluster
;
// Dont keep following a dead end
if
(
Cluster
==
FAT32_LAST_CLUSTER
)
break
;
}
// If we have reached the end of the chain, allocate more!
if
(
Cluster
==
FAT32_LAST_CLUSTER
)
{
// Add some more cluster(s) to the last good cluster chain
if
(
!
fatfs_add_free_space
(
&
_fs
,
&
LastCluster
,
(
TotalWriteCount
+
_fs
.
sectors_per_cluster
-
1
)
/
_fs
.
sectors_per_cluster
))
return
0
;
Cluster
=
LastCluster
;
}
// Record current cluster lookup details
file
->
last_fat_lookup
.
CurrentCluster
=
Cluster
;
file
->
last_fat_lookup
.
ClusterIdx
=
ClusterIdx
;
}
// Calculate write address
lba
=
fatfs_lba_of_cluster
(
&
_fs
,
Cluster
)
+
SectorNumber
;
if
(
fatfs_sector_write
(
&
_fs
,
lba
,
buf
,
count
))
return
count
;
else
return
0
;
}
#endif
//-----------------------------------------------------------------------------
// fl_fflush: Flush un-written data to the file
//-----------------------------------------------------------------------------
int
fl_fflush
(
void
*
f
)
{
#if FATFS_INC_WRITE_SUPPORT
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
// If first call to library, initialise
CHECK_FL_INIT
();
if
(
file
)
{
FL_LOCK
(
&
_fs
);
// If some write data still in buffer
if
(
file
->
file_data_dirty
)
{
// Write back current sector before loading next
if
(
_write_sectors
(
file
,
file
->
file_data_address
,
file
->
file_data_sector
,
1
))
file
->
file_data_dirty
=
0
;
}
FL_UNLOCK
(
&
_fs
);
}
#endif
return
0
;
}
//-----------------------------------------------------------------------------
// fl_fclose: Close an open file
//-----------------------------------------------------------------------------
void
fl_fclose
(
void
*
f
)
{
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
// If first call to library, initialise
CHECK_FL_INIT
();
if
(
file
)
{
FL_LOCK
(
&
_fs
);
// Flush un-written data to file
fl_fflush
(
f
);
// File size changed?
if
(
file
->
filelength_changed
)
{
#if FATFS_INC_WRITE_SUPPORT
// Update filesize in directory
fatfs_update_file_length
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
shortfilename
,
file
->
filelength
);
#endif
file
->
filelength_changed
=
0
;
}
file
->
bytenum
=
0
;
file
->
filelength
=
0
;
file
->
startcluster
=
0
;
file
->
file_data_address
=
0xFFFFFFFF
;
file
->
file_data_dirty
=
0
;
file
->
filelength_changed
=
0
;
// Free file handle
_free_file
(
file
);
fatfs_fat_purge
(
&
_fs
);
FL_UNLOCK
(
&
_fs
);
}
}
//-----------------------------------------------------------------------------
// fl_fgetc: Get a character in the stream
//-----------------------------------------------------------------------------
int
fl_fgetc
(
void
*
f
)
{
int
res
;
uint8
data
=
0
;
res
=
fl_fread
(
&
data
,
1
,
1
,
f
);
if
(
res
==
1
)
return
(
int
)
data
;
else
return
res
;
}
//-----------------------------------------------------------------------------
// fl_fgets: Get a string from a stream
//-----------------------------------------------------------------------------
char
*
fl_fgets
(
char
*
s
,
int
n
,
void
*
f
)
{
int
idx
=
0
;
// Space for null terminator?
if
(
n
>
0
)
{
// While space (+space for null terminator)
while
(
idx
<
(
n
-
1
))
{
int
ch
=
fl_fgetc
(
f
);
// EOF / Error?
if
(
ch
<
0
)
break
;
// Store character read from stream
s
[
idx
++
]
=
(
char
)
ch
;
// End of line?
if
(
ch
==
'\n'
)
break
;
}
if
(
idx
>
0
)
s
[
idx
]
=
'\0'
;
}
return
(
idx
>
0
)
?
s
:
0
;
}
//-----------------------------------------------------------------------------
// fl_fread: Read a block of data from the file
//-----------------------------------------------------------------------------
int
fl_fread
(
void
*
buffer
,
int
size
,
int
length
,
void
*
f
)
{
uint32
sector
;
uint32
offset
;
int
copyCount
;
int
count
=
size
*
length
;
int
bytesRead
=
0
;
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
// If first call to library, initialise
CHECK_FL_INIT
();
if
(
buffer
==
NULL
||
file
==
NULL
)
return
-
1
;
// No read permissions
if
(
!
(
file
->
flags
&
FILE_READ
))
return
-
1
;
// Nothing to be done
if
(
!
count
)
return
0
;
// Check if read starts past end of file
if
(
file
->
bytenum
>=
file
->
filelength
)
return
-
1
;
// Limit to file size
if
(
(
file
->
bytenum
+
count
)
>
file
->
filelength
)
count
=
file
->
filelength
-
file
->
bytenum
;
// Calculate start sector
sector
=
file
->
bytenum
/
FAT_SECTOR_SIZE
;
// Offset to start copying data from first sector
offset
=
file
->
bytenum
%
FAT_SECTOR_SIZE
;
while
(
bytesRead
<
count
)
{
// Read whole sector, read from media directly into target buffer
if
((
offset
==
0
)
&&
((
count
-
bytesRead
)
>=
FAT_SECTOR_SIZE
))
{
// Read as many sectors as possible into target buffer
uint32
sectorsRead
=
_read_sectors
(
file
,
sector
,
(
uint8
*
)((
uint8
*
)
buffer
+
bytesRead
),
(
count
-
bytesRead
)
/
FAT_SECTOR_SIZE
);
if
(
sectorsRead
)
{
// We have upto one sector to copy
copyCount
=
FAT_SECTOR_SIZE
*
sectorsRead
;
// Move onto next sector and reset copy offset
sector
+=
sectorsRead
;
offset
=
0
;
}
else
break
;
}
else
{
// Do we need to re-read the sector?
if
(
file
->
file_data_address
!=
sector
)
{
// Flush un-written data to file
if
(
file
->
file_data_dirty
)
fl_fflush
(
file
);
// Get LBA of sector offset within file
if
(
!
_read_sectors
(
file
,
sector
,
file
->
file_data_sector
,
1
))
// Read failed - out of range (probably)
break
;
file
->
file_data_address
=
sector
;
file
->
file_data_dirty
=
0
;
}
// We have upto one sector to copy
copyCount
=
FAT_SECTOR_SIZE
-
offset
;
// Only require some of this sector?
if
(
copyCount
>
(
count
-
bytesRead
))
copyCount
=
(
count
-
bytesRead
);
// Copy to application buffer
memcpy
(
(
uint8
*
)((
uint8
*
)
buffer
+
bytesRead
),
(
uint8
*
)(
file
->
file_data_sector
+
offset
),
copyCount
);
// Move onto next sector and reset copy offset
sector
++
;
offset
=
0
;
}
// Increase total read count
bytesRead
+=
copyCount
;
// Increment file pointer
file
->
bytenum
+=
copyCount
;
}
return
bytesRead
;
}
//-----------------------------------------------------------------------------
// fl_fseek: Seek to a specific place in the file
//-----------------------------------------------------------------------------
int
fl_fseek
(
void
*
f
,
long
offset
,
int
origin
)
{
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
int
res
=
-
1
;
// If first call to library, initialise
CHECK_FL_INIT
();
if
(
!
file
)
return
-
1
;
if
(
origin
==
SEEK_END
&&
offset
!=
0
)
return
-
1
;
FL_LOCK
(
&
_fs
);
// Invalidate file buffer
file
->
file_data_address
=
0xFFFFFFFF
;
file
->
file_data_dirty
=
0
;
if
(
origin
==
SEEK_SET
)
{
file
->
bytenum
=
(
uint32
)
offset
;
if
(
file
->
bytenum
>
file
->
filelength
)
file
->
bytenum
=
file
->
filelength
;
res
=
0
;
}
else
if
(
origin
==
SEEK_CUR
)
{
// Positive shift
if
(
offset
>=
0
)
{
file
->
bytenum
+=
offset
;
if
(
file
->
bytenum
>
file
->
filelength
)
file
->
bytenum
=
file
->
filelength
;
}
// Negative shift
else
{
// Make shift positive
offset
=
-
offset
;
// Limit to negative shift to start of file
if
((
uint32
)
offset
>
file
->
bytenum
)
file
->
bytenum
=
0
;
else
file
->
bytenum
-=
offset
;
}
res
=
0
;
}
else
if
(
origin
==
SEEK_END
)
{
file
->
bytenum
=
file
->
filelength
;
res
=
0
;
}
else
res
=
-
1
;
FL_UNLOCK
(
&
_fs
);
return
res
;
}
//-----------------------------------------------------------------------------
// fl_fgetpos: Get the current file position
//-----------------------------------------------------------------------------
int
fl_fgetpos
(
void
*
f
,
uint32
*
position
)
{
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
if
(
!
file
)
return
-
1
;
FL_LOCK
(
&
_fs
);
// Get position
*
position
=
file
->
bytenum
;
FL_UNLOCK
(
&
_fs
);
return
0
;
}
//-----------------------------------------------------------------------------
// fl_ftell: Get the current file position
//-----------------------------------------------------------------------------
long
fl_ftell
(
void
*
f
)
{
uint32
pos
=
0
;
fl_fgetpos
(
f
,
&
pos
);
return
(
long
)
pos
;
}
//-----------------------------------------------------------------------------
// fl_feof: Is the file pointer at the end of the stream?
//-----------------------------------------------------------------------------
int
fl_feof
(
void
*
f
)
{
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
int
res
;
if
(
!
file
)
return
-
1
;
FL_LOCK
(
&
_fs
);
if
(
file
->
bytenum
==
file
->
filelength
)
res
=
EOF
;
else
res
=
0
;
FL_UNLOCK
(
&
_fs
);
return
res
;
}
//-----------------------------------------------------------------------------
// fl_fputc: Write a character to the stream
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fl_fputc
(
int
c
,
void
*
f
)
{
uint8
data
=
(
uint8
)
c
;
int
res
;
res
=
fl_fwrite
(
&
data
,
1
,
1
,
f
);
if
(
res
==
1
)
return
c
;
else
return
res
;
}
#endif
//-----------------------------------------------------------------------------
// fl_fwrite: Write a block of data to the stream
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fl_fwrite
(
const
void
*
data
,
int
size
,
int
count
,
void
*
f
)
{
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
uint32
sector
;
uint32
offset
;
uint32
length
=
(
size
*
count
);
uint8
*
buffer
=
(
uint8
*
)
data
;
uint32
bytesWritten
=
0
;
uint32
copyCount
;
// If first call to library, initialise
CHECK_FL_INIT
();
if
(
!
file
)
return
-
1
;
FL_LOCK
(
&
_fs
);
// No write permissions
if
(
!
(
file
->
flags
&
FILE_WRITE
))
{
FL_UNLOCK
(
&
_fs
);
return
-
1
;
}
// Append writes to end of file
if
(
file
->
flags
&
FILE_APPEND
)
file
->
bytenum
=
file
->
filelength
;
// Else write to current position
// Calculate start sector
sector
=
file
->
bytenum
/
FAT_SECTOR_SIZE
;
// Offset to start copying data from first sector
offset
=
file
->
bytenum
%
FAT_SECTOR_SIZE
;
while
(
bytesWritten
<
length
)
{
// Whole sector or more to be written?
if
((
offset
==
0
)
&&
((
length
-
bytesWritten
)
>=
FAT_SECTOR_SIZE
))
{
uint32
sectorsWrote
;
// Buffered sector, flush back to disk
if
(
file
->
file_data_address
!=
0xFFFFFFFF
)
{
// Flush un-written data to file
if
(
file
->
file_data_dirty
)
fl_fflush
(
file
);
file
->
file_data_address
=
0xFFFFFFFF
;
file
->
file_data_dirty
=
0
;
}
// Write as many sectors as possible
sectorsWrote
=
_write_sectors
(
file
,
sector
,
(
uint8
*
)(
buffer
+
bytesWritten
),
(
length
-
bytesWritten
)
/
FAT_SECTOR_SIZE
);
copyCount
=
FAT_SECTOR_SIZE
*
sectorsWrote
;
// Increase total read count
bytesWritten
+=
copyCount
;
// Increment file pointer
file
->
bytenum
+=
copyCount
;
// Move onto next sector and reset copy offset
sector
+=
sectorsWrote
;
offset
=
0
;
if
(
!
sectorsWrote
)
break
;
}
else
{
// We have upto one sector to copy
copyCount
=
FAT_SECTOR_SIZE
-
offset
;
// Only require some of this sector?
if
(
copyCount
>
(
length
-
bytesWritten
))
copyCount
=
(
length
-
bytesWritten
);
// Do we need to read a new sector?
if
(
file
->
file_data_address
!=
sector
)
{
// Flush un-written data to file
if
(
file
->
file_data_dirty
)
fl_fflush
(
file
);
// If we plan to overwrite the whole sector, we don't need to read it first!
if
(
copyCount
!=
FAT_SECTOR_SIZE
)
{
// NOTE: This does not have succeed; if last sector of file
// reached, no valid data will be read in, but write will
// allocate some more space for new data.
// Get LBA of sector offset within file
if
(
!
_read_sectors
(
file
,
sector
,
file
->
file_data_sector
,
1
))
memset
(
file
->
file_data_sector
,
0x00
,
FAT_SECTOR_SIZE
);
}
file
->
file_data_address
=
sector
;
file
->
file_data_dirty
=
0
;
}
// Copy from application buffer into sector buffer
memcpy
((
uint8
*
)(
file
->
file_data_sector
+
offset
),
(
uint8
*
)(
buffer
+
bytesWritten
),
copyCount
);
// Mark buffer as dirty
file
->
file_data_dirty
=
1
;
// Increase total read count
bytesWritten
+=
copyCount
;
// Increment file pointer
file
->
bytenum
+=
copyCount
;
// Move onto next sector and reset copy offset
sector
++
;
offset
=
0
;
}
}
// Write increased extent of the file?
if
(
file
->
bytenum
>
file
->
filelength
)
{
// Increase file size to new point
file
->
filelength
=
file
->
bytenum
;
// We are changing the file length and this
// will need to be writen back at some point
file
->
filelength_changed
=
1
;
}
#if FATFS_INC_TIME_DATE_SUPPORT
// If time & date support is enabled, always force directory entry to be
// written in-order to update file modify / access time & date.
file
->
filelength_changed
=
1
;
#endif
FL_UNLOCK
(
&
_fs
);
return
(
size
*
count
);
}
#endif
//-----------------------------------------------------------------------------
// fl_fputs: Write a character string to the stream
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fl_fputs
(
const
char
*
str
,
void
*
f
)
{
int
len
=
(
int
)
strlen
(
str
);
int
res
=
fl_fwrite
(
str
,
1
,
len
,
f
);
if
(
res
==
len
)
return
len
;
else
return
res
;
}
#endif
//-----------------------------------------------------------------------------
// fl_remove: Remove a file from the filesystem
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fl_remove
(
const
char
*
filename
)
{
FL_FILE
*
file
;
int
res
=
-
1
;
FL_LOCK
(
&
_fs
);
// Use read_file as this will check if the file is already open!
file
=
fl_fopen
((
char
*
)
filename
,
"r"
);
if
(
file
)
{
// Delete allocated space
if
(
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
))
{
// Remove directory entries
if
(
fatfs_mark_file_deleted
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
shortfilename
))
{
// Close the file handle (this should not write anything to the file
// as we have not changed the file since opening it!)
fl_fclose
(
file
);
res
=
0
;
}
}
}
FL_UNLOCK
(
&
_fs
);
return
res
;
}
#endif
//-----------------------------------------------------------------------------
// fl_createdirectory: Create a directory based on a path
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fl_createdirectory
(
const
char
*
path
)
{
int
res
;
// If first call to library, initialise
CHECK_FL_INIT
();
FL_LOCK
(
&
_fs
);
res
=
_create_directory
((
char
*
)
path
);
FL_UNLOCK
(
&
_fs
);
return
res
;
}
#endif
//-----------------------------------------------------------------------------
// fl_listdirectory: List a directory based on a path
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
void
fl_listdirectory
(
const
char
*
path
)
{
FL_DIR
dirstat
;
// If first call to library, initialise
CHECK_FL_INIT
();
FL_LOCK
(
&
_fs
);
FAT_PRINTF
((
"
\r\n
Directory %s
\r\n
"
,
path
));
if
(
fl_opendir
(
path
,
&
dirstat
))
{
struct
fs_dir_ent
dirent
;
while
(
fl_readdir
(
&
dirstat
,
&
dirent
)
==
0
)
{
#if FATFS_INC_TIME_DATE_SUPPORT
int
d
,
m
,
y
,
h
,
mn
,
s
;
fatfs_convert_from_fat_time
(
dirent
.
write_time
,
&
h
,
&
m
,
&
s
);
fatfs_convert_from_fat_date
(
dirent
.
write_date
,
&
d
,
&
mn
,
&
y
);
FAT_PRINTF
((
"%02d/%02d/%04d %02d:%02d "
,
d
,
mn
,
y
,
h
,
m
));
#endif
if
(
dirent
.
is_dir
)
{
FAT_PRINTF
((
"%s <DIR>
\r\n
"
,
dirent
.
filename
));
}
else
{
FAT_PRINTF
((
"%s [%d bytes]
\r\n
"
,
dirent
.
filename
,
dirent
.
size
));
}
}
fl_closedir
(
&
dirstat
);
}
FL_UNLOCK
(
&
_fs
);
}
#endif
//-----------------------------------------------------------------------------
// fl_opendir: Opens a directory for listing
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
FL_DIR
*
fl_opendir
(
const
char
*
path
,
FL_DIR
*
dir
)
{
int
levels
;
int
res
=
1
;
uint32
cluster
=
FAT32_INVALID_CLUSTER
;
// If first call to library, initialise
CHECK_FL_INIT
();
FL_LOCK
(
&
_fs
);
levels
=
fatfs_total_path_levels
((
char
*
)
path
)
+
1
;
// If path is in the root dir
if
(
levels
==
0
)
cluster
=
fatfs_get_root_cluster
(
&
_fs
);
// Find parent directory start cluster
else
res
=
_open_directory
((
char
*
)
path
,
&
cluster
);
if
(
res
)
fatfs_list_directory_start
(
&
_fs
,
dir
,
cluster
);
FL_UNLOCK
(
&
_fs
);
return
cluster
!=
FAT32_INVALID_CLUSTER
?
dir
:
0
;
}
#endif
//-----------------------------------------------------------------------------
// fl_readdir: Get next item in directory
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
int
fl_readdir
(
FL_DIR
*
dirls
,
fl_dirent
*
entry
)
{
int
res
=
0
;
// If first call to library, initialise
CHECK_FL_INIT
();
FL_LOCK
(
&
_fs
);
res
=
fatfs_list_directory_next
(
&
_fs
,
dirls
,
entry
);
FL_UNLOCK
(
&
_fs
);
return
res
?
0
:
-
1
;
}
#endif
//-----------------------------------------------------------------------------
// fl_closedir: Close directory after listing
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
int
fl_closedir
(
FL_DIR
*
dir
)
{
// Not used
return
0
;
}
#endif
//-----------------------------------------------------------------------------
// fl_is_dir: Is this a directory?
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
int
fl_is_dir
(
const
char
*
path
)
{
int
res
=
0
;
FL_DIR
dir
;
if
(
fl_opendir
(
path
,
&
dir
))
{
res
=
1
;
fl_closedir
(
&
dir
);
}
return
res
;
}
#endif
//-----------------------------------------------------------------------------
// fl_format: Format a partition with either FAT16 or FAT32 based on size
//-----------------------------------------------------------------------------
#if FATFS_INC_FORMAT_SUPPORT
int
fl_format
(
uint32
volume_sectors
,
const
char
*
name
)
{
return
fatfs_format
(
&
_fs
,
volume_sectors
,
name
);
}
#endif
/*FATFS_INC_FORMAT_SUPPORT*/
//-----------------------------------------------------------------------------
// fl_get_fs:
//-----------------------------------------------------------------------------
#ifdef FATFS_INC_TEST_HOOKS
struct
fatfs
*
fl_get_fs
(
void
)
{
return
&
_fs
;
}
#endif
vtoycli/fat_io_lib/release/fat_filelib.h
0 → 100644
View file @
b0568922
#ifndef __FAT_FILELIB_H__
#define __FAT_FILELIB_H__
#include "fat_opts.h"
#include "fat_access.h"
#include "fat_list.h"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef SEEK_END
#define SEEK_END 2
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef EOF
#define EOF (-1)
#endif
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct
sFL_FILE
;
struct
cluster_lookup
{
uint32
ClusterIdx
;
uint32
CurrentCluster
;
};
typedef
struct
sFL_FILE
{
uint32
parentcluster
;
uint32
startcluster
;
uint32
bytenum
;
uint32
filelength
;
int
filelength_changed
;
char
path
[
FATFS_MAX_LONG_FILENAME
];
char
filename
[
FATFS_MAX_LONG_FILENAME
];
uint8
shortfilename
[
11
];
#ifdef FAT_CLUSTER_CACHE_ENTRIES
uint32
cluster_cache_idx
[
FAT_CLUSTER_CACHE_ENTRIES
];
uint32
cluster_cache_data
[
FAT_CLUSTER_CACHE_ENTRIES
];
#endif
// Cluster Lookup
struct
cluster_lookup
last_fat_lookup
;
// Read/Write sector buffer
uint8
file_data_sector
[
FAT_SECTOR_SIZE
];
uint32
file_data_address
;
int
file_data_dirty
;
// File fopen flags
uint8
flags
;
#define FILE_READ (1 << 0)
#define FILE_WRITE (1 << 1)
#define FILE_APPEND (1 << 2)
#define FILE_BINARY (1 << 3)
#define FILE_ERASE (1 << 4)
#define FILE_CREATE (1 << 5)
struct
fat_node
list_node
;
}
FL_FILE
;
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
// External
void
fl_init
(
void
);
void
fl_attach_locks
(
void
(
*
lock
)(
void
),
void
(
*
unlock
)(
void
));
int
fl_attach_media
(
fn_diskio_read
rd
,
fn_diskio_write
wr
);
void
fl_shutdown
(
void
);
// Standard API
void
*
fl_fopen
(
const
char
*
path
,
const
char
*
modifiers
);
void
fl_fclose
(
void
*
file
);
int
fl_fflush
(
void
*
file
);
int
fl_fgetc
(
void
*
file
);
char
*
fl_fgets
(
char
*
s
,
int
n
,
void
*
f
);
int
fl_fputc
(
int
c
,
void
*
file
);
int
fl_fputs
(
const
char
*
str
,
void
*
file
);
int
fl_fwrite
(
const
void
*
data
,
int
size
,
int
count
,
void
*
file
);
int
fl_fread
(
void
*
data
,
int
size
,
int
count
,
void
*
file
);
int
fl_fseek
(
void
*
file
,
long
offset
,
int
origin
);
int
fl_fgetpos
(
void
*
file
,
uint32
*
position
);
long
fl_ftell
(
void
*
f
);
int
fl_feof
(
void
*
f
);
int
fl_remove
(
const
char
*
filename
);
// Equivelant dirent.h
typedef
struct
fs_dir_list_status
FL_DIR
;
typedef
struct
fs_dir_ent
fl_dirent
;
FL_DIR
*
fl_opendir
(
const
char
*
path
,
FL_DIR
*
dir
);
int
fl_readdir
(
FL_DIR
*
dirls
,
fl_dirent
*
entry
);
int
fl_closedir
(
FL_DIR
*
dir
);
// Extensions
void
fl_listdirectory
(
const
char
*
path
);
int
fl_createdirectory
(
const
char
*
path
);
int
fl_is_dir
(
const
char
*
path
);
int
fl_format
(
uint32
volume_sectors
,
const
char
*
name
);
// Test hooks
#ifdef FATFS_INC_TEST_HOOKS
struct
fatfs
*
fl_get_fs
(
void
);
#endif
//-----------------------------------------------------------------------------
// Stdio file I/O names
//-----------------------------------------------------------------------------
#ifdef USE_FILELIB_STDIO_COMPAT_NAMES
#define FILE FL_FILE
#define fopen(a,b) fl_fopen(a, b)
#define fclose(a) fl_fclose(a)
#define fflush(a) fl_fflush(a)
#define fgetc(a) fl_fgetc(a)
#define fgets(a,b,c) fl_fgets(a, b, c)
#define fputc(a,b) fl_fputc(a, b)
#define fputs(a,b) fl_fputs(a, b)
#define fwrite(a,b,c,d) fl_fwrite(a, b, c, d)
#define fread(a,b,c,d) fl_fread(a, b, c, d)
#define fseek(a,b,c) fl_fseek(a, b, c)
#define fgetpos(a,b) fl_fgetpos(a, b)
#define ftell(a) fl_ftell(a)
#define feof(a) fl_feof(a)
#define remove(a) fl_remove(a)
#define mkdir(a) fl_createdirectory(a)
#define rmdir(a) 0
#endif
#endif
vtoycli/fat_io_lib/release/fat_format.c
0 → 100644
View file @
b0568922
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include "fat_defs.h"
#include "fat_access.h"
#include "fat_table.h"
#include "fat_write.h"
#include "fat_string.h"
#include "fat_misc.h"
#include "fat_format.h"
#if FATFS_INC_FORMAT_SUPPORT
//-----------------------------------------------------------------------------
// Tables
//-----------------------------------------------------------------------------
struct
sec_per_clus_table
{
uint32
sectors
;
uint8
sectors_per_cluster
;
};
struct
sec_per_clus_table
_cluster_size_table16
[]
=
{
{
32680
,
2
},
// 16MB - 1K
{
262144
,
4
},
// 128MB - 2K
{
524288
,
8
},
// 256MB - 4K
{
1048576
,
16
},
// 512MB - 8K
{
2097152
,
32
},
// 1GB - 16K
{
4194304
,
64
},
// 2GB - 32K
{
8388608
,
128
},
// 2GB - 64K [Warning only supported by Windows XP onwards]
{
0
,
0
}
// Invalid
};
struct
sec_per_clus_table
_cluster_size_table32
[]
=
{
{
532480
,
1
},
// 260MB - 512b
{
16777216
,
8
},
// 8GB - 4K
{
33554432
,
16
},
// 16GB - 8K
{
67108864
,
32
},
// 32GB - 16K
{
0xFFFFFFFF
,
64
},
// >32GB - 32K
{
0
,
0
}
// Invalid
};
//-----------------------------------------------------------------------------
// fatfs_calc_cluster_size: Calculate what cluster size should be used
//-----------------------------------------------------------------------------
static
uint8
fatfs_calc_cluster_size
(
uint32
sectors
,
int
is_fat32
)
{
int
i
;
if
(
!
is_fat32
)
{
for
(
i
=
0
;
_cluster_size_table16
[
i
].
sectors_per_cluster
!=
0
;
i
++
)
if
(
sectors
<=
_cluster_size_table16
[
i
].
sectors
)
return
_cluster_size_table16
[
i
].
sectors_per_cluster
;
}
else
{
for
(
i
=
0
;
_cluster_size_table32
[
i
].
sectors_per_cluster
!=
0
;
i
++
)
if
(
sectors
<=
_cluster_size_table32
[
i
].
sectors
)
return
_cluster_size_table32
[
i
].
sectors_per_cluster
;
}
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_erase_sectors: Erase a number of sectors
//-----------------------------------------------------------------------------
static
int
fatfs_erase_sectors
(
struct
fatfs
*
fs
,
uint32
lba
,
int
count
)
{
int
i
;
// Zero sector first
memset
(
fs
->
currentsector
.
sector
,
0
,
FAT_SECTOR_SIZE
);
for
(
i
=
0
;
i
<
count
;
i
++
)
if
(
!
fs
->
disk_io
.
write_media
(
lba
+
i
,
fs
->
currentsector
.
sector
,
1
))
return
0
;
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_create_boot_sector: Create the boot sector
//-----------------------------------------------------------------------------
static
int
fatfs_create_boot_sector
(
struct
fatfs
*
fs
,
uint32
boot_sector_lba
,
uint32
vol_sectors
,
const
char
*
name
,
int
is_fat32
)
{
uint32
total_clusters
;
int
i
;
// Zero sector initially
memset
(
fs
->
currentsector
.
sector
,
0
,
FAT_SECTOR_SIZE
);
// OEM Name & Jump Code
fs
->
currentsector
.
sector
[
0
]
=
0xEB
;
fs
->
currentsector
.
sector
[
1
]
=
0x3C
;
fs
->
currentsector
.
sector
[
2
]
=
0x90
;
fs
->
currentsector
.
sector
[
3
]
=
0x4D
;
fs
->
currentsector
.
sector
[
4
]
=
0x53
;
fs
->
currentsector
.
sector
[
5
]
=
0x44
;
fs
->
currentsector
.
sector
[
6
]
=
0x4F
;
fs
->
currentsector
.
sector
[
7
]
=
0x53
;
fs
->
currentsector
.
sector
[
8
]
=
0x35
;
fs
->
currentsector
.
sector
[
9
]
=
0x2E
;
fs
->
currentsector
.
sector
[
10
]
=
0x30
;
// Bytes per sector
fs
->
currentsector
.
sector
[
11
]
=
(
FAT_SECTOR_SIZE
>>
0
)
&
0xFF
;
fs
->
currentsector
.
sector
[
12
]
=
(
FAT_SECTOR_SIZE
>>
8
)
&
0xFF
;
// Get sectors per cluster size for the disk
fs
->
sectors_per_cluster
=
fatfs_calc_cluster_size
(
vol_sectors
,
is_fat32
);
if
(
!
fs
->
sectors_per_cluster
)
return
0
;
// Invalid disk size
// Sectors per cluster
fs
->
currentsector
.
sector
[
13
]
=
fs
->
sectors_per_cluster
;
// Reserved Sectors
if
(
!
is_fat32
)
fs
->
reserved_sectors
=
8
;
else
fs
->
reserved_sectors
=
32
;
fs
->
currentsector
.
sector
[
14
]
=
(
fs
->
reserved_sectors
>>
0
)
&
0xFF
;
fs
->
currentsector
.
sector
[
15
]
=
(
fs
->
reserved_sectors
>>
8
)
&
0xFF
;
// Number of FATS
fs
->
num_of_fats
=
2
;
fs
->
currentsector
.
sector
[
16
]
=
fs
->
num_of_fats
;
// Max entries in root dir (FAT16 only)
if
(
!
is_fat32
)
{
fs
->
root_entry_count
=
512
;
fs
->
currentsector
.
sector
[
17
]
=
(
fs
->
root_entry_count
>>
0
)
&
0xFF
;
fs
->
currentsector
.
sector
[
18
]
=
(
fs
->
root_entry_count
>>
8
)
&
0xFF
;
}
else
{
fs
->
root_entry_count
=
0
;
fs
->
currentsector
.
sector
[
17
]
=
0
;
fs
->
currentsector
.
sector
[
18
]
=
0
;
}
// [FAT16] Total sectors (use FAT32 count instead)
fs
->
currentsector
.
sector
[
19
]
=
0x00
;
fs
->
currentsector
.
sector
[
20
]
=
0x00
;
// Media type
fs
->
currentsector
.
sector
[
21
]
=
0xF8
;
// FAT16 BS Details
if
(
!
is_fat32
)
{
// Count of sectors used by the FAT table (FAT16 only)
total_clusters
=
(
vol_sectors
/
fs
->
sectors_per_cluster
)
+
1
;
fs
->
fat_sectors
=
(
total_clusters
/
(
FAT_SECTOR_SIZE
/
2
))
+
1
;
fs
->
currentsector
.
sector
[
22
]
=
(
uint8
)((
fs
->
fat_sectors
>>
0
)
&
0xFF
);
fs
->
currentsector
.
sector
[
23
]
=
(
uint8
)((
fs
->
fat_sectors
>>
8
)
&
0xFF
);
// Sectors per track
fs
->
currentsector
.
sector
[
24
]
=
0x00
;
fs
->
currentsector
.
sector
[
25
]
=
0x00
;
// Heads
fs
->
currentsector
.
sector
[
26
]
=
0x00
;
fs
->
currentsector
.
sector
[
27
]
=
0x00
;
// Hidden sectors
fs
->
currentsector
.
sector
[
28
]
=
0x20
;
fs
->
currentsector
.
sector
[
29
]
=
0x00
;
fs
->
currentsector
.
sector
[
30
]
=
0x00
;
fs
->
currentsector
.
sector
[
31
]
=
0x00
;
// Total sectors for this volume
fs
->
currentsector
.
sector
[
32
]
=
(
uint8
)((
vol_sectors
>>
0
)
&
0xFF
);
fs
->
currentsector
.
sector
[
33
]
=
(
uint8
)((
vol_sectors
>>
8
)
&
0xFF
);
fs
->
currentsector
.
sector
[
34
]
=
(
uint8
)((
vol_sectors
>>
16
)
&
0xFF
);
fs
->
currentsector
.
sector
[
35
]
=
(
uint8
)((
vol_sectors
>>
24
)
&
0xFF
);
// Drive number
fs
->
currentsector
.
sector
[
36
]
=
0x00
;
// Reserved
fs
->
currentsector
.
sector
[
37
]
=
0x00
;
// Boot signature
fs
->
currentsector
.
sector
[
38
]
=
0x29
;
// Volume ID
fs
->
currentsector
.
sector
[
39
]
=
0x12
;
fs
->
currentsector
.
sector
[
40
]
=
0x34
;
fs
->
currentsector
.
sector
[
41
]
=
0x56
;
fs
->
currentsector
.
sector
[
42
]
=
0x78
;
// Volume name
for
(
i
=
0
;
i
<
11
;
i
++
)
{
if
(
i
<
(
int
)
strlen
(
name
))
fs
->
currentsector
.
sector
[
i
+
43
]
=
name
[
i
];
else
fs
->
currentsector
.
sector
[
i
+
43
]
=
' '
;
}
// File sys type
fs
->
currentsector
.
sector
[
54
]
=
'F'
;
fs
->
currentsector
.
sector
[
55
]
=
'A'
;
fs
->
currentsector
.
sector
[
56
]
=
'T'
;
fs
->
currentsector
.
sector
[
57
]
=
'1'
;
fs
->
currentsector
.
sector
[
58
]
=
'6'
;
fs
->
currentsector
.
sector
[
59
]
=
' '
;
fs
->
currentsector
.
sector
[
60
]
=
' '
;
fs
->
currentsector
.
sector
[
61
]
=
' '
;
// Signature
fs
->
currentsector
.
sector
[
510
]
=
0x55
;
fs
->
currentsector
.
sector
[
511
]
=
0xAA
;
}
// FAT32 BS Details
else
{
// Count of sectors used by the FAT table (FAT16 only)
fs
->
currentsector
.
sector
[
22
]
=
0
;
fs
->
currentsector
.
sector
[
23
]
=
0
;
// Sectors per track (default)
fs
->
currentsector
.
sector
[
24
]
=
0x3F
;
fs
->
currentsector
.
sector
[
25
]
=
0x00
;
// Heads (default)
fs
->
currentsector
.
sector
[
26
]
=
0xFF
;
fs
->
currentsector
.
sector
[
27
]
=
0x00
;
// Hidden sectors
fs
->
currentsector
.
sector
[
28
]
=
0x00
;
fs
->
currentsector
.
sector
[
29
]
=
0x00
;
fs
->
currentsector
.
sector
[
30
]
=
0x00
;
fs
->
currentsector
.
sector
[
31
]
=
0x00
;
// Total sectors for this volume
fs
->
currentsector
.
sector
[
32
]
=
(
uint8
)((
vol_sectors
>>
0
)
&
0xFF
);
fs
->
currentsector
.
sector
[
33
]
=
(
uint8
)((
vol_sectors
>>
8
)
&
0xFF
);
fs
->
currentsector
.
sector
[
34
]
=
(
uint8
)((
vol_sectors
>>
16
)
&
0xFF
);
fs
->
currentsector
.
sector
[
35
]
=
(
uint8
)((
vol_sectors
>>
24
)
&
0xFF
);
total_clusters
=
(
vol_sectors
/
fs
->
sectors_per_cluster
)
+
1
;
fs
->
fat_sectors
=
(
total_clusters
/
(
FAT_SECTOR_SIZE
/
4
))
+
1
;
// BPB_FATSz32
fs
->
currentsector
.
sector
[
36
]
=
(
uint8
)((
fs
->
fat_sectors
>>
0
)
&
0xFF
);
fs
->
currentsector
.
sector
[
37
]
=
(
uint8
)((
fs
->
fat_sectors
>>
8
)
&
0xFF
);
fs
->
currentsector
.
sector
[
38
]
=
(
uint8
)((
fs
->
fat_sectors
>>
16
)
&
0xFF
);
fs
->
currentsector
.
sector
[
39
]
=
(
uint8
)((
fs
->
fat_sectors
>>
24
)
&
0xFF
);
// BPB_ExtFlags
fs
->
currentsector
.
sector
[
40
]
=
0
;
fs
->
currentsector
.
sector
[
41
]
=
0
;
// BPB_FSVer
fs
->
currentsector
.
sector
[
42
]
=
0
;
fs
->
currentsector
.
sector
[
43
]
=
0
;
// BPB_RootClus
fs
->
currentsector
.
sector
[
44
]
=
(
uint8
)((
fs
->
rootdir_first_cluster
>>
0
)
&
0xFF
);
fs
->
currentsector
.
sector
[
45
]
=
(
uint8
)((
fs
->
rootdir_first_cluster
>>
8
)
&
0xFF
);
fs
->
currentsector
.
sector
[
46
]
=
(
uint8
)((
fs
->
rootdir_first_cluster
>>
16
)
&
0xFF
);
fs
->
currentsector
.
sector
[
47
]
=
(
uint8
)((
fs
->
rootdir_first_cluster
>>
24
)
&
0xFF
);
// BPB_FSInfo
fs
->
currentsector
.
sector
[
48
]
=
(
uint8
)((
fs
->
fs_info_sector
>>
0
)
&
0xFF
);
fs
->
currentsector
.
sector
[
49
]
=
(
uint8
)((
fs
->
fs_info_sector
>>
8
)
&
0xFF
);
// BPB_BkBootSec
fs
->
currentsector
.
sector
[
50
]
=
6
;
fs
->
currentsector
.
sector
[
51
]
=
0
;
// Drive number
fs
->
currentsector
.
sector
[
64
]
=
0x00
;
// Boot signature
fs
->
currentsector
.
sector
[
66
]
=
0x29
;
// Volume ID
fs
->
currentsector
.
sector
[
67
]
=
0x12
;
fs
->
currentsector
.
sector
[
68
]
=
0x34
;
fs
->
currentsector
.
sector
[
69
]
=
0x56
;
fs
->
currentsector
.
sector
[
70
]
=
0x78
;
// Volume name
for
(
i
=
0
;
i
<
11
;
i
++
)
{
if
(
i
<
(
int
)
strlen
(
name
))
fs
->
currentsector
.
sector
[
i
+
71
]
=
name
[
i
];
else
fs
->
currentsector
.
sector
[
i
+
71
]
=
' '
;
}
// File sys type
fs
->
currentsector
.
sector
[
82
]
=
'F'
;
fs
->
currentsector
.
sector
[
83
]
=
'A'
;
fs
->
currentsector
.
sector
[
84
]
=
'T'
;
fs
->
currentsector
.
sector
[
85
]
=
'3'
;
fs
->
currentsector
.
sector
[
86
]
=
'2'
;
fs
->
currentsector
.
sector
[
87
]
=
' '
;
fs
->
currentsector
.
sector
[
88
]
=
' '
;
fs
->
currentsector
.
sector
[
89
]
=
' '
;
// Signature
fs
->
currentsector
.
sector
[
510
]
=
0x55
;
fs
->
currentsector
.
sector
[
511
]
=
0xAA
;
}
if
(
fs
->
disk_io
.
write_media
(
boot_sector_lba
,
fs
->
currentsector
.
sector
,
1
))
return
1
;
else
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_create_fsinfo_sector: Create the FSInfo sector (FAT32)
//-----------------------------------------------------------------------------
static
int
fatfs_create_fsinfo_sector
(
struct
fatfs
*
fs
,
uint32
sector_lba
)
{
// Zero sector initially
memset
(
fs
->
currentsector
.
sector
,
0
,
FAT_SECTOR_SIZE
);
// FSI_LeadSig
fs
->
currentsector
.
sector
[
0
]
=
0x52
;
fs
->
currentsector
.
sector
[
1
]
=
0x52
;
fs
->
currentsector
.
sector
[
2
]
=
0x61
;
fs
->
currentsector
.
sector
[
3
]
=
0x41
;
// FSI_StrucSig
fs
->
currentsector
.
sector
[
484
]
=
0x72
;
fs
->
currentsector
.
sector
[
485
]
=
0x72
;
fs
->
currentsector
.
sector
[
486
]
=
0x41
;
fs
->
currentsector
.
sector
[
487
]
=
0x61
;
// FSI_Free_Count
fs
->
currentsector
.
sector
[
488
]
=
0xFF
;
fs
->
currentsector
.
sector
[
489
]
=
0xFF
;
fs
->
currentsector
.
sector
[
490
]
=
0xFF
;
fs
->
currentsector
.
sector
[
491
]
=
0xFF
;
// FSI_Nxt_Free
fs
->
currentsector
.
sector
[
492
]
=
0xFF
;
fs
->
currentsector
.
sector
[
493
]
=
0xFF
;
fs
->
currentsector
.
sector
[
494
]
=
0xFF
;
fs
->
currentsector
.
sector
[
495
]
=
0xFF
;
// Signature
fs
->
currentsector
.
sector
[
510
]
=
0x55
;
fs
->
currentsector
.
sector
[
511
]
=
0xAA
;
if
(
fs
->
disk_io
.
write_media
(
sector_lba
,
fs
->
currentsector
.
sector
,
1
))
return
1
;
else
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_erase_fat: Erase FAT table using fs details in fs struct
//-----------------------------------------------------------------------------
static
int
fatfs_erase_fat
(
struct
fatfs
*
fs
,
int
is_fat32
)
{
uint32
i
;
// Zero sector initially
memset
(
fs
->
currentsector
.
sector
,
0
,
FAT_SECTOR_SIZE
);
// Initialise default allocate / reserved clusters
if
(
!
is_fat32
)
{
SET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
0
,
0xFFF8
);
SET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
2
,
0xFFFF
);
}
else
{
SET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
0
,
0x0FFFFFF8
);
SET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
4
,
0xFFFFFFFF
);
SET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
8
,
0x0FFFFFFF
);
}
if
(
!
fs
->
disk_io
.
write_media
(
fs
->
fat_begin_lba
+
0
,
fs
->
currentsector
.
sector
,
1
))
return
0
;
// Zero remaining FAT sectors
memset
(
fs
->
currentsector
.
sector
,
0
,
FAT_SECTOR_SIZE
);
for
(
i
=
1
;
i
<
fs
->
fat_sectors
*
fs
->
num_of_fats
;
i
++
)
if
(
!
fs
->
disk_io
.
write_media
(
fs
->
fat_begin_lba
+
i
,
fs
->
currentsector
.
sector
,
1
))
return
0
;
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_format_fat16: Format a FAT16 partition
//-----------------------------------------------------------------------------
int
fatfs_format_fat16
(
struct
fatfs
*
fs
,
uint32
volume_sectors
,
const
char
*
name
)
{
fs
->
currentsector
.
address
=
FAT32_INVALID_CLUSTER
;
fs
->
currentsector
.
dirty
=
0
;
fs
->
next_free_cluster
=
0
;
// Invalid
fatfs_fat_init
(
fs
);
// Make sure we have read + write functions
if
(
!
fs
->
disk_io
.
read_media
||
!
fs
->
disk_io
.
write_media
)
return
FAT_INIT_MEDIA_ACCESS_ERROR
;
// Volume is FAT16
fs
->
fat_type
=
FAT_TYPE_16
;
// Not valid for FAT16
fs
->
fs_info_sector
=
0
;
fs
->
rootdir_first_cluster
=
0
;
// Sector 0: Boot sector
// NOTE: We don't need an MBR, it is a waste of a good sector!
fs
->
lba_begin
=
0
;
if
(
!
fatfs_create_boot_sector
(
fs
,
fs
->
lba_begin
,
volume_sectors
,
name
,
0
))
return
0
;
// For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector
fs
->
rootdir_first_sector
=
fs
->
reserved_sectors
+
(
fs
->
num_of_fats
*
fs
->
fat_sectors
);
fs
->
rootdir_sectors
=
((
fs
->
root_entry_count
*
32
)
+
(
FAT_SECTOR_SIZE
-
1
))
/
FAT_SECTOR_SIZE
;
// First FAT LBA address
fs
->
fat_begin_lba
=
fs
->
lba_begin
+
fs
->
reserved_sectors
;
// The address of the first data cluster on this volume
fs
->
cluster_begin_lba
=
fs
->
fat_begin_lba
+
(
fs
->
num_of_fats
*
fs
->
fat_sectors
);
// Initialise FAT sectors
if
(
!
fatfs_erase_fat
(
fs
,
0
))
return
0
;
// Erase Root directory
if
(
!
fatfs_erase_sectors
(
fs
,
fs
->
lba_begin
+
fs
->
rootdir_first_sector
,
fs
->
rootdir_sectors
))
return
0
;
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_format_fat32: Format a FAT32 partition
//-----------------------------------------------------------------------------
int
fatfs_format_fat32
(
struct
fatfs
*
fs
,
uint32
volume_sectors
,
const
char
*
name
)
{
fs
->
currentsector
.
address
=
FAT32_INVALID_CLUSTER
;
fs
->
currentsector
.
dirty
=
0
;
fs
->
next_free_cluster
=
0
;
// Invalid
fatfs_fat_init
(
fs
);
// Make sure we have read + write functions
if
(
!
fs
->
disk_io
.
read_media
||
!
fs
->
disk_io
.
write_media
)
return
FAT_INIT_MEDIA_ACCESS_ERROR
;
// Volume is FAT32
fs
->
fat_type
=
FAT_TYPE_32
;
// Basic defaults for normal FAT32 partitions
fs
->
fs_info_sector
=
1
;
fs
->
rootdir_first_cluster
=
2
;
// Sector 0: Boot sector
// NOTE: We don't need an MBR, it is a waste of a good sector!
fs
->
lba_begin
=
0
;
if
(
!
fatfs_create_boot_sector
(
fs
,
fs
->
lba_begin
,
volume_sectors
,
name
,
1
))
return
0
;
// First FAT LBA address
fs
->
fat_begin_lba
=
fs
->
lba_begin
+
fs
->
reserved_sectors
;
// The address of the first data cluster on this volume
fs
->
cluster_begin_lba
=
fs
->
fat_begin_lba
+
(
fs
->
num_of_fats
*
fs
->
fat_sectors
);
// Initialise FSInfo sector
if
(
!
fatfs_create_fsinfo_sector
(
fs
,
fs
->
fs_info_sector
))
return
0
;
// Initialise FAT sectors
if
(
!
fatfs_erase_fat
(
fs
,
1
))
return
0
;
// Erase Root directory
if
(
!
fatfs_erase_sectors
(
fs
,
fatfs_lba_of_cluster
(
fs
,
fs
->
rootdir_first_cluster
),
fs
->
sectors_per_cluster
))
return
0
;
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_format: Format a partition with either FAT16 or FAT32 based on size
//-----------------------------------------------------------------------------
int
fatfs_format
(
struct
fatfs
*
fs
,
uint32
volume_sectors
,
const
char
*
name
)
{
// 2GB - 32K limit for safe behaviour for FAT16
if
(
volume_sectors
<=
4194304
)
return
fatfs_format_fat16
(
fs
,
volume_sectors
,
name
);
else
return
fatfs_format_fat32
(
fs
,
volume_sectors
,
name
);
}
#endif
/*FATFS_INC_FORMAT_SUPPORT*/
vtoycli/fat_io_lib/release/fat_format.h
0 → 100644
View file @
b0568922
#ifndef __FAT_FORMAT_H__
#define __FAT_FORMAT_H__
#include "fat_defs.h"
#include "fat_opts.h"
#include "fat_access.h"
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
int
fatfs_format
(
struct
fatfs
*
fs
,
uint32
volume_sectors
,
const
char
*
name
);
int
fatfs_format_fat16
(
struct
fatfs
*
fs
,
uint32
volume_sectors
,
const
char
*
name
);
int
fatfs_format_fat32
(
struct
fatfs
*
fs
,
uint32
volume_sectors
,
const
char
*
name
);
#endif
vtoycli/fat_io_lib/release/fat_list.h
0 → 100644
View file @
b0568922
#ifndef __FAT_LIST_H__
#define __FAT_LIST_H__
#ifndef FAT_ASSERT
#define FAT_ASSERT(x)
#endif
#ifndef FAT_INLINE
#define FAT_INLINE
#endif
//-----------------------------------------------------------------
// Types
//-----------------------------------------------------------------
struct
fat_list
;
struct
fat_node
{
struct
fat_node
*
previous
;
struct
fat_node
*
next
;
};
struct
fat_list
{
struct
fat_node
*
head
;
struct
fat_node
*
tail
;
};
//-----------------------------------------------------------------
// Macros
//-----------------------------------------------------------------
#define fat_list_entry(p, t, m) p ? ((t *)((char *)(p)-(char*)(&((t *)0)->m))) : 0
#define fat_list_next(l, p) (p)->next
#define fat_list_prev(l, p) (p)->previous
#define fat_list_first(l) (l)->head
#define fat_list_last(l) (l)->tail
#define fat_list_for_each(l, p) for ((p) = (l)->head; (p); (p) = (p)->next)
//-----------------------------------------------------------------
// Inline Functions
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// fat_list_init:
//-----------------------------------------------------------------
static
FAT_INLINE
void
fat_list_init
(
struct
fat_list
*
list
)
{
FAT_ASSERT
(
list
);
list
->
head
=
list
->
tail
=
0
;
}
//-----------------------------------------------------------------
// fat_list_remove:
//-----------------------------------------------------------------
static
FAT_INLINE
void
fat_list_remove
(
struct
fat_list
*
list
,
struct
fat_node
*
node
)
{
FAT_ASSERT
(
list
);
FAT_ASSERT
(
node
);
if
(
!
node
->
previous
)
list
->
head
=
node
->
next
;
else
node
->
previous
->
next
=
node
->
next
;
if
(
!
node
->
next
)
list
->
tail
=
node
->
previous
;
else
node
->
next
->
previous
=
node
->
previous
;
}
//-----------------------------------------------------------------
// fat_list_insert_after:
//-----------------------------------------------------------------
static
FAT_INLINE
void
fat_list_insert_after
(
struct
fat_list
*
list
,
struct
fat_node
*
node
,
struct
fat_node
*
new_node
)
{
FAT_ASSERT
(
list
);
FAT_ASSERT
(
node
);
FAT_ASSERT
(
new_node
);
new_node
->
previous
=
node
;
new_node
->
next
=
node
->
next
;
if
(
!
node
->
next
)
list
->
tail
=
new_node
;
else
node
->
next
->
previous
=
new_node
;
node
->
next
=
new_node
;
}
//-----------------------------------------------------------------
// fat_list_insert_before:
//-----------------------------------------------------------------
static
FAT_INLINE
void
fat_list_insert_before
(
struct
fat_list
*
list
,
struct
fat_node
*
node
,
struct
fat_node
*
new_node
)
{
FAT_ASSERT
(
list
);
FAT_ASSERT
(
node
);
FAT_ASSERT
(
new_node
);
new_node
->
previous
=
node
->
previous
;
new_node
->
next
=
node
;
if
(
!
node
->
previous
)
list
->
head
=
new_node
;
else
node
->
previous
->
next
=
new_node
;
node
->
previous
=
new_node
;
}
//-----------------------------------------------------------------
// fat_list_insert_first:
//-----------------------------------------------------------------
static
FAT_INLINE
void
fat_list_insert_first
(
struct
fat_list
*
list
,
struct
fat_node
*
node
)
{
FAT_ASSERT
(
list
);
FAT_ASSERT
(
node
);
if
(
!
list
->
head
)
{
list
->
head
=
node
;
list
->
tail
=
node
;
node
->
previous
=
0
;
node
->
next
=
0
;
}
else
fat_list_insert_before
(
list
,
list
->
head
,
node
);
}
//-----------------------------------------------------------------
// fat_list_insert_last:
//-----------------------------------------------------------------
static
FAT_INLINE
void
fat_list_insert_last
(
struct
fat_list
*
list
,
struct
fat_node
*
node
)
{
FAT_ASSERT
(
list
);
FAT_ASSERT
(
node
);
if
(
!
list
->
tail
)
fat_list_insert_first
(
list
,
node
);
else
fat_list_insert_after
(
list
,
list
->
tail
,
node
);
}
//-----------------------------------------------------------------
// fat_list_is_empty:
//-----------------------------------------------------------------
static
FAT_INLINE
int
fat_list_is_empty
(
struct
fat_list
*
list
)
{
FAT_ASSERT
(
list
);
return
!
list
->
head
;
}
//-----------------------------------------------------------------
// fat_list_pop_head:
//-----------------------------------------------------------------
static
FAT_INLINE
struct
fat_node
*
fat_list_pop_head
(
struct
fat_list
*
list
)
{
struct
fat_node
*
node
;
FAT_ASSERT
(
list
);
node
=
fat_list_first
(
list
);
if
(
node
)
fat_list_remove
(
list
,
node
);
return
node
;
}
#endif
vtoycli/fat_io_lib/release/fat_misc.c
0 → 100644
View file @
b0568922
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <stdlib.h>
#include <string.h>
#include "fat_misc.h"
//-----------------------------------------------------------------------------
// fatfs_lfn_cache_init: Clear long file name cache
//-----------------------------------------------------------------------------
void
fatfs_lfn_cache_init
(
struct
lfn_cache
*
lfn
,
int
wipeTable
)
{
int
i
=
0
;
lfn
->
no_of_strings
=
0
;
#if FATFS_INC_LFN_SUPPORT
// Zero out buffer also
if
(
wipeTable
)
for
(
i
=
0
;
i
<
MAX_LONGFILENAME_ENTRIES
;
i
++
)
memset
(
lfn
->
String
[
i
],
0x00
,
MAX_LFN_ENTRY_LENGTH
);
#endif
}
//-----------------------------------------------------------------------------
// fatfs_lfn_cache_entry - Function extracts long file name text from sector
// at a specific offset
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
void
fatfs_lfn_cache_entry
(
struct
lfn_cache
*
lfn
,
uint8
*
entryBuffer
)
{
uint8
LFNIndex
,
i
;
LFNIndex
=
entryBuffer
[
0
]
&
0x1F
;
// Limit file name to cache size!
if
(
LFNIndex
>
MAX_LONGFILENAME_ENTRIES
)
return
;
// This is an error condition
if
(
LFNIndex
==
0
)
return
;
if
(
lfn
->
no_of_strings
==
0
)
lfn
->
no_of_strings
=
LFNIndex
;
lfn
->
String
[
LFNIndex
-
1
][
0
]
=
entryBuffer
[
1
];
lfn
->
String
[
LFNIndex
-
1
][
1
]
=
entryBuffer
[
3
];
lfn
->
String
[
LFNIndex
-
1
][
2
]
=
entryBuffer
[
5
];
lfn
->
String
[
LFNIndex
-
1
][
3
]
=
entryBuffer
[
7
];
lfn
->
String
[
LFNIndex
-
1
][
4
]
=
entryBuffer
[
9
];
lfn
->
String
[
LFNIndex
-
1
][
5
]
=
entryBuffer
[
0x0E
];
lfn
->
String
[
LFNIndex
-
1
][
6
]
=
entryBuffer
[
0x10
];
lfn
->
String
[
LFNIndex
-
1
][
7
]
=
entryBuffer
[
0x12
];
lfn
->
String
[
LFNIndex
-
1
][
8
]
=
entryBuffer
[
0x14
];
lfn
->
String
[
LFNIndex
-
1
][
9
]
=
entryBuffer
[
0x16
];
lfn
->
String
[
LFNIndex
-
1
][
10
]
=
entryBuffer
[
0x18
];
lfn
->
String
[
LFNIndex
-
1
][
11
]
=
entryBuffer
[
0x1C
];
lfn
->
String
[
LFNIndex
-
1
][
12
]
=
entryBuffer
[
0x1E
];
for
(
i
=
0
;
i
<
MAX_LFN_ENTRY_LENGTH
;
i
++
)
if
(
lfn
->
String
[
LFNIndex
-
1
][
i
]
==
0xFF
)
lfn
->
String
[
LFNIndex
-
1
][
i
]
=
0x20
;
// Replace with spaces
}
#endif
//-----------------------------------------------------------------------------
// fatfs_lfn_cache_get: Get a reference to the long filename
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
char
*
fatfs_lfn_cache_get
(
struct
lfn_cache
*
lfn
)
{
// Null terminate long filename
if
(
lfn
->
no_of_strings
==
MAX_LONGFILENAME_ENTRIES
)
lfn
->
Null
=
'\0'
;
else
if
(
lfn
->
no_of_strings
)
lfn
->
String
[
lfn
->
no_of_strings
][
0
]
=
'\0'
;
else
lfn
->
String
[
0
][
0
]
=
'\0'
;
return
(
char
*
)
&
lfn
->
String
[
0
][
0
];
}
#endif
//-----------------------------------------------------------------------------
// fatfs_entry_lfn_text: If LFN text entry found
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
int
fatfs_entry_lfn_text
(
struct
fat_dir_entry
*
entry
)
{
if
((
entry
->
Attr
&
FILE_ATTR_LFN_TEXT
)
==
FILE_ATTR_LFN_TEXT
)
return
1
;
else
return
0
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_entry_lfn_invalid: If SFN found not relating to LFN
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
int
fatfs_entry_lfn_invalid
(
struct
fat_dir_entry
*
entry
)
{
if
(
(
entry
->
Name
[
0
]
==
FILE_HEADER_BLANK
)
||
(
entry
->
Name
[
0
]
==
FILE_HEADER_DELETED
)
||
(
entry
->
Attr
==
FILE_ATTR_VOLUME_ID
)
||
(
entry
->
Attr
&
FILE_ATTR_SYSHID
)
)
return
1
;
else
return
0
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_entry_lfn_exists: If LFN exists and correlation SFN found
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
int
fatfs_entry_lfn_exists
(
struct
lfn_cache
*
lfn
,
struct
fat_dir_entry
*
entry
)
{
if
(
(
entry
->
Attr
!=
FILE_ATTR_LFN_TEXT
)
&&
(
entry
->
Name
[
0
]
!=
FILE_HEADER_BLANK
)
&&
(
entry
->
Name
[
0
]
!=
FILE_HEADER_DELETED
)
&&
(
entry
->
Attr
!=
FILE_ATTR_VOLUME_ID
)
&&
(
!
(
entry
->
Attr
&
FILE_ATTR_SYSHID
))
&&
(
lfn
->
no_of_strings
)
)
return
1
;
else
return
0
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_entry_sfn_only: If SFN only exists
//-----------------------------------------------------------------------------
int
fatfs_entry_sfn_only
(
struct
fat_dir_entry
*
entry
)
{
if
(
(
entry
->
Attr
!=
FILE_ATTR_LFN_TEXT
)
&&
(
entry
->
Name
[
0
]
!=
FILE_HEADER_BLANK
)
&&
(
entry
->
Name
[
0
]
!=
FILE_HEADER_DELETED
)
&&
(
entry
->
Attr
!=
FILE_ATTR_VOLUME_ID
)
&&
(
!
(
entry
->
Attr
&
FILE_ATTR_SYSHID
))
)
return
1
;
else
return
0
;
}
// TODO: FILE_ATTR_SYSHID ?!?!??!
//-----------------------------------------------------------------------------
// fatfs_entry_is_dir: Returns 1 if a directory
//-----------------------------------------------------------------------------
int
fatfs_entry_is_dir
(
struct
fat_dir_entry
*
entry
)
{
if
(
entry
->
Attr
&
FILE_TYPE_DIR
)
return
1
;
else
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_entry_is_file: Returns 1 is a file entry
//-----------------------------------------------------------------------------
int
fatfs_entry_is_file
(
struct
fat_dir_entry
*
entry
)
{
if
(
entry
->
Attr
&
FILE_TYPE_FILE
)
return
1
;
else
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_lfn_entries_required: Calculate number of 13 characters entries
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
int
fatfs_lfn_entries_required
(
char
*
filename
)
{
int
length
=
(
int
)
strlen
(
filename
);
if
(
length
)
return
(
length
+
MAX_LFN_ENTRY_LENGTH
-
1
)
/
MAX_LFN_ENTRY_LENGTH
;
else
return
0
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_filename_to_lfn:
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
void
fatfs_filename_to_lfn
(
char
*
filename
,
uint8
*
buffer
,
int
entry
,
uint8
sfnChk
)
{
int
i
;
int
nameIndexes
[
MAX_LFN_ENTRY_LENGTH
]
=
{
1
,
3
,
5
,
7
,
9
,
0x0E
,
0x10
,
0x12
,
0x14
,
0x16
,
0x18
,
0x1C
,
0x1E
};
// 13 characters entries
int
length
=
(
int
)
strlen
(
filename
);
int
entriesRequired
=
fatfs_lfn_entries_required
(
filename
);
// Filename offset
int
start
=
entry
*
MAX_LFN_ENTRY_LENGTH
;
// Initialise to zeros
memset
(
buffer
,
0x00
,
FAT_DIR_ENTRY_SIZE
);
// LFN entry number
buffer
[
0
]
=
(
uint8
)(((
entriesRequired
-
1
)
==
entry
)
?
(
0x40
|
(
entry
+
1
))
:
(
entry
+
1
));
// LFN flag
buffer
[
11
]
=
0x0F
;
// Checksum of short filename
buffer
[
13
]
=
sfnChk
;
// Copy to buffer
for
(
i
=
0
;
i
<
MAX_LFN_ENTRY_LENGTH
;
i
++
)
{
if
(
(
start
+
i
)
<
length
)
buffer
[
nameIndexes
[
i
]]
=
filename
[
start
+
i
];
else
if
(
(
start
+
i
)
==
length
)
buffer
[
nameIndexes
[
i
]]
=
0x00
;
else
{
buffer
[
nameIndexes
[
i
]]
=
0xFF
;
buffer
[
nameIndexes
[
i
]
+
1
]
=
0xFF
;
}
}
}
#endif
//-----------------------------------------------------------------------------
// fatfs_sfn_create_entry: Create the short filename directory entry
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
void
fatfs_sfn_create_entry
(
char
*
shortfilename
,
uint32
size
,
uint32
startCluster
,
struct
fat_dir_entry
*
entry
,
int
dir
)
{
int
i
;
// Copy short filename
for
(
i
=
0
;
i
<
FAT_SFN_SIZE_FULL
;
i
++
)
entry
->
Name
[
i
]
=
shortfilename
[
i
];
// Unless we have a RTC we might as well set these to 1980
entry
->
CrtTimeTenth
=
0x00
;
entry
->
CrtTime
[
1
]
=
entry
->
CrtTime
[
0
]
=
0x00
;
entry
->
CrtDate
[
1
]
=
0x00
;
entry
->
CrtDate
[
0
]
=
0x20
;
entry
->
LstAccDate
[
1
]
=
0x00
;
entry
->
LstAccDate
[
0
]
=
0x20
;
entry
->
WrtTime
[
1
]
=
entry
->
WrtTime
[
0
]
=
0x00
;
entry
->
WrtDate
[
1
]
=
0x00
;
entry
->
WrtDate
[
0
]
=
0x20
;
if
(
!
dir
)
entry
->
Attr
=
FILE_TYPE_FILE
;
else
entry
->
Attr
=
FILE_TYPE_DIR
;
entry
->
NTRes
=
0x00
;
entry
->
FstClusHI
=
FAT_HTONS
((
uint16
)((
startCluster
>>
16
)
&
0xFFFF
));
entry
->
FstClusLO
=
FAT_HTONS
((
uint16
)((
startCluster
>>
0
)
&
0xFFFF
));
entry
->
FileSize
=
FAT_HTONL
(
size
);
}
#endif
//-----------------------------------------------------------------------------
// fatfs_lfn_create_sfn: Create a padded SFN
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_lfn_create_sfn
(
char
*
sfn_output
,
char
*
filename
)
{
int
i
;
int
dotPos
=
-
1
;
char
ext
[
3
];
int
pos
;
int
len
=
(
int
)
strlen
(
filename
);
// Invalid to start with .
if
(
filename
[
0
]
==
'.'
)
return
0
;
memset
(
sfn_output
,
' '
,
FAT_SFN_SIZE_FULL
);
memset
(
ext
,
' '
,
3
);
// Find dot seperator
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
filename
[
i
]
==
'.'
)
dotPos
=
i
;
}
// Extract extensions
if
(
dotPos
!=-
1
)
{
// Copy first three chars of extension
for
(
i
=
(
dotPos
+
1
);
i
<
(
dotPos
+
1
+
3
);
i
++
)
if
(
i
<
len
)
ext
[
i
-
(
dotPos
+
1
)]
=
filename
[
i
];
// Shorten the length to the dot position
len
=
dotPos
;
}
// Add filename part
pos
=
0
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
(
filename
[
i
]
!=
' '
)
&&
(
filename
[
i
]
!=
'.'
)
)
{
if
(
filename
[
i
]
>=
'a'
&&
filename
[
i
]
<=
'z'
)
sfn_output
[
pos
++
]
=
filename
[
i
]
-
'a'
+
'A'
;
else
sfn_output
[
pos
++
]
=
filename
[
i
];
}
// Fill upto 8 characters
if
(
pos
==
FAT_SFN_SIZE_PARTIAL
)
break
;
}
// Add extension part
for
(
i
=
FAT_SFN_SIZE_PARTIAL
;
i
<
FAT_SFN_SIZE_FULL
;
i
++
)
{
if
(
ext
[
i
-
FAT_SFN_SIZE_PARTIAL
]
>=
'a'
&&
ext
[
i
-
FAT_SFN_SIZE_PARTIAL
]
<=
'z'
)
sfn_output
[
i
]
=
ext
[
i
-
FAT_SFN_SIZE_PARTIAL
]
-
'a'
+
'A'
;
else
sfn_output
[
i
]
=
ext
[
i
-
FAT_SFN_SIZE_PARTIAL
];
}
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_itoa:
//-----------------------------------------------------------------------------
static
void
fatfs_itoa
(
uint32
num
,
char
*
s
)
{
char
*
cp
;
char
outbuf
[
12
];
const
char
digits
[]
=
"0123456789ABCDEF"
;
// Build string backwards
cp
=
outbuf
;
do
{
*
cp
++
=
digits
[(
int
)(
num
%
10
)];
}
while
((
num
/=
10
)
>
0
);
*
cp
--
=
0
;
// Copy in forwards
while
(
cp
>=
outbuf
)
*
s
++
=
*
cp
--
;
*
s
=
0
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_lfn_generate_tail:
// sfn_input = Input short filename, spaced format & in upper case
// sfn_output = Output short filename with tail
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_lfn_generate_tail
(
char
*
sfn_output
,
char
*
sfn_input
,
uint32
tailNum
)
{
int
tail_chars
;
char
tail_str
[
12
];
if
(
tailNum
>
99999
)
return
0
;
// Convert to number
memset
(
tail_str
,
0x00
,
sizeof
(
tail_str
));
tail_str
[
0
]
=
'~'
;
fatfs_itoa
(
tailNum
,
tail_str
+
1
);
// Copy in base filename
memcpy
(
sfn_output
,
sfn_input
,
FAT_SFN_SIZE_FULL
);
// Overwrite with tail
tail_chars
=
(
int
)
strlen
(
tail_str
);
memcpy
(
sfn_output
+
(
FAT_SFN_SIZE_PARTIAL
-
tail_chars
),
tail_str
,
tail_chars
);
return
1
;
}
#endif
#endif
//-----------------------------------------------------------------------------
// fatfs_convert_from_fat_time: Convert FAT time to h/m/s
//-----------------------------------------------------------------------------
#if FATFS_INC_TIME_DATE_SUPPORT
void
fatfs_convert_from_fat_time
(
uint16
fat_time
,
int
*
hours
,
int
*
minutes
,
int
*
seconds
)
{
*
hours
=
(
fat_time
>>
FAT_TIME_HOURS_SHIFT
)
&
FAT_TIME_HOURS_MASK
;
*
minutes
=
(
fat_time
>>
FAT_TIME_MINUTES_SHIFT
)
&
FAT_TIME_MINUTES_MASK
;
*
seconds
=
(
fat_time
>>
FAT_TIME_SECONDS_SHIFT
)
&
FAT_TIME_SECONDS_MASK
;
*
seconds
=
*
seconds
*
FAT_TIME_SECONDS_SCALE
;
}
//-----------------------------------------------------------------------------
// fatfs_convert_from_fat_date: Convert FAT date to d/m/y
//-----------------------------------------------------------------------------
void
fatfs_convert_from_fat_date
(
uint16
fat_date
,
int
*
day
,
int
*
month
,
int
*
year
)
{
*
day
=
(
fat_date
>>
FAT_DATE_DAY_SHIFT
)
&
FAT_DATE_DAY_MASK
;
*
month
=
(
fat_date
>>
FAT_DATE_MONTH_SHIFT
)
&
FAT_DATE_MONTH_MASK
;
*
year
=
(
fat_date
>>
FAT_DATE_YEAR_SHIFT
)
&
FAT_DATE_YEAR_MASK
;
*
year
=
*
year
+
FAT_DATE_YEAR_OFFSET
;
}
//-----------------------------------------------------------------------------
// fatfs_convert_to_fat_time: Convert h/m/s to FAT time
//-----------------------------------------------------------------------------
uint16
fatfs_convert_to_fat_time
(
int
hours
,
int
minutes
,
int
seconds
)
{
uint16
fat_time
=
0
;
// Most FAT times are to a resolution of 2 seconds
seconds
/=
FAT_TIME_SECONDS_SCALE
;
fat_time
=
(
hours
&
FAT_TIME_HOURS_MASK
)
<<
FAT_TIME_HOURS_SHIFT
;
fat_time
|=
(
minutes
&
FAT_TIME_MINUTES_MASK
)
<<
FAT_TIME_MINUTES_SHIFT
;
fat_time
|=
(
seconds
&
FAT_TIME_SECONDS_MASK
)
<<
FAT_TIME_SECONDS_SHIFT
;
return
fat_time
;
}
//-----------------------------------------------------------------------------
// fatfs_convert_to_fat_date: Convert d/m/y to FAT date
//-----------------------------------------------------------------------------
uint16
fatfs_convert_to_fat_date
(
int
day
,
int
month
,
int
year
)
{
uint16
fat_date
=
0
;
// FAT dates are relative to 1980
if
(
year
>=
FAT_DATE_YEAR_OFFSET
)
year
-=
FAT_DATE_YEAR_OFFSET
;
fat_date
=
(
day
&
FAT_DATE_DAY_MASK
)
<<
FAT_DATE_DAY_SHIFT
;
fat_date
|=
(
month
&
FAT_DATE_MONTH_MASK
)
<<
FAT_DATE_MONTH_SHIFT
;
fat_date
|=
(
year
&
FAT_DATE_YEAR_MASK
)
<<
FAT_DATE_YEAR_SHIFT
;
return
fat_date
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_print_sector:
//-----------------------------------------------------------------------------
#ifdef FATFS_DEBUG
void
fatfs_print_sector
(
uint32
sector
,
uint8
*
data
)
{
int
i
;
int
j
;
FAT_PRINTF
((
"Sector %d:
\n
"
,
sector
));
for
(
i
=
0
;
i
<
FAT_SECTOR_SIZE
;
i
++
)
{
if
(
!
((
i
)
%
16
))
{
FAT_PRINTF
((
" %04d: "
,
i
));
}
FAT_PRINTF
((
"%02x"
,
data
[
i
]));
if
(
!
((
i
+
1
)
%
4
))
{
FAT_PRINTF
((
" "
));
}
if
(
!
((
i
+
1
)
%
16
))
{
FAT_PRINTF
((
" "
));
for
(
j
=
0
;
j
<
16
;
j
++
)
{
char
ch
=
data
[
i
-
15
+
j
];
// Is printable?
if
(
ch
>
31
&&
ch
<
127
)
{
FAT_PRINTF
((
"%c"
,
ch
));
}
else
{
FAT_PRINTF
((
"."
));
}
}
FAT_PRINTF
((
"
\n
"
));
}
}
}
#endif
vtoycli/fat_io_lib/release/fat_misc.h
0 → 100644
View file @
b0568922
#ifndef __FAT_MISC_H__
#define __FAT_MISC_H__
#include "fat_defs.h"
#include "fat_opts.h"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
#define MAX_LONGFILENAME_ENTRIES 20
#define MAX_LFN_ENTRY_LENGTH 13
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
#define GET_32BIT_WORD(buffer, location) ( ((uint32)buffer[location+3]<<24) + ((uint32)buffer[location+2]<<16) + ((uint32)buffer[location+1]<<8) + (uint32)buffer[location+0] )
#define GET_16BIT_WORD(buffer, location) ( ((uint16)buffer[location+1]<<8) + (uint16)buffer[location+0] )
#define SET_32BIT_WORD(buffer, location, value) { buffer[location+0] = (uint8)((value)&0xFF); \
buffer[location+1] = (uint8)((value>>8)&0xFF); \
buffer[location+2] = (uint8)((value>>16)&0xFF); \
buffer[location+3] = (uint8)((value>>24)&0xFF); }
#define SET_16BIT_WORD(buffer, location, value) { buffer[location+0] = (uint8)((value)&0xFF); \
buffer[location+1] = (uint8)((value>>8)&0xFF); }
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct
lfn_cache
{
#if FATFS_INC_LFN_SUPPORT
// Long File Name Structure (max 260 LFN length)
uint8
String
[
MAX_LONGFILENAME_ENTRIES
][
MAX_LFN_ENTRY_LENGTH
];
uint8
Null
;
#endif
uint8
no_of_strings
;
};
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
void
fatfs_lfn_cache_init
(
struct
lfn_cache
*
lfn
,
int
wipeTable
);
void
fatfs_lfn_cache_entry
(
struct
lfn_cache
*
lfn
,
uint8
*
entryBuffer
);
char
*
fatfs_lfn_cache_get
(
struct
lfn_cache
*
lfn
);
int
fatfs_entry_lfn_text
(
struct
fat_dir_entry
*
entry
);
int
fatfs_entry_lfn_invalid
(
struct
fat_dir_entry
*
entry
);
int
fatfs_entry_lfn_exists
(
struct
lfn_cache
*
lfn
,
struct
fat_dir_entry
*
entry
);
int
fatfs_entry_sfn_only
(
struct
fat_dir_entry
*
entry
);
int
fatfs_entry_is_dir
(
struct
fat_dir_entry
*
entry
);
int
fatfs_entry_is_file
(
struct
fat_dir_entry
*
entry
);
int
fatfs_lfn_entries_required
(
char
*
filename
);
void
fatfs_filename_to_lfn
(
char
*
filename
,
uint8
*
buffer
,
int
entry
,
uint8
sfnChk
);
void
fatfs_sfn_create_entry
(
char
*
shortfilename
,
uint32
size
,
uint32
startCluster
,
struct
fat_dir_entry
*
entry
,
int
dir
);
int
fatfs_lfn_create_sfn
(
char
*
sfn_output
,
char
*
filename
);
int
fatfs_lfn_generate_tail
(
char
*
sfn_output
,
char
*
sfn_input
,
uint32
tailNum
);
void
fatfs_convert_from_fat_time
(
uint16
fat_time
,
int
*
hours
,
int
*
minutes
,
int
*
seconds
);
void
fatfs_convert_from_fat_date
(
uint16
fat_date
,
int
*
day
,
int
*
month
,
int
*
year
);
uint16
fatfs_convert_to_fat_time
(
int
hours
,
int
minutes
,
int
seconds
);
uint16
fatfs_convert_to_fat_date
(
int
day
,
int
month
,
int
year
);
void
fatfs_print_sector
(
uint32
sector
,
uint8
*
data
);
#endif
vtoycli/fat_io_lib/release/fat_opts.h
0 → 100644
View file @
b0568922
#ifndef __FAT_OPTS_H__
#define __FAT_OPTS_H__
#ifdef FATFS_USE_CUSTOM_OPTS_FILE
#include "fat_custom.h"
#endif
//-------------------------------------------------------------
// Configuration
//-------------------------------------------------------------
// Is the processor little endian (1) or big endian (0)
#ifndef FATFS_IS_LITTLE_ENDIAN
#define FATFS_IS_LITTLE_ENDIAN 1
#endif
// Max filename Length
#ifndef FATFS_MAX_LONG_FILENAME
#define FATFS_MAX_LONG_FILENAME 260
#endif
// Max open files (reduce to lower memory requirements)
#ifndef FATFS_MAX_OPEN_FILES
#define FATFS_MAX_OPEN_FILES 2
#endif
// Number of sectors per FAT_BUFFER (min 1)
#ifndef FAT_BUFFER_SECTORS
#define FAT_BUFFER_SECTORS 1
#endif
// Max FAT sectors to buffer (min 1)
// (mem used is FAT_BUFFERS * FAT_BUFFER_SECTORS * FAT_SECTOR_SIZE)
#ifndef FAT_BUFFERS
#define FAT_BUFFERS 1
#endif
// Size of cluster chain cache (can be undefined)
// Mem used = FAT_CLUSTER_CACHE_ENTRIES * 4 * 2
// Improves access speed considerably
//#define FAT_CLUSTER_CACHE_ENTRIES 128
// Include support for writing files (1 / 0)?
#ifndef FATFS_INC_WRITE_SUPPORT
#define FATFS_INC_WRITE_SUPPORT 1
#endif
// Support long filenames (1 / 0)?
// (if not (0) only 8.3 format is supported)
#ifndef FATFS_INC_LFN_SUPPORT
#define FATFS_INC_LFN_SUPPORT 1
#endif
// Support directory listing (1 / 0)?
#ifndef FATFS_DIR_LIST_SUPPORT
#define FATFS_DIR_LIST_SUPPORT 1
#endif
// Support time/date (1 / 0)?
#ifndef FATFS_INC_TIME_DATE_SUPPORT
#define FATFS_INC_TIME_DATE_SUPPORT 0
#endif
// Include support for formatting disks (1 / 0)?
#ifndef FATFS_INC_FORMAT_SUPPORT
#define FATFS_INC_FORMAT_SUPPORT 1
#endif
// Sector size used
#define FAT_SECTOR_SIZE 512
// Printf output (directory listing / debug)
#ifndef FAT_PRINTF
// Don't include stdio, but there is a printf function available
#ifdef FAT_PRINTF_NOINC_STDIO
extern
int
printf
(
const
char
*
ctrl1
,
...
);
#define FAT_PRINTF(a) printf a
// Include stdio to use printf
#else
#include <stdio.h>
#define FAT_PRINTF(a) printf a
#endif
#endif
// Time/Date support requires time.h
#if FATFS_INC_TIME_DATE_SUPPORT
#include <time.h>
#endif
#endif
vtoycli/fat_io_lib/release/fat_string.c
0 → 100644
View file @
b0568922
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include <assert.h>
#include "fat_string.h"
//-----------------------------------------------------------------------------
// fatfs_total_path_levels: Take a filename and path and count the sub levels
// of folders. E.g. C:\folder\file.zip = 1 level
// Acceptable input formats are:
// c:\folder\file.zip
// /dev/etc/samba.conf
// Returns: -1 = Error, 0 or more = Ok
//-----------------------------------------------------------------------------
int
fatfs_total_path_levels
(
char
*
path
)
{
int
levels
=
0
;
char
expectedchar
;
if
(
!
path
)
return
-
1
;
// Acceptable formats:
// c:\folder\file.zip
// /dev/etc/samba.conf
if
(
*
path
==
'/'
)
{
expectedchar
=
'/'
;
path
++
;
}
else
if
(
path
[
1
]
==
':'
||
path
[
2
]
==
'\\'
)
{
expectedchar
=
'\\'
;
path
+=
3
;
}
else
return
-
1
;
// Count levels in path string
while
(
*
path
)
{
// Fast forward through actual subdir text to next slash
for
(;
*
path
;
)
{
// If slash detected escape from for loop
if
(
*
path
==
expectedchar
)
{
path
++
;
break
;
}
path
++
;
}
// Increase number of subdirs founds
levels
++
;
}
// Subtract the file itself
return
levels
-
1
;
}
//-----------------------------------------------------------------------------
// fatfs_get_substring: Get a substring from 'path' which contains the folder
// (or file) at the specified level.
// E.g. C:\folder\file.zip : Level 0 = C:\folder, Level 1 = file.zip
// Returns: -1 = Error, 0 = Ok
//-----------------------------------------------------------------------------
int
fatfs_get_substring
(
char
*
path
,
int
levelreq
,
char
*
output
,
int
max_len
)
{
int
i
;
int
pathlen
=
0
;
int
levels
=
0
;
int
copypnt
=
0
;
char
expectedchar
;
if
(
!
path
||
max_len
<=
0
)
return
-
1
;
// Acceptable formats:
// c:\folder\file.zip
// /dev/etc/samba.conf
if
(
*
path
==
'/'
)
{
expectedchar
=
'/'
;
path
++
;
}
else
if
(
path
[
1
]
==
':'
||
path
[
2
]
==
'\\'
)
{
expectedchar
=
'\\'
;
path
+=
3
;
}
else
return
-
1
;
// Get string length of path
pathlen
=
(
int
)
strlen
(
path
);
// Loop through the number of times as characters in 'path'
for
(
i
=
0
;
i
<
pathlen
;
i
++
)
{
// If a '\' is found then increase level
if
(
*
path
==
expectedchar
)
levels
++
;
// If correct level and the character is not a '\' or '/' then copy text to 'output'
if
(
(
levels
==
levelreq
)
&&
(
*
path
!=
expectedchar
)
&&
(
copypnt
<
(
max_len
-
1
)))
output
[
copypnt
++
]
=
*
path
;
// Increment through path string
path
++
;
}
// Null Terminate
output
[
copypnt
]
=
'\0'
;
// If a string was copied return 0 else return 1
if
(
output
[
0
]
!=
'\0'
)
return
0
;
// OK
else
return
-
1
;
// Error
}
//-----------------------------------------------------------------------------
// fatfs_split_path: Full path contains the passed in string.
// Returned is the path string and file Name string
// E.g. C:\folder\file.zip -> path = C:\folder filename = file.zip
// E.g. C:\file.zip -> path = [blank] filename = file.zip
//-----------------------------------------------------------------------------
int
fatfs_split_path
(
char
*
full_path
,
char
*
path
,
int
max_path
,
char
*
filename
,
int
max_filename
)
{
int
strindex
;
// Count the levels to the filepath
int
levels
=
fatfs_total_path_levels
(
full_path
);
if
(
levels
==
-
1
)
return
-
1
;
// Get filename part of string
if
(
fatfs_get_substring
(
full_path
,
levels
,
filename
,
max_filename
)
!=
0
)
return
-
1
;
// If root file
if
(
levels
==
0
)
path
[
0
]
=
'\0'
;
else
{
strindex
=
(
int
)
strlen
(
full_path
)
-
(
int
)
strlen
(
filename
);
if
(
strindex
>
max_path
)
strindex
=
max_path
;
memcpy
(
path
,
full_path
,
strindex
);
path
[
strindex
-
1
]
=
'\0'
;
}
return
0
;
}
//-----------------------------------------------------------------------------
// FileString_StrCmpNoCase: Compare two strings case with case sensitivity
//-----------------------------------------------------------------------------
static
int
FileString_StrCmpNoCase
(
char
*
s1
,
char
*
s2
,
int
n
)
{
int
diff
;
char
a
,
b
;
while
(
n
--
)
{
a
=
*
s1
;
b
=
*
s2
;
// Make lower case if uppercase
if
((
a
>=
'A'
)
&&
(
a
<=
'Z'
))
a
+=
32
;
if
((
b
>=
'A'
)
&&
(
b
<=
'Z'
))
b
+=
32
;
diff
=
a
-
b
;
// If different
if
(
diff
)
return
diff
;
// If run out of strings
if
(
(
*
s1
==
0
)
||
(
*
s2
==
0
)
)
break
;
s1
++
;
s2
++
;
}
return
0
;
}
//-----------------------------------------------------------------------------
// FileString_GetExtension: Get index to extension within filename
// Returns -1 if not found or index otherwise
//-----------------------------------------------------------------------------
static
int
FileString_GetExtension
(
char
*
str
)
{
int
dotPos
=
-
1
;
char
*
strSrc
=
str
;
// Find last '.' in string (if at all)
while
(
*
strSrc
)
{
if
(
*
strSrc
==
'.'
)
dotPos
=
(
int
)(
strSrc
-
str
);
strSrc
++
;
}
return
dotPos
;
}
//-----------------------------------------------------------------------------
// FileString_TrimLength: Get length of string excluding trailing spaces
// Returns -1 if not found or index otherwise
//-----------------------------------------------------------------------------
static
int
FileString_TrimLength
(
char
*
str
,
int
strLen
)
{
int
length
=
strLen
;
char
*
strSrc
=
str
+
strLen
-
1
;
// Find last non white space
while
(
strLen
!=
0
)
{
if
(
*
strSrc
==
' '
)
length
=
(
int
)(
strSrc
-
str
);
else
break
;
strSrc
--
;
strLen
--
;
}
return
length
;
}
//-----------------------------------------------------------------------------
// fatfs_compare_names: Compare two filenames (without copying or changing origonals)
// Returns 1 if match, 0 if not
//-----------------------------------------------------------------------------
int
fatfs_compare_names
(
char
*
strA
,
char
*
strB
)
{
char
*
ext1
=
NULL
;
char
*
ext2
=
NULL
;
int
ext1Pos
,
ext2Pos
;
int
file1Len
,
file2Len
;
// Get both files extension
ext1Pos
=
FileString_GetExtension
(
strA
);
ext2Pos
=
FileString_GetExtension
(
strB
);
// NOTE: Extension position can be different for matching
// filename if trailing space are present before it!
// Check that if one has an extension, so does the other
if
((
ext1Pos
==-
1
)
&&
(
ext2Pos
!=-
1
))
return
0
;
if
((
ext2Pos
==-
1
)
&&
(
ext1Pos
!=-
1
))
return
0
;
// If they both have extensions, compare them
if
(
ext1Pos
!=-
1
)
{
// Set pointer to start of extension
ext1
=
strA
+
ext1Pos
+
1
;
ext2
=
strB
+
ext2Pos
+
1
;
// Verify that the file extension lengths match!
if
(
strlen
(
ext1
)
!=
strlen
(
ext2
))
return
0
;
// If they dont match
if
(
FileString_StrCmpNoCase
(
ext1
,
ext2
,
(
int
)
strlen
(
ext1
))
!=
0
)
return
0
;
// Filelength is upto extensions
file1Len
=
ext1Pos
;
file2Len
=
ext2Pos
;
}
// No extensions
else
{
// Filelength is actual filelength
file1Len
=
(
int
)
strlen
(
strA
);
file2Len
=
(
int
)
strlen
(
strB
);
}
// Find length without trailing spaces (before ext)
file1Len
=
FileString_TrimLength
(
strA
,
file1Len
);
file2Len
=
FileString_TrimLength
(
strB
,
file2Len
);
// Check the file lengths match
if
(
file1Len
!=
file2Len
)
return
0
;
// Compare main part of filenames
if
(
FileString_StrCmpNoCase
(
strA
,
strB
,
file1Len
)
!=
0
)
return
0
;
else
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_string_ends_with_slash: Does the string end with a slash (\ or /)
//-----------------------------------------------------------------------------
int
fatfs_string_ends_with_slash
(
char
*
path
)
{
if
(
path
)
{
while
(
*
path
)
{
// Last character?
if
(
!
(
*
(
path
+
1
)))
{
if
(
*
path
==
'\\'
||
*
path
==
'/'
)
return
1
;
}
path
++
;
}
}
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_get_sfn_display_name: Get display name for SFN entry
//-----------------------------------------------------------------------------
int
fatfs_get_sfn_display_name
(
char
*
out
,
char
*
in
)
{
int
len
=
0
;
while
(
*
in
&&
len
<=
11
)
{
char
a
=
*
in
++
;
if
(
a
==
' '
)
continue
;
// Make lower case if uppercase
else
if
((
a
>=
'A'
)
&&
(
a
<=
'Z'
))
a
+=
32
;
*
out
++
=
a
;
len
++
;
}
*
out
=
'\0'
;
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_get_extension: Get extension of filename passed in 'filename'.
// Returned extension is always lower case.
// Returns: 1 if ok, 0 if not.
//-----------------------------------------------------------------------------
int
fatfs_get_extension
(
char
*
filename
,
char
*
out
,
int
maxlen
)
{
int
len
=
0
;
// Get files extension offset
int
ext_pos
=
FileString_GetExtension
(
filename
);
if
(
ext_pos
>
0
&&
out
&&
maxlen
)
{
filename
+=
ext_pos
+
1
;
while
(
*
filename
&&
len
<
(
maxlen
-
1
))
{
char
a
=
*
filename
++
;
// Make lowercase if uppercase
if
((
a
>=
'A'
)
&&
(
a
<=
'Z'
))
a
+=
32
;
*
out
++
=
a
;
len
++
;
}
*
out
=
'\0'
;
return
1
;
}
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_create_path_string: Append path & filename to create file path string.
// Returns: 1 if ok, 0 if not.
//-----------------------------------------------------------------------------
int
fatfs_create_path_string
(
char
*
path
,
char
*
filename
,
char
*
out
,
int
maxlen
)
{
int
len
=
0
;
char
last
=
0
;
char
seperator
=
'/'
;
if
(
path
&&
filename
&&
out
&&
maxlen
>
0
)
{
while
(
*
path
&&
len
<
(
maxlen
-
2
))
{
last
=
*
path
++
;
if
(
last
==
'\\'
)
seperator
=
'\\'
;
*
out
++
=
last
;
len
++
;
}
// Add a seperator if trailing one not found
if
(
last
!=
'\\'
&&
last
!=
'/'
)
*
out
++
=
seperator
;
while
(
*
filename
&&
len
<
(
maxlen
-
1
))
{
*
out
++
=
*
filename
++
;
len
++
;
}
*
out
=
'\0'
;
return
1
;
}
return
0
;
}
//-----------------------------------------------------------------------------
// Test Bench
//-----------------------------------------------------------------------------
#ifdef FAT_STRING_TESTBENCH
void
main
(
void
)
{
char
output
[
255
];
char
output2
[
255
];
assert
(
fatfs_total_path_levels
(
"C:
\\
folder
\\
file.zip"
)
==
1
);
assert
(
fatfs_total_path_levels
(
"C:
\\
file.zip"
)
==
0
);
assert
(
fatfs_total_path_levels
(
"C:
\\
folder
\\
folder2
\\
file.zip"
)
==
2
);
assert
(
fatfs_total_path_levels
(
"C:
\\
"
)
==
-
1
);
assert
(
fatfs_total_path_levels
(
""
)
==
-
1
);
assert
(
fatfs_total_path_levels
(
"/dev/etc/file.zip"
)
==
2
);
assert
(
fatfs_total_path_levels
(
"/dev/file.zip"
)
==
1
);
assert
(
fatfs_get_substring
(
"C:
\\
folder
\\
file.zip"
,
0
,
output
,
sizeof
(
output
))
==
0
);
assert
(
strcmp
(
output
,
"folder"
)
==
0
);
assert
(
fatfs_get_substring
(
"C:
\\
folder
\\
file.zip"
,
1
,
output
,
sizeof
(
output
))
==
0
);
assert
(
strcmp
(
output
,
"file.zip"
)
==
0
);
assert
(
fatfs_get_substring
(
"/dev/etc/file.zip"
,
0
,
output
,
sizeof
(
output
))
==
0
);
assert
(
strcmp
(
output
,
"dev"
)
==
0
);
assert
(
fatfs_get_substring
(
"/dev/etc/file.zip"
,
1
,
output
,
sizeof
(
output
))
==
0
);
assert
(
strcmp
(
output
,
"etc"
)
==
0
);
assert
(
fatfs_get_substring
(
"/dev/etc/file.zip"
,
2
,
output
,
sizeof
(
output
))
==
0
);
assert
(
strcmp
(
output
,
"file.zip"
)
==
0
);
assert
(
fatfs_split_path
(
"C:
\\
folder
\\
file.zip"
,
output
,
sizeof
(
output
),
output2
,
sizeof
(
output2
))
==
0
);
assert
(
strcmp
(
output
,
"C:
\\
folder"
)
==
0
);
assert
(
strcmp
(
output2
,
"file.zip"
)
==
0
);
assert
(
fatfs_split_path
(
"C:
\\
file.zip"
,
output
,
sizeof
(
output
),
output2
,
sizeof
(
output2
))
==
0
);
assert
(
output
[
0
]
==
0
);
assert
(
strcmp
(
output2
,
"file.zip"
)
==
0
);
assert
(
fatfs_split_path
(
"/dev/etc/file.zip"
,
output
,
sizeof
(
output
),
output2
,
sizeof
(
output2
))
==
0
);
assert
(
strcmp
(
output
,
"/dev/etc"
)
==
0
);
assert
(
strcmp
(
output2
,
"file.zip"
)
==
0
);
assert
(
FileString_GetExtension
(
"C:
\\
file.zip"
)
==
strlen
(
"C:
\\
file"
));
assert
(
FileString_GetExtension
(
"C:
\\
file.zip.ext"
)
==
strlen
(
"C:
\\
file.zip"
));
assert
(
FileString_GetExtension
(
"C:
\\
file.zip."
)
==
strlen
(
"C:
\\
file.zip"
));
assert
(
FileString_TrimLength
(
"C:
\\
file.zip"
,
strlen
(
"C:
\\
file.zip"
))
==
strlen
(
"C:
\\
file.zip"
));
assert
(
FileString_TrimLength
(
"C:
\\
file.zip "
,
strlen
(
"C:
\\
file.zip "
))
==
strlen
(
"C:
\\
file.zip"
));
assert
(
FileString_TrimLength
(
" "
,
strlen
(
" "
))
==
0
);
assert
(
fatfs_compare_names
(
"C:
\\
file.ext"
,
"C:
\\
file.ext"
)
==
1
);
assert
(
fatfs_compare_names
(
"C:
\\
file2.ext"
,
"C:
\\
file.ext"
)
==
0
);
assert
(
fatfs_compare_names
(
"C:
\\
file .ext"
,
"C:
\\
file.ext"
)
==
1
);
assert
(
fatfs_compare_names
(
"C:
\\
file .ext"
,
"C:
\\
file2.ext"
)
==
0
);
assert
(
fatfs_string_ends_with_slash
(
"C:
\\
folder"
)
==
0
);
assert
(
fatfs_string_ends_with_slash
(
"C:
\\
folder
\\
"
)
==
1
);
assert
(
fatfs_string_ends_with_slash
(
"/path"
)
==
0
);
assert
(
fatfs_string_ends_with_slash
(
"/path/a"
)
==
0
);
assert
(
fatfs_string_ends_with_slash
(
"/path/"
)
==
1
);
assert
(
fatfs_get_extension
(
"/mypath/file.wav"
,
output
,
4
)
==
1
);
assert
(
strcmp
(
output
,
"wav"
)
==
0
);
assert
(
fatfs_get_extension
(
"/mypath/file.WAV"
,
output
,
4
)
==
1
);
assert
(
strcmp
(
output
,
"wav"
)
==
0
);
assert
(
fatfs_get_extension
(
"/mypath/file.zip"
,
output
,
4
)
==
1
);
assert
(
strcmp
(
output
,
"ext"
)
!=
0
);
assert
(
fatfs_create_path_string
(
"/mydir1"
,
"myfile.txt"
,
output
,
sizeof
(
output
))
==
1
);
assert
(
strcmp
(
output
,
"/mydir1/myfile.txt"
)
==
0
);
assert
(
fatfs_create_path_string
(
"/mydir2/"
,
"myfile2.txt"
,
output
,
sizeof
(
output
))
==
1
);
assert
(
strcmp
(
output
,
"/mydir2/myfile2.txt"
)
==
0
);
assert
(
fatfs_create_path_string
(
"C:
\\
mydir3"
,
"myfile3.txt"
,
output
,
sizeof
(
output
))
==
1
);
assert
(
strcmp
(
output
,
"C:
\\
mydir3
\\
myfile3.txt"
)
==
0
);
}
#endif
vtoycli/fat_io_lib/release/fat_string.h
0 → 100644
View file @
b0568922
#ifndef __FILESTRING_H__
#define __FILESTRING_H__
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
int
fatfs_total_path_levels
(
char
*
path
);
int
fatfs_get_substring
(
char
*
Path
,
int
levelreq
,
char
*
output
,
int
max_len
);
int
fatfs_split_path
(
char
*
FullPath
,
char
*
Path
,
int
max_path
,
char
*
FileName
,
int
max_filename
);
int
fatfs_compare_names
(
char
*
strA
,
char
*
strB
);
int
fatfs_string_ends_with_slash
(
char
*
path
);
int
fatfs_get_sfn_display_name
(
char
*
out
,
char
*
in
);
int
fatfs_get_extension
(
char
*
filename
,
char
*
out
,
int
maxlen
);
int
fatfs_create_path_string
(
char
*
path
,
char
*
filename
,
char
*
out
,
int
maxlen
);
#ifndef NULL
#define NULL 0
#endif
#endif
vtoycli/fat_io_lib/release/fat_table.c
0 → 100644
View file @
b0568922
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include "fat_defs.h"
#include "fat_access.h"
#include "fat_table.h"
#ifndef FAT_BUFFERS
#define FAT_BUFFERS 1
#endif
#ifndef FAT_BUFFER_SECTORS
#define FAT_BUFFER_SECTORS 1
#endif
#if FAT_BUFFERS < 1 || FAT_BUFFER_SECTORS < 1
#error "FAT_BUFFERS & FAT_BUFFER_SECTORS must be at least 1"
#endif
//-----------------------------------------------------------------------------
// FAT Sector Buffer
//-----------------------------------------------------------------------------
#define FAT32_GET_32BIT_WORD(pbuf, location) ( GET_32BIT_WORD(pbuf->ptr, location) )
#define FAT32_SET_32BIT_WORD(pbuf, location, value) { SET_32BIT_WORD(pbuf->ptr, location, value); pbuf->dirty = 1; }
#define FAT16_GET_16BIT_WORD(pbuf, location) ( GET_16BIT_WORD(pbuf->ptr, location) )
#define FAT16_SET_16BIT_WORD(pbuf, location, value) { SET_16BIT_WORD(pbuf->ptr, location, value); pbuf->dirty = 1; }
//-----------------------------------------------------------------------------
// fatfs_fat_init:
//-----------------------------------------------------------------------------
void
fatfs_fat_init
(
struct
fatfs
*
fs
)
{
int
i
;
// FAT buffer chain head
fs
->
fat_buffer_head
=
NULL
;
for
(
i
=
0
;
i
<
FAT_BUFFERS
;
i
++
)
{
// Initialise buffers to invalid
fs
->
fat_buffers
[
i
].
address
=
FAT32_INVALID_CLUSTER
;
fs
->
fat_buffers
[
i
].
dirty
=
0
;
memset
(
fs
->
fat_buffers
[
i
].
sector
,
0x00
,
sizeof
(
fs
->
fat_buffers
[
i
].
sector
));
fs
->
fat_buffers
[
i
].
ptr
=
NULL
;
// Add to head of queue
fs
->
fat_buffers
[
i
].
next
=
fs
->
fat_buffer_head
;
fs
->
fat_buffer_head
=
&
fs
->
fat_buffers
[
i
];
}
}
//-----------------------------------------------------------------------------
// fatfs_fat_writeback: Writeback 'dirty' FAT sectors to disk
//-----------------------------------------------------------------------------
static
int
fatfs_fat_writeback
(
struct
fatfs
*
fs
,
struct
fat_buffer
*
pcur
)
{
if
(
pcur
)
{
// Writeback sector if changed
if
(
pcur
->
dirty
)
{
if
(
fs
->
disk_io
.
write_media
)
{
uint32
sectors
=
FAT_BUFFER_SECTORS
;
uint32
offset
=
pcur
->
address
-
fs
->
fat_begin_lba
;
// Limit to sectors used for the FAT
if
((
offset
+
FAT_BUFFER_SECTORS
)
<=
fs
->
fat_sectors
)
sectors
=
FAT_BUFFER_SECTORS
;
else
sectors
=
fs
->
fat_sectors
-
offset
;
if
(
!
fs
->
disk_io
.
write_media
(
pcur
->
address
,
pcur
->
sector
,
sectors
))
return
0
;
}
pcur
->
dirty
=
0
;
}
return
1
;
}
else
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_fat_read_sector: Read a FAT sector
//-----------------------------------------------------------------------------
static
struct
fat_buffer
*
fatfs_fat_read_sector
(
struct
fatfs
*
fs
,
uint32
sector
)
{
struct
fat_buffer
*
last
=
NULL
;
struct
fat_buffer
*
pcur
=
fs
->
fat_buffer_head
;
// Itterate through sector buffer list
while
(
pcur
)
{
// Sector within this buffer?
if
((
sector
>=
pcur
->
address
)
&&
(
sector
<
(
pcur
->
address
+
FAT_BUFFER_SECTORS
)))
break
;
// End of list?
if
(
pcur
->
next
==
NULL
)
{
// Remove buffer from list
if
(
last
)
last
->
next
=
NULL
;
// We the first and last buffer in the chain?
else
fs
->
fat_buffer_head
=
NULL
;
}
last
=
pcur
;
pcur
=
pcur
->
next
;
}
// We found the sector already in FAT buffer chain
if
(
pcur
)
{
pcur
->
ptr
=
(
uint8
*
)(
pcur
->
sector
+
((
sector
-
pcur
->
address
)
*
FAT_SECTOR_SIZE
));
return
pcur
;
}
// Else, we removed the last item from the list
pcur
=
last
;
// Add to start of sector buffer list (now newest sector)
pcur
->
next
=
fs
->
fat_buffer_head
;
fs
->
fat_buffer_head
=
pcur
;
// Writeback sector if changed
if
(
pcur
->
dirty
)
if
(
!
fatfs_fat_writeback
(
fs
,
pcur
))
return
0
;
// Address is now new sector
pcur
->
address
=
sector
;
// Read next sector
if
(
!
fs
->
disk_io
.
read_media
(
pcur
->
address
,
pcur
->
sector
,
FAT_BUFFER_SECTORS
))
{
// Read failed, invalidate buffer address
pcur
->
address
=
FAT32_INVALID_CLUSTER
;
return
NULL
;
}
pcur
->
ptr
=
pcur
->
sector
;
return
pcur
;
}
//-----------------------------------------------------------------------------
// fatfs_fat_purge: Purge 'dirty' FAT sectors to disk
//-----------------------------------------------------------------------------
int
fatfs_fat_purge
(
struct
fatfs
*
fs
)
{
struct
fat_buffer
*
pcur
=
fs
->
fat_buffer_head
;
// Itterate through sector buffer list
while
(
pcur
)
{
// Writeback sector if changed
if
(
pcur
->
dirty
)
if
(
!
fatfs_fat_writeback
(
fs
,
pcur
))
return
0
;
pcur
=
pcur
->
next
;
}
return
1
;
}
//-----------------------------------------------------------------------------
// General FAT Table Operations
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// fatfs_find_next_cluster: Return cluster number of next cluster in chain by
// reading FAT table and traversing it. Return 0xffffffff for end of chain.
//-----------------------------------------------------------------------------
uint32
fatfs_find_next_cluster
(
struct
fatfs
*
fs
,
uint32
current_cluster
)
{
uint32
fat_sector_offset
,
position
;
uint32
nextcluster
;
struct
fat_buffer
*
pbuf
;
// Why is '..' labelled with cluster 0 when it should be 2 ??
if
(
current_cluster
==
0
)
current_cluster
=
2
;
// Find which sector of FAT table to read
if
(
fs
->
fat_type
==
FAT_TYPE_16
)
fat_sector_offset
=
current_cluster
/
256
;
else
fat_sector_offset
=
current_cluster
/
128
;
// Read FAT sector into buffer
pbuf
=
fatfs_fat_read_sector
(
fs
,
fs
->
fat_begin_lba
+
fat_sector_offset
);
if
(
!
pbuf
)
return
(
FAT32_LAST_CLUSTER
);
if
(
fs
->
fat_type
==
FAT_TYPE_16
)
{
// Find 32 bit entry of current sector relating to cluster number
position
=
(
current_cluster
-
(
fat_sector_offset
*
256
))
*
2
;
// Read Next Clusters value from Sector Buffer
nextcluster
=
FAT16_GET_16BIT_WORD
(
pbuf
,
(
uint16
)
position
);
// If end of chain found
if
(
nextcluster
>=
0xFFF8
&&
nextcluster
<=
0xFFFF
)
return
(
FAT32_LAST_CLUSTER
);
}
else
{
// Find 32 bit entry of current sector relating to cluster number
position
=
(
current_cluster
-
(
fat_sector_offset
*
128
))
*
4
;
// Read Next Clusters value from Sector Buffer
nextcluster
=
FAT32_GET_32BIT_WORD
(
pbuf
,
(
uint16
)
position
);
// Mask out MS 4 bits (its 28bit addressing)
nextcluster
=
nextcluster
&
0x0FFFFFFF
;
// If end of chain found
if
(
nextcluster
>=
0x0FFFFFF8
&&
nextcluster
<=
0x0FFFFFFF
)
return
(
FAT32_LAST_CLUSTER
);
}
// Else return next cluster
return
(
nextcluster
);
}
//-----------------------------------------------------------------------------
// fatfs_set_fs_info_next_free_cluster: Write the next free cluster to the FSINFO table
//-----------------------------------------------------------------------------
void
fatfs_set_fs_info_next_free_cluster
(
struct
fatfs
*
fs
,
uint32
newValue
)
{
if
(
fs
->
fat_type
==
FAT_TYPE_16
)
;
else
{
// Load sector to change it
struct
fat_buffer
*
pbuf
=
fatfs_fat_read_sector
(
fs
,
fs
->
lba_begin
+
fs
->
fs_info_sector
);
if
(
!
pbuf
)
return
;
// Change
FAT32_SET_32BIT_WORD
(
pbuf
,
492
,
newValue
);
fs
->
next_free_cluster
=
newValue
;
// Write back FSINFO sector to disk
if
(
fs
->
disk_io
.
write_media
)
fs
->
disk_io
.
write_media
(
pbuf
->
address
,
pbuf
->
sector
,
1
);
// Invalidate cache entry
pbuf
->
address
=
FAT32_INVALID_CLUSTER
;
pbuf
->
dirty
=
0
;
}
}
//-----------------------------------------------------------------------------
// fatfs_find_blank_cluster: Find a free cluster entry by reading the FAT
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_find_blank_cluster
(
struct
fatfs
*
fs
,
uint32
start_cluster
,
uint32
*
free_cluster
)
{
uint32
fat_sector_offset
,
position
;
uint32
nextcluster
;
uint32
current_cluster
=
start_cluster
;
struct
fat_buffer
*
pbuf
;
do
{
// Find which sector of FAT table to read
if
(
fs
->
fat_type
==
FAT_TYPE_16
)
fat_sector_offset
=
current_cluster
/
256
;
else
fat_sector_offset
=
current_cluster
/
128
;
if
(
fat_sector_offset
<
fs
->
fat_sectors
)
{
// Read FAT sector into buffer
pbuf
=
fatfs_fat_read_sector
(
fs
,
fs
->
fat_begin_lba
+
fat_sector_offset
);
if
(
!
pbuf
)
return
0
;
if
(
fs
->
fat_type
==
FAT_TYPE_16
)
{
// Find 32 bit entry of current sector relating to cluster number
position
=
(
current_cluster
-
(
fat_sector_offset
*
256
))
*
2
;
// Read Next Clusters value from Sector Buffer
nextcluster
=
FAT16_GET_16BIT_WORD
(
pbuf
,
(
uint16
)
position
);
}
else
{
// Find 32 bit entry of current sector relating to cluster number
position
=
(
current_cluster
-
(
fat_sector_offset
*
128
))
*
4
;
// Read Next Clusters value from Sector Buffer
nextcluster
=
FAT32_GET_32BIT_WORD
(
pbuf
,
(
uint16
)
position
);
// Mask out MS 4 bits (its 28bit addressing)
nextcluster
=
nextcluster
&
0x0FFFFFFF
;
}
if
(
nextcluster
!=
0
)
current_cluster
++
;
}
else
// Otherwise, run out of FAT sectors to check...
return
0
;
}
while
(
nextcluster
!=
0x0
);
// Found blank entry
*
free_cluster
=
current_cluster
;
return
1
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_fat_set_cluster: Set a cluster link in the chain. NOTE: Immediate
// write (slow).
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_fat_set_cluster
(
struct
fatfs
*
fs
,
uint32
cluster
,
uint32
next_cluster
)
{
struct
fat_buffer
*
pbuf
;
uint32
fat_sector_offset
,
position
;
// Find which sector of FAT table to read
if
(
fs
->
fat_type
==
FAT_TYPE_16
)
fat_sector_offset
=
cluster
/
256
;
else
fat_sector_offset
=
cluster
/
128
;
// Read FAT sector into buffer
pbuf
=
fatfs_fat_read_sector
(
fs
,
fs
->
fat_begin_lba
+
fat_sector_offset
);
if
(
!
pbuf
)
return
0
;
if
(
fs
->
fat_type
==
FAT_TYPE_16
)
{
// Find 16 bit entry of current sector relating to cluster number
position
=
(
cluster
-
(
fat_sector_offset
*
256
))
*
2
;
// Write Next Clusters value to Sector Buffer
FAT16_SET_16BIT_WORD
(
pbuf
,
(
uint16
)
position
,
((
uint16
)
next_cluster
));
}
else
{
// Find 32 bit entry of current sector relating to cluster number
position
=
(
cluster
-
(
fat_sector_offset
*
128
))
*
4
;
// Write Next Clusters value to Sector Buffer
FAT32_SET_32BIT_WORD
(
pbuf
,
(
uint16
)
position
,
next_cluster
);
}
return
1
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_free_cluster_chain: Follow a chain marking each element as free
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_free_cluster_chain
(
struct
fatfs
*
fs
,
uint32
start_cluster
)
{
uint32
last_cluster
;
uint32
next_cluster
=
start_cluster
;
// Loop until end of chain
while
(
(
next_cluster
!=
FAT32_LAST_CLUSTER
)
&&
(
next_cluster
!=
0x00000000
)
)
{
last_cluster
=
next_cluster
;
// Find next link
next_cluster
=
fatfs_find_next_cluster
(
fs
,
next_cluster
);
// Clear last link
fatfs_fat_set_cluster
(
fs
,
last_cluster
,
0x00000000
);
}
return
1
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_fat_add_cluster_to_chain: Follow a chain marking and then add a new entry
// to the current tail.
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_fat_add_cluster_to_chain
(
struct
fatfs
*
fs
,
uint32
start_cluster
,
uint32
newEntry
)
{
uint32
last_cluster
=
FAT32_LAST_CLUSTER
;
uint32
next_cluster
=
start_cluster
;
if
(
start_cluster
==
FAT32_LAST_CLUSTER
)
return
0
;
// Loop until end of chain
while
(
next_cluster
!=
FAT32_LAST_CLUSTER
)
{
last_cluster
=
next_cluster
;
// Find next link
next_cluster
=
fatfs_find_next_cluster
(
fs
,
next_cluster
);
if
(
!
next_cluster
)
return
0
;
}
// Add link in for new cluster
fatfs_fat_set_cluster
(
fs
,
last_cluster
,
newEntry
);
// Mark new cluster as end of chain
fatfs_fat_set_cluster
(
fs
,
newEntry
,
FAT32_LAST_CLUSTER
);
return
1
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_count_free_clusters:
//-----------------------------------------------------------------------------
uint32
fatfs_count_free_clusters
(
struct
fatfs
*
fs
)
{
uint32
i
,
j
;
uint32
count
=
0
;
struct
fat_buffer
*
pbuf
;
for
(
i
=
0
;
i
<
fs
->
fat_sectors
;
i
++
)
{
// Read FAT sector into buffer
pbuf
=
fatfs_fat_read_sector
(
fs
,
fs
->
fat_begin_lba
+
i
);
if
(
!
pbuf
)
break
;
for
(
j
=
0
;
j
<
FAT_SECTOR_SIZE
;
)
{
if
(
fs
->
fat_type
==
FAT_TYPE_16
)
{
if
(
FAT16_GET_16BIT_WORD
(
pbuf
,
(
uint16
)
j
)
==
0
)
count
++
;
j
+=
2
;
}
else
{
if
(
FAT32_GET_32BIT_WORD
(
pbuf
,
(
uint16
)
j
)
==
0
)
count
++
;
j
+=
4
;
}
}
}
return
count
;
}
vtoycli/fat_io_lib/release/fat_table.h
0 → 100644
View file @
b0568922
#ifndef __FAT_TABLE_H__
#define __FAT_TABLE_H__
#include "fat_opts.h"
#include "fat_misc.h"
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
void
fatfs_fat_init
(
struct
fatfs
*
fs
);
int
fatfs_fat_purge
(
struct
fatfs
*
fs
);
uint32
fatfs_find_next_cluster
(
struct
fatfs
*
fs
,
uint32
current_cluster
);
void
fatfs_set_fs_info_next_free_cluster
(
struct
fatfs
*
fs
,
uint32
newValue
);
int
fatfs_find_blank_cluster
(
struct
fatfs
*
fs
,
uint32
start_cluster
,
uint32
*
free_cluster
);
int
fatfs_fat_set_cluster
(
struct
fatfs
*
fs
,
uint32
cluster
,
uint32
next_cluster
);
int
fatfs_fat_add_cluster_to_chain
(
struct
fatfs
*
fs
,
uint32
start_cluster
,
uint32
newEntry
);
int
fatfs_free_cluster_chain
(
struct
fatfs
*
fs
,
uint32
start_cluster
);
uint32
fatfs_count_free_clusters
(
struct
fatfs
*
fs
);
#endif
vtoycli/fat_io_lib/release/fat_types.h
0 → 100644
View file @
b0568922
#ifndef __FAT_TYPES_H__
#define __FAT_TYPES_H__
// Detect 64-bit compilation on GCC
#if defined(__GNUC__) && defined(__SIZEOF_LONG__)
#if __SIZEOF_LONG__ == 8
#define FATFS_DEF_UINT32_AS_INT
#endif
#endif
//-------------------------------------------------------------
// System specific types
//-------------------------------------------------------------
#ifndef FATFS_NO_DEF_TYPES
typedef
unsigned
char
uint8
;
typedef
unsigned
short
uint16
;
// If compiling on a 64-bit machine, use int as 32-bits
#ifdef FATFS_DEF_UINT32_AS_INT
typedef
unsigned
int
uint32
;
// Else for 32-bit machines & embedded systems, use long...
#else
typedef
unsigned
long
uint32
;
#endif
#endif
#ifndef NULL
#define NULL 0
#endif
//-------------------------------------------------------------
// Endian Macros
//-------------------------------------------------------------
// FAT is little endian so big endian systems need to swap words
// Little Endian - No swap required
#if FATFS_IS_LITTLE_ENDIAN == 1
#define FAT_HTONS(n) (n)
#define FAT_HTONL(n) (n)
// Big Endian - Swap required
#else
#define FAT_HTONS(n) ((((uint16)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))
#define FAT_HTONL(n) (((((uint32)(n) & 0xFF)) << 24) | \
((((uint32)(n) & 0xFF00)) << 8) | \
((((uint32)(n) & 0xFF0000)) >> 8) | \
((((uint32)(n) & 0xFF000000)) >> 24))
#endif
//-------------------------------------------------------------
// Structure Packing Compile Options
//-------------------------------------------------------------
#ifdef __GNUC__
#define STRUCT_PACK
#define STRUCT_PACK_BEGIN
#define STRUCT_PACK_END
#define STRUCT_PACKED __attribute__ ((packed))
#else
// Other compilers may require other methods of packing structures
#define STRUCT_PACK
#define STRUCT_PACK_BEGIN
#define STRUCT_PACK_END
#define STRUCT_PACKED
#endif
#endif
vtoycli/fat_io_lib/release/fat_write.c
0 → 100644
View file @
b0568922
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include "fat_defs.h"
#include "fat_access.h"
#include "fat_table.h"
#include "fat_write.h"
#include "fat_string.h"
#include "fat_misc.h"
#if FATFS_INC_WRITE_SUPPORT
//-----------------------------------------------------------------------------
// fatfs_add_free_space: Allocate another cluster of free space to the end
// of a files cluster chain.
//-----------------------------------------------------------------------------
int
fatfs_add_free_space
(
struct
fatfs
*
fs
,
uint32
*
startCluster
,
uint32
clusters
)
{
uint32
i
;
uint32
nextcluster
;
uint32
start
=
*
startCluster
;
// Set the next free cluster hint to unknown
if
(
fs
->
next_free_cluster
!=
FAT32_LAST_CLUSTER
)
fatfs_set_fs_info_next_free_cluster
(
fs
,
FAT32_LAST_CLUSTER
);
for
(
i
=
0
;
i
<
clusters
;
i
++
)
{
// Start looking for free clusters from the beginning
if
(
fatfs_find_blank_cluster
(
fs
,
fs
->
rootdir_first_cluster
,
&
nextcluster
))
{
// Point last to this
fatfs_fat_set_cluster
(
fs
,
start
,
nextcluster
);
// Point this to end of file
fatfs_fat_set_cluster
(
fs
,
nextcluster
,
FAT32_LAST_CLUSTER
);
// Adjust argument reference
start
=
nextcluster
;
if
(
i
==
0
)
*
startCluster
=
nextcluster
;
}
else
return
0
;
}
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_allocate_free_space: Add an ammount of free space to a file either from
// 'startCluster' if newFile = false, or allocating a new start to the chain if
// newFile = true.
//-----------------------------------------------------------------------------
int
fatfs_allocate_free_space
(
struct
fatfs
*
fs
,
int
newFile
,
uint32
*
startCluster
,
uint32
size
)
{
uint32
clusterSize
;
uint32
clusterCount
;
uint32
nextcluster
;
if
(
size
==
0
)
return
0
;
// Set the next free cluster hint to unknown
if
(
fs
->
next_free_cluster
!=
FAT32_LAST_CLUSTER
)
fatfs_set_fs_info_next_free_cluster
(
fs
,
FAT32_LAST_CLUSTER
);
// Work out size and clusters
clusterSize
=
fs
->
sectors_per_cluster
*
FAT_SECTOR_SIZE
;
clusterCount
=
(
size
/
clusterSize
);
// If any left over
if
(
size
-
(
clusterSize
*
clusterCount
))
clusterCount
++
;
// Allocated first link in the chain if a new file
if
(
newFile
)
{
if
(
!
fatfs_find_blank_cluster
(
fs
,
fs
->
rootdir_first_cluster
,
&
nextcluster
))
return
0
;
// If this is all that is needed then all done
if
(
clusterCount
==
1
)
{
fatfs_fat_set_cluster
(
fs
,
nextcluster
,
FAT32_LAST_CLUSTER
);
*
startCluster
=
nextcluster
;
return
1
;
}
}
// Allocate from end of current chain (startCluster is end of chain)
else
nextcluster
=
*
startCluster
;
if
(
!
fatfs_add_free_space
(
fs
,
&
nextcluster
,
clusterCount
))
return
0
;
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_find_free_dir_offset: Find a free space in the directory for a new entry
// which takes up 'entryCount' blocks (or allocate some more)
//-----------------------------------------------------------------------------
static
int
fatfs_find_free_dir_offset
(
struct
fatfs
*
fs
,
uint32
dirCluster
,
int
entryCount
,
uint32
*
pSector
,
uint8
*
pOffset
)
{
struct
fat_dir_entry
*
directoryEntry
;
uint8
item
=
0
;
uint16
recordoffset
=
0
;
uint8
i
=
0
;
int
x
=
0
;
int
possible_spaces
=
0
;
int
start_recorded
=
0
;
// No entries required?
if
(
entryCount
==
0
)
return
0
;
// Main cluster following loop
while
(
1
)
{
// Read sector
if
(
fatfs_sector_reader
(
fs
,
dirCluster
,
x
++
,
0
))
{
// Analyse Sector
for
(
item
=
0
;
item
<
FAT_DIR_ENTRIES_PER_SECTOR
;
item
++
)
{
// Create the multiplier for sector access
recordoffset
=
FAT_DIR_ENTRY_SIZE
*
item
;
// Overlay directory entry over buffer
directoryEntry
=
(
struct
fat_dir_entry
*
)(
fs
->
currentsector
.
sector
+
recordoffset
);
// LFN Entry
if
(
fatfs_entry_lfn_text
(
directoryEntry
))
{
// First entry?
if
(
possible_spaces
==
0
)
{
// Store start
*
pSector
=
x
-
1
;
*
pOffset
=
item
;
start_recorded
=
1
;
}
// Increment the count in-case the file turns
// out to be deleted...
possible_spaces
++
;
}
// SFN Entry
else
{
// Has file been deleted?
if
(
fs
->
currentsector
.
sector
[
recordoffset
]
==
FILE_HEADER_DELETED
)
{
// First entry?
if
(
possible_spaces
==
0
)
{
// Store start
*
pSector
=
x
-
1
;
*
pOffset
=
item
;
start_recorded
=
1
;
}
possible_spaces
++
;
// We have found enough space?
if
(
possible_spaces
>=
entryCount
)
return
1
;
// Else continue counting until we find a valid entry!
}
// Is the file entry empty?
else
if
(
fs
->
currentsector
.
sector
[
recordoffset
]
==
FILE_HEADER_BLANK
)
{
// First entry?
if
(
possible_spaces
==
0
)
{
// Store start
*
pSector
=
x
-
1
;
*
pOffset
=
item
;
start_recorded
=
1
;
}
// Increment the blank entries count
possible_spaces
++
;
// We have found enough space?
if
(
possible_spaces
>=
entryCount
)
return
1
;
}
// File entry is valid
else
{
// Reset all flags
possible_spaces
=
0
;
start_recorded
=
0
;
}
}
}
// End of for
}
// End of if
// Run out of free space in the directory, allocate some more
else
{
uint32
newCluster
;
// Get a new cluster for directory
if
(
!
fatfs_find_blank_cluster
(
fs
,
fs
->
rootdir_first_cluster
,
&
newCluster
))
return
0
;
// Add cluster to end of directory tree
if
(
!
fatfs_fat_add_cluster_to_chain
(
fs
,
dirCluster
,
newCluster
))
return
0
;
// Erase new directory cluster
memset
(
fs
->
currentsector
.
sector
,
0x00
,
FAT_SECTOR_SIZE
);
for
(
i
=
0
;
i
<
fs
->
sectors_per_cluster
;
i
++
)
{
if
(
!
fatfs_write_sector
(
fs
,
newCluster
,
i
,
0
))
return
0
;
}
// If non of the name fitted on previous sectors
if
(
!
start_recorded
)
{
// Store start
*
pSector
=
(
x
-
1
);
*
pOffset
=
0
;
start_recorded
=
1
;
}
return
1
;
}
}
// End of while loop
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_add_file_entry: Add a directory entry to a location found by FindFreeOffset
//-----------------------------------------------------------------------------
int
fatfs_add_file_entry
(
struct
fatfs
*
fs
,
uint32
dirCluster
,
char
*
filename
,
char
*
shortfilename
,
uint32
startCluster
,
uint32
size
,
int
dir
)
{
uint8
item
=
0
;
uint16
recordoffset
=
0
;
uint8
i
=
0
;
uint32
x
=
0
;
int
entryCount
;
struct
fat_dir_entry
shortEntry
;
int
dirtySector
=
0
;
uint32
dirSector
=
0
;
uint8
dirOffset
=
0
;
int
foundEnd
=
0
;
uint8
checksum
;
uint8
*
pSname
;
// No write access?
if
(
!
fs
->
disk_io
.
write_media
)
return
0
;
#if FATFS_INC_LFN_SUPPORT
// How many LFN entries are required?
// NOTE: We always request one LFN even if it would fit in a SFN!
entryCount
=
fatfs_lfn_entries_required
(
filename
);
if
(
!
entryCount
)
return
0
;
#else
entryCount
=
0
;
#endif
// Find space in the directory for this filename (or allocate some more)
// NOTE: We need to find space for at least the LFN + SFN (or just the SFN if LFNs not supported).
if
(
!
fatfs_find_free_dir_offset
(
fs
,
dirCluster
,
entryCount
+
1
,
&
dirSector
,
&
dirOffset
))
return
0
;
// Generate checksum of short filename
pSname
=
(
uint8
*
)
shortfilename
;
checksum
=
0
;
for
(
i
=
11
;
i
!=
0
;
i
--
)
checksum
=
((
checksum
&
1
)
?
0x80
:
0
)
+
(
checksum
>>
1
)
+
*
pSname
++
;
// Start from current sector where space was found!
x
=
dirSector
;
// Main cluster following loop
while
(
1
)
{
// Read sector
if
(
fatfs_sector_reader
(
fs
,
dirCluster
,
x
++
,
0
))
{
// Analyse Sector
for
(
item
=
0
;
item
<
FAT_DIR_ENTRIES_PER_SECTOR
;
item
++
)
{
// Create the multiplier for sector access
recordoffset
=
FAT_DIR_ENTRY_SIZE
*
item
;
// If the start position for the entry has been found
if
(
foundEnd
==
0
)
if
(
(
dirSector
==
(
x
-
1
))
&&
(
dirOffset
==
item
)
)
foundEnd
=
1
;
// Start adding filename
if
(
foundEnd
)
{
if
(
entryCount
==
0
)
{
// Short filename
fatfs_sfn_create_entry
(
shortfilename
,
size
,
startCluster
,
&
shortEntry
,
dir
);
#if FATFS_INC_TIME_DATE_SUPPORT
// Update create, access & modify time & date
fatfs_update_timestamps
(
&
shortEntry
,
1
,
1
,
1
);
#endif
memcpy
(
&
fs
->
currentsector
.
sector
[
recordoffset
],
&
shortEntry
,
sizeof
(
shortEntry
));
// Writeback
return
fs
->
disk_io
.
write_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
#if FATFS_INC_LFN_SUPPORT
else
{
entryCount
--
;
// Copy entry to directory buffer
fatfs_filename_to_lfn
(
filename
,
&
fs
->
currentsector
.
sector
[
recordoffset
],
entryCount
,
checksum
);
dirtySector
=
1
;
}
#endif
}
}
// End of if
// Write back to disk before loading another sector
if
(
dirtySector
)
{
if
(
!
fs
->
disk_io
.
write_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
))
return
0
;
dirtySector
=
0
;
}
}
else
return
0
;
}
// End of while loop
return
0
;
}
#endif
vtoycli/fat_io_lib/release/fat_write.h
0 → 100644
View file @
b0568922
#ifndef __FAT_WRITE_H__
#define __FAT_WRITE_H__
#include "fat_defs.h"
#include "fat_opts.h"
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
int
fatfs_add_file_entry
(
struct
fatfs
*
fs
,
uint32
dirCluster
,
char
*
filename
,
char
*
shortfilename
,
uint32
startCluster
,
uint32
size
,
int
dir
);
int
fatfs_add_free_space
(
struct
fatfs
*
fs
,
uint32
*
startCluster
,
uint32
clusters
);
int
fatfs_allocate_free_space
(
struct
fatfs
*
fs
,
int
newFile
,
uint32
*
startCluster
,
uint32
size
);
#endif
Prev
1
2
3
4
5
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment